2 * Copyright (c) 2000,2001,2002 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.
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.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sbin/atacontrol/atacontrol.c,v 1.11.2.5 2002/08/21 13:18:17 sos Exp $
29 * $DragonFly: src/sbin/atacontrol/atacontrol.c,v 1.4 2005/01/09 04:43:33 cpressey Exp $
40 static const char *mode2str(int);
41 static int str2mode(char *);
42 static void usage(void);
43 static int version(int);
44 static void param_print(struct ata_params
*);
45 static void cap_print(struct ata_params
*);
46 static int ata_cap_print(int, int, int);
47 static int info_print(int, int, int);
53 case ATA_PIO
: return "BIOSPIO";
54 case ATA_PIO0
: return "PIO0";
55 case ATA_PIO1
: return "PIO1";
56 case ATA_PIO2
: return "PIO2";
57 case ATA_PIO3
: return "PIO3";
58 case ATA_PIO4
: return "PIO4";
59 case ATA_WDMA2
: return "WDMA2";
60 case ATA_UDMA2
: return "UDMA33";
61 case ATA_UDMA4
: return "UDMA66";
62 case ATA_UDMA5
: return "UDMA100";
63 case ATA_UDMA6
: return "UDMA133";
64 case ATA_DMA
: return "BIOSDMA";
65 default: return "???";
72 if (!strcasecmp(str
, "BIOSPIO")) return ATA_PIO
;
73 if (!strcasecmp(str
, "PIO0")) return ATA_PIO0
;
74 if (!strcasecmp(str
, "PIO1")) return ATA_PIO1
;
75 if (!strcasecmp(str
, "PIO2")) return ATA_PIO2
;
76 if (!strcasecmp(str
, "PIO3")) return ATA_PIO3
;
77 if (!strcasecmp(str
, "PIO4")) return ATA_PIO4
;
78 if (!strcasecmp(str
, "WDMA2")) return ATA_WDMA2
;
79 if (!strcasecmp(str
, "UDMA2")) return ATA_UDMA2
;
80 if (!strcasecmp(str
, "UDMA33")) return ATA_UDMA2
;
81 if (!strcasecmp(str
, "UDMA4")) return ATA_UDMA4
;
82 if (!strcasecmp(str
, "UDMA66")) return ATA_UDMA4
;
83 if (!strcasecmp(str
, "UDMA5")) return ATA_UDMA5
;
84 if (!strcasecmp(str
, "UDMA100")) return ATA_UDMA5
;
85 if (!strcasecmp(str
, "UDMA6")) return ATA_UDMA6
;
86 if (!strcasecmp(str
, "UDMA133")) return ATA_UDMA6
;
87 if (!strcasecmp(str
, "BIOSDMA")) return ATA_DMA
;
95 fprintf(stderr
, "usage: atacontrol <command> channel [args]\n");
106 for (bit
= 15; bit
>= 0; bit
--)
107 if (ver
& (1 << bit
))
113 param_print(struct ata_params
*parm
)
115 printf("<%.40s/%.8s> ATA/ATAPI rev %d\n",
116 parm
->model
, parm
->revision
, version(parm
->version_major
));
120 cap_print(struct ata_params
*parm
)
123 printf("ATA/ATAPI revision %d\n", version(parm
->version_major
));
124 printf("device model %.40s\n", parm
->model
);
125 printf("serial number %.20s\n", parm
->serial
);
126 printf("firmware revision %.8s\n", parm
->revision
);
128 printf("cylinders %d\n", parm
->cylinders
);
129 printf("heads %d\n", parm
->heads
);
130 printf("sectors/track %d\n", parm
->sectors
);
132 printf("lba%ssupported ", parm
->support_lba
? " " : " not ");
134 printf("%d sectors\n", parm
->lba_size
);
138 printf("lba48%ssupported ", parm
->support
.address48
? " " : " not ");
139 if (parm
->lba_size48
)
140 printf("%ju sectors\n", (uintmax_t)parm
->lba_size48
);
143 printf("dma%ssupported\n", parm
->support_dma
? " " : " not");
145 printf("overlap%ssupported\n", parm
->support_queueing
? " " : " not ");
147 printf("\nFeature Support Enable Value Vendor\n");
149 printf("write cache %s %s\n",
150 parm
->support
.write_cache
? "yes" : "no",
151 parm
->enabled
.write_cache
? "yes" : "no");
153 printf("read ahead %s %s\n",
154 parm
->support
.look_ahead
? "yes" : "no",
155 parm
->enabled
.look_ahead
? "yes" : "no");
157 printf("dma queued %s %s %d/%02X\n",
158 parm
->support
.queued
? "yes" : "no",
159 parm
->enabled
.queued
? "yes" : "no",
160 parm
->queuelen
, parm
->queuelen
);
162 printf("SMART %s %s\n",
163 parm
->support
.smart
? "yes" : "no",
164 parm
->enabled
.smart
? "yes" : "no");
166 printf("microcode download %s %s\n",
167 parm
->support
.microcode
? "yes" : "no",
168 parm
->enabled
.microcode
? "yes" : "no");
170 printf("security %s %s\n",
171 parm
->support
.smart
? "yes" : "no",
172 parm
->enabled
.smart
? "yes" : "no");
174 printf("power management %s %s\n",
175 parm
->support
.power_mngt
? "yes" : "no",
176 parm
->enabled
.power_mngt
? "yes" : "no");
178 printf("advanced power management %s %s %d/%02X\n",
179 parm
->support
.apm
? "yes" : "no",
180 parm
->enabled
.apm
? "yes" : "no",
181 parm
->apm_value
, parm
->apm_value
);
183 printf("automatic acoustic management %s %s %d/%02X %d/%02X\n",
184 parm
->support
.auto_acoustic
? "yes" : "no",
185 parm
->enabled
.auto_acoustic
? "yes" : "no",
186 parm
->current_acoustic
, parm
->current_acoustic
,
187 parm
->vendor_acoustic
, parm
->vendor_acoustic
);
191 ata_cap_print(int fd
, int channel
, int device
)
193 struct ata_cmd iocmd
;
195 bzero(&iocmd
, sizeof(struct ata_cmd
));
197 iocmd
.channel
= channel
;
199 iocmd
.cmd
= ATAGPARM
;
201 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
204 printf("ATA channel %d, %s", channel
, device
==0 ? "Master" : "Slave");
206 if (iocmd
.u
.param
.type
[device
]) {
207 printf(", device %s:\n", iocmd
.u
.param
.name
[device
]);
208 cap_print(&iocmd
.u
.param
.params
[device
]);
211 printf(": no device present\n");
216 info_print(int fd
, int channel
, int prchan
)
218 struct ata_cmd iocmd
;
220 bzero(&iocmd
, sizeof(struct ata_cmd
));
221 iocmd
.channel
= channel
;
223 iocmd
.cmd
= ATAGPARM
;
224 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
227 printf("ATA channel %d:\n", channel
);
228 printf("%sMaster: ", prchan
? " " : "");
229 if (iocmd
.u
.param
.type
[0]) {
230 printf("%4.4s ", iocmd
.u
.param
.name
[0]);
231 param_print(&iocmd
.u
.param
.params
[0]);
234 printf(" no device present\n");
235 printf("%sSlave: ", prchan
? " " : "");
236 if (iocmd
.u
.param
.type
[1]) {
237 printf("%4.4s ", iocmd
.u
.param
.name
[1]);
238 param_print(&iocmd
.u
.param
.params
[1]);
241 printf(" no device present\n");
246 main(int argc
, char **argv
)
248 struct ata_cmd iocmd
;
251 if ((fd
= open("/dev/ata", O_RDWR
)) < 0)
252 err(1, "control device not found");
257 bzero(&iocmd
, sizeof(struct ata_cmd
));
259 if (argc
> 2 && strcmp(argv
[1], "create")) {
262 if (!strcmp(argv
[1], "delete") ||
263 !strcmp(argv
[1], "status") ||
264 !strcmp(argv
[1], "rebuild")) {
265 if (!(sscanf(argv
[2], "%d", &chan
) == 1 ||
266 sscanf(argv
[2], "ar%d", &chan
) == 1))
270 if (!(sscanf(argv
[2], "%d", &chan
) == 1 ||
271 sscanf(argv
[2], "ata%d", &chan
) == 1))
274 iocmd
.channel
= chan
;
277 if (!strcmp(argv
[1], "list") && argc
== 2) {
280 while (info_print(fd
, unit
++, 1) != ENXIO
);
282 else if (!strcmp(argv
[1], "info") && argc
== 3) {
283 info_print(fd
, iocmd
.channel
, 0);
285 else if (!strcmp(argv
[1], "cap") && argc
== 4) {
286 ata_cap_print(fd
, iocmd
.channel
, atoi(argv
[3]));
288 else if (!strcmp(argv
[1], "enclosure") && argc
== 4) {
289 iocmd
.device
= atoi(argv
[3]);
290 iocmd
.cmd
= ATAENCSTAT
;
291 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
292 err(1, "ioctl(ATAENCSTAT)");
293 printf("fan RPM: %d temp: %.1f 5V: %.2f 12V: %.2f\n",
294 iocmd
.u
.enclosure
.fan
,
295 (double)iocmd
.u
.enclosure
.temp
/ 10,
296 (double)iocmd
.u
.enclosure
.v05
/ 1000,
297 (double)iocmd
.u
.enclosure
.v12
/ 1000);
299 else if (!strcmp(argv
[1], "detach") && argc
== 3) {
300 iocmd
.cmd
= ATADETACH
;
301 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
302 err(1, "ioctl(ATADETACH)");
304 else if (!strcmp(argv
[1], "attach") && argc
== 3) {
305 iocmd
.cmd
= ATAATTACH
;
306 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
307 err(1, "ioctl(ATAATTACH)");
308 info_print(fd
, iocmd
.channel
, 0);
310 else if (!strcmp(argv
[1], "reinit") && argc
== 3) {
311 iocmd
.cmd
= ATAREINIT
;
312 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
313 warn("ioctl(ATAREINIT)");
314 info_print(fd
, iocmd
.channel
, 0);
316 else if (!strcmp(argv
[1], "create")) {
317 int disk
, dev
, offset
;
319 iocmd
.cmd
= ATARAIDCREATE
;
320 if (!strcmp(argv
[2], "RAID0") || !strcmp(argv
[2], "stripe"))
321 iocmd
.u
.raid_setup
.type
= 1;
322 if (!strcmp(argv
[2], "RAID1") || !strcmp(argv
[2],"mirror"))
323 iocmd
.u
.raid_setup
.type
= 2;
324 if (!strcmp(argv
[2], "RAID0+1"))
325 iocmd
.u
.raid_setup
.type
= 3;
326 if (!strcmp(argv
[2], "SPAN") || !strcmp(argv
[2], "JBOD"))
327 iocmd
.u
.raid_setup
.type
= 4;
328 if (!iocmd
.u
.raid_setup
.type
)
331 if (iocmd
.u
.raid_setup
.type
& 1) {
332 if (!sscanf(argv
[3], "%d",
333 &iocmd
.u
.raid_setup
.interleave
) == 1)
340 for (disk
= 0; disk
< 16 && (offset
+ disk
) < argc
; disk
++) {
341 if (!(sscanf(argv
[offset
+ disk
], "%d", &dev
) == 1 ||
342 sscanf(argv
[offset
+ disk
], "ad%d", &dev
) == 1))
344 iocmd
.u
.raid_setup
.disks
[disk
] = dev
;
346 iocmd
.u
.raid_setup
.total_disks
= disk
;
347 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
348 err(1, "ioctl(ATARAIDCREATE)");
350 printf("ar%d created\n", iocmd
.u
.raid_setup
.unit
);
352 else if (!strcmp(argv
[1], "delete") && argc
== 3) {
353 iocmd
.cmd
= ATARAIDDELETE
;
354 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
355 warn("ioctl(ATARAIDDELETE)");
357 else if (!strcmp(argv
[1], "rebuild") && argc
== 3) {
358 iocmd
.cmd
= ATARAIDREBUILD
;
359 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
360 warn("ioctl(ATARAIDREBUILD)");
362 else if (!strcmp(argv
[1], "status") && argc
== 3) {
365 iocmd
.cmd
= ATARAIDSTATUS
;
366 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
367 err(1, "ioctl(ATARAIDSTATUS)");
368 printf("ar%d: ATA ", iocmd
.channel
);
369 switch (iocmd
.u
.raid_status
.type
) {
376 case AR_RAID0
| AR_RAID1
:
383 printf(" subdisks: ");
384 for (i
= 0; i
< iocmd
.u
.raid_status
.total_disks
; i
++) {
385 if (iocmd
.u
.raid_status
.disks
[i
] >= 0)
386 printf("ad%d ", iocmd
.u
.raid_status
.disks
[i
]);
391 switch (iocmd
.u
.raid_status
.status
) {
395 case AR_READY
| AR_DEGRADED
:
396 printf("DEGRADED\n");
398 case AR_READY
| AR_DEGRADED
| AR_REBUILDING
:
399 printf("REBUILDING %d%% completed\n",
400 iocmd
.u
.raid_status
.progress
);
406 else if (!strcmp(argv
[1], "mode") && (argc
== 3 || argc
== 5)) {
408 iocmd
.cmd
= ATASMODE
;
410 iocmd
.u
.mode
.mode
[0] = str2mode(argv
[3]);
411 iocmd
.u
.mode
.mode
[1] = str2mode(argv
[4]);
412 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
413 warn("ioctl(ATASMODE)");
415 if (argc
== 3 || argc
== 5) {
416 iocmd
.cmd
= ATAGMODE
;
418 if (ioctl(fd
, IOCATA
, &iocmd
) < 0)
419 err(1, "ioctl(ATAGMODE)");
420 printf("Master = %s \nSlave = %s\n",
421 mode2str(iocmd
.u
.mode
.mode
[0]),
422 mode2str(iocmd
.u
.mode
.mode
[1]));