Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / dpt / dpt_dm / dpt_dm.c
1 /*
2  *       Copyright (c) 1997 by Simon Shapiro
3  *       All Rights Reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD: src/usr.sbin/dpt/dpt_dm/dpt_dm.c,v 1.3 1999/08/28 01:16:07 peter Exp $
30  * $DragonFly: src/usr.sbin/dpt/dpt_dm/dpt_dm.c,v 1.2 2003/06/17 04:29:53 dillon Exp $
31  */
32
33 /* dpt_dm.c: Dump a DPT metrics structure */
34
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <sys/time.h>
41 #include <sys/stat.h>
42 #include <sys/queue.h>
43 #include <sys/ioctl.h>
44 #include <scsi/scsi_all.h>
45 #include <scsi/scsi_message.h>
46 #include <scsi/scsiconf.h>
47
48 #define DPT_MEASURE_PERFORMANCE
49
50 #include <sys/dpt.h>
51
52 char    *
53 scsi_cmd_name(u_int8_t cmd)
54 {
55     switch (cmd) {
56     case 0x40:
57         return ("Change Definition [7.1]");
58         break;
59     case 0x39:
60         return ("Compare [7,2]");
61         break;
62     case 0x18:
63         return ("Copy [7.3]");
64         break;
65     case 0x3a:
66         return ("Copy and Verify [7.4]");
67         break;
68     case 0x04:
69         return ("Format Unit [6.1.1]");
70         break;
71     case 0x12:
72         return ("Inquiry [7.5]");
73         break;
74     case 0x36:
75         return ("lock/Unlock Cache [6.1.2]");
76         break;
77     case 0x4c:
78         return ("Log Select [7.6]");
79         break;
80     case 0x4d:
81         return ("Log Sense [7.7]");
82         break;
83     case 0x15:
84         return ("Mode select (6) [7.8]");
85         break;
86     case 0x55:
87         return ("Mode Select (10) [7.9]");
88         break;
89     case 0x1a:
90         return ("Mode Sense (6) [7.10]");
91         break;
92     case 0x5a:
93         return ("Mode Sense (10) [7.11]");
94         break;
95     case 0xa7:
96         return ("Move Medium Attached [SMC]");
97         break;
98     case 0x5e:
99         return ("Persistent Reserve In [7.12]");
100         break;
101     case 0x5f:
102         return ("Persistent Reserve Out [7.13]");
103         break;
104     case 0x1e:
105         return ("Prevent/Allow Medium Removal [7.14]");
106         break;
107     case 0x08:
108         return ("Read, Receive (6) [6.1.5]");
109         break;
110     case 0x28:
111         return ("Read (10) [6.1.5]");
112         break;
113     case 0xa8:
114         return ("Read (12) [6.1.5]");
115         break;
116     case 0x3c:
117         return ("Read Buffer [7.15]");
118         break;
119     case 0x25:
120         return ("Read Capacity [6.1.6]");
121         break;
122     case 0x37:
123         return ("Read Defect Data (10) [6.1.7]");
124         break;
125     case 0xb7:
126         return ("Read Defect Data (12) [6.2.5]");
127         break;
128     case 0xb4:
129         return ("Read Element Status Attached [SMC]");
130         break;
131     case 0x3e:
132         return ("Read Long [6.1.8]");
133         break;
134     case 0x07:
135         return ("Reassign Blocks [6.1.9]");
136         break;
137     case 0x81:
138         return ("Rebuild [6.1.10]");
139         break;
140     case 0x1c:
141         return ("Receive Diagnostics Result [7.16]");
142         break;
143     case 0x82:
144         return ("Regenerate [6.1.11]");
145         break;
146     case 0x17:
147         return ("Release(6) [7.17]");
148         break;
149     case 0x57:
150         return ("Release(10) [7.18]");
151         break;
152     case 0xa0:
153         return ("Report LUNs [7.19]");
154         break;
155     case 0x03:
156         return ("Request Sense [7.20]");
157         break;
158     case 0x16:
159         return ("Resereve (6) [7.21]");
160         break;
161     case 0x56:
162         return ("Reserve(10) [7.22]");
163         break;
164     case 0x2b:
165         return ("Reserve(10) [6.1.12]");
166         break;
167     case 0x1d:
168         return ("Send Disagnostics [7.23]");
169         break;
170     case 0x33:
171         return ("Set Limit (10) [6.1.13]");
172         break;
173     case 0xb3:
174         return ("Set Limit (12) [6.2.8]");
175         break;
176     case 0x1b:
177         return ("Start/Stop Unit [6.1.14]");
178         break;
179     case 0x35:
180         return ("Synchronize Cache [6.1.15]");
181         break;
182     case 0x00:
183         return ("Test Unit Ready [7.24]");
184         break;
185     case 0x3d:
186         return ("Update Block (6.2.9");
187         break;
188     case 0x2f:
189         return ("Verify (10) [6.1.16, 6.2.10]");
190         break;
191     case 0xaf:
192         return ("Verify (12) [6.2.11]");
193         break;
194     case 0x0a:
195         return ("Write, Send (6) [6.1.17, 9.2]");
196         break;
197     case 0x2a:
198         return ("Write (10) [6.1.18]");
199         break;
200     case 0xaa:
201         return ("Write (12) [6.2.13]");
202         break;
203     case 0x2e:
204         return ("Write and Verify (10) [6.1.19, 6.2.14]");
205         break;
206     case 0xae:
207         return ("Write and Verify (12) [6.1.19, 6.2.15]");
208         break;
209     case 0x03b:
210         return ("Write Buffer [7.25]");
211         break;
212     case 0x03f:
213         return ("Write Long [6.1.20]");
214         break;
215     case 0x041:
216         return ("Write Same [6.1.21]");
217         break;
218     case 0x052:
219         return ("XD Read [6.1.22]");
220         break;
221     case 0x050:
222         return ("XD Write [6.1.22]");
223         break;
224     case 0x080:
225         return ("XD Write Extended [6.1.22]");
226         break;
227     case 0x051:
228         return ("XO Write [6.1.22]");
229         break;
230     default:
231         return ("Unknown SCSI Command");
232     }
233 }
234
235 static const char *
236 tmpsprintf(int buffer, const char *format, ...) 
237 {
238     static char buffers[16][16];
239     va_list ap;
240
241     va_start(ap, format);
242     vsnprintf(buffers[buffer], 16, format, ap);
243     va_end(ap);
244     return buffers[buffer];
245 }
246
247
248 int
249 main(int argc, char **argv, char **argp)
250 {
251     dpt_perf_t metrics;
252     int result;
253     int fd;
254     int ndx;
255
256     if ( (fd = open(argv[1], O_RDWR, S_IRUSR | S_IWUSR)) == -1 ) {
257         (void)fprintf(stderr, "%s ERROR:  Failed to open \"%s\" - %s\n",
258                       argv[0], argv[1], strerror(errno));
259         exit(1);
260     }
261
262     if ( (result = ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, &metrics)) != 0 ) {
263         (void)fprintf(stderr, "%s ERROR:  Failed to send IOCTL %lx - %s\n",
264                       argv[0], DPT_IOCTL_INTERNAL_METRICS,
265                       strerror(errno));
266         exit(2);
267     }
268
269     /* Interrupt related measurements */
270     (void)fprintf(stdout, "Interrupts:%u:%u:%s:%u\n\nCommands:\n",
271                   metrics.aborted_interrupts,
272                   metrics.spurious_interrupts,
273                   metrics.min_intr_time == BIG_ENOUGH ?
274                         "N/A" :
275                         tmpsprintf(0, "%u", metrics.min_intr_time),
276                   metrics.max_intr_time);
277
278     /* SCSI Commands, can be no more than 256 of them */
279     for (ndx = 0; ndx < 256; ndx++) {
280         if (metrics.command_count[ndx] != 0) {
281             (void)fprintf(stdout, "%u:%s:%u:%s:%d\n",
282                           ndx,
283                           scsi_cmd_name((u_int8_t)ndx), 
284                           metrics.command_count[ndx],
285                           metrics.min_command_time[ndx] == BIG_ENOUGH ?
286                                 "N/A" :
287                                 tmpsprintf(0, "%u", metrics.min_command_time[ndx]),
288                           metrics.max_command_time[ndx]);
289         }
290     }
291     
292     (void)fprintf(stdout, "\nREAD by size:\n");
293
294     /* READ/WRITE statistics, per block size */
295
296     for ( ndx = 0; ndx < 10; ndx++) {           
297         if (metrics.read_by_size_count[ndx] != 0) {
298             char* block_size;
299         
300             switch ( ndx ) {
301             case SIZE_512:
302                 block_size = "512";
303                 break;
304             case SIZE_1K:       
305                 block_size = "1K";
306                 break;
307             case SIZE_2K:
308                 block_size = "2K";
309                 break;  
310             case SIZE_4K:       
311                 block_size = "4K";
312                 break;
313             case SIZE_8K:
314                 block_size = "8K";
315                 break;
316             case SIZE_16K:
317                 block_size = "16K";
318                 break;
319             case SIZE_32K:
320                 block_size = "32K";
321                 break;
322             case SIZE_64K:
323                 block_size = "64K";
324                 break;
325             case SIZE_BIGGER:
326                 block_size = "BIGGER";
327                 break;
328             case SIZE_OTHER:
329                 block_size = "OTHER";
330                 break;
331             default:
332                 block_size = "Gcc, shut up!";
333             }
334             
335             (void)fprintf(stdout, "%s:%u:%u:%u\n", block_size,
336                           metrics.read_by_size_count[ndx],
337                           metrics.read_by_size_min_time[ndx],
338                           metrics.read_by_size_max_time[ndx]);
339         }
340     }
341             
342     (void)fprintf(stdout, "\nWRITE by size:\n");
343
344     for ( ndx = 0; ndx < 10; ndx++) {           
345         if (metrics.write_by_size_count[ndx] != 0) {
346             char* block_size;
347         
348             switch ( ndx ) {
349             case SIZE_512:
350                 block_size = "512";
351                 break;
352             case SIZE_1K:       
353                 block_size = "1K";
354                 break;
355             case SIZE_2K:
356                 block_size = "2K";
357                 break;  
358             case SIZE_4K:       
359                 block_size = "4K";
360                 break;
361             case SIZE_8K:
362                 block_size = "8K";
363                 break;
364             case SIZE_16K:
365                 block_size = "16K";
366                 break;
367             case SIZE_32K:
368                 block_size = "32K";
369                 break;
370             case SIZE_64K:
371                 block_size = "64K";
372                 break;
373             case SIZE_BIGGER:
374                 block_size = "BIGGER";
375                 break;
376             case SIZE_OTHER:
377                 block_size = "OTHER";
378                 break;
379             default:
380                 block_size = "Gcc, shut up!";
381             }
382             
383             (void)fprintf(stdout, "%s:%u:%u:%u\n", block_size,
384                           metrics.write_by_size_count[ndx],
385                           metrics.write_by_size_min_time[ndx],
386                           metrics.write_by_size_max_time[ndx]);
387         }
388         
389     }
390     
391     (void)fprintf(stdout, "\nQueues:%u:%s:%u:%u:%s:%u:%u:%s:%u\n", 
392                   metrics.max_waiting_count,
393                   metrics.min_waiting_time == BIG_ENOUGH ?
394                         "N/A" :
395                         tmpsprintf(0, "%u", metrics.min_waiting_time),
396                   metrics.max_waiting_time,
397                   metrics.max_submit_count,
398                   metrics.min_submit_time == BIG_ENOUGH ?
399                         "N/A" :
400                         tmpsprintf(1, "%u", metrics.min_submit_time),
401                   metrics.max_submit_time,
402                   metrics.max_complete_count,
403                   metrics.min_complete_time == BIG_ENOUGH ?
404                         "N/A" :
405                         tmpsprintf(2, "%u", metrics.min_complete_time),
406                   metrics.max_complete_time);
407
408     (void)fprintf(stdout, "Hardware Ports:%u:%u:%u:%s\n",
409                   metrics.command_collisions,
410                   metrics.command_too_busy,
411                   metrics.max_eata_tries,
412                   metrics.min_eata_tries == BIG_ENOUGH ?
413                         "N/A" :
414                         tmpsprintf(0, "%u", metrics.min_eata_tries));
415
416     return(0);
417 }