camcontrol.c (274322) | camcontrol.c (276835) |
---|---|
1/* 2 * Copyright (c) 1997-2007 Kenneth D. Merry 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 --- 13 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 1997-2007 Kenneth D. Merry 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 --- 13 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sbin/camcontrol/camcontrol.c 274322 2014-11-09 18:13:08Z bryanv $"); | 30__FBSDID("$FreeBSD: head/sbin/camcontrol/camcontrol.c 276835 2015-01-08 16:58:40Z ken $"); |
31 32#include <sys/ioctl.h> 33#include <sys/stdint.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <sys/endian.h> 37#include <sys/sbuf.h> 38 --- 123 unchanged lines hidden (view full) --- 162struct ata_set_max_pwd 163{ 164 u_int16_t reserved1; 165 u_int8_t password[32]; 166 u_int16_t reserved2[239]; 167}; 168 169static const char scsicmd_opts[] = "a:c:dfi:o:r"; | 31 32#include <sys/ioctl.h> 33#include <sys/stdint.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <sys/endian.h> 37#include <sys/sbuf.h> 38 --- 123 unchanged lines hidden (view full) --- 162struct ata_set_max_pwd 163{ 164 u_int16_t reserved1; 165 u_int8_t password[32]; 166 u_int16_t reserved2[239]; 167}; 168 169static const char scsicmd_opts[] = "a:c:dfi:o:r"; |
170static const char readdefect_opts[] = "f:GP"; | 170static const char readdefect_opts[] = "f:GPqsS:X"; |
171static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; 172static const char smprg_opts[] = "l"; 173static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:"; 174static const char smpphylist_opts[] = "lq"; 175static char pwd_opt; 176#endif 177 178static struct camcontrol_opts option_table[] = { --- 3185 unchanged lines hidden (view full) --- 3364 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n", 3365 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun, 3366 ccb.ccb_h.status & CAM_STATUS_MASK); 3367 return(1); 3368 } 3369} 3370 3371#ifndef MINIMALISTIC | 171static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; 172static const char smprg_opts[] = "l"; 173static const char smppc_opts[] = "a:A:d:lm:M:o:p:s:S:T:"; 174static const char smpphylist_opts[] = "lq"; 175static char pwd_opt; 176#endif 177 178static struct camcontrol_opts option_table[] = { --- 3185 unchanged lines hidden (view full) --- 3364 fprintf(stdout, "%s of %d:%d:%jx returned error %#x\n", 3365 scan? "Re-scan" : "Reset", bus, target, (uintmax_t)lun, 3366 ccb.ccb_h.status & CAM_STATUS_MASK); 3367 return(1); 3368 } 3369} 3370 3371#ifndef MINIMALISTIC |
3372 3373static struct scsi_nv defect_list_type_map[] = { 3374 { "block", SRDD10_BLOCK_FORMAT }, 3375 { "extbfi", SRDD10_EXT_BFI_FORMAT }, 3376 { "extphys", SRDD10_EXT_PHYS_FORMAT }, 3377 { "longblock", SRDD10_LONG_BLOCK_FORMAT }, 3378 { "bfi", SRDD10_BYTES_FROM_INDEX_FORMAT }, 3379 { "phys", SRDD10_PHYSICAL_SECTOR_FORMAT } 3380}; 3381 |
|
3372static int 3373readdefects(struct cam_device *device, int argc, char **argv, 3374 char *combinedopt, int retry_count, int timeout) 3375{ 3376 union ccb *ccb = NULL; | 3382static int 3383readdefects(struct cam_device *device, int argc, char **argv, 3384 char *combinedopt, int retry_count, int timeout) 3385{ 3386 union ccb *ccb = NULL; |
3377 struct scsi_read_defect_data_10 *rdd_cdb; | 3387 struct scsi_read_defect_data_hdr_10 *hdr10 = NULL; 3388 struct scsi_read_defect_data_hdr_12 *hdr12 = NULL; 3389 size_t hdr_size = 0, entry_size = 0; 3390 int use_12byte = 0; 3391 int hex_format = 0; |
3378 u_int8_t *defect_list = NULL; | 3392 u_int8_t *defect_list = NULL; |
3379 u_int32_t max_dlist_length = SRDD10_MAX_LENGTH, dlist_length = 0; 3380 u_int32_t returned_length = 0; 3381 u_int32_t num_returned = 0; 3382 u_int8_t returned_format; | 3393 u_int8_t list_format = 0; 3394 int list_type_set = 0; 3395 u_int32_t dlist_length = 0; 3396 u_int32_t returned_length = 0, valid_len = 0; 3397 u_int32_t num_returned = 0, num_valid = 0; 3398 u_int32_t max_possible_size = 0, hdr_max = 0; 3399 u_int32_t starting_offset = 0; 3400 u_int8_t returned_format, returned_type; |
3383 unsigned int i; | 3401 unsigned int i; |
3402 int summary = 0, quiet = 0; |
|
3384 int c, error = 0; | 3403 int c, error = 0; |
3385 int lists_specified; 3386 int get_length = 1; | 3404 int lists_specified = 0; 3405 int get_length = 1, first_pass = 1; 3406 int mads = 0; |
3387 3388 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3389 switch(c){ 3390 case 'f': 3391 { | 3407 3408 while ((c = getopt(argc, argv, combinedopt)) != -1) { 3409 switch(c){ 3410 case 'f': 3411 { |
3392 char *tstr; 3393 tstr = optarg; 3394 while (isspace(*tstr) && (*tstr != '\0')) 3395 tstr++; 3396 if (strcmp(tstr, "block") == 0) 3397 arglist |= CAM_ARG_FORMAT_BLOCK; 3398 else if (strcmp(tstr, "bfi") == 0) 3399 arglist |= CAM_ARG_FORMAT_BFI; 3400 else if (strcmp(tstr, "phys") == 0) 3401 arglist |= CAM_ARG_FORMAT_PHYS; 3402 else { | 3412 scsi_nv_status status; 3413 int entry_num = 0; 3414 3415 status = scsi_get_nv(defect_list_type_map, 3416 sizeof(defect_list_type_map) / 3417 sizeof(defect_list_type_map[0]), optarg, 3418 &entry_num, SCSI_NV_FLAG_IG_CASE); 3419 3420 if (status == SCSI_NV_FOUND) { 3421 list_format = defect_list_type_map[ 3422 entry_num].value; 3423 list_type_set = 1; 3424 } else { 3425 warnx("%s: %s %s option %s", __func__, 3426 (status == SCSI_NV_AMBIGUOUS) ? 3427 "ambiguous" : "invalid", "defect list type", 3428 optarg); |
3403 error = 1; | 3429 error = 1; |
3404 warnx("invalid defect format %s", tstr); | |
3405 goto defect_bailout; 3406 } 3407 break; 3408 } 3409 case 'G': 3410 arglist |= CAM_ARG_GLIST; 3411 break; 3412 case 'P': 3413 arglist |= CAM_ARG_PLIST; 3414 break; | 3430 goto defect_bailout; 3431 } 3432 break; 3433 } 3434 case 'G': 3435 arglist |= CAM_ARG_GLIST; 3436 break; 3437 case 'P': 3438 arglist |= CAM_ARG_PLIST; 3439 break; |
3440 case 'q': 3441 quiet = 1; 3442 break; 3443 case 's': 3444 summary = 1; 3445 break; 3446 case 'S': { 3447 char *endptr; 3448 3449 starting_offset = strtoul(optarg, &endptr, 0); 3450 if (*endptr != '\0') { 3451 error = 1; 3452 warnx("invalid starting offset %s", optarg); 3453 goto defect_bailout; 3454 } 3455 break; 3456 } 3457 case 'X': 3458 hex_format = 1; 3459 break; |
|
3415 default: 3416 break; 3417 } 3418 } 3419 | 3460 default: 3461 break; 3462 } 3463 } 3464 |
3420 ccb = cam_getccb(device); 3421 3422 /* 3423 * Eventually we should probably support the 12 byte READ DEFECT 3424 * DATA command. It supports a longer parameter list, which may be 3425 * necessary on newer drives with lots of defects. According to 3426 * the SBC-3 spec, drives are supposed to return an illegal request 3427 * if they have more defect data than will fit in 64K. 3428 */ 3429 defect_list = malloc(max_dlist_length); 3430 if (defect_list == NULL) { 3431 warnx("can't malloc memory for defect list"); | 3465 if (list_type_set == 0) { |
3432 error = 1; | 3466 error = 1; |
3467 warnx("no defect list format specified"); |
|
3433 goto defect_bailout; 3434 } 3435 | 3468 goto defect_bailout; 3469 } 3470 |
3471 if (arglist & CAM_ARG_PLIST) { 3472 list_format |= SRDD10_PLIST; 3473 lists_specified++; 3474 } 3475 3476 if (arglist & CAM_ARG_GLIST) { 3477 list_format |= SRDD10_GLIST; 3478 lists_specified++; 3479 } 3480 |
|
3436 /* | 3481 /* |
3482 * This implies a summary, and was the previous behavior. 3483 */ 3484 if (lists_specified == 0) 3485 summary = 1; 3486 3487 ccb = cam_getccb(device); 3488 3489retry_12byte: 3490 3491 /* |
|
3437 * We start off asking for just the header to determine how much 3438 * defect data is available. Some Hitachi drives return an error 3439 * if you ask for more data than the drive has. Once we know the 3440 * length, we retry the command with the returned length. 3441 */ | 3492 * We start off asking for just the header to determine how much 3493 * defect data is available. Some Hitachi drives return an error 3494 * if you ask for more data than the drive has. Once we know the 3495 * length, we retry the command with the returned length. 3496 */ |
3442 dlist_length = sizeof(struct scsi_read_defect_data_hdr_10); | 3497 if (use_12byte == 0) 3498 dlist_length = sizeof(*hdr10); 3499 else 3500 dlist_length = sizeof(*hdr12); |
3443 | 3501 |
3444 rdd_cdb =(struct scsi_read_defect_data_10 *)&ccb->csio.cdb_io.cdb_bytes; 3445 | |
3446retry: | 3502retry: |
3503 if (defect_list != NULL) { 3504 free(defect_list); 3505 defect_list = NULL; 3506 } 3507 defect_list = malloc(dlist_length); 3508 if (defect_list == NULL) { 3509 warnx("can't malloc memory for defect list"); 3510 error = 1; 3511 goto defect_bailout; 3512 } |
|
3447 | 3513 |
3448 lists_specified = 0; | 3514next_batch: 3515 bzero(defect_list, dlist_length); |
3449 3450 /* 3451 * cam_getccb() zeros the CCB header only. So we need to zero the 3452 * payload portion of the ccb. 3453 */ 3454 bzero(&(&ccb->ccb_h)[1], 3455 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 3456 | 3516 3517 /* 3518 * cam_getccb() zeros the CCB header only. So we need to zero the 3519 * payload portion of the ccb. 3520 */ 3521 bzero(&(&ccb->ccb_h)[1], 3522 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 3523 |
3457 cam_fill_csio(&ccb->csio, 3458 /*retries*/ retry_count, 3459 /*cbfcnp*/ NULL, 3460 /*flags*/ CAM_DIR_IN | ((arglist & CAM_ARG_ERR_RECOVER) ? 3461 CAM_PASS_ERR_RECOVER : 0), 3462 /*tag_action*/ MSG_SIMPLE_Q_TAG, 3463 /*data_ptr*/ defect_list, 3464 /*dxfer_len*/ dlist_length, 3465 /*sense_len*/ SSD_FULL_SIZE, 3466 /*cdb_len*/ sizeof(struct scsi_read_defect_data_10), 3467 /*timeout*/ timeout ? timeout : 5000); | 3524 scsi_read_defects(&ccb->csio, 3525 /*retries*/ retry_count, 3526 /*cbfcnp*/ NULL, 3527 /*tag_action*/ MSG_SIMPLE_Q_TAG, 3528 /*list_format*/ list_format, 3529 /*addr_desc_index*/ starting_offset, 3530 /*data_ptr*/ defect_list, 3531 /*dxfer_len*/ dlist_length, 3532 /*minimum_cmd_size*/ use_12byte ? 12 : 0, 3533 /*sense_len*/ SSD_FULL_SIZE, 3534 /*timeout*/ timeout ? timeout : 5000); |
3468 | 3535 |
3469 rdd_cdb->opcode = READ_DEFECT_DATA_10; 3470 if (arglist & CAM_ARG_FORMAT_BLOCK) 3471 rdd_cdb->format = SRDD10_BLOCK_FORMAT; 3472 else if (arglist & CAM_ARG_FORMAT_BFI) 3473 rdd_cdb->format = SRDD10_BYTES_FROM_INDEX_FORMAT; 3474 else if (arglist & CAM_ARG_FORMAT_PHYS) 3475 rdd_cdb->format = SRDD10_PHYSICAL_SECTOR_FORMAT; 3476 else { 3477 error = 1; 3478 warnx("no defect list format specified"); 3479 goto defect_bailout; 3480 } 3481 if (arglist & CAM_ARG_PLIST) { 3482 rdd_cdb->format |= SRDD10_PLIST; 3483 lists_specified++; 3484 } 3485 3486 if (arglist & CAM_ARG_GLIST) { 3487 rdd_cdb->format |= SRDD10_GLIST; 3488 lists_specified++; 3489 } 3490 3491 scsi_ulto2b(dlist_length, rdd_cdb->alloc_length); 3492 | |
3493 /* Disable freezing the device queue */ 3494 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3495 3496 if (cam_send_ccb(device, ccb) < 0) { 3497 perror("error reading defect list"); 3498 3499 if (arglist & CAM_ARG_VERBOSE) { 3500 cam_error_print(device, ccb, CAM_ESF_ALL, 3501 CAM_EPF_ALL, stderr); 3502 } 3503 3504 error = 1; 3505 goto defect_bailout; 3506 } 3507 | 3536 /* Disable freezing the device queue */ 3537 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 3538 3539 if (cam_send_ccb(device, ccb) < 0) { 3540 perror("error reading defect list"); 3541 3542 if (arglist & CAM_ARG_VERBOSE) { 3543 cam_error_print(device, ccb, CAM_ESF_ALL, 3544 CAM_EPF_ALL, stderr); 3545 } 3546 3547 error = 1; 3548 goto defect_bailout; 3549 } 3550 |
3508 returned_length = scsi_2btoul(((struct 3509 scsi_read_defect_data_hdr_10 *)defect_list)->length); | 3551 valid_len = ccb->csio.dxfer_len - ccb->csio.resid; |
3510 | 3552 |
3553 if (use_12byte == 0) { 3554 hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list; 3555 hdr_size = sizeof(*hdr10); 3556 hdr_max = SRDDH10_MAX_LENGTH; 3557 3558 if (valid_len >= hdr_size) { 3559 returned_length = scsi_2btoul(hdr10->length); 3560 returned_format = hdr10->format; 3561 } else { 3562 returned_length = 0; 3563 returned_format = 0; 3564 } 3565 } else { 3566 hdr12 = (struct scsi_read_defect_data_hdr_12 *)defect_list; 3567 hdr_size = sizeof(*hdr12); 3568 hdr_max = SRDDH12_MAX_LENGTH; 3569 3570 if (valid_len >= hdr_size) { 3571 returned_length = scsi_4btoul(hdr12->length); 3572 returned_format = hdr12->format; 3573 } else { 3574 returned_length = 0; 3575 returned_format = 0; 3576 } 3577 } 3578 3579 returned_type = returned_format & SRDDH10_DLIST_FORMAT_MASK; 3580 switch (returned_type) { 3581 case SRDD10_BLOCK_FORMAT: 3582 entry_size = sizeof(struct scsi_defect_desc_block); 3583 break; 3584 case SRDD10_LONG_BLOCK_FORMAT: 3585 entry_size = sizeof(struct scsi_defect_desc_long_block); 3586 break; 3587 case SRDD10_EXT_PHYS_FORMAT: 3588 case SRDD10_PHYSICAL_SECTOR_FORMAT: 3589 entry_size = sizeof(struct scsi_defect_desc_phys_sector); 3590 break; 3591 case SRDD10_EXT_BFI_FORMAT: 3592 case SRDD10_BYTES_FROM_INDEX_FORMAT: 3593 entry_size = sizeof(struct scsi_defect_desc_bytes_from_index); 3594 break; 3595 default: 3596 warnx("Unknown defect format 0x%x\n", returned_type); 3597 error = 1; 3598 goto defect_bailout; 3599 break; 3600 } 3601 3602 max_possible_size = (hdr_max / entry_size) * entry_size; 3603 num_returned = returned_length / entry_size; 3604 num_valid = min(returned_length, valid_len - hdr_size); 3605 num_valid /= entry_size; 3606 |
|
3511 if (get_length != 0) { 3512 get_length = 0; 3513 3514 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 3515 CAM_SCSI_STATUS_ERROR) { 3516 struct scsi_sense_data *sense; 3517 int error_code, sense_key, asc, ascq; 3518 --- 6 unchanged lines hidden (view full) --- 3525 * If the drive is reporting that it just doesn't 3526 * support the defect list format, go ahead and use 3527 * the length it reported. Otherwise, the length 3528 * may not be valid, so use the maximum. 3529 */ 3530 if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3531 && (asc == 0x1c) && (ascq == 0x00) 3532 && (returned_length > 0)) { | 3607 if (get_length != 0) { 3608 get_length = 0; 3609 3610 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 3611 CAM_SCSI_STATUS_ERROR) { 3612 struct scsi_sense_data *sense; 3613 int error_code, sense_key, asc, ascq; 3614 --- 6 unchanged lines hidden (view full) --- 3621 * If the drive is reporting that it just doesn't 3622 * support the defect list format, go ahead and use 3623 * the length it reported. Otherwise, the length 3624 * may not be valid, so use the maximum. 3625 */ 3626 if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3627 && (asc == 0x1c) && (ascq == 0x00) 3628 && (returned_length > 0)) { |
3533 dlist_length = returned_length + 3534 sizeof(struct scsi_read_defect_data_hdr_10); 3535 dlist_length = min(dlist_length, 3536 SRDD10_MAX_LENGTH); 3537 } else 3538 dlist_length = max_dlist_length; | 3629 if ((use_12byte == 0) 3630 && (returned_length >= max_possible_size)) { 3631 get_length = 1; 3632 use_12byte = 1; 3633 goto retry_12byte; 3634 } 3635 dlist_length = returned_length + hdr_size; 3636 } else if ((sense_key == SSD_KEY_RECOVERED_ERROR) 3637 && (asc == 0x1f) && (ascq == 0x00) 3638 && (returned_length > 0)) { 3639 /* Partial defect list transfer */ 3640 /* 3641 * Hitachi drives return this error 3642 * along with a partial defect list if they 3643 * have more defects than the 10 byte 3644 * command can support. Retry with the 12 3645 * byte command. 3646 */ 3647 if (use_12byte == 0) { 3648 get_length = 1; 3649 use_12byte = 1; 3650 goto retry_12byte; 3651 } 3652 dlist_length = returned_length + hdr_size; 3653 } else if ((sense_key == SSD_KEY_ILLEGAL_REQUEST) 3654 && (asc == 0x24) && (ascq == 0x00)) { 3655 /* Invalid field in CDB */ 3656 /* 3657 * SBC-3 says that if the drive has more 3658 * defects than can be reported with the 3659 * 10 byte command, it should return this 3660 * error and no data. Retry with the 12 3661 * byte command. 3662 */ 3663 if (use_12byte == 0) { 3664 get_length = 1; 3665 use_12byte = 1; 3666 goto retry_12byte; 3667 } 3668 dlist_length = returned_length + hdr_size; 3669 } else { 3670 /* 3671 * If we got a SCSI error and no valid length, 3672 * just use the 10 byte maximum. The 12 3673 * byte maximum is too large. 3674 */ 3675 if (returned_length == 0) 3676 dlist_length = SRDD10_MAX_LENGTH; 3677 else { 3678 if ((use_12byte == 0) 3679 && (returned_length >= 3680 max_possible_size)) { 3681 get_length = 1; 3682 use_12byte = 1; 3683 goto retry_12byte; 3684 } 3685 dlist_length = returned_length + 3686 hdr_size; 3687 } 3688 } |
3539 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != 3540 CAM_REQ_CMP){ 3541 error = 1; 3542 warnx("Error reading defect header"); 3543 if (arglist & CAM_ARG_VERBOSE) 3544 cam_error_print(device, ccb, CAM_ESF_ALL, 3545 CAM_EPF_ALL, stderr); 3546 goto defect_bailout; 3547 } else { | 3689 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != 3690 CAM_REQ_CMP){ 3691 error = 1; 3692 warnx("Error reading defect header"); 3693 if (arglist & CAM_ARG_VERBOSE) 3694 cam_error_print(device, ccb, CAM_ESF_ALL, 3695 CAM_EPF_ALL, stderr); 3696 goto defect_bailout; 3697 } else { |
3548 dlist_length = returned_length + 3549 sizeof(struct scsi_read_defect_data_hdr_10); 3550 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH); | 3698 if ((use_12byte == 0) 3699 && (returned_length >= max_possible_size)) { 3700 get_length = 1; 3701 use_12byte = 1; 3702 goto retry_12byte; 3703 } 3704 dlist_length = returned_length + hdr_size; |
3551 } | 3705 } |
3706 if (summary != 0) { 3707 fprintf(stdout, "%u", num_returned); 3708 if (quiet == 0) { 3709 fprintf(stdout, " defect%s", 3710 (num_returned != 1) ? "s" : ""); 3711 } 3712 fprintf(stdout, "\n"); |
|
3552 | 3713 |
3714 goto defect_bailout; 3715 } 3716 3717 /* 3718 * We always limit the list length to the 10-byte maximum 3719 * length (0xffff). The reason is that some controllers 3720 * can't handle larger I/Os, and we can transfer the entire 3721 * 10 byte list in one shot. For drives that support the 12 3722 * byte read defects command, we'll step through the list 3723 * by specifying a starting offset. For drives that don't 3724 * support the 12 byte command's starting offset, we'll 3725 * just display the first 64K. 3726 */ 3727 dlist_length = min(dlist_length, SRDD10_MAX_LENGTH); 3728 |
|
3553 goto retry; 3554 } 3555 | 3729 goto retry; 3730 } 3731 |
3556 returned_format = ((struct scsi_read_defect_data_hdr_10 *) 3557 defect_list)->format; | |
3558 3559 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 3560 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) 3561 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 3562 struct scsi_sense_data *sense; 3563 int error_code, sense_key, asc, ascq; 3564 3565 sense = &ccb->csio.sense_data; 3566 scsi_extract_sense_len(sense, ccb->csio.sense_len - 3567 ccb->csio.sense_resid, &error_code, &sense_key, &asc, 3568 &ascq, /*show_errors*/ 1); 3569 3570 /* 3571 * According to the SCSI spec, if the disk doesn't support 3572 * the requested format, it will generally return a sense 3573 * key of RECOVERED ERROR, and an additional sense code | 3732 3733 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) 3734 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) 3735 && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { 3736 struct scsi_sense_data *sense; 3737 int error_code, sense_key, asc, ascq; 3738 3739 sense = &ccb->csio.sense_data; 3740 scsi_extract_sense_len(sense, ccb->csio.sense_len - 3741 ccb->csio.sense_resid, &error_code, &sense_key, &asc, 3742 &ascq, /*show_errors*/ 1); 3743 3744 /* 3745 * According to the SCSI spec, if the disk doesn't support 3746 * the requested format, it will generally return a sense 3747 * key of RECOVERED ERROR, and an additional sense code |
3574 * of "DEFECT LIST NOT FOUND". So, we check for that, and 3575 * also check to make sure that the returned length is 3576 * greater than 0, and then print out whatever format the 3577 * disk gave us. | 3748 * of "DEFECT LIST NOT FOUND". HGST drives also return 3749 * Primary/Grown defect list not found errors. So just 3750 * check for an ASC of 0x1c. |
3578 */ 3579 if ((sense_key == SSD_KEY_RECOVERED_ERROR) | 3751 */ 3752 if ((sense_key == SSD_KEY_RECOVERED_ERROR) |
3580 && (asc == 0x1c) && (ascq == 0x00) 3581 && (returned_length > 0)) { 3582 warnx("requested defect format not available"); 3583 switch(returned_format & SRDDH10_DLIST_FORMAT_MASK) { 3584 case SRDD10_BLOCK_FORMAT: 3585 warnx("Device returned block format"); 3586 break; 3587 case SRDD10_BYTES_FROM_INDEX_FORMAT: 3588 warnx("Device returned bytes from index" 3589 " format"); 3590 break; 3591 case SRDD10_PHYSICAL_SECTOR_FORMAT: 3592 warnx("Device returned physical sector format"); 3593 break; 3594 default: | 3753 && (asc == 0x1c)) { 3754 const char *format_str; 3755 3756 format_str = scsi_nv_to_str(defect_list_type_map, 3757 sizeof(defect_list_type_map) / 3758 sizeof(defect_list_type_map[0]), 3759 list_format & SRDD10_DLIST_FORMAT_MASK); 3760 warnx("requested defect format %s not available", 3761 format_str ? format_str : "unknown"); 3762 3763 format_str = scsi_nv_to_str(defect_list_type_map, 3764 sizeof(defect_list_type_map) / 3765 sizeof(defect_list_type_map[0]), returned_type); 3766 if (format_str != NULL) { 3767 warnx("Device returned %s format", 3768 format_str); 3769 } else { |
3595 error = 1; 3596 warnx("Device returned unknown defect" | 3770 error = 1; 3771 warnx("Device returned unknown defect" |
3597 " data format %#x", returned_format); | 3772 " data format %#x", returned_type); |
3598 goto defect_bailout; | 3773 goto defect_bailout; |
3599 break; /* NOTREACHED */ | |
3600 } 3601 } else { 3602 error = 1; 3603 warnx("Error returned from read defect data command"); 3604 if (arglist & CAM_ARG_VERBOSE) 3605 cam_error_print(device, ccb, CAM_ESF_ALL, 3606 CAM_EPF_ALL, stderr); 3607 goto defect_bailout; 3608 } 3609 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3610 error = 1; 3611 warnx("Error returned from read defect data command"); 3612 if (arglist & CAM_ARG_VERBOSE) 3613 cam_error_print(device, ccb, CAM_ESF_ALL, 3614 CAM_EPF_ALL, stderr); 3615 goto defect_bailout; 3616 } 3617 | 3774 } 3775 } else { 3776 error = 1; 3777 warnx("Error returned from read defect data command"); 3778 if (arglist & CAM_ARG_VERBOSE) 3779 cam_error_print(device, ccb, CAM_ESF_ALL, 3780 CAM_EPF_ALL, stderr); 3781 goto defect_bailout; 3782 } 3783 } else if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 3784 error = 1; 3785 warnx("Error returned from read defect data command"); 3786 if (arglist & CAM_ARG_VERBOSE) 3787 cam_error_print(device, ccb, CAM_ESF_ALL, 3788 CAM_EPF_ALL, stderr); 3789 goto defect_bailout; 3790 } 3791 |
3792 if (first_pass != 0) { 3793 fprintf(stderr, "Got %d defect", num_returned); 3794 3795 if ((lists_specified == 0) || (num_returned == 0)) { 3796 fprintf(stderr, "s.\n"); 3797 goto defect_bailout; 3798 } else if (num_returned == 1) 3799 fprintf(stderr, ":\n"); 3800 else 3801 fprintf(stderr, "s:\n"); 3802 3803 first_pass = 0; 3804 } 3805 |
|
3618 /* 3619 * XXX KDM I should probably clean up the printout format for the 3620 * disk defects. 3621 */ | 3806 /* 3807 * XXX KDM I should probably clean up the printout format for the 3808 * disk defects. 3809 */ |
3622 switch (returned_format & SRDDH10_DLIST_FORMAT_MASK){ 3623 case SRDDH10_PHYSICAL_SECTOR_FORMAT: 3624 { 3625 struct scsi_defect_desc_phys_sector *dlist; | 3810 switch (returned_type) { 3811 case SRDD10_PHYSICAL_SECTOR_FORMAT: 3812 case SRDD10_EXT_PHYS_FORMAT: 3813 { 3814 struct scsi_defect_desc_phys_sector *dlist; |
3626 | 3815 |
3627 dlist = (struct scsi_defect_desc_phys_sector *) 3628 (defect_list + 3629 sizeof(struct scsi_read_defect_data_hdr_10)); | 3816 dlist = (struct scsi_defect_desc_phys_sector *) 3817 (defect_list + hdr_size); |
3630 | 3818 |
3631 num_returned = returned_length / 3632 sizeof(struct scsi_defect_desc_phys_sector); | 3819 for (i = 0; i < num_valid; i++) { 3820 uint32_t sector; |
3633 | 3821 |
3634 fprintf(stderr, "Got %d defect", num_returned); 3635 3636 if ((lists_specified == 0) || (num_returned == 0)) { 3637 fprintf(stderr, "s.\n"); 3638 break; 3639 } else if (num_returned == 1) 3640 fprintf(stderr, ":\n"); | 3822 sector = scsi_4btoul(dlist[i].sector); 3823 if (returned_type == SRDD10_EXT_PHYS_FORMAT) { 3824 mads = (sector & SDD_EXT_PHYS_MADS) ? 3825 0 : 1; 3826 sector &= ~SDD_EXT_PHYS_FLAG_MASK; 3827 } 3828 if (hex_format == 0) 3829 fprintf(stdout, "%d:%d:%d%s", 3830 scsi_3btoul(dlist[i].cylinder), 3831 dlist[i].head, 3832 scsi_4btoul(dlist[i].sector), 3833 mads ? " - " : "\n"); |
3641 else | 3834 else |
3642 fprintf(stderr, "s:\n"); 3643 3644 for (i = 0; i < num_returned; i++) { 3645 fprintf(stdout, "%d:%d:%d\n", | 3835 fprintf(stdout, "0x%x:0x%x:0x%x%s", |
3646 scsi_3btoul(dlist[i].cylinder), 3647 dlist[i].head, | 3836 scsi_3btoul(dlist[i].cylinder), 3837 dlist[i].head, |
3648 scsi_4btoul(dlist[i].sector)); 3649 } 3650 break; | 3838 scsi_4btoul(dlist[i].sector), 3839 mads ? " - " : "\n"); 3840 mads = 0; |
3651 } | 3841 } |
3652 case SRDDH10_BYTES_FROM_INDEX_FORMAT: 3653 { 3654 struct scsi_defect_desc_bytes_from_index *dlist; | 3842 if (num_valid < num_returned) { 3843 starting_offset += num_valid; 3844 goto next_batch; 3845 } 3846 break; 3847 } 3848 case SRDD10_BYTES_FROM_INDEX_FORMAT: 3849 case SRDD10_EXT_BFI_FORMAT: 3850 { 3851 struct scsi_defect_desc_bytes_from_index *dlist; |
3655 | 3852 |
3656 dlist = (struct scsi_defect_desc_bytes_from_index *) 3657 (defect_list + 3658 sizeof(struct scsi_read_defect_data_hdr_10)); | 3853 dlist = (struct scsi_defect_desc_bytes_from_index *) 3854 (defect_list + hdr_size); |
3659 | 3855 |
3660 num_returned = returned_length / 3661 sizeof(struct scsi_defect_desc_bytes_from_index); | 3856 for (i = 0; i < num_valid; i++) { 3857 uint32_t bfi; |
3662 | 3858 |
3663 fprintf(stderr, "Got %d defect", num_returned); 3664 3665 if ((lists_specified == 0) || (num_returned == 0)) { 3666 fprintf(stderr, "s.\n"); 3667 break; 3668 } else if (num_returned == 1) 3669 fprintf(stderr, ":\n"); | 3859 bfi = scsi_4btoul(dlist[i].bytes_from_index); 3860 if (returned_type == SRDD10_EXT_BFI_FORMAT) { 3861 mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0; 3862 bfi &= ~SDD_EXT_BFI_FLAG_MASK; 3863 } 3864 if (hex_format == 0) 3865 fprintf(stdout, "%d:%d:%d%s", 3866 scsi_3btoul(dlist[i].cylinder), 3867 dlist[i].head, 3868 scsi_4btoul(dlist[i].bytes_from_index), 3869 mads ? " - " : "\n"); |
3670 else | 3870 else |
3671 fprintf(stderr, "s:\n"); 3672 3673 for (i = 0; i < num_returned; i++) { 3674 fprintf(stdout, "%d:%d:%d\n", | 3871 fprintf(stdout, "0x%x:0x%x:0x%x%s", |
3675 scsi_3btoul(dlist[i].cylinder), 3676 dlist[i].head, | 3872 scsi_3btoul(dlist[i].cylinder), 3873 dlist[i].head, |
3677 scsi_4btoul(dlist[i].bytes_from_index)); 3678 } 3679 break; | 3874 scsi_4btoul(dlist[i].bytes_from_index), 3875 mads ? " - " : "\n"); 3876 3877 mads = 0; |
3680 } | 3878 } |
3681 case SRDDH10_BLOCK_FORMAT: 3682 { 3683 struct scsi_defect_desc_block *dlist; | 3879 if (num_valid < num_returned) { 3880 starting_offset += num_valid; 3881 goto next_batch; 3882 } 3883 break; 3884 } 3885 case SRDDH10_BLOCK_FORMAT: 3886 { 3887 struct scsi_defect_desc_block *dlist; |
3684 | 3888 |
3685 dlist = (struct scsi_defect_desc_block *)(defect_list + 3686 sizeof(struct scsi_read_defect_data_hdr_10)); | 3889 dlist = (struct scsi_defect_desc_block *) 3890 (defect_list + hdr_size); |
3687 | 3891 |
3688 num_returned = returned_length / 3689 sizeof(struct scsi_defect_desc_block); | 3892 for (i = 0; i < num_valid; i++) { 3893 if (hex_format == 0) 3894 fprintf(stdout, "%u\n", 3895 scsi_4btoul(dlist[i].address)); 3896 else 3897 fprintf(stdout, "0x%x\n", 3898 scsi_4btoul(dlist[i].address)); 3899 } |
3690 | 3900 |
3691 fprintf(stderr, "Got %d defect", num_returned); | 3901 if (num_valid < num_returned) { 3902 starting_offset += num_valid; 3903 goto next_batch; 3904 } |
3692 | 3905 |
3693 if ((lists_specified == 0) || (num_returned == 0)) { 3694 fprintf(stderr, "s.\n"); 3695 break; 3696 } else if (num_returned == 1) 3697 fprintf(stderr, ":\n"); | 3906 break; 3907 } 3908 case SRDD10_LONG_BLOCK_FORMAT: 3909 { 3910 struct scsi_defect_desc_long_block *dlist; 3911 3912 dlist = (struct scsi_defect_desc_long_block *) 3913 (defect_list + hdr_size); 3914 3915 for (i = 0; i < num_valid; i++) { 3916 if (hex_format == 0) 3917 fprintf(stdout, "%ju\n", 3918 (uintmax_t)scsi_8btou64( 3919 dlist[i].address)); |
3698 else | 3920 else |
3699 fprintf(stderr, "s:\n"); | 3921 fprintf(stdout, "0x%jx\n", 3922 (uintmax_t)scsi_8btou64( 3923 dlist[i].address)); 3924 } |
3700 | 3925 |
3701 for (i = 0; i < num_returned; i++) 3702 fprintf(stdout, "%u\n", 3703 scsi_4btoul(dlist[i].address)); 3704 break; | 3926 if (num_valid < num_returned) { 3927 starting_offset += num_valid; 3928 goto next_batch; |
3705 } | 3929 } |
3706 default: 3707 fprintf(stderr, "Unknown defect format %d\n", 3708 returned_format & SRDDH10_DLIST_FORMAT_MASK); 3709 error = 1; 3710 break; | 3930 break; |
3711 } | 3931 } |
3932 default: 3933 fprintf(stderr, "Unknown defect format 0x%x\n", 3934 returned_type); 3935 error = 1; 3936 break; 3937 } |
|
3712defect_bailout: 3713 3714 if (defect_list != NULL) 3715 free(defect_list); 3716 3717 if (ccb != NULL) 3718 cam_freeccb(ccb); 3719 --- 4076 unchanged lines hidden (view full) --- 7796" camcontrol stop [dev_id][generic args]\n" 7797" camcontrol load [dev_id][generic args]\n" 7798" camcontrol eject [dev_id][generic args]\n" 7799#endif /* MINIMALISTIC */ 7800" camcontrol rescan <all | bus[:target:lun]>\n" 7801" camcontrol reset <all | bus[:target:lun]>\n" 7802#ifndef MINIMALISTIC 7803" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" | 3938defect_bailout: 3939 3940 if (defect_list != NULL) 3941 free(defect_list); 3942 3943 if (ccb != NULL) 3944 cam_freeccb(ccb); 3945 --- 4076 unchanged lines hidden (view full) --- 8022" camcontrol stop [dev_id][generic args]\n" 8023" camcontrol load [dev_id][generic args]\n" 8024" camcontrol eject [dev_id][generic args]\n" 8025#endif /* MINIMALISTIC */ 8026" camcontrol rescan <all | bus[:target:lun]>\n" 8027" camcontrol reset <all | bus[:target:lun]>\n" 8028#ifndef MINIMALISTIC 8029" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" |
8030" [-q][-s][-S offset][-X]\n" |
|
7804" camcontrol modepage [dev_id][generic args] <-m page | -l>\n" 7805" [-P pagectl][-e | -b][-d]\n" 7806" camcontrol cmd [dev_id][generic args]\n" 7807" <-a cmd [args] | -c cmd [args]>\n" 7808" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n" 7809" camcontrol smpcmd [dev_id][generic args]\n" 7810" <-r len fmt [args]> <-R len fmt [args]>\n" 7811" camcontrol smprg [dev_id][generic args][-l]\n" --- 575 unchanged lines hidden --- | 8031" camcontrol modepage [dev_id][generic args] <-m page | -l>\n" 8032" [-P pagectl][-e | -b][-d]\n" 8033" camcontrol cmd [dev_id][generic args]\n" 8034" <-a cmd [args] | -c cmd [args]>\n" 8035" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n" 8036" camcontrol smpcmd [dev_id][generic args]\n" 8037" <-r len fmt [args]> <-R len fmt [args]>\n" 8038" camcontrol smprg [dev_id][generic args][-l]\n" --- 575 unchanged lines hidden --- |