diff options
Diffstat (limited to 'sys/cam/ctl/ctl_error.c')
-rw-r--r-- | sys/cam/ctl/ctl_error.c | 175 |
1 files changed, 107 insertions, 68 deletions
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c index 6aa6f45..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,62 +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; + *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, |