2 * Copyright (c) 2000 - 2006 Søren Schmidt <sos@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
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 $
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
);
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 "???";
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
;
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"
126 for (bit
= 15; bit
>= 0; bit
--)
133 param_print(struct ata_params
*parm
)
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");
142 printf("Unknown serial ATA version\n");
145 printf("ATA/ATAPI revision %d\n", version(parm
->version_major
));
149 cap_print(struct ata_params
*parm
)
151 u_int32_t lbasize
= (u_int32_t
)parm
->lba_size_1
|
152 ((u_int32_t
)parm
->lba_size_2
<< 16);
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);
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");
167 printf("Unknown serial ATA version\n");
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
);
175 printf("cylinders %d\n", parm
->cylinders
);
176 printf("heads %d\n", parm
->heads
);
177 printf("sectors/track %d\n", parm
->sectors
);
179 printf("lba%ssupported ",
180 parm
->capabilities1
& ATA_SUPPORT_LBA
? " " : " not ");
182 printf("%d sectors\n", lbasize
);
186 printf("lba48%ssupported ",
187 parm
->support
.command2
& ATA_SUPPORT_ADDRESS48
? " " : " not ");
189 printf("%llu sectors\n", (unsigned long long)lbasize48
);
193 printf("dma%ssupported\n",
194 parm
->capabilities1
& ATA_SUPPORT_DMA
? " " : " not ");
196 printf("overlap%ssupported\n",
197 parm
->capabilities1
& ATA_SUPPORT_OVERLAP
? " " : " not ");
200 "Support Enable Value Vendor\n");
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");
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");
210 if (parm
->satacapabilities
&& parm
->satacapabilities
!= 0xffff) {
211 printf("Native Command Queuing (NCQ) %s %s"
213 parm
->satacapabilities
& ATA_SUPPORT_NCQ
?
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);
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
));
225 printf("SMART %s %s\n",
226 parm
->support
.command1
& ATA_SUPPORT_SMART
? "yes" : "no",
227 parm
->enabled
.command1
& ATA_SUPPORT_SMART
? "yes" : "no");
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");
233 printf("security %s %s\n",
234 parm
->support
.command1
& ATA_SUPPORT_SECURITY
? "yes" : "no",
235 parm
->enabled
.command1
& ATA_SUPPORT_SECURITY
? "yes" : "no");
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");
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
);
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
));
257 ata_cap_print(int fd
)
259 struct ata_params params
;
261 if (ioctl(fd
, IOCATAGPARM
, ¶ms
) < 0)
268 info_print(int fd
, int channel
, int prchan
)
270 struct ata_ioc_devices devices
;
272 devices
.channel
= channel
;
274 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0)
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]);
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]);
292 printf(" no device present\n");
297 main(int argc
, char **argv
)
304 if (!strcmp(argv
[1], "mode") && (argc
== 3 || argc
== 4)) {
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",
316 sprintf(device
, "/dev/%s", argv
[2]);
317 if ((fd
= open(device
, O_RDONLY
)) < 0)
318 err(1, "device not found");
320 mode
= str2mode(argv
[3]);
321 if (ioctl(fd
, IOCATASMODE
, &mode
) < 0)
322 warn("ioctl(IOCATASMODE)");
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
));
331 if (!strcmp(argv
[1], "cap") && argc
== 3) {
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",
343 sprintf(device
, "/dev/%s", argv
[2]);
344 if ((fd
= open(device
, O_RDONLY
)) < 0)
345 err(1, "device not found");
350 if ((fd
= open("/dev/ata", O_RDWR
)) < 0)
351 err(1, "control device not found");
353 if (!strcmp(argv
[1], "list") && argc
== 2) {
354 int maxchannel
, channel
;
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);
362 if (!strcmp(argv
[1], "info") && argc
== 3) {
365 if (!(sscanf(argv
[2], "ata%d", &channel
) == 1)) {
367 "natacontrol: Invalid channel %s\n", argv
[2]);
370 info_print(fd
, channel
, 0);
373 if (!strcmp(argv
[1], "detach") && argc
== 3) {
376 if (!(sscanf(argv
[2], "ata%d", &channel
) == 1)) {
378 "natacontrol: Invalid channel %s\n", argv
[2]);
381 if (ioctl(fd
, IOCATADETACH
, &channel
) < 0)
382 err(1, "ioctl(IOCATADETACH)");
385 if (!strcmp(argv
[1], "attach") && argc
== 3) {
388 if (!(sscanf(argv
[2], "ata%d", &channel
) == 1)) {
390 "natacontrol: Invalid channel %s\n", argv
[2]);
393 if (ioctl(fd
, IOCATAATTACH
, &channel
) < 0)
394 err(1, "ioctl(IOCATAATTACH)");
395 info_print(fd
, channel
, 0);
398 if (!strcmp(argv
[1], "reinit") && argc
== 3) {
401 if (!(sscanf(argv
[2], "ata%d", &channel
) == 1)) {
403 "natacontrol: Invalid channel %s\n", argv
[2]);
406 if (ioctl(fd
, IOCATAREINIT
, &channel
) < 0)
407 warn("ioctl(IOCATAREINIT)");
408 info_print(fd
, channel
, 0);
411 if (!strcmp(argv
[1], "create")) {
412 int disk
, dev
, offset
;
413 struct ata_ioc_raid_config config
;
415 bzero(&config
, sizeof(config
));
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
;
434 fprintf(stderr
, "natacontrol: Invalid RAID type %s\n",
436 fprintf(stderr
, "natacontrol: Valid RAID types: \n");
437 fprintf(stderr
, " stripe | mirror | "
438 "RAID0 | RAID1 | RAID0+1 | RAID5 | "
443 if (config
.type
== AR_RAID0
||
444 config
.type
== AR_RAID01
||
445 config
.type
== AR_RAID5
) {
447 !sscanf(argv
[3], "%d", &config
.interleave
) == 1) {
449 "natacontrol: Invalid interleave %s\n",
458 for (disk
= 0; disk
< 16 && (offset
+ disk
) < argc
; disk
++) {
459 if (!(sscanf(argv
[offset
+ disk
], "ad%d", &dev
) == 1)) {
461 "natacontrol: Invalid disk %s\n",
462 argv
[offset
+ disk
]);
465 config
.disks
[disk
] = dev
;
468 if ((config
.type
== AR_RAID1
|| config
.type
== AR_RAID01
) &&
470 fprintf(stderr
, "natacontrol: At least 2 disks must be "
475 config
.total_disks
= disk
;
476 if (ioctl(fd
, IOCATARAIDCREATE
, &config
) < 0)
477 err(1, "ioctl(IOCATARAIDCREATE)");
479 printf("ar%d created\n", config
.lun
);
482 if (!strcmp(argv
[1], "delete") && argc
== 3) {
485 if (!(sscanf(argv
[2], "ar%d", &array
) == 1)) {
487 "natacontrol: Invalid array %s\n", argv
[2]);
490 if (ioctl(fd
, IOCATARAIDDELETE
, &array
) < 0)
491 warn("ioctl(IOCATARAIDDELETE)");
494 if (!strcmp(argv
[1], "addspare") && argc
== 4) {
495 struct ata_ioc_raid_config config
;
497 if (!(sscanf(argv
[2], "ar%d", &config
.lun
) == 1)) {
499 "natacontrol: Invalid array %s\n", argv
[2]);
502 if (!(sscanf(argv
[3], "ad%d", &config
.disks
[0]) == 1)) {
504 "natacontrol: Invalid disk %s\n", argv
[3]);
507 if (ioctl(fd
, IOCATARAIDADDSPARE
, &config
) < 0)
508 warn("ioctl(IOCATARAIDADDSPARE)");
511 if (!strcmp(argv
[1], "rebuild") && argc
== 3) {
514 if (!(sscanf(argv
[2], "ar%d", &array
) == 1)) {
516 "natacontrol: Invalid array %s\n", argv
[2]);
519 if (ioctl(fd
, IOCATARAIDREBUILD
, &array
) < 0)
520 warn("ioctl(IOCATARAIDREBUILD)");
527 if (daemon(0, 1) == -1)
530 snprintf(device
, sizeof(device
), "/dev/ar%d",
532 if ((arfd
= open(device
, O_RDONLY
)) == -1)
533 err(1, "open %s", device
);
534 if ((buffer
= malloc(1024 * 1024)) == NULL
)
536 while ((len
= read(arfd
, buffer
, 1024 * 1024)) > 0)
542 "atacontrol: ar%d rebuild completed\n",
549 if (!strcmp(argv
[1], "status") && argc
== 3) {
550 struct ata_ioc_raid_config config
;
553 if (!(sscanf(argv
[2], "ar%d", &config
.lun
) == 1)) {
555 "natacontrol: Invalid array %s\n", argv
[2]);
558 if (ioctl(fd
, IOCATARAIDSTATUS
, &config
) < 0)
559 err(1, "ioctl(IOCATARAIDSTATUS)");
561 printf("ar%d: ATA ", config
.lun
);
562 switch (config
.type
) {
564 printf("RAID0 stripesize=%d", config
.interleave
);
570 printf("RAID0+1 stripesize=%d", config
.interleave
);
573 printf("RAID5 stripesize=%d", config
.interleave
);
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
]);
589 switch (config
.status
) {
593 case AR_READY
| AR_DEGRADED
:
594 printf("DEGRADED\n");
596 case AR_READY
| AR_DEGRADED
| AR_REBUILDING
:
597 printf("REBUILDING %d%% completed\n",