summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/ctl_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/ctl_error.c')
-rw-r--r--sys/cam/ctl/ctl_error.c188
1 files changed, 122 insertions, 66 deletions
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 8ef5176..4eec276 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -365,62 +365,35 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
SSD_ELEM_NONE);
}
-ctl_ua_type
-ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
- struct scsi_sense_data *sense, scsi_sense_data_type sense_format)
+static void
+ctl_ua_to_acsq(ctl_ua_type ua_to_build, int *asc, int *ascq,
+ ctl_ua_type *ua_to_clear)
{
- ctl_ua_type *ua;
- ctl_ua_type ua_to_build, ua_to_clear;
- int asc, ascq;
- uint32_t p, i;
-
- mtx_assert(&lun->lun_lock, MA_OWNED);
- p = initidx / CTL_MAX_INIT_PER_PORT;
- if ((ua = lun->pending_ua[p]) == NULL) {
- mtx_unlock(&lun->lun_lock);
- ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
- M_CTL, M_WAITOK);
- mtx_lock(&lun->lun_lock);
- if (lun->pending_ua[p] == NULL) {
- lun->pending_ua[p] = ua;
- for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
- ua[i] = CTL_UA_POWERON;
- } else {
- free(ua, M_CTL);
- ua = lun->pending_ua[p];
- }
- }
- i = initidx % CTL_MAX_INIT_PER_PORT;
- if (ua[i] == CTL_UA_NONE)
- return (CTL_UA_NONE);
-
- ua_to_build = (1 << (ffs(ua[i]) - 1));
- ua_to_clear = ua_to_build;
switch (ua_to_build) {
case CTL_UA_POWERON:
/* 29h/01h POWER ON OCCURRED */
- asc = 0x29;
- ascq = 0x01;
- ua_to_clear = ~0;
+ *asc = 0x29;
+ *ascq = 0x01;
+ *ua_to_clear = ~0;
break;
case CTL_UA_BUS_RESET:
/* 29h/02h SCSI BUS RESET OCCURRED */
- asc = 0x29;
- ascq = 0x02;
- ua_to_clear = ~0;
+ *asc = 0x29;
+ *ascq = 0x02;
+ *ua_to_clear = ~0;
break;
case CTL_UA_TARG_RESET:
/* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/
- asc = 0x29;
- ascq = 0x03;
- ua_to_clear = ~0;
+ *asc = 0x29;
+ *ascq = 0x03;
+ *ua_to_clear = ~0;
break;
case CTL_UA_I_T_NEXUS_LOSS:
/* 29h/07h I_T NEXUS LOSS OCCURRED */
- asc = 0x29;
- ascq = 0x07;
- ua_to_clear = ~0;
+ *asc = 0x29;
+ *ascq = 0x07;
+ *ua_to_clear = ~0;
break;
case CTL_UA_LUN_RESET:
/* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
@@ -428,57 +401,128 @@ ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
* Since we don't have a specific ASC/ASCQ pair for a LUN
* reset, just return the generic reset code.
*/
- asc = 0x29;
- ascq = 0x00;
+ *asc = 0x29;
+ *ascq = 0x00;
break;
case CTL_UA_LUN_CHANGE:
/* 3Fh/0Eh REPORTED LUNS DATA HAS CHANGED */
- asc = 0x3F;
- ascq = 0x0E;
+ *asc = 0x3F;
+ *ascq = 0x0E;
break;
case CTL_UA_MODE_CHANGE:
/* 2Ah/01h MODE PARAMETERS CHANGED */
- asc = 0x2A;
- ascq = 0x01;
+ *asc = 0x2A;
+ *ascq = 0x01;
break;
case CTL_UA_LOG_CHANGE:
/* 2Ah/02h LOG PARAMETERS CHANGED */
- asc = 0x2A;
- ascq = 0x02;
+ *asc = 0x2A;
+ *ascq = 0x02;
+ break;
+ case CTL_UA_INQ_CHANGE:
+ /* 3Fh/03h INQUIRY DATA HAS CHANGED */
+ *asc = 0x3F;
+ *ascq = 0x03;
break;
case CTL_UA_RES_PREEMPT:
/* 2Ah/03h RESERVATIONS PREEMPTED */
- asc = 0x2A;
- ascq = 0x03;
+ *asc = 0x2A;
+ *ascq = 0x03;
break;
case CTL_UA_RES_RELEASE:
/* 2Ah/04h RESERVATIONS RELEASED */
- asc = 0x2A;
- ascq = 0x04;
+ *asc = 0x2A;
+ *ascq = 0x04;
break;
case CTL_UA_REG_PREEMPT:
/* 2Ah/05h REGISTRATIONS PREEMPTED */
- asc = 0x2A;
- ascq = 0x05;
+ *asc = 0x2A;
+ *ascq = 0x05;
break;
case CTL_UA_ASYM_ACC_CHANGE:
- /* 2Ah/06n ASYMMETRIC ACCESS STATE CHANGED */
- asc = 0x2A;
- ascq = 0x06;
+ /* 2Ah/06h ASYMMETRIC ACCESS STATE CHANGED */
+ *asc = 0x2A;
+ *ascq = 0x06;
break;
case CTL_UA_CAPACITY_CHANGED:
- /* 2Ah/09n CAPACITY DATA HAS CHANGED */
- asc = 0x2A;
- ascq = 0x09;
+ /* 2Ah/09h CAPACITY DATA HAS CHANGED */
+ *asc = 0x2A;
+ *ascq = 0x09;
break;
case CTL_UA_THIN_PROV_THRES:
- /* 38h/07n THIN PROVISIONING SOFT THRESHOLD REACHED */
- asc = 0x38;
- ascq = 0x07;
+ /* 38h/07h THIN PROVISIONING SOFT THRESHOLD REACHED */
+ *asc = 0x38;
+ *ascq = 0x07;
break;
default:
- panic("ctl_build_ua: Unknown UA %x", ua_to_build);
+ panic("%s: Unknown UA %x", __func__, ua_to_build);
+ }
+}
+
+ctl_ua_type
+ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp)
+{
+ ctl_ua_type ua;
+ ctl_ua_type ua_to_build, ua_to_clear;
+ int asc, ascq;
+ uint32_t p, i;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ p = initidx / CTL_MAX_INIT_PER_PORT;
+ i = initidx % CTL_MAX_INIT_PER_PORT;
+ if (lun->pending_ua[p] == NULL)
+ ua = CTL_UA_POWERON;
+ else
+ ua = lun->pending_ua[p][i];
+ if (ua == CTL_UA_NONE)
+ return (CTL_UA_NONE);
+
+ ua_to_build = (1 << (ffs(ua) - 1));
+ ua_to_clear = ua_to_build;
+ ctl_ua_to_acsq(ua_to_build, &asc, &ascq, &ua_to_clear);
+
+ resp[0] = SSD_KEY_UNIT_ATTENTION;
+ if (ua_to_build == ua)
+ resp[0] |= 0x10;
+ else
+ resp[0] |= 0x20;
+ resp[1] = asc;
+ resp[2] = ascq;
+ return (ua);
+}
+
+ctl_ua_type
+ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
+ struct scsi_sense_data *sense, scsi_sense_data_type sense_format)
+{
+ ctl_ua_type *ua;
+ ctl_ua_type ua_to_build, ua_to_clear;
+ int asc, ascq;
+ uint32_t p, i;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ p = initidx / CTL_MAX_INIT_PER_PORT;
+ if ((ua = lun->pending_ua[p]) == NULL) {
+ mtx_unlock(&lun->lun_lock);
+ ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
+ M_CTL, M_WAITOK);
+ mtx_lock(&lun->lun_lock);
+ if (lun->pending_ua[p] == NULL) {
+ lun->pending_ua[p] = ua;
+ for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
+ ua[i] = CTL_UA_POWERON;
+ } else {
+ free(ua, M_CTL);
+ ua = lun->pending_ua[p];
+ }
}
+ i = initidx % CTL_MAX_INIT_PER_PORT;
+ if (ua[i] == CTL_UA_NONE)
+ return (CTL_UA_NONE);
+
+ ua_to_build = (1 << (ffs(ua[i]) - 1));
+ ua_to_clear = ua_to_build;
+ ctl_ua_to_acsq(ua_to_build, &asc, &ascq, &ua_to_clear);
ctl_set_sense_data(sense,
/*lun*/ NULL,
@@ -843,6 +887,18 @@ ctl_set_task_aborted(struct ctl_scsiio *ctsio)
}
void
+ctl_set_hw_write_protected(struct ctl_scsiio *ctsio)
+{
+ /* "Hardware write protected" */
+ ctl_set_sense(ctsio,
+ /*current_error*/ 1,
+ /*sense_key*/ SSD_KEY_DATA_PROTECT,
+ /*asc*/ 0x27,
+ /*ascq*/ 0x01,
+ SSD_ELEM_NONE);
+}
+
+void
ctl_set_space_alloc_fail(struct ctl_scsiio *ctsio)
{
/* "Space allocation failed write protect" */
OpenPOWER on IntegriCloud