diff options
| author | Matt Jacob <mjacob@FreeBSD.org> | 2000-01-25 17:42:27 +0000 |
|---|---|---|
| committer | Matt Jacob <mjacob@FreeBSD.org> | 2000-01-25 17:42:27 +0000 |
| commit | 937097d9cce60fa7a0b7f85407d2b7996b641012 (patch) | |
| tree | 3597508b02b6bc8dc319c110b474010ad0853ab0 | |
| parent | 471da22662c7655b327f3b0badae31b8e771629a (diff) | |
Notes
| -rw-r--r-- | sys/cam/scsi/scsi_target.c | 139 |
1 files changed, 88 insertions, 51 deletions
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c index 85e45dde80ae..c1c771d2c13b 100644 --- a/sys/cam/scsi/scsi_target.c +++ b/sys/cam/scsi/scsi_target.c @@ -78,7 +78,7 @@ typedef enum { #define MAX_ACCEPT 16 #define MAX_IMMEDIATE 16 #define MAX_BUF_SIZE 256 /* Max inquiry/sense/mode page transfer */ -#define MAX_INITIATORS 16 /* XXX More for Fibre-Channel */ +#define MAX_INITIATORS 256 /* includes widest fibre channel for now */ #define MIN(a, b) ((a > b) ? b : a) @@ -213,11 +213,12 @@ static void fill_sense(struct targ_softc *softc, u_int initiator_id, u_int error_code, u_int sense_key, u_int asc, u_int ascq); static void copy_sense(struct targ_softc *softc, - struct ccb_scsiio *csio); + struct initiator_state *istate, + u_int8_t *sense_buffer, size_t sense_len); static void set_unit_attention_cond(struct cam_periph *periph, u_int initiator_id, ua_types ua); -static void set_contingent_allegiance_cond(struct cam_periph *periph, - u_int initiator_id, ca_types ca); +static void set_ca_condition(struct cam_periph *periph, + u_int initiator_id, ca_types ca); static void abort_pending_transactions(struct cam_periph *periph, u_int initiator_id, u_int tag_id, int errno, int to_held_queue); @@ -1260,6 +1261,8 @@ targrunqueue(struct cam_periph *periph, struct targ_softc *softc) desc->data = &bp->b_data[bp->b_bcount - bp->b_resid]; desc->data_increment = MIN(desc->data_resid, bp->b_resid); + desc->data_increment = + MIN(desc->data_increment, 32); } CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Buffer command: data %x: datacnt %d\n", @@ -1329,6 +1332,22 @@ targstart(struct cam_periph *periph, union ccb *start_ccb) /*dxfer_len*/desc->data_increment, /*timeout*/desc->timeout); + if ((flags & CAM_SEND_STATUS) != 0 + && (desc->status == SCSI_STATUS_CHECK_COND + || desc->status == SCSI_STATUS_CMD_TERMINATED)) { + struct initiator_state *istate; + + istate = &softc->istate[atio->init_id]; + csio->sense_len = istate->sense_data.extra_len + + offsetof(struct scsi_sense_data, + extra_len); + bcopy(&istate->sense_data, &csio->sense_data, + csio->sense_len); + csio->ccb_h.flags |= CAM_SEND_SENSE; + } else { + csio->sense_len = 0; + } + start_ccb->ccb_h.ccb_flags = TARG_CCB_NONE; start_ccb->ccb_h.ccb_atio = atio; CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, @@ -1376,19 +1395,38 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) return; } - if (istate->pending_ca == 0 - && istate->pending_ua != 0 - && cdb[0] != INQUIRY) { + if (atio->sense_len != 0) { + + /* + * We had an error in the reception of + * this command. Immediately issue a CA. + */ + atio->ccb_h.flags &= ~CAM_DIR_MASK; + atio->ccb_h.flags |= CAM_DIR_NONE; + descr->data_resid = 0; + descr->data_increment = 0; + descr->status = SCSI_STATUS_CHECK_COND; + copy_sense(softc, istate, (u_int8_t *)&atio->sense_data, + atio->sense_len); + set_ca_condition(periph, atio->init_id, CA_CMD_SENSE); + } else if (istate->pending_ca == 0 + && istate->pending_ua != 0 + && cdb[0] != INQUIRY) { + /* Pending UA, tell initiator */ /* Direction is always relative to the initator */ - istate->pending_ca = CA_UNIT_ATTN; atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; descr->data_resid = 0; descr->data_increment = 0; descr->timeout = 5 * 1000; descr->status = SCSI_STATUS_CHECK_COND; - } else { + fill_sense(softc, atio->init_id, + SSD_CURRENT_ERROR, SSD_KEY_UNIT_ATTENTION, + 0x29, + istate->pending_ua == UA_POWER_ON ? 1 : 2); + set_ca_condition(periph, atio->init_id, CA_UNIT_ATTN); + } else { /* * Save the current CA and UA status so * they can be used by this command. @@ -1401,16 +1439,13 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) /* * As per the SCSI2 spec, any command that occurs - * after a CA is reported, clears the CA. If the - * command is not an inquiry, we are also supposed - * to clear the UA condition, if any, that caused - * the CA to occur assuming the UA is not a - * persistant state. + * after a CA is reported, clears the CA. We must + * also clear the UA condition, if any, that caused + * the CA to occur assuming the UA is not for a + * persistant condition. */ istate->pending_ca = CA_NONE; - if ((pending_ca - & (CA_CMD_SENSE|CA_UNIT_ATTN)) == CA_UNIT_ATTN - && cdb[0] != INQUIRY) + if (pending_ca == CA_UNIT_ATTN) istate->pending_ua = UA_NONE; /* @@ -1434,7 +1469,6 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) */ if ((inq->byte2 & SI_EVPD) != 0 || inq->page_code != 0) { - istate->pending_ca = CA_CMD_SENSE; atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; descr->data_resid = 0; @@ -1449,6 +1483,8 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) extra_bytes) - offsetof(struct scsi_sense_data, extra_len); + set_ca_condition(periph, atio->init_id, + CA_CMD_SENSE); } if ((inq->byte2 & SI_EVPD) != 0) { @@ -1459,7 +1495,6 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) sense->sense_key_spec[2] = offsetof(struct scsi_inquiry, byte2); - break; } else if (inq->page_code != 0) { sense->sense_key_spec[0] = SSD_SCS_VALID|SSD_FIELDPTR_CMD; @@ -1467,8 +1502,10 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) sense->sense_key_spec[2] = offsetof(struct scsi_inquiry, page_code); - break; } + if (descr->status == SCSI_STATUS_CHECK_COND) + break; + /* * Direction is always relative * to the initator. @@ -1506,20 +1543,6 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("No pending CA!\n")); - } else if (pending_ca == CA_UNIT_ATTN) { - u_int ascq; - - if (pending_ua == UA_POWER_ON) - ascq = 0x1; - else - ascq = 0x2; - fill_sense(softc, atio->init_id, - SSD_CURRENT_ERROR, - SSD_KEY_UNIT_ATTENTION, - 0x29, ascq); - CAM_DEBUG(periph->path, - CAM_DEBUG_PERIPH, - ("Pending UA!\n")); } /* * Direction is always relative @@ -1638,6 +1661,23 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) } } else error = 0; + + /* + * If we shipped back sense data when completing + * this command, clear the pending CA for it. + */ + if (done_ccb->ccb_h.status & CAM_SENT_SENSE) { + struct initiator_state *istate; + + istate = &softc->istate[csio->init_id]; + if (istate->pending_ca == CA_UNIT_ATTN) + istate->pending_ua = UA_NONE; + istate->pending_ca = CA_NONE; + softc->istate[csio->init_id].pending_ca = CA_NONE; + done_ccb->ccb_h.status &= ~CAM_SENT_SENSE; + } + done_ccb->ccb_h.flags &= ~CAM_SEND_SENSE; + desc->data_increment -= csio->resid; desc->data_resid -= desc->data_increment; if ((bp = desc->bp) != NULL) { @@ -1846,6 +1886,7 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) struct cam_periph *periph; struct targ_softc *softc; struct ccb_scsiio *csio; + struct initiator_state *istate; cam_status status; int frozen; int sense; @@ -1860,18 +1901,17 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) status &= CAM_STATUS_MASK; on_held_queue = FALSE; csio = &ccb->csio; + istate = &softc->istate[csio->init_id]; switch (status) { case CAM_REQ_ABORTED: printf("Request Aborted!\n"); if ((ccb->ccb_h.ccb_flags & TARG_CCB_ABORT_TO_HELDQ) != 0) { - struct initiator_state *istate; /* * Place this CCB into the initiators * 'held' queue until the pending CA is cleared. * If there is no CA pending, reissue immediately. */ - istate = &softc->istate[ccb->csio.init_id]; if (istate->pending_ca == 0) { ccb->ccb_h.ccb_flags = TARG_CCB_NONE; xpt_action(ccb); @@ -1904,9 +1944,7 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) csio->resid = csio->dxfer_len; fill_sense(softc, csio->init_id, SSD_CURRENT_ERROR, SSD_KEY_HARDWARE_ERROR, 0x45, 0x00); - set_contingent_allegiance_cond(periph, - csio->init_id, - CA_CMD_SENSE); + set_ca_condition(periph, csio->init_id, CA_CMD_SENSE); error = EIO; } break; @@ -1914,7 +1952,7 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) /* "SCSI parity error" */ fill_sense(softc, csio->init_id, SSD_CURRENT_ERROR, SSD_KEY_HARDWARE_ERROR, 0x47, 0x00); - set_contingent_allegiance_cond(periph, csio->init_id, + set_ca_condition(periph, csio->init_id, CA_CMD_SENSE); csio->resid = csio->dxfer_len; error = EIO; @@ -1925,8 +1963,9 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) break; case CAM_SEQUENCE_FAIL: if (sense != 0) { - copy_sense(softc, csio); - set_contingent_allegiance_cond(periph, + copy_sense(softc, istate, (u_int8_t *)&csio->sense_data, + csio->sense_len); + set_ca_condition(periph, csio->init_id, CA_CMD_SENSE); } @@ -1937,7 +1976,7 @@ targerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags) /* "Initiator detected error message received" */ fill_sense(softc, csio->init_id, SSD_CURRENT_ERROR, SSD_KEY_HARDWARE_ERROR, 0x48, 0x00); - set_contingent_allegiance_cond(periph, csio->init_id, + set_ca_condition(periph, csio->init_id, CA_CMD_SENSE); csio->resid = csio->dxfer_len; error = EIO; @@ -2021,18 +2060,17 @@ fill_sense(struct targ_softc *softc, u_int initiator_id, u_int error_code, } static void -copy_sense(struct targ_softc *softc, struct ccb_scsiio *csio) +copy_sense(struct targ_softc *softc, struct initiator_state *istate, + u_int8_t *sense_buffer, size_t sense_len) { - struct initiator_state *istate; struct scsi_sense_data *sense; size_t copylen; - istate = &softc->istate[csio->init_id]; sense = &istate->sense_data; copylen = sizeof(*sense); - if (copylen > csio->sense_len) - copylen = csio->sense_len; - bcopy(&csio->sense_data, sense, copylen); + if (copylen > sense_len) + copylen = sense_len; + bcopy(sense_buffer, sense, copylen); } static void @@ -2057,8 +2095,7 @@ set_unit_attention_cond(struct cam_periph *periph, } static void -set_contingent_allegiance_cond(struct cam_periph *periph, - u_int initiator_id, ca_types ca) +set_ca_condition(struct cam_periph *periph, u_int initiator_id, ca_types ca) { struct targ_softc *softc; |
