diff options
-rw-r--r-- | sys/cam/ctl/ctl.c | 384 | ||||
-rw-r--r-- | sys/cam/ctl/ctl.h | 19 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_error.c | 8 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_private.h | 24 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_all.h | 29 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_da.h | 14 |
6 files changed, 240 insertions, 238 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 51751d7..c889ec1 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -93,25 +93,6 @@ struct ctl_softc *control_softc = NULL; * Note that these are default values only. The actual values will be * filled in when the user does a mode sense. */ -const static struct copan_debugconf_subpage debugconf_page_default = { - DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */ - DBGCNF_SUBPAGE_CODE, /* subpage */ - {(sizeof(struct copan_debugconf_subpage) - 4) >> 8, - (sizeof(struct copan_debugconf_subpage) - 4) >> 0}, /* page_length */ - DBGCNF_VERSION, /* page_version */ - {CTL_TIME_IO_DEFAULT_SECS>>8, - CTL_TIME_IO_DEFAULT_SECS>>0}, /* ctl_time_io_secs */ -}; - -const static struct copan_debugconf_subpage debugconf_page_changeable = { - DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */ - DBGCNF_SUBPAGE_CODE, /* subpage */ - {(sizeof(struct copan_debugconf_subpage) - 4) >> 8, - (sizeof(struct copan_debugconf_subpage) - 4) >> 0}, /* page_length */ - 0, /* page_version */ - {0xff,0xff}, /* ctl_time_io_secs */ -}; - const static struct scsi_da_rw_recovery_page rw_er_page_default = { /*page_code*/SMS_RW_ERROR_RECOVERY_PAGE, /*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2, @@ -129,12 +110,12 @@ const static struct scsi_da_rw_recovery_page rw_er_page_default = { const static struct scsi_da_rw_recovery_page rw_er_page_changeable = { /*page_code*/SMS_RW_ERROR_RECOVERY_PAGE, /*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2, - /*byte3*/0, + /*byte3*/SMS_RWER_PER, /*read_retry_count*/0, /*correction_span*/0, /*head_offset_count*/0, /*data_strobe_offset_cnt*/0, - /*byte8*/0, + /*byte8*/SMS_RWER_LBPERE, /*write_retry_count*/0, /*reserved2*/0, /*recovery_time_limit*/{0, 0}, @@ -206,6 +187,24 @@ const static struct scsi_rigid_disk_page rigid_disk_page_changeable = { /*reserved2*/ {0, 0} }; +const static struct scsi_da_verify_recovery_page verify_er_page_default = { + /*page_code*/SMS_VERIFY_ERROR_RECOVERY_PAGE, + /*page_length*/sizeof(struct scsi_da_verify_recovery_page) - 2, + /*byte3*/0, + /*read_retry_count*/0, + /*reserved*/{ 0, 0, 0, 0, 0, 0 }, + /*recovery_time_limit*/{0, 0}, +}; + +const static struct scsi_da_verify_recovery_page verify_er_page_changeable = { + /*page_code*/SMS_VERIFY_ERROR_RECOVERY_PAGE, + /*page_length*/sizeof(struct scsi_da_verify_recovery_page) - 2, + /*byte3*/SMS_VER_PER, + /*read_retry_count*/0, + /*reserved*/{ 0, 0, 0, 0, 0, 0 }, + /*recovery_time_limit*/{0, 0}, +}; + const static struct scsi_caching_page caching_page_default = { /*page_code*/SMS_CACHING_PAGE, /*page_length*/sizeof(struct scsi_caching_page) - 2, @@ -285,19 +284,20 @@ const static struct scsi_control_ext_page control_ext_page_changeable = { const static struct scsi_info_exceptions_page ie_page_default = { /*page_code*/SMS_INFO_EXCEPTIONS_PAGE, /*page_length*/sizeof(struct scsi_info_exceptions_page) - 2, - /*info_flags*/SIEP_FLAGS_DEXCPT, - /*mrie*/0, + /*info_flags*/SIEP_FLAGS_EWASC, + /*mrie*/SIEP_MRIE_NO, /*interval_timer*/{0, 0, 0, 0}, - /*report_count*/{0, 0, 0, 0} + /*report_count*/{0, 0, 0, 1} }; const static struct scsi_info_exceptions_page ie_page_changeable = { /*page_code*/SMS_INFO_EXCEPTIONS_PAGE, /*page_length*/sizeof(struct scsi_info_exceptions_page) - 2, - /*info_flags*/0, - /*mrie*/0, - /*interval_timer*/{0, 0, 0, 0}, - /*report_count*/{0, 0, 0, 0} + /*info_flags*/SIEP_FLAGS_EWASC | SIEP_FLAGS_DEXCPT | SIEP_FLAGS_TEST | + SIEP_FLAGS_LOGERR, + /*mrie*/0x0f, + /*interval_timer*/{0xff, 0xff, 0xff, 0xff}, + /*report_count*/{0xff, 0xff, 0xff, 0xff} }; #define CTL_LBPM_LEN (sizeof(struct ctl_logical_block_provisioning_page) - 4) @@ -4061,6 +4061,26 @@ ctl_init_page_index(struct ctl_lun *lun) (uint8_t *)lun->mode_pages.rigid_disk_page; break; } + case SMS_VERIFY_ERROR_RECOVERY_PAGE: { + KASSERT(page_index->subpage == SMS_SUBPAGE_PAGE_0, + ("subpage %#x for page %#x is incorrect!", + page_index->subpage, page_code)); + memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_CURRENT], + &verify_er_page_default, + sizeof(verify_er_page_default)); + memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_CHANGEABLE], + &verify_er_page_changeable, + sizeof(verify_er_page_changeable)); + memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_DEFAULT], + &verify_er_page_default, + sizeof(verify_er_page_default)); + memcpy(&lun->mode_pages.verify_er_page[CTL_PAGE_SAVED], + &verify_er_page_default, + sizeof(verify_er_page_default)); + page_index->page_data = + (uint8_t *)lun->mode_pages.verify_er_page; + break; + } case SMS_CACHING_PAGE: { struct scsi_caching_page *caching_page; @@ -4271,35 +4291,6 @@ ctl_init_page_index(struct ctl_lun *lun) (uint8_t *)lun->mode_pages.cddvd_page; break; } - case SMS_VENDOR_SPECIFIC_PAGE:{ - switch (page_index->subpage) { - case DBGCNF_SUBPAGE_CODE: { - memcpy(&lun->mode_pages.debugconf_subpage[ - CTL_PAGE_CURRENT], - &debugconf_page_default, - sizeof(debugconf_page_default)); - memcpy(&lun->mode_pages.debugconf_subpage[ - CTL_PAGE_CHANGEABLE], - &debugconf_page_changeable, - sizeof(debugconf_page_changeable)); - memcpy(&lun->mode_pages.debugconf_subpage[ - CTL_PAGE_DEFAULT], - &debugconf_page_default, - sizeof(debugconf_page_default)); - memcpy(&lun->mode_pages.debugconf_subpage[ - CTL_PAGE_SAVED], - &debugconf_page_default, - sizeof(debugconf_page_default)); - page_index->page_data = - (uint8_t *)lun->mode_pages.debugconf_subpage; - break; - } - default: - panic("subpage %#x for page %#x is incorrect!", - page_index->subpage, page_code); - } - break; - } default: panic("invalid page code value %#x", page_code); } @@ -4352,6 +4343,8 @@ ctl_init_log_page_index(struct ctl_lun *lun) lun->log_pages.index[2].page_len = 12*CTL_NUM_LBP_PARAMS; lun->log_pages.index[3].page_data = (uint8_t *)&lun->log_pages.stat_page; lun->log_pages.index[3].page_len = sizeof(lun->log_pages.stat_page); + lun->log_pages.index[4].page_data = (uint8_t *)&lun->log_pages.ie_page; + lun->log_pages.index[4].page_len = sizeof(lun->log_pages.ie_page); return (CTL_RETVAL_COMPLETE); } @@ -4582,6 +4575,8 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun, TAILQ_INIT(&lun->ooa_queue); TAILQ_INIT(&lun->blocked_queue); STAILQ_INIT(&lun->error_list); + lun->ie_reported = 1; + callout_init_mtx(&lun->ie_callout, &lun->lun_lock, 0); ctl_tpc_lun_init(lun); /* @@ -4655,6 +4650,9 @@ ctl_free_lun(struct ctl_lun *lun) atomic_subtract_int(&lun->be_lun->be->num_luns, 1); lun->be_lun->lun_shutdown(lun->be_lun->be_lun); + lun->ie_reportcnt = UINT32_MAX; + callout_drain(&lun->ie_callout); + ctl_tpc_lun_shutdown(lun); mtx_destroy(&lun->lun_lock); free(lun->lun_devid, M_CTL); @@ -5823,25 +5821,12 @@ done: return (CTL_RETVAL_COMPLETE); } -/* - * Note that this function currently doesn't actually do anything inside - * CTL to enforce things if the DQue bit is turned on. - * - * Also note that this function can't be used in the default case, because - * the DQue bit isn't set in the changeable mask for the control mode page - * anyway. This is just here as an example for how to implement a page - * handler, and a placeholder in case we want to allow the user to turn - * tagged queueing on and off. - * - * The D_SENSE bit handling is functional, however, and will turn - * descriptor sense on and off for a given LUN. - */ int -ctl_control_page_handler(struct ctl_scsiio *ctsio, +ctl_default_page_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, uint8_t *page_ptr) { - struct scsi_control_page *current_cp, *saved_cp, *user_cp; struct ctl_lun *lun; + uint8_t *current_cp, *saved_cp; int set_ua; uint32_t initidx; @@ -5849,50 +5834,15 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio, initidx = ctl_get_initindex(&ctsio->io_hdr.nexus); set_ua = 0; - user_cp = (struct scsi_control_page *)page_ptr; - current_cp = (struct scsi_control_page *) - (page_index->page_data + (page_index->page_len * - CTL_PAGE_CURRENT)); - saved_cp = (struct scsi_control_page *) - (page_index->page_data + (page_index->page_len * - CTL_PAGE_SAVED)); + current_cp = (page_index->page_data + (page_index->page_len * + CTL_PAGE_CURRENT)); + saved_cp = (page_index->page_data + (page_index->page_len * + CTL_PAGE_SAVED)); mtx_lock(&lun->lun_lock); - if (((current_cp->rlec & SCP_DSENSE) == 0) - && ((user_cp->rlec & SCP_DSENSE) != 0)) { - /* - * Descriptor sense is currently turned off and the user - * wants to turn it on. - */ - current_cp->rlec |= SCP_DSENSE; - saved_cp->rlec |= SCP_DSENSE; - lun->flags |= CTL_LUN_SENSE_DESC; - set_ua = 1; - } else if (((current_cp->rlec & SCP_DSENSE) != 0) - && ((user_cp->rlec & SCP_DSENSE) == 0)) { - /* - * Descriptor sense is currently turned on, and the user - * wants to turn it off. - */ - current_cp->rlec &= ~SCP_DSENSE; - saved_cp->rlec &= ~SCP_DSENSE; - lun->flags &= ~CTL_LUN_SENSE_DESC; - set_ua = 1; - } - if ((current_cp->queue_flags & SCP_QUEUE_ALG_MASK) != - (user_cp->queue_flags & SCP_QUEUE_ALG_MASK)) { - current_cp->queue_flags &= ~SCP_QUEUE_ALG_MASK; - current_cp->queue_flags |= user_cp->queue_flags & SCP_QUEUE_ALG_MASK; - saved_cp->queue_flags &= ~SCP_QUEUE_ALG_MASK; - saved_cp->queue_flags |= user_cp->queue_flags & SCP_QUEUE_ALG_MASK; - set_ua = 1; - } - if ((current_cp->eca_and_aen & SCP_SWP) != - (user_cp->eca_and_aen & SCP_SWP)) { - current_cp->eca_and_aen &= ~SCP_SWP; - current_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP; - saved_cp->eca_and_aen &= ~SCP_SWP; - saved_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP; + if (memcmp(current_cp, page_ptr, page_index->page_len)) { + memcpy(current_cp, page_ptr, page_index->page_len); + memcpy(saved_cp, page_ptr, page_index->page_len); set_ua = 1; } if (set_ua != 0) @@ -5903,101 +5853,78 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio, ctl_get_initindex(&ctsio->io_hdr.nexus), page_index->page_code, page_index->subpage); } - return (0); + return (CTL_RETVAL_COMPLETE); } -int -ctl_caching_sp_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, uint8_t *page_ptr) +static void +ctl_ie_timer(void *arg) { - struct scsi_caching_page *current_cp, *saved_cp, *user_cp; - struct ctl_lun *lun; - int set_ua; - uint32_t initidx; + struct ctl_lun *lun = arg; + struct scsi_info_exceptions_page *pg; + uint64_t t; - lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; - initidx = ctl_get_initindex(&ctsio->io_hdr.nexus); - set_ua = 0; + if (lun->ie_asc == 0) + return; - user_cp = (struct scsi_caching_page *)page_ptr; - current_cp = (struct scsi_caching_page *) - (page_index->page_data + (page_index->page_len * - CTL_PAGE_CURRENT)); - saved_cp = (struct scsi_caching_page *) - (page_index->page_data + (page_index->page_len * - CTL_PAGE_SAVED)); + pg = &lun->mode_pages.ie_page[CTL_PAGE_CURRENT]; + if (pg->mrie == SIEP_MRIE_UA) + ctl_est_ua_all(lun, -1, CTL_UA_IE); + else + lun->ie_reported = 0; - mtx_lock(&lun->lun_lock); - if ((current_cp->flags1 & (SCP_WCE | SCP_RCD)) != - (user_cp->flags1 & (SCP_WCE | SCP_RCD))) { - current_cp->flags1 &= ~(SCP_WCE | SCP_RCD); - current_cp->flags1 |= user_cp->flags1 & (SCP_WCE | SCP_RCD); - saved_cp->flags1 &= ~(SCP_WCE | SCP_RCD); - saved_cp->flags1 |= user_cp->flags1 & (SCP_WCE | SCP_RCD); - set_ua = 1; + if (lun->ie_reportcnt < scsi_4btoul(pg->report_count)) { + lun->ie_reportcnt++; + t = scsi_4btoul(pg->interval_timer); + if (t == 0 || t == UINT32_MAX) + t = 3000; /* 5 min */ + callout_schedule(&lun->ie_callout, t * hz / 10); } - if (set_ua != 0) - ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE); - mtx_unlock(&lun->lun_lock); - if (set_ua) { - ctl_isc_announce_mode(lun, - ctl_get_initindex(&ctsio->io_hdr.nexus), - page_index->page_code, page_index->subpage); - } - return (0); } int -ctl_debugconf_sp_select_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, - uint8_t *page_ptr) -{ - uint8_t *c; - int i; - - c = ((struct copan_debugconf_subpage *)page_ptr)->ctl_time_io_secs; - ctl_time_io_secs = - (c[0] << 8) | - (c[1] << 0) | - 0; - CTL_DEBUG_PRINT(("set ctl_time_io_secs to %d\n", ctl_time_io_secs)); - printf("set ctl_time_io_secs to %d\n", ctl_time_io_secs); - printf("page data:"); - for (i=0; i<8; i++) - printf(" %.2x",page_ptr[i]); - printf("\n"); - return (0); -} - -int -ctl_debugconf_sp_sense_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, - int pc) +ctl_ie_page_handler(struct ctl_scsiio *ctsio, + struct ctl_page_index *page_index, uint8_t *page_ptr) { - struct copan_debugconf_subpage *page; + struct scsi_info_exceptions_page *pg; + struct ctl_lun *lun; + uint64_t t; - page = (struct copan_debugconf_subpage *)page_index->page_data + - (page_index->page_len * pc); + (void)ctl_default_page_handler(ctsio, page_index, page_ptr); - switch (pc) { - case SMS_PAGE_CTRL_CHANGEABLE >> 6: - case SMS_PAGE_CTRL_DEFAULT >> 6: - case SMS_PAGE_CTRL_SAVED >> 6: - /* - * We don't update the changeable or default bits for this page. - */ - break; - case SMS_PAGE_CTRL_CURRENT >> 6: - page->ctl_time_io_secs[0] = ctl_time_io_secs >> 8; - page->ctl_time_io_secs[1] = ctl_time_io_secs >> 0; - break; - default: - break; + lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; + pg = (struct scsi_info_exceptions_page *)page_ptr; + mtx_lock(&lun->lun_lock); + if (pg->info_flags & SIEP_FLAGS_TEST) { + lun->ie_asc = 0x5d; + lun->ie_ascq = 0xff; + if (pg->mrie == SIEP_MRIE_UA) { + ctl_est_ua_all(lun, -1, CTL_UA_IE); + lun->ie_reported = 1; + } else { + ctl_clr_ua_all(lun, -1, CTL_UA_IE); + lun->ie_reported = -1; + } + lun->ie_reportcnt = 1; + if (lun->ie_reportcnt < scsi_4btoul(pg->report_count)) { + lun->ie_reportcnt++; + t = scsi_4btoul(pg->interval_timer); + if (t == 0 || t == UINT32_MAX) + t = 3000; /* 5 min */ + callout_reset(&lun->ie_callout, t * hz / 10, + ctl_ie_timer, lun); + } + } else { + lun->ie_asc = 0; + lun->ie_ascq = 0; + lun->ie_reported = 1; + ctl_clr_ua_all(lun, -1, CTL_UA_IE); + lun->ie_reportcnt = UINT32_MAX; + callout_stop(&lun->ie_callout); } - return (0); + mtx_unlock(&lun->lun_lock); + return (CTL_RETVAL_COMPLETE); } - static int ctl_do_mode_select(union ctl_io *io) { @@ -6815,8 +6742,27 @@ ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio, sizeof(struct scsi_log_param_header); scsi_ulto4b(3, data->ti.exponent); scsi_ulto4b(1, data->ti.integer); + return (0); +} + +int +ctl_ie_log_sense_handler(struct ctl_scsiio *ctsio, + struct ctl_page_index *page_index, + int pc) +{ + struct ctl_lun *lun; + struct scsi_log_informational_exceptions *data; - page_index->page_len = sizeof(*data); + lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; + data = (struct scsi_log_informational_exceptions *)page_index->page_data; + + scsi_ulto2b(SLP_IE_GEN, data->hdr.param_code); + data->hdr.param_control = SLP_LBIN; + data->hdr.param_len = sizeof(struct scsi_log_informational_exceptions) - + sizeof(struct scsi_log_param_header); + data->ie_asc = lun->ie_asc; + data->ie_ascq = lun->ie_ascq; + data->temperature = 0xff; return (0); } @@ -9256,6 +9202,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio) int have_error; scsi_sense_data_type sense_format; ctl_ua_type ua_type; + uint8_t asc = 0, ascq = 0; cdb = (struct scsi_request_sense *)ctsio->cdb; @@ -9374,19 +9321,23 @@ ctl_request_sense(struct ctl_scsiio *ctsio) return (CTL_RETVAL_COMPLETE); } -no_sense: - /* * No sense information to report, so we report that everything is - * okay. + * okay, unless we have allowed Informational Exception. */ + if (lun->mode_pages.ie_page[CTL_PAGE_CURRENT].mrie != SIEP_MRIE_NO) { + asc = lun->ie_asc; + ascq = lun->ie_ascq; + } + +no_sense: ctl_set_sense_data(sense_ptr, lun, sense_format, /*current_error*/ 1, /*sense_key*/ SSD_KEY_NO_SENSE, - /*asc*/ 0x00, - /*ascq*/ 0x00, + /*asc*/ asc, + /*ascq*/ ascq, SSD_ELEM_NONE); /* @@ -13256,6 +13207,37 @@ ctl_process_done(union ctl_io *io) mtx_lock(&lun->lun_lock); /* + * Check to see if we have any informational exception and status + * of this command can be modified to report it in form of either + * RECOVERED ERROR or NO SENSE, depending on MRIE mode page field. + */ + if (lun->ie_reported == 0 && lun->ie_asc != 0 && + io->io_hdr.status == CTL_SUCCESS && + (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) == 0) { + uint8_t mrie = lun->mode_pages.ie_page[CTL_PAGE_CURRENT].mrie; + uint8_t per = + ((lun->mode_pages.rw_er_page[CTL_PAGE_CURRENT].byte3 & + SMS_RWER_PER) || + (lun->mode_pages.verify_er_page[CTL_PAGE_CURRENT].byte3 & + SMS_VER_PER)); + if (((mrie == SIEP_MRIE_REC_COND && per) || + mrie == SIEP_MRIE_REC_UNCOND || + mrie == SIEP_MRIE_NO_SENSE) && + (ctl_get_cmd_entry(&io->scsiio, NULL)->flags & + CTL_CMD_FLAG_NO_SENSE) == 0) { + ctl_set_sense(&io->scsiio, + /*current_error*/ 1, + /*sense_key*/ (mrie == SIEP_MRIE_NO_SENSE) ? + SSD_KEY_NO_SENSE : SSD_KEY_RECOVERED_ERROR, + /*asc*/ lun->ie_asc, + /*ascq*/ lun->ie_ascq, + SSD_ELEM_NONE); + lun->ie_reported = 1; + } + } else if (lun->ie_reported < 0) + lun->ie_reported = 0; + + /* * Check to see if we have any errors to inject here. We only * inject errors for commands that don't already have errors set. */ @@ -13528,10 +13510,6 @@ ctl_done(union ctl_io *io) #ifdef CTL_IO_DELAY if (io->io_hdr.flags & CTL_FLAG_DELAY_DONE) { - struct ctl_lun *lun; - - lun =(struct ctl_lun *)io->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; - io->io_hdr.flags &= ~CTL_FLAG_DELAY_DONE; } else { struct ctl_lun *lun; diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h index 3c47a6f..7b4d06c 100644 --- a/sys/cam/ctl/ctl.h +++ b/sys/cam/ctl/ctl.h @@ -127,7 +127,8 @@ typedef enum { CTL_UA_ASYM_ACC_CHANGE = 0x2000, CTL_UA_CAPACITY_CHANGE = 0x4000, CTL_UA_THIN_PROV_THRES = 0x8000, - CTL_UA_MEDIUM_CHANGE = 0x10000 + CTL_UA_MEDIUM_CHANGE = 0x10000, + CTL_UA_IE = 0x20000 } ctl_ua_type; #ifdef _KERNEL @@ -154,23 +155,21 @@ int ctl_ffz(uint32_t *mask, uint32_t first, uint32_t last); int ctl_set_mask(uint32_t *mask, uint32_t bit); int ctl_clear_mask(uint32_t *mask, uint32_t bit); int ctl_is_set(uint32_t *mask, uint32_t bit); -int ctl_caching_sp_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, uint8_t *page_ptr); -int ctl_control_page_handler(struct ctl_scsiio *ctsio, +int ctl_default_page_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, uint8_t *page_ptr); -int ctl_debugconf_sp_sense_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, - int pc); -int ctl_debugconf_sp_select_handler(struct ctl_scsiio *ctsio, - struct ctl_page_index *page_index, - uint8_t *page_ptr); +int ctl_ie_page_handler(struct ctl_scsiio *ctsio, + struct ctl_page_index *page_index, + uint8_t *page_ptr); int ctl_lbp_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc); int ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc); +int ctl_ie_log_sense_handler(struct ctl_scsiio *ctsio, + struct ctl_page_index *page_index, + int pc); int ctl_config_move_done(union ctl_io *io); void ctl_datamove(union ctl_io *io); void ctl_serseq_done(union ctl_io *io); diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c index 61ec4ec..014499f 100644 --- a/sys/cam/ctl/ctl_error.c +++ b/sys/cam/ctl/ctl_error.c @@ -84,7 +84,8 @@ ctl_set_sense_data_va(struct scsi_sense_data *sense_data, void *lunptr, * on for that LUN. */ if ((lun != NULL) - && (lun->flags & CTL_LUN_SENSE_DESC)) + && (lun->mode_pages.control_page[CTL_PAGE_CURRENT].rlec & + SCP_DSENSE)) sense_format = SSD_TYPE_DESC; else sense_format = SSD_TYPE_FIXED; @@ -461,6 +462,11 @@ ctl_ua_to_acsq(struct ctl_lun *lun, ctl_ua_type ua_to_build, int *asc, *asc = 0x28; *ascq = 0x00; break; + case CTL_UA_IE: + /* Informational exception */ + *asc = lun->ie_asc; + *ascq = lun->ie_ascq; + break; default: panic("%s: Unknown UA %x", __func__, ua_to_build); } diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 959d79e..483feda 100644 --- a/sys/cam/ctl/ctl_private.h +++ b/sys/cam/ctl/ctl_private.h @@ -151,7 +151,6 @@ typedef enum { CTL_LUN_EJECTED = 0x080, CTL_LUN_PR_RESERVED = 0x100, CTL_LUN_PRIMARY_SC = 0x200, - CTL_LUN_SENSE_DESC = 0x400, CTL_LUN_READONLY = 0x800, CTL_LUN_PEER_SC_PRIMARY = 0x1000, CTL_LUN_REMOVABLE = 0x2000 @@ -272,30 +271,29 @@ struct ctl_logical_block_provisioning_page { static const struct ctl_page_index page_index_template[] = { {SMS_RW_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_rw_recovery_page), NULL, - CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, NULL}, + CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, ctl_default_page_handler}, {SMS_FORMAT_DEVICE_PAGE, 0, sizeof(struct scsi_format_page), NULL, CTL_PAGE_FLAG_DIRECT, NULL, NULL}, {SMS_RIGID_DISK_PAGE, 0, sizeof(struct scsi_rigid_disk_page), NULL, CTL_PAGE_FLAG_DIRECT, NULL, NULL}, + {SMS_VERIFY_ERROR_RECOVERY_PAGE, 0, sizeof(struct scsi_da_verify_recovery_page), NULL, + CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, NULL, ctl_default_page_handler}, {SMS_CACHING_PAGE, 0, sizeof(struct scsi_caching_page), NULL, CTL_PAGE_FLAG_DIRECT | CTL_PAGE_FLAG_CDROM, - NULL, ctl_caching_sp_handler}, + NULL, ctl_default_page_handler}, {SMS_CONTROL_MODE_PAGE, 0, sizeof(struct scsi_control_page), NULL, - CTL_PAGE_FLAG_ALL, NULL, ctl_control_page_handler}, + CTL_PAGE_FLAG_ALL, NULL, ctl_default_page_handler}, {SMS_CONTROL_MODE_PAGE | SMPH_SPF, 0x01, sizeof(struct scsi_control_ext_page), NULL, CTL_PAGE_FLAG_ALL, NULL, NULL}, {SMS_INFO_EXCEPTIONS_PAGE, 0, sizeof(struct scsi_info_exceptions_page), NULL, - CTL_PAGE_FLAG_ALL, NULL, NULL}, + CTL_PAGE_FLAG_ALL, NULL, ctl_ie_page_handler}, {SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF, 0x02, sizeof(struct ctl_logical_block_provisioning_page), NULL, CTL_PAGE_FLAG_DIRECT, NULL, NULL}, {SMS_CDDVD_CAPS_PAGE, 0, sizeof(struct scsi_cddvd_capabilities_page), NULL, CTL_PAGE_FLAG_CDROM, NULL, NULL}, - {SMS_VENDOR_SPECIFIC_PAGE | SMPH_SPF, DBGCNF_SUBPAGE_CODE, - sizeof(struct copan_debugconf_subpage), NULL, CTL_PAGE_FLAG_ALL, - ctl_debugconf_sp_sense_handler, ctl_debugconf_sp_select_handler}, }; #define CTL_NUM_MODE_PAGES sizeof(page_index_template)/ \ @@ -305,13 +303,13 @@ struct ctl_mode_pages { struct scsi_da_rw_recovery_page rw_er_page[4]; struct scsi_format_page format_page[4]; struct scsi_rigid_disk_page rigid_disk_page[4]; + struct scsi_da_verify_recovery_page verify_er_page[4]; struct scsi_caching_page caching_page[4]; struct scsi_control_page control_page[4]; struct scsi_control_ext_page control_ext_page[4]; struct scsi_info_exceptions_page ie_page[4]; struct ctl_logical_block_provisioning_page lbp_page[4]; struct scsi_cddvd_capabilities_page cddvd_page[4]; - struct copan_debugconf_subpage debugconf_subpage[4]; struct ctl_page_index index[CTL_NUM_MODE_PAGES]; }; @@ -324,6 +322,8 @@ static const struct ctl_page_index log_page_index_template[] = { CTL_PAGE_FLAG_DIRECT, ctl_lbp_log_sense_handler, NULL}, {SLS_STAT_AND_PERF, 0, 0, NULL, CTL_PAGE_FLAG_ALL, ctl_sap_log_sense_handler, NULL}, + {SLS_IE_PAGE, 0, 0, NULL, + CTL_PAGE_FLAG_ALL, ctl_ie_log_sense_handler, NULL}, }; #define CTL_NUM_LOG_PAGES sizeof(log_page_index_template)/ \ @@ -338,6 +338,7 @@ struct ctl_log_pages { struct scsi_log_idle_time it; struct scsi_log_time_interval ti; } stat_page; + struct scsi_log_informational_exceptions ie_page; struct ctl_page_index index[CTL_NUM_LOG_PAGES]; }; @@ -385,6 +386,11 @@ struct ctl_lun { ctl_ua_type *pending_ua[CTL_MAX_PORTS]; uint8_t ua_tpt_info[8]; time_t lasttpt; + uint8_t ie_asc; /* Informational exceptions */ + uint8_t ie_ascq; + int ie_reported; /* Already reported */ + uint32_t ie_reportcnt; /* REPORT COUNT */ + struct callout ie_callout; /* INTERVAL TIMER */ struct ctl_mode_pages mode_pages; struct ctl_log_pages log_pages; struct ctl_lun_io_stats stats; diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index fc54a6f..7dc70e9 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -662,6 +662,14 @@ struct scsi_log_fua_stat_and_perf { uint8_t fuanv_write_int[8]; }; +struct scsi_log_informational_exceptions { + struct scsi_log_param_header hdr; +#define SLP_IE_GEN 0x0000 + uint8_t ie_asc; + uint8_t ie_ascq; + uint8_t temperature; +}; + struct scsi_control_page { u_int8_t page_code; u_int8_t page_length; @@ -763,21 +771,6 @@ struct scsi_caching_page { uint8_t non_cache_seg_size[3]; }; -/* - * XXX KDM move this off to a vendor shim. - */ -struct copan_debugconf_subpage { - uint8_t page_code; -#define DBGCNF_PAGE_CODE 0x00 - uint8_t subpage; -#define DBGCNF_SUBPAGE_CODE 0xF0 - uint8_t page_length[2]; - uint8_t page_version; -#define DBGCNF_VERSION 0x00 - uint8_t ctl_time_io_secs[2]; -}; - - struct scsi_info_exceptions_page { u_int8_t page_code; #define SIEP_PAGE_SAVABLE 0x80 /* Page is savable */ @@ -791,6 +784,12 @@ struct scsi_info_exceptions_page { #define SIEP_FLAGS_EBACKERR 0x02 #define SIEP_FLAGS_LOGERR 0x01 u_int8_t mrie; +#define SIEP_MRIE_NO 0x00 +#define SIEP_MRIE_UA 0x02 +#define SIEP_MRIE_REC_COND 0x03 +#define SIEP_MRIE_REC_UNCOND 0x04 +#define SIEP_MRIE_NO_SENSE 0x05 +#define SIEP_MRIE_ON_REQ 0x06 u_int8_t interval_timer[4]; u_int8_t report_count[4]; }; diff --git a/sys/cam/scsi/scsi_da.h b/sys/cam/scsi/scsi_da.h index ad4d0db..1af4db4 100644 --- a/sys/cam/scsi/scsi_da.h +++ b/sys/cam/scsi/scsi_da.h @@ -554,6 +554,20 @@ struct scsi_da_rw_recovery_page { u_int8_t recovery_time_limit[2]; }; +struct scsi_da_verify_recovery_page { + u_int8_t page_code; +#define SMS_VERIFY_ERROR_RECOVERY_PAGE 0x07 + u_int8_t page_length; + u_int8_t byte3; +#define SMS_VER_EER 0x08 +#define SMS_VER_PER 0x04 +#define SMS_VER_DTE 0x02 +#define SMS_VER_DCR 0x01 + u_int8_t read_retry_count; + u_int8_t reserved[6]; + u_int8_t recovery_time_limit[2]; +}; + __BEGIN_DECLS /* * XXX These are only left out of the kernel build to silence warnings. If, |