1 /* $NetBSD: scsictl.c,v 1.39 2016/11/19 08:43:40 flxd Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * scsictl(8) - a program to manipulate SCSI devices and busses. 35 */ 36 #include <sys/cdefs.h> 37 38 #ifndef lint 39 __RCSID("$NetBSD: scsictl.c,v 1.39 2016/11/19 08:43:40 flxd Exp $"); 40 #endif 41 42 43 #include <sys/param.h> 44 #include <sys/ioctl.h> 45 #include <sys/scsiio.h> 46 #include <err.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <limits.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #include <util.h> 55 56 #include <dev/scsipi/scsi_spc.h> 57 #include <dev/scsipi/scsipi_all.h> 58 #include <dev/scsipi/scsi_disk.h> 59 #include <dev/scsipi/scsipiconf.h> 60 61 #include "extern.h" 62 63 struct command { 64 const char *cmd_name; 65 const char *arg_names; 66 void (*cmd_func)(int, char *[]); 67 }; 68 69 __dead static void usage(void); 70 71 static int fd; /* file descriptor for device */ 72 const char *dvname; /* device name */ 73 static char dvname_store[MAXPATHLEN]; /* for opendisk(3) */ 74 static const char *cmdname; /* command user issued */ 75 static struct scsi_addr dvaddr; /* SCSI device's address */ 76 77 static void device_defects(int, char *[]); 78 static void device_format(int, char *[]); 79 static void device_identify(int, char *[]); 80 static void device_reassign(int, char *[]); 81 static void device_release(int, char *[]); 82 static void device_reserve(int, char *[]); 83 static void device_reset(int, char *[]); 84 static void device_debug(int, char *[]); 85 static void device_prevent(int, char *[]); 86 static void device_allow(int, char *[]); 87 static void device_start(int, char *[]); 88 static void device_stop(int, char *[]); 89 static void device_tur(int, char *[]); 90 static void device_getcache(int, char *[]); 91 static void device_setcache(int, char *[]); 92 static void device_flushcache(int, char *[]); 93 static void device_setspeed(int, char *[]); 94 static void device_getrealloc(int, char *[]); 95 static void device_setrealloc(int, char *[]); 96 97 static struct command device_commands[] = { 98 { "defects", "[primary] [grown] [block|byte|physical]", 99 device_defects }, 100 { "format", "[blocksize [immediate]]", device_format }, 101 { "identify", "", device_identify }, 102 { "reassign", "blkno [blkno [...]]", device_reassign }, 103 { "release", "", device_release }, 104 { "reserve", "", device_reserve }, 105 { "reset", "", device_reset }, 106 { "debug", "level", device_debug }, 107 { "prevent", "", device_prevent }, 108 { "allow", "", device_allow }, 109 { "start", "", device_start }, 110 { "stop", "", device_stop }, 111 { "tur", "", device_tur }, 112 { "getcache", "", device_getcache }, 113 { "setcache", "none|r|w|rw [save]", device_setcache }, 114 { "flushcache", "", device_flushcache }, 115 { "setspeed", "[speed]", device_setspeed }, 116 { "getrealloc", "", device_getrealloc }, 117 { "setrealloc", "none|r|w|rw [save]", device_setrealloc }, 118 { NULL, NULL, NULL }, 119 }; 120 121 static void bus_reset(int, char *[]); 122 static void bus_scan(int, char *[]); 123 static void bus_detach(int, char *[]); 124 125 static struct command bus_commands[] = { 126 { "reset", "", bus_reset }, 127 { "scan", "target lun", bus_scan }, 128 { "detach", "target lun", bus_detach }, 129 { NULL, NULL, NULL }, 130 }; 131 132 int 133 main(int argc, char *argv[]) 134 { 135 struct command *commands; 136 int i; 137 138 /* Must have at least: device command */ 139 if (argc < 3) 140 usage(); 141 142 /* Skip program name, get and skip device name and command. */ 143 dvname = argv[1]; 144 cmdname = argv[2]; 145 argv += 3; 146 argc -= 3; 147 148 /* 149 * Open the device and determine if it's a scsibus or an actual 150 * device. Devices respond to the SCIOCIDENTIFY ioctl. 151 */ 152 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0); 153 if (fd == -1) { 154 if (errno == ENOENT) { 155 /* 156 * Device doesn't exist. Probably trying to open 157 * a device which doesn't use disk semantics for 158 * device name. Try again, specifying "cooked", 159 * which leaves off the "r" in front of the device's 160 * name. 161 */ 162 fd = opendisk(dvname, O_RDWR, dvname_store, 163 sizeof(dvname_store), 1); 164 if (fd == -1) 165 err(1, "%s", dvname); 166 } else 167 err(1, "%s", dvname); 168 } 169 170 /* 171 * Point the dvname at the actual device name that opendisk() opened. 172 */ 173 dvname = dvname_store; 174 175 if (ioctl(fd, SCIOCIDENTIFY, &dvaddr) < 0) 176 commands = bus_commands; 177 else 178 commands = device_commands; 179 180 /* Look up and call the command. */ 181 for (i = 0; commands[i].cmd_name != NULL; i++) 182 if (strcmp(cmdname, commands[i].cmd_name) == 0) 183 break; 184 if (commands[i].cmd_name == NULL) 185 errx(1, "unknown %s command: %s", 186 commands == bus_commands ? "bus" : "device", cmdname); 187 188 (*commands[i].cmd_func)(argc, argv); 189 exit(0); 190 } 191 192 static void 193 usage(void) 194 { 195 int i; 196 197 fprintf(stderr, "usage: %s device command [arg [...]]\n", 198 getprogname()); 199 200 fprintf(stderr, " Commands pertaining to scsi devices:\n"); 201 for (i=0; device_commands[i].cmd_name != NULL; i++) 202 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name, 203 device_commands[i].arg_names); 204 fprintf(stderr, " Commands pertaining to scsi busses:\n"); 205 for (i=0; bus_commands[i].cmd_name != NULL; i++) 206 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name, 207 bus_commands[i].arg_names); 208 fprintf(stderr, " Use `any' or `all' to wildcard target or lun\n"); 209 210 exit(1); 211 } 212 213 /* 214 * DEVICE COMMANDS 215 */ 216 217 /* 218 * device_read_defect: 219 * 220 * Read primary and/or growth defect list in physical or block 221 * format from a direct access device. 222 * 223 * XXX Does not handle very large defect lists. Needs SCSI3 12 224 * byte READ DEFECT DATA command. 225 */ 226 227 static void print_bf_dd(union scsi_defect_descriptor *); 228 static void print_bfif_dd(union scsi_defect_descriptor *); 229 static void print_psf_dd(union scsi_defect_descriptor *); 230 231 static void 232 device_defects(int argc, char *argv[]) 233 { 234 struct scsi_read_defect_data cmd; 235 struct scsi_read_defect_data_data *data; 236 size_t dlen; 237 int i, dlfmt = -1; 238 int defects; 239 char msg[256]; 240 void (*pfunc)(union scsi_defect_descriptor *); 241 #define RDD_P_G_MASK 0x18 242 #define RDD_DLF_MASK 0x7 243 244 dlen = USHRT_MAX; /* XXX - this may not be enough room 245 * for all of the defects. 246 */ 247 data = malloc(dlen); 248 if (data == NULL) 249 errx(1, "unable to allocate defect list"); 250 memset(data, 0, dlen); 251 memset(&cmd, 0, sizeof(cmd)); 252 defects = 0; 253 pfunc = NULL; 254 255 /* determine which defect list(s) to read. */ 256 for (i = 0; i < argc; i++) { 257 if (strncmp("primary", argv[i], 7) == 0) { 258 cmd.flags |= RDD_PRIMARY; 259 continue; 260 } 261 if (strncmp("grown", argv[i], 5) == 0) { 262 cmd.flags |= RDD_GROWN; 263 continue; 264 } 265 break; 266 } 267 268 /* no defect list sepecified, assume both. */ 269 if ((cmd.flags & (RDD_PRIMARY|RDD_GROWN)) == 0) 270 cmd.flags |= (RDD_PRIMARY|RDD_GROWN); 271 272 /* list format option. */ 273 if (i < argc) { 274 if (strncmp("block", argv[i], 5) == 0) { 275 cmd.flags |= RDD_BF; 276 dlfmt = RDD_BF; 277 } 278 else if (strncmp("byte", argv[i], 4) == 0) { 279 cmd.flags |= RDD_BFIF; 280 dlfmt = RDD_BFIF; 281 } 282 else if (strncmp("physical", argv[i], 4) == 0) { 283 cmd.flags |= RDD_PSF; 284 dlfmt = RDD_PSF; 285 } 286 else { 287 usage(); 288 } 289 } 290 291 /* 292 * no list format specified; since block format not 293 * recommended use physical sector format as default. 294 */ 295 if (dlfmt < 0) { 296 cmd.flags |= RDD_PSF; 297 dlfmt = RDD_PSF; 298 } 299 300 cmd.opcode = SCSI_READ_DEFECT_DATA; 301 _lto2b(dlen, &cmd.length[0]); 302 303 scsi_command(fd, &cmd, sizeof(cmd), data, dlen, 30000, SCCMD_READ); 304 305 msg[0] = '\0'; 306 307 /* is the defect list in the format asked for? */ 308 if ((data->flags & RDD_DLF_MASK) != dlfmt) { 309 strcpy(msg, "\n\tnotice:" 310 "requested defect list format not supported by device\n\n"); 311 dlfmt = (data->flags & RDD_DLF_MASK); 312 } 313 314 if (data->flags & RDD_PRIMARY) 315 strcat(msg, "primary"); 316 317 if (data->flags & RDD_GROWN) { 318 if (data->flags & RDD_PRIMARY) 319 strcat(msg, " and "); 320 strcat(msg, "grown"); 321 } 322 323 strcat(msg, " defects"); 324 325 if ((data->flags & RDD_P_G_MASK) == 0) 326 strcat(msg, ": none reported\n"); 327 328 329 printf("%s: scsibus%d target %d lun %d %s", 330 dvname, dvaddr.addr.scsi.scbus, dvaddr.addr.scsi.target, 331 dvaddr.addr.scsi.lun, msg); 332 333 /* device did not return either defect list. */ 334 if ((data->flags & RDD_P_G_MASK) == 0) 335 return; 336 337 switch (dlfmt) { 338 case RDD_BF: 339 defects = _2btol(data->length) / 340 sizeof(struct scsi_defect_descriptor_bf); 341 pfunc = print_bf_dd; 342 strcpy(msg, "block address\n" 343 "-------------\n"); 344 break; 345 case RDD_BFIF: 346 defects = _2btol(data->length) / 347 sizeof(struct scsi_defect_descriptor_bfif); 348 pfunc = print_bfif_dd; 349 strcpy(msg, " bytes from\n" 350 "cylinder head index\n" 351 "-------- ---- ----------\n"); 352 break; 353 case RDD_PSF: 354 defects = _2btol(data->length) / 355 sizeof(struct scsi_defect_descriptor_psf); 356 pfunc = print_psf_dd; 357 strcpy(msg, "cylinder head sector\n" 358 "-------- ---- ----------\n"); 359 break; 360 } 361 362 /* device did not return any defects. */ 363 if (defects == 0) { 364 printf(": none\n"); 365 return; 366 } 367 368 printf(": %d\n", defects); 369 370 /* print heading. */ 371 printf("%s", msg); 372 373 /* print defect list. */ 374 for (i = 0 ; i < defects; i++) { 375 pfunc(&data->defect_descriptor[i]); 376 } 377 378 free(data); 379 return; 380 } 381 382 /* 383 * print_bf_dd: 384 * 385 * Print a block format defect descriptor. 386 */ 387 static void 388 print_bf_dd(union scsi_defect_descriptor *dd) 389 { 390 u_int32_t block; 391 392 block = _4btol(dd->bf.block_address); 393 394 printf("%13u\n", block); 395 } 396 397 #define DEFECTIVE_TRACK 0xffffffff 398 399 /* 400 * print_bfif_dd: 401 * 402 * Print a bytes from index format defect descriptor. 403 */ 404 static void 405 print_bfif_dd(union scsi_defect_descriptor *dd) 406 { 407 u_int32_t cylinder; 408 u_int32_t head; 409 u_int32_t bytes_from_index; 410 411 cylinder = _3btol(dd->bfif.cylinder); 412 head = dd->bfif.head; 413 bytes_from_index = _4btol(dd->bfif.bytes_from_index); 414 415 printf("%8u %4u ", cylinder, head); 416 417 if (bytes_from_index == DEFECTIVE_TRACK) 418 printf("entire track defective\n"); 419 else 420 printf("%10u\n", bytes_from_index); 421 } 422 423 /* 424 * print_psf_dd: 425 * 426 * Print a physical sector format defect descriptor. 427 */ 428 static void 429 print_psf_dd(union scsi_defect_descriptor *dd) 430 { 431 u_int32_t cylinder; 432 u_int32_t head; 433 u_int32_t sector; 434 435 cylinder = _3btol(dd->psf.cylinder); 436 head = dd->psf.head; 437 sector = _4btol(dd->psf.sector); 438 439 printf("%8u %4u ", cylinder, head); 440 441 if (sector == DEFECTIVE_TRACK) 442 printf("entire track defective\n"); 443 else 444 printf("%10u\n", sector); 445 } 446 447 /* 448 * device_format: 449 * 450 * Format a direct access device. 451 */ 452 static void 453 device_format(int argc, char *argv[]) 454 { 455 u_int32_t blksize; 456 int i, j, immediate; 457 #define PC (65536/10) 458 static int complete[] = { 459 PC*1, PC*2, PC*3, PC*4, PC*5, PC*6, PC*7, PC*8, PC*9, 65536 460 }; 461 char *cp, buffer[64]; 462 struct scsi_sense_data sense; 463 struct scsi_format_unit cmd; 464 struct { 465 struct scsi_format_unit_defect_list_header header; 466 /* optional initialization pattern */ 467 /* optional defect list */ 468 } dfl; 469 struct { 470 struct scsi_mode_parameter_header_6 header; 471 struct scsi_general_block_descriptor blk_desc; 472 struct page_disk_format format_page; 473 } mode_page; 474 struct { 475 struct scsi_mode_parameter_header_6 header; 476 struct scsi_general_block_descriptor blk_desc; 477 } data_select; 478 479 480 /* Blocksize is an optional argument. */ 481 if (argc > 2) 482 usage(); 483 484 /* 485 * Loop doing Request Sense to clear any pending Unit Attention. 486 * 487 * Multiple conditions may exist on the drive which are returned 488 * in priority order. 489 */ 490 for (i = 0; i < 8; i++) { 491 scsi_request_sense(fd, &sense, sizeof (sense)); 492 if ((j = SSD_SENSE_KEY(sense.flags)) == SKEY_NO_SENSE) 493 break; 494 } 495 /* 496 * Make sure we cleared any pending Unit Attention 497 */ 498 if (j != SKEY_NO_SENSE) { 499 cp = scsi_decode_sense((const unsigned char *) &sense, 2, 500 buffer, sizeof (buffer)); 501 errx(1, "failed to clean Unit Attention: %s", cp); 502 } 503 504 /* 505 * Get the DISK FORMAT mode page. SCSI-2 recommends specifying the 506 * interleave read from this page in the FORMAT UNIT command. 507 */ 508 scsi_mode_sense(fd, 0x03, 0x00, &mode_page, sizeof(mode_page)); 509 510 j = (mode_page.format_page.bytes_s[0] << 8) | 511 (mode_page.format_page.bytes_s[1]); 512 513 if (j != DEV_BSIZE) 514 printf("current disk sector size: %d\n", j); 515 516 memset(&cmd, 0, sizeof(cmd)); 517 518 cmd.opcode = SCSI_FORMAT_UNIT; 519 memcpy(cmd.interleave, mode_page.format_page.interleave, 520 sizeof(cmd.interleave)); 521 522 /* 523 * The blocksize on the device is only changed if the user 524 * specified a new blocksize. If not specified the blocksize 525 * used for the device will be the Default value in the device. 526 * We don't specify the number of blocks since the format 527 * command will always reformat the entire drive. Also by 528 * not specifying a block count the drive will reset the 529 * block count to the maximum available after the format 530 * completes if the blocksize was changed in the format. 531 * Finally, the new disk geometry will not but updated on 532 * the drive in permanent storage until _AFTER_ the format 533 * completes successfully. 534 */ 535 if (argc > 0) { 536 blksize = strtoul(argv[0], &cp, 10); 537 if (*cp != '\0') 538 errx(1, "invalid block size: %s", argv[0]); 539 540 memset(&data_select, 0, sizeof(data_select)); 541 542 data_select.header.blk_desc_len = 543 sizeof(struct scsi_general_block_descriptor); 544 /* 545 * blklen in desc is 3 bytes with a leading reserved byte 546 */ 547 _lto4b(blksize, &data_select.blk_desc.reserved); 548 549 /* 550 * Issue Mode Select to modify the device blocksize to be 551 * used on the Format. The modified device geometry will 552 * be stored as Current and Saved Page 3 parameters when 553 * the Format completes. 554 */ 555 scsi_mode_select(fd, 0, &data_select, sizeof(data_select)); 556 557 /* 558 * Since user specified a specific block size make sure it 559 * gets stored in the device when the format completes. 560 * 561 * Also scrub the defect list back to the manufacturers 562 * original. 563 */ 564 cmd.flags = SFU_CMPLST | SFU_FMTDATA; 565 } 566 567 memset(&dfl, 0, sizeof(dfl)); 568 569 if (argc > 1 && strncmp(argv[1], "imm", 3) == 0) { 570 /* 571 * Signal target for an immediate return from Format. 572 * 573 * We'll poll for completion status. 574 */ 575 dfl.header.flags = DLH_IMMED; 576 immediate = 1; 577 } else { 578 immediate = 0; 579 } 580 581 scsi_command(fd, &cmd, sizeof(cmd), &dfl, sizeof(dfl), 582 8 * 60 * 60 * 1000, SCCMD_WRITE); 583 584 /* 585 * Poll device for completion of Format 586 */ 587 if (immediate) { 588 i = 0; 589 printf("formatting."); 590 fflush(stdout); 591 do { 592 scsireq_t req; 593 struct scsi_test_unit_ready tcmd; 594 595 memset(&tcmd, 0, sizeof(tcmd)); 596 tcmd.opcode = SCSI_TEST_UNIT_READY; 597 598 memset(&req, 0, sizeof(req)); 599 memcpy(req.cmd, &tcmd, 6); 600 req.cmdlen = 6; 601 req.timeout = 10000; 602 req.senselen = SENSEBUFLEN; 603 604 if (ioctl(fd, SCIOCCOMMAND, &req) == -1) { 605 err(1, "SCIOCCOMMAND"); 606 } 607 608 if (req.retsts == SCCMD_OK) { 609 break; 610 } else if (req.retsts == SCCMD_TIMEOUT) { 611 fprintf(stderr, "%s: SCSI command timed out", 612 dvname); 613 break; 614 } else if (req.retsts == SCCMD_BUSY) { 615 fprintf(stderr, "%s: device is busy", 616 dvname); 617 break; 618 } else if (req.retsts != SCCMD_SENSE) { 619 fprintf(stderr, 620 "%s: device had unknown status %x", dvname, 621 req.retsts); 622 break; 623 } 624 memcpy(&sense, req.sense, sizeof(sense)); 625 if (sense.sks.sks_bytes[0] & SSD_SKSV) { 626 j = (sense.sks.sks_bytes[1] << 8) | 627 (sense.sks.sks_bytes[2]); 628 if (j >= complete[i]) { 629 printf(".%d0%%.", ++i); 630 fflush(stdout); 631 } 632 } 633 sleep(10); 634 } while (SSD_SENSE_KEY(sense.flags) == SKEY_NOT_READY); 635 printf(".100%%..done.\n"); 636 } 637 return; 638 } 639 640 /* 641 * device_identify: 642 * 643 * Display the identity of the device, including its SCSI bus, 644 * target, lun, and its vendor/product/revision information. 645 */ 646 static void 647 device_identify(int argc, char *argv[]) 648 { 649 struct scsipi_inquiry_data inqbuf; 650 struct scsipi_inquiry cmd; 651 652 /* x4 in case every character is escaped, +1 for NUL. */ 653 char vendor[(sizeof(inqbuf.vendor) * 4) + 1], 654 product[(sizeof(inqbuf.product) * 4) + 1], 655 revision[(sizeof(inqbuf.revision) * 4) + 1]; 656 657 /* No arguments. */ 658 if (argc != 0) 659 usage(); 660 661 memset(&cmd, 0, sizeof(cmd)); 662 memset(&inqbuf, 0, sizeof(inqbuf)); 663 664 cmd.opcode = INQUIRY; 665 cmd.length = sizeof(inqbuf); 666 667 scsi_command(fd, &cmd, sizeof(cmd), &inqbuf, sizeof(inqbuf), 668 10000, SCCMD_READ); 669 670 scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor, 671 sizeof(inqbuf.vendor)); 672 scsi_strvis(product, sizeof(product), inqbuf.product, 673 sizeof(inqbuf.product)); 674 scsi_strvis(revision, sizeof(revision), inqbuf.revision, 675 sizeof(inqbuf.revision)); 676 677 printf("%s: scsibus%d target %d lun %d <%s, %s, %s>\n", 678 dvname, dvaddr.addr.scsi.scbus, dvaddr.addr.scsi.target, 679 dvaddr.addr.scsi.lun, vendor, product, revision); 680 681 return; 682 } 683 684 /* 685 * device_reassign: 686 * 687 * Reassign bad blocks on a direct access device. 688 */ 689 static void 690 device_reassign(int argc, char *argv[]) 691 { 692 struct scsi_reassign_blocks cmd; 693 struct scsi_reassign_blocks_data *data; 694 size_t dlen; 695 u_int32_t blkno; 696 int i; 697 char *cp; 698 699 /* We get a list of block numbers. */ 700 if (argc < 1) 701 usage(); 702 703 /* 704 * Allocate the reassign blocks descriptor. The 4 comes from the 705 * size of the block address in the defect descriptor. 706 */ 707 dlen = sizeof(struct scsi_reassign_blocks_data) + ((argc - 1) * 4); 708 data = malloc(dlen); 709 if (data == NULL) 710 errx(1, "unable to allocate defect descriptor"); 711 memset(data, 0, dlen); 712 713 cmd.opcode = SCSI_REASSIGN_BLOCKS; 714 cmd.byte2 = 0; 715 cmd.unused[0] = 0; 716 cmd.unused[1] = 0; 717 cmd.unused[2] = 0; 718 cmd.control = 0; 719 720 /* Defect descriptor length. */ 721 _lto2b(argc * 4, data->length); 722 723 /* Build the defect descriptor list. */ 724 for (i = 0; i < argc; i++) { 725 blkno = strtoul(argv[i], &cp, 10); 726 if (*cp != '\0') 727 errx(1, "invalid block number: %s", argv[i]); 728 _lto4b(blkno, data->defect_descriptor[i].dlbaddr); 729 } 730 731 scsi_command(fd, &cmd, sizeof(cmd), data, dlen, 30000, SCCMD_WRITE); 732 733 free(data); 734 return; 735 } 736 737 /* 738 * device_release: 739 * 740 * Issue a RELEASE command to a SCSI device. 741 */ 742 #ifndef SCSI_RELEASE 743 #define SCSI_RELEASE 0x17 744 #endif 745 static void 746 device_release(int argc, char *argv[]) 747 { 748 struct scsi_test_unit_ready cmd; /* close enough */ 749 750 /* No arguments. */ 751 if (argc != 0) 752 usage(); 753 754 memset(&cmd, 0, sizeof(cmd)); 755 756 cmd.opcode = SCSI_RELEASE; 757 758 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 759 760 return; 761 } 762 763 764 765 /* 766 * device_reserve: 767 * 768 * Issue a RESERVE command to a SCSI device. 769 */ 770 #ifndef SCSI_RESERVE 771 #define SCSI_RESERVE 0x16 772 #endif 773 static void 774 device_reserve(int argc, char *argv[]) 775 { 776 struct scsi_test_unit_ready cmd; /* close enough */ 777 778 /* No arguments. */ 779 if (argc != 0) 780 usage(); 781 782 memset(&cmd, 0, sizeof(cmd)); 783 784 cmd.opcode = SCSI_RESERVE; 785 786 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 787 788 return; 789 } 790 791 /* 792 * device_reset: 793 * 794 * Issue a reset to a SCSI device. 795 */ 796 static void 797 device_reset(int argc, char *argv[]) 798 { 799 800 /* No arguments. */ 801 if (argc != 0) 802 usage(); 803 804 if (ioctl(fd, SCIOCRESET, NULL) != 0) 805 err(1, "SCIOCRESET"); 806 807 return; 808 } 809 810 /* 811 * device_debug: 812 * 813 * Set debug level to a SCSI device. 814 * scsipi will print anything iff SCSIPI_DEBUG set in config. 815 */ 816 static void 817 device_debug(int argc, char *argv[]) 818 { 819 int lvl; 820 821 if (argc < 1) 822 usage(); 823 824 lvl = atoi(argv[0]); 825 826 if (ioctl(fd, SCIOCDEBUG, &lvl) != 0) 827 err(1, "SCIOCDEBUG"); 828 829 return; 830 } 831 832 /* 833 * device_getcache: 834 * 835 * Get the caching parameters for a SCSI disk. 836 */ 837 static void 838 device_getcache(int argc, char *argv[]) 839 { 840 struct { 841 struct scsi_mode_parameter_header_6 header; 842 struct scsi_general_block_descriptor blk_desc; 843 struct page_caching caching_params; 844 } data; 845 846 /* No arguments. */ 847 if (argc != 0) 848 usage(); 849 850 scsi_mode_sense(fd, 0x08, 0x00, &data, sizeof(data)); 851 852 if ((data.caching_params.flags & (CACHING_RCD|CACHING_WCE)) == 853 CACHING_RCD) 854 printf("%s: no caches enabled\n", dvname); 855 else { 856 printf("%s: read cache %senabled\n", dvname, 857 (data.caching_params.flags & CACHING_RCD) ? "not " : ""); 858 printf("%s: write-back cache %senabled\n", dvname, 859 (data.caching_params.flags & CACHING_WCE) ? "" : "not "); 860 } 861 printf("%s: caching parameters are %ssavable\n", dvname, 862 (data.caching_params.pg_code & PGCODE_PS) ? "" : "not "); 863 } 864 865 /* 866 * device_setcache: 867 * 868 * Set cache enables for a SCSI disk. 869 */ 870 static void 871 device_setcache(int argc, char *argv[]) 872 { 873 struct { 874 struct scsi_mode_parameter_header_6 header; 875 struct scsi_general_block_descriptor blk_desc; 876 struct page_caching caching_params; 877 } data; 878 int dlen; 879 u_int8_t flags, byte2; 880 881 if (argc > 2 || argc == 0) 882 usage(); 883 884 flags = 0; 885 byte2 = 0; 886 if (strcmp(argv[0], "none") == 0) 887 flags = CACHING_RCD; 888 else if (strcmp(argv[0], "r") == 0) 889 flags = 0; 890 else if (strcmp(argv[0], "w") == 0) 891 flags = CACHING_RCD|CACHING_WCE; 892 else if (strcmp(argv[0], "rw") == 0) 893 flags = CACHING_WCE; 894 else 895 usage(); 896 897 if (argc == 2) { 898 if (strcmp(argv[1], "save") == 0) 899 byte2 = SMS_SP; 900 else 901 usage(); 902 } 903 904 scsi_mode_sense(fd, 0x08, 0x00, &data, sizeof(data)); 905 906 data.caching_params.pg_code &= PGCODE_MASK; 907 data.caching_params.flags = 908 (data.caching_params.flags & ~(CACHING_RCD|CACHING_WCE)) | flags; 909 910 data.caching_params.cache_segment_size[0] = 0; 911 data.caching_params.cache_segment_size[1] = 0; 912 913 data.header.data_length = 0; 914 915 dlen = sizeof(data.header) + sizeof(data.blk_desc) + 2 + 916 data.caching_params.pg_length; 917 918 scsi_mode_select(fd, byte2, &data, dlen); 919 } 920 921 /* 922 * device_flushcache: 923 * 924 * Issue a FLUSH CACHE command to a SCSI device. 925 */ 926 #ifndef SCSI_FLUSHCACHE 927 #define SCSI_FLUSHCACHE 0x35 928 #endif 929 static void 930 device_flushcache(int argc, char *argv[]) 931 { 932 struct scsi_test_unit_ready cmd; /* close enough */ 933 934 /* No arguments. */ 935 if (argc != 0) 936 usage(); 937 938 memset(&cmd, 0, sizeof(cmd)); 939 940 cmd.opcode = SCSI_FLUSHCACHE; 941 942 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 943 944 return; 945 } 946 947 /* 948 * device_setspeed: 949 * 950 * Set rotation speed to a CD/DVD drive. 951 */ 952 static void 953 device_setspeed(int argc, char *argv[]) 954 { 955 u_char cmd[11]; 956 u_char pd[28]; 957 u_int32_t speed; 958 959 if (argc != 1) 960 usage(); 961 962 speed = atoi(argv[0]) * 177; 963 964 memset(&pd, 0, sizeof(pd)); 965 if (speed == 0) 966 pd[0] = 4; /* restore drive defaults */ 967 pd[8] = 0xff; 968 pd[9] = 0xff; 969 pd[10] = 0xff; 970 pd[11] = 0xff; 971 pd[12] = pd[20] = (speed >> 24) & 0xff; 972 pd[13] = pd[21] = (speed >> 16) & 0xff; 973 pd[14] = pd[22] = (speed >> 8) & 0xff; 974 pd[15] = pd[23] = speed & 0xff; 975 pd[18] = pd[26] = 1000 >> 8; 976 pd[19] = pd[27] = 1000 & 0xff; 977 978 memset(&cmd, 0, sizeof(cmd)); 979 cmd[0] = 0xb6; 980 cmd[10] = sizeof(pd); 981 982 scsi_command(fd, &cmd, sizeof(cmd), pd, sizeof(pd), 10000, SCCMD_WRITE); 983 984 return; 985 } 986 987 /* 988 * device_getrealloc: 989 * 990 * Get the automatic reallocation parameters for a SCSI disk. 991 */ 992 static void 993 device_getrealloc(int argc, char *argv[]) 994 { 995 struct { 996 struct scsi_mode_parameter_header_6 header; 997 struct scsi_general_block_descriptor blk_desc; 998 struct page_err_recov err_recov_params; 999 } data; 1000 u_int8_t flags; 1001 1002 /* No arguments. */ 1003 if (argc != 0) 1004 usage(); 1005 1006 scsi_mode_sense(fd, 0x01, 0x00, &data, sizeof(data)); 1007 1008 flags = data.err_recov_params.flags; 1009 if ((flags & (ERR_RECOV_ARRE | ERR_RECOV_AWRE)) == 0) 1010 printf("%s: no automatic reallocation enabled\n", dvname); 1011 else { 1012 printf("%s: automatic read reallocation %senabled\n", dvname, 1013 (flags & ERR_RECOV_ARRE) ? "" : "not "); 1014 printf("%s: automatic write reallocation %senabled\n", dvname, 1015 (flags & ERR_RECOV_AWRE) ? "" : "not "); 1016 } 1017 printf("%s: error recovery parameters are %ssavable\n", dvname, 1018 (data.err_recov_params.pg_code & PGCODE_PS) ? "" : "not "); 1019 } 1020 1021 /* 1022 * device_setrealloc: 1023 * 1024 * Set the automatic reallocation parameters for a SCSI disk. 1025 */ 1026 static void 1027 device_setrealloc(int argc, char *argv[]) 1028 { 1029 struct { 1030 struct scsi_mode_parameter_header_6 header; 1031 struct scsi_general_block_descriptor blk_desc; 1032 struct page_err_recov err_recov_params; 1033 } data; 1034 int dlen; 1035 u_int8_t flags, byte2; 1036 1037 if (argc > 2 || argc == 0) 1038 usage(); 1039 1040 flags = 0; 1041 byte2 = 0; 1042 if (strcmp(argv[0], "none") == 0) 1043 flags = 0; 1044 else if (strcmp(argv[0], "r") == 0) 1045 flags = ERR_RECOV_ARRE; 1046 else if (strcmp(argv[0], "w") == 0) 1047 flags = ERR_RECOV_AWRE; 1048 else if (strcmp(argv[0], "rw") == 0) 1049 flags = ERR_RECOV_ARRE | ERR_RECOV_AWRE; 1050 else 1051 usage(); 1052 1053 if (argc == 2) { 1054 if (strcmp(argv[1], "save") == 0) 1055 byte2 = SMS_SP; 1056 else 1057 usage(); 1058 } 1059 1060 scsi_mode_sense(fd, 0x01, 0x00, &data, sizeof(data)); 1061 1062 data.err_recov_params.pg_code &= PGCODE_MASK; 1063 data.err_recov_params.flags &= ~(ERR_RECOV_ARRE | ERR_RECOV_AWRE); 1064 data.err_recov_params.flags |= flags; 1065 1066 data.header.data_length = 0; 1067 1068 dlen = sizeof(data.header) + sizeof(data.blk_desc) + 2 + 1069 data.err_recov_params.pg_length; 1070 1071 scsi_mode_select(fd, byte2, &data, dlen); 1072 } 1073 1074 /* 1075 * device_prevent: 1076 * 1077 * Issue a prevent to a SCSI device. 1078 */ 1079 static void 1080 device_prevent(int argc, char *argv[]) 1081 { 1082 struct scsi_prevent_allow_medium_removal cmd; 1083 1084 /* No arguments. */ 1085 if (argc != 0) 1086 usage(); 1087 1088 memset(&cmd, 0, sizeof(cmd)); 1089 1090 cmd.opcode = SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL; 1091 cmd.how = SPAMR_PREVENT_DT; /* XXX SMAMR_PREVENT_ALL? */ 1092 1093 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 1094 1095 return; 1096 } 1097 1098 /* 1099 * device_allow: 1100 * 1101 * Issue a stop to a SCSI device. 1102 */ 1103 static void 1104 device_allow(int argc, char *argv[]) 1105 { 1106 struct scsi_prevent_allow_medium_removal cmd; 1107 1108 /* No arguments. */ 1109 if (argc != 0) 1110 usage(); 1111 1112 memset(&cmd, 0, sizeof(cmd)); 1113 1114 cmd.opcode = SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL; 1115 cmd.how = SPAMR_ALLOW; 1116 1117 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 1118 1119 return; 1120 } 1121 1122 /* 1123 * device_start: 1124 * 1125 * Issue a start to a SCSI device. 1126 */ 1127 static void 1128 device_start(int argc, char *argv[]) 1129 { 1130 struct scsipi_start_stop cmd; 1131 1132 /* No arguments. */ 1133 if (argc != 0) 1134 usage(); 1135 1136 memset(&cmd, 0, sizeof(cmd)); 1137 1138 cmd.opcode = START_STOP; 1139 cmd.how = SSS_START; 1140 1141 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 30000, 0); 1142 1143 return; 1144 } 1145 1146 /* 1147 * device_stop: 1148 * 1149 * Issue a stop to a SCSI device. 1150 */ 1151 static void 1152 device_stop(int argc, char *argv[]) 1153 { 1154 struct scsipi_start_stop cmd; 1155 1156 /* No arguments. */ 1157 if (argc != 0) 1158 usage(); 1159 1160 memset(&cmd, 0, sizeof(cmd)); 1161 1162 cmd.opcode = START_STOP; 1163 cmd.how = SSS_STOP; 1164 1165 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 30000, 0); 1166 1167 return; 1168 } 1169 1170 /* 1171 * device_tur: 1172 * 1173 * Issue a TEST UNIT READY to a SCSI device. 1174 */ 1175 static void 1176 device_tur(int argc, char *argv[]) 1177 { 1178 struct scsi_test_unit_ready cmd; 1179 1180 /* No arguments. */ 1181 if (argc != 0) 1182 usage(); 1183 1184 memset(&cmd, 0, sizeof(cmd)); 1185 1186 cmd.opcode = SCSI_TEST_UNIT_READY; 1187 1188 scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 10000, 0); 1189 1190 return; 1191 } 1192 1193 /* 1194 * BUS COMMANDS 1195 */ 1196 1197 /* 1198 * bus_reset: 1199 * 1200 * Issue a reset to a SCSI bus. 1201 */ 1202 static void 1203 bus_reset(int argc, char *argv[]) 1204 { 1205 1206 /* No arguments. */ 1207 if (argc != 0) 1208 usage(); 1209 1210 if (ioctl(fd, SCBUSIORESET, NULL) != 0) 1211 err(1, "SCBUSIORESET"); 1212 1213 return; 1214 } 1215 1216 /* 1217 * bus_scan: 1218 * 1219 * Rescan a SCSI bus for new devices. 1220 */ 1221 static void 1222 bus_scan(int argc, char *argv[]) 1223 { 1224 struct scbusioscan_args args; 1225 char *cp; 1226 1227 /* Must have two args: target lun */ 1228 if (argc != 2) 1229 usage(); 1230 1231 if (strcmp(argv[0], "any") == 0 || strcmp(argv[0], "all") == 0) 1232 args.sa_target = -1; 1233 else { 1234 args.sa_target = strtol(argv[0], &cp, 10); 1235 if (*cp != '\0' || args.sa_target < 0) 1236 errx(1, "invalid target: %s", argv[0]); 1237 } 1238 1239 if (strcmp(argv[1], "any") == 0 || strcmp(argv[1], "all") == 0) 1240 args.sa_lun = -1; 1241 else { 1242 args.sa_lun = strtol(argv[1], &cp, 10); 1243 if (*cp != '\0' || args.sa_lun < 0) 1244 errx(1, "invalid lun: %s", argv[1]); 1245 } 1246 1247 if (ioctl(fd, SCBUSIOSCAN, &args) != 0) 1248 err(1, "SCBUSIOSCAN"); 1249 1250 return; 1251 } 1252 1253 /* 1254 * bus_detach: 1255 * 1256 * detach SCSI devices from a bus. 1257 */ 1258 static void 1259 bus_detach(int argc, char *argv[]) 1260 { 1261 struct scbusiodetach_args args; 1262 char *cp; 1263 1264 /* Must have two args: target lun */ 1265 if (argc != 2) 1266 usage(); 1267 1268 if (strcmp(argv[0], "any") == 0 || strcmp(argv[0], "all") == 0) 1269 args.sa_target = -1; 1270 else { 1271 args.sa_target = strtol(argv[0], &cp, 10); 1272 if (*cp != '\0' || args.sa_target < 0) 1273 errx(1, "invalid target: %s", argv[0]); 1274 } 1275 1276 if (strcmp(argv[1], "any") == 0 || strcmp(argv[1], "all") == 0) 1277 args.sa_lun = -1; 1278 else { 1279 args.sa_lun = strtol(argv[1], &cp, 10); 1280 if (*cp != '\0' || args.sa_lun < 0) 1281 errx(1, "invalid lun: %s", argv[1]); 1282 } 1283 1284 if (ioctl(fd, SCBUSIODETACH, &args) != 0) 1285 err(1, "SCBUSIODETACH"); 1286 1287 return; 1288 } 1289