Fix number of problems found while testing on SAT devices.
- Remove incomplete and dangerous ata_res decoding from ata_do_cmd(). Instead switch all functions that need the result to use get_ata_status(), doing the same, but more careful, also reducing code duplication. - Made get_ata_status() to also decode fixed format sense. In many cases it is still not enough to make it useful, since it can only report results of 28-bit command, but it is slightly better then nothing. - Organize error reporting in ata_do_cmd(), so that if caller specified AP_FLAG_CHK_COND, it is responsible for command errors (non-ioctl ones). - Make HPA/AMA errors not fatal for `identify` subcommand. - Fix reprobe() not being called on HPA/AMA when in quiet mode. - Remove not very useful messages from `format` and `sanitize` commands with -y flag. Once they started, they often can't be stopped any way. MFC after: 5 days Sponsored by: iXsystems, Inc.
This commit is contained in:
parent
17adfbe017
commit
bdd2f4e1c1
@ -1751,7 +1751,7 @@ atacapprint(struct ata_params *parm)
|
||||
}
|
||||
|
||||
static int
|
||||
scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb)
|
||||
{
|
||||
struct ata_pass_16 *ata_pass_16;
|
||||
struct ata_cmd ata_cmd;
|
||||
@ -1774,24 +1774,21 @@ scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
|
||||
|
||||
if (cam_send_ccb(device, ccb) < 0) {
|
||||
if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
|
||||
warn("error sending ATA %s via pass_16",
|
||||
ata_op_string(&ata_cmd));
|
||||
}
|
||||
warn("error sending ATA %s via pass_16", ata_op_string(&ata_cmd));
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Consider any non-CAM_REQ_CMP status as error and report it here,
|
||||
* unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
|
||||
*/
|
||||
if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
|
||||
(ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
|
||||
warnx("ATA %s via pass_16 failed",
|
||||
ata_op_string(&ata_cmd));
|
||||
}
|
||||
warnx("ATA %s via pass_16 failed", ata_op_string(&ata_cmd));
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -1800,7 +1797,7 @@ scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
|
||||
|
||||
static int
|
||||
ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
ata_cam_send(struct cam_device *device, union ccb *ccb)
|
||||
{
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
warnx("sending ATA %s with timeout of %u msecs",
|
||||
@ -1815,24 +1812,21 @@ ata_cam_send(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
|
||||
|
||||
if (cam_send_ccb(device, ccb) < 0) {
|
||||
if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
|
||||
warn("error sending ATA %s",
|
||||
ata_op_string(&(ccb->ataio.cmd)));
|
||||
}
|
||||
warn("error sending ATA %s", ata_op_string(&(ccb->ataio.cmd)));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
if (quiet != 1 || arglist & CAM_ARG_VERBOSE) {
|
||||
warnx("ATA %s failed: %d",
|
||||
ata_op_string(&(ccb->ataio.cmd)), quiet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Consider any non-CAM_REQ_CMP status as error and report it here,
|
||||
* unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
|
||||
*/
|
||||
if (!(ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT) &&
|
||||
(ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
warnx("ATA %s failed", ata_op_string(&(ccb->ataio.cmd)));
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -1844,7 +1838,7 @@ ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
|
||||
u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
|
||||
u_int8_t tag_action, u_int8_t command, u_int16_t features,
|
||||
u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr,
|
||||
u_int16_t dxfer_len, int timeout, int quiet)
|
||||
u_int16_t dxfer_len, int timeout)
|
||||
{
|
||||
if (data_ptr != NULL) {
|
||||
if (flags & CAM_DIR_OUT)
|
||||
@ -1874,7 +1868,7 @@ ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
|
||||
/*sense_len*/SSD_FULL_SIZE,
|
||||
timeout);
|
||||
|
||||
return scsi_cam_pass_16_send(device, ccb, quiet);
|
||||
return scsi_cam_pass_16_send(device, ccb);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1910,50 +1904,10 @@ ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
|
||||
return (1);
|
||||
|
||||
if (retval == 1) {
|
||||
int error;
|
||||
|
||||
/* Try using SCSI Passthrough */
|
||||
error = ata_do_pass_16(device, ccb, retries, flags, protocol,
|
||||
return (ata_do_pass_16(device, ccb, retries, flags, protocol,
|
||||
ata_flags, tag_action, command, features,
|
||||
lba, sector_count, data_ptr, dxfer_len,
|
||||
timeout, 0);
|
||||
|
||||
if (ata_flags & AP_FLAG_CHK_COND) {
|
||||
/* Decode ata_res from sense data */
|
||||
struct ata_res_pass16 *res_pass16;
|
||||
struct ata_res *res;
|
||||
u_int i;
|
||||
u_int16_t *ptr;
|
||||
|
||||
/* sense_data is 4 byte aligned */
|
||||
ptr = (uint16_t*)(uintptr_t)&ccb->csio.sense_data;
|
||||
for (i = 0; i < sizeof(*res_pass16) / 2; i++)
|
||||
ptr[i] = le16toh(ptr[i]);
|
||||
|
||||
/* sense_data is 4 byte aligned */
|
||||
res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
|
||||
&ccb->csio.sense_data;
|
||||
res = &ccb->ataio.res;
|
||||
res->flags = res_pass16->flags;
|
||||
res->status = res_pass16->status;
|
||||
res->error = res_pass16->error;
|
||||
res->lba_low = res_pass16->lba_low;
|
||||
res->lba_mid = res_pass16->lba_mid;
|
||||
res->lba_high = res_pass16->lba_high;
|
||||
res->device = res_pass16->device;
|
||||
res->lba_low_exp = res_pass16->lba_low_exp;
|
||||
res->lba_mid_exp = res_pass16->lba_mid_exp;
|
||||
res->lba_high_exp = res_pass16->lba_high_exp;
|
||||
res->sector_count = res_pass16->sector_count;
|
||||
res->sector_count_exp = res_pass16->sector_count_exp;
|
||||
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
|
||||
if (res->status & ATA_STATUS_ERROR)
|
||||
ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR;
|
||||
else
|
||||
ccb->ccb_h.status |= CAM_REQ_CMP;
|
||||
}
|
||||
|
||||
return (error);
|
||||
timeout));
|
||||
}
|
||||
|
||||
CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->ataio);
|
||||
@ -1974,7 +1928,7 @@ ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
|
||||
if (ata_flags & AP_FLAG_CHK_COND)
|
||||
ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
|
||||
|
||||
return ata_cam_send(device, ccb, 0);
|
||||
return ata_cam_send(device, ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1994,23 +1948,31 @@ dump_data(uint16_t *ptr, uint32_t len)
|
||||
}
|
||||
|
||||
static int
|
||||
atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
|
||||
int is48bit, u_int64_t *hpasize)
|
||||
atahpa_proc_resp(struct cam_device *device, union ccb *ccb, u_int64_t *hpasize)
|
||||
{
|
||||
struct ata_res *res;
|
||||
uint8_t error = 0, ata_device = 0, status = 0;
|
||||
uint16_t count = 0;
|
||||
uint64_t lba = 0;
|
||||
int retval;
|
||||
|
||||
res = &ccb->ataio.res;
|
||||
if (res->status & ATA_STATUS_ERROR) {
|
||||
retval = get_ata_status(device, ccb, &error, &count, &lba, &ata_device,
|
||||
&status);
|
||||
if (retval == 1) {
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
}
|
||||
warnx("Can't get ATA command status");
|
||||
return (retval);
|
||||
}
|
||||
|
||||
if (status & ATA_STATUS_ERROR) {
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
printf("error = 0x%02x, sector_count = 0x%04x, "
|
||||
"device = 0x%02x, status = 0x%02x\n",
|
||||
res->error, res->sector_count,
|
||||
res->device, res->status);
|
||||
}
|
||||
|
||||
if (res->error & ATA_ERROR_ID_NOT_FOUND) {
|
||||
if (error & ATA_ERROR_ID_NOT_FOUND) {
|
||||
warnx("Max address has already been set since "
|
||||
"last power-on or hardware reset");
|
||||
}
|
||||
@ -2018,28 +1980,10 @@ atahpa_proc_resp(struct cam_device *device, union ccb *ccb,
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
fprintf(stdout, "%s%d: Raw native max data:\n",
|
||||
device->device_name, device->dev_unit_num);
|
||||
/* res is 4 byte aligned */
|
||||
dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
|
||||
|
||||
printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
|
||||
"status = 0x%02x\n", res->error, res->sector_count,
|
||||
res->device, res->status);
|
||||
}
|
||||
|
||||
if (hpasize != NULL) {
|
||||
if (is48bit) {
|
||||
*hpasize = (((u_int64_t)((res->lba_high_exp << 16) |
|
||||
(res->lba_mid_exp << 8) | res->lba_low_exp) << 24) |
|
||||
((res->lba_high << 16) | (res->lba_mid << 8) |
|
||||
res->lba_low)) + 1;
|
||||
} else {
|
||||
*hpasize = (((res->device & 0x0f) << 24) |
|
||||
(res->lba_high << 16) | (res->lba_mid << 8) |
|
||||
res->lba_low) + 1;
|
||||
}
|
||||
if (retval == 2 || retval == 6)
|
||||
return (1);
|
||||
*hpasize = lba;
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -2083,7 +2027,7 @@ ata_read_native_max(struct cam_device *device, int retry_count,
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, hpasize);
|
||||
return atahpa_proc_resp(device, ccb, hpasize);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2127,7 +2071,7 @@ atahpa_set_max(struct cam_device *device, int retry_count,
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, NULL);
|
||||
return atahpa_proc_resp(device, ccb, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2135,20 +2079,19 @@ atahpa_password(struct cam_device *device, int retry_count,
|
||||
u_int32_t timeout, union ccb *ccb,
|
||||
int is48bit, struct ata_set_max_pwd *pwd)
|
||||
{
|
||||
int error;
|
||||
u_int cmd;
|
||||
u_int8_t protocol;
|
||||
|
||||
protocol = AP_PROTO_PIO_OUT;
|
||||
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
|
||||
|
||||
error = ata_do_cmd(device,
|
||||
return (ata_do_cmd(device,
|
||||
ccb,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_OUT,
|
||||
/*protocol*/protocol,
|
||||
/*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
|
||||
AP_FLAG_TLEN_SECT_CNT | AP_FLAG_CHK_COND,
|
||||
AP_FLAG_TLEN_SECT_CNT,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/cmd,
|
||||
/*features*/ATA_HPA_FEAT_SET_PWD,
|
||||
@ -2157,31 +2100,25 @@ atahpa_password(struct cam_device *device, int retry_count,
|
||||
/*data_ptr*/(u_int8_t*)pwd,
|
||||
/*dxfer_len*/sizeof(*pwd),
|
||||
timeout ? timeout : 1000,
|
||||
is48bit);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, NULL);
|
||||
is48bit));
|
||||
}
|
||||
|
||||
static int
|
||||
atahpa_lock(struct cam_device *device, int retry_count,
|
||||
u_int32_t timeout, union ccb *ccb, int is48bit)
|
||||
{
|
||||
int error;
|
||||
u_int cmd;
|
||||
u_int8_t protocol;
|
||||
|
||||
protocol = AP_PROTO_NON_DATA;
|
||||
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
|
||||
|
||||
error = ata_do_cmd(device,
|
||||
return (ata_do_cmd(device,
|
||||
ccb,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
/*protocol*/protocol,
|
||||
/*ata_flags*/AP_FLAG_CHK_COND,
|
||||
/*ata_flags*/0,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/cmd,
|
||||
/*features*/ATA_HPA_FEAT_LOCK,
|
||||
@ -2190,12 +2127,7 @@ atahpa_lock(struct cam_device *device, int retry_count,
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
timeout ? timeout : 1000,
|
||||
is48bit);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, NULL);
|
||||
is48bit));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2203,20 +2135,19 @@ atahpa_unlock(struct cam_device *device, int retry_count,
|
||||
u_int32_t timeout, union ccb *ccb,
|
||||
int is48bit, struct ata_set_max_pwd *pwd)
|
||||
{
|
||||
int error;
|
||||
u_int cmd;
|
||||
u_int8_t protocol;
|
||||
|
||||
protocol = AP_PROTO_PIO_OUT;
|
||||
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
|
||||
|
||||
error = ata_do_cmd(device,
|
||||
return (ata_do_cmd(device,
|
||||
ccb,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_OUT,
|
||||
/*protocol*/protocol,
|
||||
/*ata_flags*/AP_FLAG_BYT_BLOK_BLOCKS |
|
||||
AP_FLAG_TLEN_SECT_CNT | AP_FLAG_CHK_COND,
|
||||
AP_FLAG_TLEN_SECT_CNT,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/cmd,
|
||||
/*features*/ATA_HPA_FEAT_UNLOCK,
|
||||
@ -2225,31 +2156,25 @@ atahpa_unlock(struct cam_device *device, int retry_count,
|
||||
/*data_ptr*/(u_int8_t*)pwd,
|
||||
/*dxfer_len*/sizeof(*pwd),
|
||||
timeout ? timeout : 1000,
|
||||
is48bit);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, NULL);
|
||||
is48bit));
|
||||
}
|
||||
|
||||
static int
|
||||
atahpa_freeze_lock(struct cam_device *device, int retry_count,
|
||||
u_int32_t timeout, union ccb *ccb, int is48bit)
|
||||
{
|
||||
int error;
|
||||
u_int cmd;
|
||||
u_int8_t protocol;
|
||||
|
||||
protocol = AP_PROTO_NON_DATA;
|
||||
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
|
||||
|
||||
error = ata_do_cmd(device,
|
||||
return (ata_do_cmd(device,
|
||||
ccb,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
/*protocol*/protocol,
|
||||
/*ata_flags*/AP_FLAG_CHK_COND,
|
||||
/*ata_flags*/0,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/cmd,
|
||||
/*features*/ATA_HPA_FEAT_FREEZE,
|
||||
@ -2258,12 +2183,7 @@ atahpa_freeze_lock(struct cam_device *device, int retry_count,
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
timeout ? timeout : 1000,
|
||||
is48bit);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, is48bit, NULL);
|
||||
is48bit));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2292,7 +2212,7 @@ ata_get_native_max(struct cam_device *device, int retry_count,
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, /*is48bit*/1, nativesize);
|
||||
return atahpa_proc_resp(device, ccb, nativesize);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2324,21 +2244,20 @@ ataama_set(struct cam_device *device, int retry_count,
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, /*is48bit*/1, NULL);
|
||||
return atahpa_proc_resp(device, ccb, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
ataama_freeze(struct cam_device *device, int retry_count,
|
||||
u_int32_t timeout, union ccb *ccb)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = ata_do_cmd(device,
|
||||
return (ata_do_cmd(device,
|
||||
ccb,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
/*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
|
||||
/*ata_flags*/AP_FLAG_CHK_COND,
|
||||
/*ata_flags*/0,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/ATA_AMAX_ADDR,
|
||||
/*features*/ATA_AMAX_ADDR_FREEZE,
|
||||
@ -2347,12 +2266,7 @@ ataama_freeze(struct cam_device *device, int retry_count,
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
timeout ? timeout : 30 * 1000,
|
||||
/*force48bit*/1);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return atahpa_proc_resp(device, ccb, /*is48bit*/1, NULL);
|
||||
/*force48bit*/1));
|
||||
}
|
||||
|
||||
int
|
||||
@ -2448,7 +2362,7 @@ ataidentify(struct cam_device *device, int retry_count, int timeout)
|
||||
{
|
||||
union ccb *ccb;
|
||||
struct ata_params *ident_buf;
|
||||
u_int64_t hpasize, nativesize;
|
||||
u_int64_t hpasize = 0, nativesize = 0;
|
||||
|
||||
if ((ccb = cam_getccb(device)) == NULL) {
|
||||
warnx("couldn't allocate CCB");
|
||||
@ -2467,22 +2381,12 @@ ataidentify(struct cam_device *device, int retry_count, int timeout)
|
||||
}
|
||||
|
||||
if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED) {
|
||||
if (ata_read_native_max(device, retry_count, timeout, ccb,
|
||||
ident_buf, &hpasize) != 0) {
|
||||
cam_freeccb(ccb);
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
hpasize = 0;
|
||||
ata_read_native_max(device, retry_count, timeout, ccb,
|
||||
ident_buf, &hpasize);
|
||||
}
|
||||
if (ident_buf->support2 & ATA_SUPPORT_AMAX_ADDR) {
|
||||
if (ata_get_native_max(device, retry_count, timeout, ccb,
|
||||
&nativesize) != 0) {
|
||||
cam_freeccb(ccb);
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
nativesize = 0;
|
||||
ata_get_native_max(device, retry_count, timeout, ccb,
|
||||
&nativesize);
|
||||
}
|
||||
|
||||
printf("%s%d: ", device->device_name, device->dev_unit_num);
|
||||
@ -3003,10 +2907,11 @@ atahpa(struct cam_device *device, int retry_count, int timeout,
|
||||
}
|
||||
|
||||
if (action == ATA_HPA_ACTION_PRINT) {
|
||||
error = ata_read_native_max(device, retry_count, timeout, ccb,
|
||||
ident_buf, &hpasize);
|
||||
if (error == 0)
|
||||
atahpa_print(ident_buf, hpasize, 1);
|
||||
hpasize = 0;
|
||||
if (ident_buf->support.command1 & ATA_SUPPORT_PROTECTED)
|
||||
ata_read_native_max(device, retry_count, timeout, ccb,
|
||||
ident_buf, &hpasize);
|
||||
atahpa_print(ident_buf, hpasize, 1);
|
||||
|
||||
cam_freeccb(ccb);
|
||||
free(ident_buf);
|
||||
@ -3049,12 +2954,14 @@ atahpa(struct cam_device *device, int retry_count, int timeout,
|
||||
if (error == 0) {
|
||||
error = atahpa_set_max(device, retry_count, timeout,
|
||||
ccb, is48bit, maxsize, persist);
|
||||
if (error == 0 && quiet == 0) {
|
||||
/* redo identify to get new lba values */
|
||||
error = ata_do_identify(device, retry_count,
|
||||
timeout, ccb,
|
||||
&ident_buf);
|
||||
atahpa_print(ident_buf, hpasize, 1);
|
||||
if (error == 0) {
|
||||
if (quiet == 0) {
|
||||
/* redo identify to get new values */
|
||||
error = ata_do_identify(device,
|
||||
retry_count, timeout, ccb,
|
||||
&ident_buf);
|
||||
atahpa_print(ident_buf, hpasize, 1);
|
||||
}
|
||||
/* Hint CAM to reprobe the device. */
|
||||
reprobe(device);
|
||||
}
|
||||
@ -3170,10 +3077,11 @@ ataama(struct cam_device *device, int retry_count, int timeout,
|
||||
}
|
||||
|
||||
if (action == ATA_AMA_ACTION_PRINT) {
|
||||
error = ata_get_native_max(device, retry_count, timeout, ccb,
|
||||
nativesize = 0;
|
||||
if (ident_buf->support2 & ATA_SUPPORT_AMAX_ADDR)
|
||||
ata_get_native_max(device, retry_count, timeout, ccb,
|
||||
&nativesize);
|
||||
if (error == 0)
|
||||
ataama_print(ident_buf, nativesize, 1);
|
||||
ataama_print(ident_buf, nativesize, 1);
|
||||
|
||||
cam_freeccb(ccb);
|
||||
free(ident_buf);
|
||||
@ -3194,11 +3102,14 @@ ataama(struct cam_device *device, int retry_count, int timeout,
|
||||
if (error == 0) {
|
||||
error = ataama_set(device, retry_count, timeout,
|
||||
ccb, maxsize);
|
||||
if (error == 0 && quiet == 0) {
|
||||
/* redo identify to get new lba values */
|
||||
error = ata_do_identify(device, retry_count,
|
||||
timeout, ccb, &ident_buf);
|
||||
ataama_print(ident_buf, nativesize, 1);
|
||||
if (error == 0) {
|
||||
if (quiet == 0) {
|
||||
/* redo identify to get new values */
|
||||
error = ata_do_identify(device,
|
||||
retry_count, timeout, ccb,
|
||||
&ident_buf);
|
||||
ataama_print(ident_buf, nativesize, 1);
|
||||
}
|
||||
/* Hint CAM to reprobe the device. */
|
||||
reprobe(device);
|
||||
}
|
||||
@ -5729,16 +5640,21 @@ build_ata_cmd(union ccb *ccb, uint32_t retry_count, uint32_t flags,
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns: 0 -- success, 1 -- error, 2 -- lba truncated,
|
||||
* 4 -- count truncated, 6 -- lba and count truncated.
|
||||
*/
|
||||
int
|
||||
get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
uint16_t *count, uint64_t *lba, uint8_t *device, uint8_t *status)
|
||||
{
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
switch (ccb->ccb_h.func_code) {
|
||||
case XPT_SCSI_IO: {
|
||||
uint8_t opcode;
|
||||
int error_code = 0, sense_key = 0, asc = 0, ascq = 0;
|
||||
u_int sense_len;
|
||||
|
||||
/*
|
||||
* In this case, we have SCSI ATA PASS-THROUGH command, 12
|
||||
@ -5750,20 +5666,17 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
opcode = ccb->csio.cdb_io.cdb_bytes[0];
|
||||
if ((opcode != ATA_PASS_12)
|
||||
&& (opcode != ATA_PASS_16)) {
|
||||
retval = 1;
|
||||
warnx("%s: unsupported opcode %02x", __func__, opcode);
|
||||
goto bailout;
|
||||
return (1);
|
||||
}
|
||||
|
||||
retval = scsi_extract_sense_ccb(ccb, &error_code, &sense_key,
|
||||
&asc, &ascq);
|
||||
/* Note: the _ccb() variant returns 0 for an error */
|
||||
if (retval == 0) {
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
} else
|
||||
retval = 0;
|
||||
if (retval == 0)
|
||||
return (1);
|
||||
|
||||
sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
|
||||
switch (error_code) {
|
||||
case SSD_DESC_CURRENT_ERROR:
|
||||
case SSD_DESC_DEFERRED_ERROR: {
|
||||
@ -5774,13 +5687,12 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
sense = (struct scsi_sense_data_desc *)
|
||||
&ccb->csio.sense_data;
|
||||
|
||||
desc_ptr = scsi_find_desc(sense, ccb->csio.sense_len -
|
||||
ccb->csio.sense_resid, SSD_DESC_ATA);
|
||||
desc_ptr = scsi_find_desc(sense, sense_len,
|
||||
SSD_DESC_ATA);
|
||||
if (desc_ptr == NULL) {
|
||||
cam_error_print(dev, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
return (1);
|
||||
}
|
||||
desc = (struct scsi_sense_ata_ret_desc *)desc_ptr;
|
||||
|
||||
@ -5812,22 +5724,47 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
}
|
||||
case SSD_CURRENT_ERROR:
|
||||
case SSD_DEFERRED_ERROR: {
|
||||
#if 0
|
||||
struct scsi_sense_data_fixed *sense;
|
||||
#endif
|
||||
uint64_t val;
|
||||
|
||||
/*
|
||||
* XXX KDM need to support fixed sense data.
|
||||
* In my understanding of SAT-5 specification, saying:
|
||||
* "without interpreting the contents of the STATUS",
|
||||
* this should not happen if CK_COND was set, but it
|
||||
* does at least for some devices, so try to revert.
|
||||
*/
|
||||
warnx("%s: Fixed sense data not supported yet",
|
||||
__func__);
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
break; /*NOTREACHED*/
|
||||
if ((sense_key == SSD_KEY_ABORTED_COMMAND) &&
|
||||
(asc == 0) && (ascq == 0)) {
|
||||
*status = ATA_STATUS_ERROR;
|
||||
*error = ATA_ERROR_ABORT;
|
||||
*device = 0;
|
||||
*count = 0;
|
||||
*lba = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((sense_key != SSD_KEY_RECOVERED_ERROR) ||
|
||||
(asc != 0x00) || (ascq != 0x1d))
|
||||
return (1);
|
||||
|
||||
val = 0;
|
||||
scsi_get_sense_info(&ccb->csio.sense_data, sense_len,
|
||||
SSD_DESC_INFO, &val, NULL);
|
||||
*error = (val >> 24) & 0xff;
|
||||
*status = (val >> 16) & 0xff;
|
||||
*device = (val >> 8) & 0xff;
|
||||
*count = val & 0xff;
|
||||
|
||||
val = 0;
|
||||
scsi_get_sense_info(&ccb->csio.sense_data, sense_len,
|
||||
SSD_DESC_COMMAND, &val, NULL);
|
||||
*lba = ((val >> 16) & 0xff) | (val & 0xff00) |
|
||||
((val & 0xff) << 16);
|
||||
|
||||
/* Report UPPER NONZERO bits as errors 2, 4 and 6. */
|
||||
return ((val >> 28) & 0x06);
|
||||
}
|
||||
default:
|
||||
retval = 1;
|
||||
goto bailout;
|
||||
break;
|
||||
return (1);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -5835,11 +5772,11 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
case XPT_ATA_IO: {
|
||||
struct ata_res *res;
|
||||
|
||||
/*
|
||||
* In this case, we have an ATA command, and we need to
|
||||
* fill in the requested values from the result register
|
||||
* set.
|
||||
*/
|
||||
/* Only some statuses return ATA result register set. */
|
||||
if (cam_ccb_status(ccb) != CAM_REQ_CMP &&
|
||||
cam_ccb_status(ccb) != CAM_ATA_STATUS_ERROR)
|
||||
return (1);
|
||||
|
||||
res = &ccb->ataio.res;
|
||||
*error = res->error;
|
||||
*status = res->status;
|
||||
@ -5848,7 +5785,7 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
*lba = (res->lba_high << 16) |
|
||||
(res->lba_mid << 8) |
|
||||
(res->lba_low);
|
||||
if (res->flags & CAM_ATAIO_48BIT) {
|
||||
if (ccb->ataio.cmd.flags & CAM_ATAIO_48BIT) {
|
||||
*count |= (res->sector_count_exp << 8);
|
||||
*lba |= ((uint64_t)res->lba_low_exp << 24) |
|
||||
((uint64_t)res->lba_mid_exp << 32) |
|
||||
@ -5859,11 +5796,9 @@ get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
retval = 1;
|
||||
break;
|
||||
return (1);
|
||||
}
|
||||
bailout:
|
||||
return (retval);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6461,7 +6396,7 @@ scsiformat(struct cam_device *device, int argc, char **argv,
|
||||
if (reportonly)
|
||||
goto doreport;
|
||||
|
||||
if (quiet == 0) {
|
||||
if (quiet == 0 && ycount == 0) {
|
||||
fprintf(stdout, "You are about to REMOVE ALL DATA from the "
|
||||
"following device:\n");
|
||||
|
||||
@ -6702,66 +6637,78 @@ scsiformat(struct cam_device *device, int argc, char **argv,
|
||||
}
|
||||
|
||||
static int
|
||||
sanitize_wait_ata(struct cam_device *device, union ccb *ccb, int quiet)
|
||||
sanitize_wait_ata(struct cam_device *device, union ccb *ccb, int quiet,
|
||||
camcontrol_devtype devtype)
|
||||
{
|
||||
struct ata_res *res;
|
||||
int retval;
|
||||
cam_status status;
|
||||
uint8_t error = 0, ata_device = 0, status = 0;
|
||||
uint16_t count = 0;
|
||||
uint64_t lba = 0;
|
||||
u_int val, perc;
|
||||
|
||||
do {
|
||||
retval = ata_do_cmd(device,
|
||||
ccb,
|
||||
/*retries*/1,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
/*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
|
||||
/*ata_flags*/AP_FLAG_CHK_COND,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/ATA_SANITIZE,
|
||||
/*features*/0x00, /* SANITIZE STATUS EXT */
|
||||
/*lba*/0,
|
||||
/*sector_count*/0,
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
/*timeout*/10000,
|
||||
/*is48bit*/1);
|
||||
if (retval < 0) {
|
||||
warn("error sending CAMIOCOMMAND ioctl");
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
retval = build_ata_cmd(ccb,
|
||||
/*retries*/ 0,
|
||||
/*flags*/ CAM_DIR_NONE,
|
||||
/*tag_action*/ MSG_SIMPLE_Q_TAG,
|
||||
/*protocol*/ AP_PROTO_NON_DATA,
|
||||
/*ata_flags*/ AP_FLAG_CHK_COND,
|
||||
/*features*/ 0x00, /* SANITIZE STATUS EXT */
|
||||
/*sector_count*/ 0,
|
||||
/*lba*/ 0,
|
||||
/*command*/ ATA_SANITIZE,
|
||||
/*auxiliary*/ 0,
|
||||
/*data_ptr*/ NULL,
|
||||
/*dxfer_len*/ 0,
|
||||
/*cdb_storage*/ NULL,
|
||||
/*cdb_storage_len*/ 0,
|
||||
/*sense_len*/ SSD_FULL_SIZE,
|
||||
/*timeout*/ 10000,
|
||||
/*is48bit*/ 1,
|
||||
/*devtype*/ devtype);
|
||||
if (retval != 0) {
|
||||
warnx("%s: build_ata_cmd() failed, likely "
|
||||
"programmer error", __func__);
|
||||
return (1);
|
||||
}
|
||||
|
||||
ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
|
||||
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
|
||||
retval = cam_send_ccb(device, ccb);
|
||||
if (retval != 0) {
|
||||
warn("error sending SANITIZE STATUS EXT command");
|
||||
return (1);
|
||||
}
|
||||
|
||||
retval = get_ata_status(device, ccb, &error, &count, &lba,
|
||||
&ata_device, &status);
|
||||
if (retval != 0) {
|
||||
warnx("Can't get SANITIZE STATUS EXT status, "
|
||||
"sanitize may still run.");
|
||||
return (retval);
|
||||
}
|
||||
if (status & ATA_STATUS_ERROR) {
|
||||
warnx("SANITIZE STATUS EXT failed, "
|
||||
"sanitize may still run.");
|
||||
return (1);
|
||||
}
|
||||
if (count & 0x4000) {
|
||||
if (quiet == 0) {
|
||||
val = lba & 0xffff;
|
||||
perc = 10000 * val;
|
||||
fprintf(stdout,
|
||||
"Sanitizing: %u.%02u%% (%d/%d)\r",
|
||||
(perc / (0x10000 * 100)),
|
||||
((perc / 0x10000) % 100),
|
||||
val, 0x10000);
|
||||
fflush(stdout);
|
||||
}
|
||||
sleep(1);
|
||||
} else if ((count & 0x8000) == 0) {
|
||||
warnx("Sanitize complete with an error. ");
|
||||
return (1);
|
||||
}
|
||||
|
||||
status = ccb->ccb_h.status & CAM_STATUS_MASK;
|
||||
if (status == CAM_REQ_CMP) {
|
||||
res = &ccb->ataio.res;
|
||||
if (res->sector_count_exp & 0x40) {
|
||||
if (quiet == 0) {
|
||||
val = (res->lba_mid << 8) + res->lba_low;
|
||||
perc = 10000 * val;
|
||||
fprintf(stdout,
|
||||
"Sanitizing: %u.%02u%% (%d/%d)\r",
|
||||
(perc / (0x10000 * 100)),
|
||||
((perc / 0x10000) % 100),
|
||||
val, 0x10000);
|
||||
fflush(stdout);
|
||||
}
|
||||
sleep(1);
|
||||
} else if ((res->sector_count_exp & 0x80) == 0) {
|
||||
warnx("Sanitize complete with an error. ");
|
||||
return (1);
|
||||
} else
|
||||
break;
|
||||
|
||||
} else if (status != CAM_REQ_CMP && status != CAM_REQUEUE_REQ) {
|
||||
warnx("Unexpected CAM status %#x", status);
|
||||
if (arglist & CAM_ARG_VERBOSE)
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
return (1);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
} while (1);
|
||||
return (0);
|
||||
}
|
||||
@ -7041,7 +6988,7 @@ sanitize(struct cam_device *device, int argc, char **argv,
|
||||
}
|
||||
}
|
||||
|
||||
if (quiet == 0) {
|
||||
if (quiet == 0 && ycount == 0) {
|
||||
fprintf(stdout, "You are about to REMOVE ALL DATA from the "
|
||||
"following device:\n");
|
||||
|
||||
@ -7169,7 +7116,7 @@ sanitize(struct cam_device *device, int argc, char **argv,
|
||||
retry_count,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
/*protocol*/AP_PROTO_NON_DATA | AP_EXTEND,
|
||||
/*ata_flags*/AP_FLAG_CHK_COND,
|
||||
/*ata_flags*/0,
|
||||
/*tag_action*/MSG_SIMPLE_Q_TAG,
|
||||
/*command*/ATA_SANITIZE,
|
||||
/*features*/feature,
|
||||
@ -7226,7 +7173,7 @@ sanitize(struct cam_device *device, int argc, char **argv,
|
||||
if (dt == CC_DT_SCSI) {
|
||||
error = sanitize_wait_scsi(device, ccb, task_attr, quiet);
|
||||
} else if (dt == CC_DT_ATA || dt == CC_DT_SATL) {
|
||||
error = sanitize_wait_ata(device, ccb, quiet);
|
||||
error = sanitize_wait_ata(device, ccb, quiet, dt);
|
||||
} else
|
||||
error = 1;
|
||||
if (error == 0 && quiet == 0)
|
||||
@ -9199,56 +9146,63 @@ smpphylist(struct cam_device *device, int argc, char **argv,
|
||||
static int
|
||||
atapm_proc_resp(struct cam_device *device, union ccb *ccb)
|
||||
{
|
||||
struct ata_res *res;
|
||||
uint8_t error = 0, ata_device = 0, status = 0;
|
||||
uint16_t count = 0;
|
||||
uint64_t lba = 0;
|
||||
int retval;
|
||||
|
||||
res = &ccb->ataio.res;
|
||||
if (res->status & ATA_STATUS_ERROR) {
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
printf("error = 0x%02x, sector_count = 0x%04x, "
|
||||
"device = 0x%02x, status = 0x%02x\n",
|
||||
res->error, res->sector_count,
|
||||
res->device, res->status);
|
||||
}
|
||||
retval = get_ata_status(device, ccb, &error, &count, &lba, &ata_device,
|
||||
&status);
|
||||
if (retval == 1) {
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
}
|
||||
warnx("Can't get ATA command status");
|
||||
return (retval);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
if (status & ATA_STATUS_ERROR) {
|
||||
cam_error_print(device, ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL, stderr);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (arglist & CAM_ARG_VERBOSE) {
|
||||
fprintf(stdout, "%s%d: Raw native check power data:\n",
|
||||
device->device_name, device->dev_unit_num);
|
||||
/* res is 4 byte aligned */
|
||||
dump_data((uint16_t*)(uintptr_t)res, sizeof(struct ata_res));
|
||||
printf("%s%d: ", device->device_name, device->dev_unit_num);
|
||||
switch (count) {
|
||||
case 0x00:
|
||||
printf("Standby mode\n");
|
||||
break;
|
||||
case 0x01:
|
||||
printf("Standby_y mode\n");
|
||||
break;
|
||||
case 0x40:
|
||||
printf("NV Cache Power Mode and the spindle is spun down or spinning down\n");
|
||||
break;
|
||||
case 0x41:
|
||||
printf("NV Cache Power Mode and the spindle is spun up or spinning up\n");
|
||||
break;
|
||||
case 0x80:
|
||||
printf("Idle mode\n");
|
||||
break;
|
||||
case 0x81:
|
||||
printf("Idle_a mode\n");
|
||||
break;
|
||||
case 0x82:
|
||||
printf("Idle_b mode\n");
|
||||
break;
|
||||
case 0x83:
|
||||
printf("Idle_c mode\n");
|
||||
break;
|
||||
case 0xff:
|
||||
printf("Active or Idle mode\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown mode 0x%02x\n", count);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("error = 0x%02x, sector_count = 0x%04x, device = 0x%02x, "
|
||||
"status = 0x%02x\n", res->error, res->sector_count,
|
||||
res->device, res->status);
|
||||
}
|
||||
|
||||
printf("%s%d: ", device->device_name, device->dev_unit_num);
|
||||
switch (res->sector_count) {
|
||||
case 0x00:
|
||||
printf("Standby mode\n");
|
||||
break;
|
||||
case 0x40:
|
||||
printf("NV Cache Power Mode and the spindle is spun down or spinning down\n");
|
||||
break;
|
||||
case 0x41:
|
||||
printf("NV Cache Power Mode and the spindle is spun up or spinning up\n");
|
||||
break;
|
||||
case 0x80:
|
||||
printf("Idle mode\n");
|
||||
break;
|
||||
case 0xff:
|
||||
printf("Active or Idle mode\n");
|
||||
break;
|
||||
default:
|
||||
printf("Unknown mode 0x%02x\n", res->sector_count);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user