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