Merge branch 'vendor/OPENSSH'
[dragonfly.git] / sbin / natacontrol / natacontrol.c
1 /*-
2  * Copyright (c) 2000 - 2006 Søren Schmidt <sos@FreeBSD.org>
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sbin/atacontrol/atacontrol.c,v 1.42 2006/03/15 19:32:43 sos Exp $
27  * $DragonFly: src/sbin/natacontrol/natacontrol.c,v 1.3 2008/09/04 21:00:28 swildner Exp $
28  */
29
30 #include <sys/nata.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <err.h>
38
39 #include <sysexits.h>
40 #include <unistd.h>
41
42 static const char *mode2str(int mode);
43 static int      str2mode(char *str);
44 static void     usage(void);
45 static int      version(int ver);
46 static void     param_print(struct ata_params *parm);
47 static void     cap_print(struct ata_params *parm);
48 static int      ata_cap_print(int fd);
49 static int      info_print(int fd, int channel, int prchan);
50
51 const char *
52 mode2str(int mode)
53 {
54         switch (mode) {
55         case ATA_PIO: return "BIOSPIO";
56         case ATA_PIO0: return "PIO0";
57         case ATA_PIO1: return "PIO1";
58         case ATA_PIO2: return "PIO2";
59         case ATA_PIO3: return "PIO3";
60         case ATA_PIO4: return "PIO4";
61         case ATA_WDMA2: return "WDMA2";
62         case ATA_UDMA2: return "UDMA33";
63         case ATA_UDMA4: return "UDMA66";
64         case ATA_UDMA5: return "UDMA100";
65         case ATA_UDMA6: return "UDMA133";
66         case ATA_SA150: return "SATA150";
67         case ATA_SA300: return "SATA300";
68         case ATA_USB: return "USB";
69         case ATA_USB1: return "USB1";
70         case ATA_USB2: return "USB2";
71         case ATA_DMA: return "BIOSDMA";
72         default: return "???";
73         }
74 }
75
76 int
77 str2mode(char *str)
78 {
79         if (!strcasecmp(str, "BIOSPIO")) return ATA_PIO;
80         if (!strcasecmp(str, "PIO0")) return ATA_PIO0;
81         if (!strcasecmp(str, "PIO1")) return ATA_PIO1;
82         if (!strcasecmp(str, "PIO2")) return ATA_PIO2;
83         if (!strcasecmp(str, "PIO3")) return ATA_PIO3;
84         if (!strcasecmp(str, "PIO4")) return ATA_PIO4;
85         if (!strcasecmp(str, "WDMA2")) return ATA_WDMA2;
86         if (!strcasecmp(str, "UDMA2")) return ATA_UDMA2;
87         if (!strcasecmp(str, "UDMA33")) return ATA_UDMA2;
88         if (!strcasecmp(str, "UDMA4")) return ATA_UDMA4;
89         if (!strcasecmp(str, "UDMA66")) return ATA_UDMA4;
90         if (!strcasecmp(str, "UDMA5")) return ATA_UDMA5;
91         if (!strcasecmp(str, "UDMA100")) return ATA_UDMA5;
92         if (!strcasecmp(str, "UDMA6")) return ATA_UDMA6;
93         if (!strcasecmp(str, "UDMA133")) return ATA_UDMA6;
94         if (!strcasecmp(str, "BIOSDMA")) return ATA_DMA;
95         return -1;
96 }
97
98 void
99 usage(void)
100 {
101         fprintf(stderr,
102                 "usage:  natacontrol <command> args:\n"
103                 "        natacontrol list\n"
104                 "        natacontrol info channel\n"
105                 "        natacontrol attach channel\n"
106                 "        natacontrol detach channel\n"
107                 "        natacontrol reinit channel\n"
108                 "        natacontrol create type [interleave] disk0 ... diskN\n"
109                 "        natacontrol delete array\n"
110                 "        natacontrol addspare array disk\n"
111                 "        natacontrol rebuild array\n"
112                 "        natacontrol status array\n"
113                 "        natacontrol mode device [mode]\n"
114                 "        natacontrol cap device\n"
115         );
116         exit(EX_USAGE);
117 }
118
119 int
120 version(int ver)
121 {
122         int bit;
123
124         if (ver == 0xffff)
125                 return 0;
126         for (bit = 15; bit >= 0; bit--)
127                 if (ver & (1<<bit))
128                         return bit;
129         return 0;
130 }
131
132 void
133 param_print(struct ata_params *parm)
134 {
135         printf("<%.40s/%.8s> ", parm->model, parm->revision);
136         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
137                 if (parm->satacapabilities & ATA_SATA_GEN2)
138                         printf("Serial ATA II\n");
139                 else if (parm->satacapabilities & ATA_SATA_GEN1)
140                         printf("Serial ATA v1.0\n");
141                 else
142                         printf("Unknown serial ATA version\n");
143         }
144         else
145                 printf("ATA/ATAPI revision %d\n", version(parm->version_major));
146 }
147
148 void
149 cap_print(struct ata_params *parm)
150 {
151         u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
152                                 ((u_int32_t)parm->lba_size_2 << 16);
153
154         u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
155                                 ((u_int64_t)parm->lba_size48_2 << 16) |
156                                 ((u_int64_t)parm->lba_size48_3 << 32) |
157                                 ((u_int64_t)parm->lba_size48_4 << 48);
158
159         printf("\n");
160         printf("Protocol              ");
161         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
162                 if (parm->satacapabilities & ATA_SATA_GEN2)
163                         printf("Serial ATA II\n");
164                 else if (parm->satacapabilities & ATA_SATA_GEN1)
165                         printf("Serial ATA v1.0\n");
166                 else
167                         printf("Unknown serial ATA version\n");
168         }
169         else
170                 printf("ATA/ATAPI revision %d\n", version(parm->version_major));
171         printf("device model          %.40s\n", parm->model);
172         printf("serial number         %.20s\n", parm->serial);
173         printf("firmware revision     %.8s\n", parm->revision);
174
175         printf("cylinders             %d\n", parm->cylinders);
176         printf("heads                 %d\n", parm->heads);
177         printf("sectors/track         %d\n", parm->sectors);
178
179         printf("lba%ssupported         ",
180                 parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
181         if (lbasize)
182                 printf("%d sectors\n", lbasize);
183         else
184                 printf("\n");
185
186         printf("lba48%ssupported       ",
187                 parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
188         if (lbasize48)
189                 printf("%llu sectors\n", (unsigned long long)lbasize48);
190         else
191                 printf("\n");
192
193         printf("dma%ssupported\n",
194                 parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
195
196         printf("overlap%ssupported\n",
197                 parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not ");
198
199         printf("\nFeature                      "
200                 "Support  Enable    Value           Vendor\n");
201
202         printf("write cache                    %s       %s\n",
203                 parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
204                 parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
205
206         printf("read ahead                     %s       %s\n",
207                 parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
208                 parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
209
210         if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
211                 printf("Native Command Queuing (NCQ)   %s       %s"
212                         "       %d/0x%02X\n",
213                         parm->satacapabilities & ATA_SUPPORT_NCQ ?
214                                 "yes" : "no", " -",
215                         (parm->satacapabilities & ATA_SUPPORT_NCQ) ?
216                                 ATA_QUEUE_LEN(parm->queue) : 0,
217                         (parm->satacapabilities & ATA_SUPPORT_NCQ) ?
218                                 ATA_QUEUE_LEN(parm->queue) : 0);
219         }
220         printf("Tagged Command Queuing (TCQ)   %s       %s      %d/0x%02X\n",
221                 parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
222                 parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
223                 ATA_QUEUE_LEN(parm->queue), ATA_QUEUE_LEN(parm->queue));
224
225         printf("SMART                          %s       %s\n",
226                 parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
227                 parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
228
229         printf("microcode download             %s       %s\n",
230                 parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
231                 parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
232
233         printf("security                       %s       %s\n",
234                 parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
235                 parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
236
237         printf("power management               %s       %s\n",
238                 parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
239                 parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
240
241         printf("advanced power management      %s       %s      %d/0x%02X\n",
242                 parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
243                 parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
244                 parm->apm_value, parm->apm_value);
245
246         printf("automatic acoustic management  %s       %s      "
247                 "%d/0x%02X      %d/0x%02X\n",
248                 parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
249                 parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
250                 ATA_ACOUSTIC_CURRENT(parm->acoustic),
251                 ATA_ACOUSTIC_CURRENT(parm->acoustic),
252                 ATA_ACOUSTIC_VENDOR(parm->acoustic),
253                 ATA_ACOUSTIC_VENDOR(parm->acoustic));
254 }
255
256 int
257 ata_cap_print(int fd)
258 {
259         struct ata_params params;
260
261         if (ioctl(fd, IOCATAGPARM, &params) < 0)
262                 return errno;
263         cap_print(&params);
264         return 0;
265 }
266
267 int
268 info_print(int fd, int channel, int prchan)
269 {
270         struct ata_ioc_devices devices;
271
272         devices.channel = channel;
273
274         if (ioctl(fd, IOCATADEVICES, &devices) < 0)
275                 return errno;
276
277         if (prchan)
278                 printf("ATA channel %d:\n", channel);
279         printf("%sMaster: ", prchan ? "    " : "");
280         if (*devices.name[0]) {
281                 printf("%4.4s ", devices.name[0]);
282                 param_print(&devices.params[0]);
283         }
284         else
285                 printf("     no device present\n");
286         printf("%sSlave:  ", prchan ? "    " : "");
287         if (*devices.name[1]) {
288                 printf("%4.4s ", devices.name[1]);
289                 param_print(&devices.params[1]);
290         }
291         else
292                 printf("     no device present\n");
293         return 0;
294 }
295
296 int
297 main(int argc, char **argv)
298 {
299         int fd;
300
301         if (argc < 2)
302                 usage();
303
304         if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 4)) {
305                 int disk, mode;
306                 char device[64];
307
308                 if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
309                       sscanf(argv[2], "acd%d", &disk) == 1 ||
310                       sscanf(argv[2], "afd%d", &disk) == 1 ||
311                       sscanf(argv[2], "ast%d", &disk) == 1)) {
312                         fprintf(stderr, "natacontrol: Invalid device %s\n",
313                                 argv[2]);
314                         exit(EX_USAGE);
315                 }
316                 sprintf(device, "/dev/%s", argv[2]);
317                 if ((fd = open(device, O_RDONLY)) < 0)
318                         err(1, "device not found");
319                 if (argc == 4) {
320                         mode = str2mode(argv[3]);
321                         if (ioctl(fd, IOCATASMODE, &mode) < 0)
322                                 warn("ioctl(IOCATASMODE)");
323                 }
324                 if (argc == 3 || argc == 4) {
325                         if (ioctl(fd, IOCATAGMODE, &mode) < 0)
326                                 err(1, "ioctl(IOCATAGMODE)");
327                         printf("current mode = %s\n", mode2str(mode));
328                 }
329                 exit(EX_OK);
330         }
331         if (!strcmp(argv[1], "cap") && argc == 3) {
332                 int disk;
333                 char device[64];
334
335                 if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
336                       sscanf(argv[2], "acd%d", &disk) == 1 ||
337                       sscanf(argv[2], "afd%d", &disk) == 1 ||
338                       sscanf(argv[2], "ast%d", &disk) == 1)) {
339                         fprintf(stderr, "natacontrol: Invalid device %s\n",
340                                 argv[2]);
341                         exit(EX_USAGE);
342                 }
343                 sprintf(device, "/dev/%s", argv[2]);
344                 if ((fd = open(device, O_RDONLY)) < 0)
345                         err(1, "device not found");
346                 ata_cap_print(fd);
347                 exit(EX_OK);
348         }
349
350         if ((fd = open("/dev/ata", O_RDWR)) < 0)
351                 err(1, "control device not found");
352
353         if (!strcmp(argv[1], "list") && argc == 2) {
354                 int maxchannel, channel;
355
356                 if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0)
357                         err(1, "ioctl(IOCATAGMAXCHANNEL)");
358                 for (channel = 0; channel < maxchannel; channel++)
359                         info_print(fd, channel, 1);
360                 exit(EX_OK);
361         }
362         if (!strcmp(argv[1], "info") && argc == 3) {
363                 int channel;
364
365                 if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
366                         fprintf(stderr,
367                                 "natacontrol: Invalid channel %s\n", argv[2]);
368                         exit(EX_USAGE);
369                 }
370                 info_print(fd, channel, 0);
371                 exit(EX_OK);
372         }
373         if (!strcmp(argv[1], "detach") && argc == 3) {
374                 int channel;
375
376                 if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
377                         fprintf(stderr,
378                                 "natacontrol: Invalid channel %s\n", argv[2]);
379                         exit(EX_USAGE);
380                 }
381                 if (ioctl(fd, IOCATADETACH, &channel) < 0)
382                         err(1, "ioctl(IOCATADETACH)");
383                 exit(EX_OK);
384         }
385         if (!strcmp(argv[1], "attach") && argc == 3) {
386                 int channel;
387
388                 if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
389                         fprintf(stderr,
390                                 "natacontrol: Invalid channel %s\n", argv[2]);
391                         exit(EX_USAGE);
392                 }
393                 if (ioctl(fd, IOCATAATTACH, &channel) < 0)
394                         err(1, "ioctl(IOCATAATTACH)");
395                 info_print(fd, channel, 0);
396                 exit(EX_OK);
397         }
398         if (!strcmp(argv[1], "reinit") && argc == 3) {
399                 int channel;
400
401                 if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
402                         fprintf(stderr,
403                                 "natacontrol: Invalid channel %s\n", argv[2]);
404                         exit(EX_USAGE);
405                 }
406                 if (ioctl(fd, IOCATAREINIT, &channel) < 0)
407                         warn("ioctl(IOCATAREINIT)");
408                 info_print(fd, channel, 0);
409                 exit(EX_OK);
410         }
411         if (!strcmp(argv[1], "create")) {
412                 int disk, dev, offset;
413                 struct ata_ioc_raid_config config;
414
415                 bzero(&config, sizeof(config));
416                 if (argc > 2) {
417                         if (!strcasecmp(argv[2], "RAID0") ||
418                             !strcasecmp(argv[2], "stripe"))
419                                 config.type = AR_RAID0;
420                         if (!strcasecmp(argv[2], "RAID1") ||
421                             !strcasecmp(argv[2],"mirror"))
422                                 config.type = AR_RAID1;
423                         if (!strcasecmp(argv[2], "RAID0+1") ||
424                             !strcasecmp(argv[2],"RAID10"))
425                                 config.type = AR_RAID01;
426                         if (!strcasecmp(argv[2], "RAID5"))
427                                 config.type = AR_RAID5;
428                         if (!strcasecmp(argv[2], "SPAN"))
429                                 config.type = AR_SPAN;
430                         if (!strcasecmp(argv[2], "JBOD"))
431                                 config.type = AR_JBOD;
432                 }
433                 if (!config.type) {
434                         fprintf(stderr, "natacontrol: Invalid RAID type %s\n",
435                                 argv[2]);
436                         fprintf(stderr, "natacontrol: Valid RAID types: \n");
437                         fprintf(stderr, "             stripe | mirror | "
438                                         "RAID0 | RAID1 | RAID0+1 | RAID5 | "
439                                         "SPAN | JBOD\n");
440                         exit(EX_USAGE);
441                 }
442
443                 if (config.type == AR_RAID0 ||
444                     config.type == AR_RAID01 ||
445                     config.type == AR_RAID5) {
446                         if (argc < 4 ||
447                             !sscanf(argv[3], "%d", &config.interleave) == 1) {
448                                 fprintf(stderr,
449                                         "natacontrol: Invalid interleave %s\n",
450                                         argv[3]);
451                                 exit(EX_USAGE);
452                         }
453                         offset = 4;
454                 }
455                 else
456                         offset = 3;
457
458                 for (disk = 0; disk < 16 && (offset + disk) < argc; disk++) {
459                         if (!(sscanf(argv[offset + disk], "ad%d", &dev) == 1)) {
460                                 fprintf(stderr,
461                                         "natacontrol: Invalid disk %s\n",
462                                         argv[offset + disk]);
463                                 exit(EX_USAGE);
464                         }
465                         config.disks[disk] = dev;
466                 }
467
468                 if ((config.type == AR_RAID1 || config.type == AR_RAID01) &&
469                     disk < 2) {
470                         fprintf(stderr, "natacontrol: At least 2 disks must be "
471                                 "specified\n");
472                         exit(EX_USAGE);
473                 }
474
475                 config.total_disks = disk;
476                 if (ioctl(fd, IOCATARAIDCREATE, &config) < 0)
477                         err(1, "ioctl(IOCATARAIDCREATE)");
478                 else
479                         printf("ar%d created\n", config.lun);
480                 exit(EX_OK);
481         }
482         if (!strcmp(argv[1], "delete") && argc == 3) {
483                 int array;
484
485                 if (!(sscanf(argv[2], "ar%d", &array) == 1)) {
486                         fprintf(stderr,
487                                 "natacontrol: Invalid array %s\n", argv[2]);
488                         exit(EX_USAGE);
489                 }
490                 if (ioctl(fd, IOCATARAIDDELETE, &array) < 0)
491                         warn("ioctl(IOCATARAIDDELETE)");
492                 exit(EX_OK);
493         }
494         if (!strcmp(argv[1], "addspare") && argc == 4) {
495                 struct ata_ioc_raid_config config;
496
497                 if (!(sscanf(argv[2], "ar%d", &config.lun) == 1)) {
498                         fprintf(stderr,
499                                 "natacontrol: Invalid array %s\n", argv[2]);
500                         usage();
501                 }
502                 if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) {
503                         fprintf(stderr,
504                                 "natacontrol: Invalid disk %s\n", argv[3]);
505                         usage();
506                 }
507                 if (ioctl(fd, IOCATARAIDADDSPARE, &config) < 0)
508                         warn("ioctl(IOCATARAIDADDSPARE)");
509                 exit(EX_OK);
510         }
511         if (!strcmp(argv[1], "rebuild") && argc == 3) {
512                 int array;
513
514                 if (!(sscanf(argv[2], "ar%d", &array) == 1)) {
515                         fprintf(stderr,
516                                 "natacontrol: Invalid array %s\n", argv[2]);
517                         usage();
518                 }
519                 if (ioctl(fd, IOCATARAIDREBUILD, &array) < 0)
520                         warn("ioctl(IOCATARAIDREBUILD)");
521                 else {
522                         char device[64];
523                         char *buffer;
524                         ssize_t len;
525                         int arfd;
526
527                         if (daemon(0, 1) == -1)
528                                 err(1, "daemon");
529                         nice(20);
530                         snprintf(device, sizeof(device), "/dev/ar%d",
531                             array);
532                         if ((arfd = open(device, O_RDONLY)) == -1)
533                                 err(1, "open %s", device);
534                         if ((buffer = malloc(1024 * 1024)) == NULL)
535                                 err(1, "malloc");
536                         while ((len = read(arfd, buffer, 1024 * 1024)) > 0)
537                                 ;
538                         if (len == -1)
539                                 err(1, "read");
540                         else
541                                 fprintf(stderr,
542                                     "atacontrol: ar%d rebuild completed\n",
543                                     array);
544                         free(buffer);
545                         close(arfd);
546                 }
547                 exit(EX_OK);
548         }
549         if (!strcmp(argv[1], "status") && argc == 3) {
550                 struct ata_ioc_raid_config config;
551                 int i;
552
553                 if (!(sscanf(argv[2], "ar%d", &config.lun) == 1)) {
554                         fprintf(stderr,
555                                 "natacontrol: Invalid array %s\n", argv[2]);
556                         usage();
557                 }
558                 if (ioctl(fd, IOCATARAIDSTATUS, &config) < 0)
559                         err(1, "ioctl(IOCATARAIDSTATUS)");
560
561                 printf("ar%d: ATA ", config.lun);
562                 switch (config.type) {
563                 case AR_RAID0:
564                         printf("RAID0 stripesize=%d", config.interleave);
565                         break;
566                 case AR_RAID1:
567                         printf("RAID1");
568                         break;
569                 case AR_RAID01:
570                         printf("RAID0+1 stripesize=%d", config.interleave);
571                         break;
572                 case AR_RAID5:
573                         printf("RAID5 stripesize=%d", config.interleave);
574                         break;
575                 case AR_JBOD:
576                         printf("JBOD");
577                 case AR_SPAN:
578                         printf("SPAN");
579                         break;
580                 }
581                 printf(" subdisks: ");
582                 for (i = 0; i < config.total_disks; i++) {
583                         if (config.disks[i] >= 0)
584                                 printf("ad%d ", config.disks[i]);
585                         else
586                                 printf("DOWN ");
587                 }
588                 printf("status: ");
589                 switch (config.status) {
590                 case AR_READY:
591                         printf("READY\n");
592                         break;
593                 case AR_READY | AR_DEGRADED:
594                         printf("DEGRADED\n");
595                         break;
596                 case AR_READY | AR_DEGRADED | AR_REBUILDING:
597                         printf("REBUILDING %d%% completed\n",
598                                 config.progress);
599                         break;
600                 default:
601                         printf("BROKEN\n");
602                 }
603                 exit(EX_OK);
604         }
605         usage();
606         exit(EX_OK);
607 }