diff options
author | mjacob <mjacob@FreeBSD.org> | 2001-04-04 21:58:29 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2001-04-04 21:58:29 +0000 |
commit | 44f132def73a73ef49478fd52284a38cb165cb63 (patch) | |
tree | 736418d2df17e3605b14a867e24209bf4ea4f91b /sys/dev/isp | |
parent | 7892febf2403585828382065ad189cfa31c4b46e (diff) | |
download | FreeBSD-src-44f132def73a73ef49478fd52284a38cb165cb63.zip FreeBSD-src-44f132def73a73ef49478fd52284a38cb165cb63.tar.gz |
Redo a lot of the target mode infrastructure to be cognizant of Dual Bus
cards like the 1280 && the 12160. Cleanup isp_target_putback_atio.
Make sure bus and correct tag ids and firmware handles get propagated
as needed.
Diffstat (limited to 'sys/dev/isp')
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 403 |
1 files changed, 215 insertions, 188 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 6ac2a8f..2a11c54 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -28,6 +28,7 @@ #include <dev/isp/isp_freebsd.h> #include <machine/stdarg.h> /* for use by isp_prt below */ + static void isp_intr_enable(void *); static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *); static void isp_poll(struct cam_sim *); @@ -172,39 +173,39 @@ isp_intr_enable(void *arg) #ifdef ISP_TARGET_MODE -static __inline int is_lun_enabled(struct ispsoftc *, lun_id_t); -static __inline int are_any_luns_enabled(struct ispsoftc *); -static __inline tstate_t *get_lun_statep(struct ispsoftc *, lun_id_t); +static __inline int is_lun_enabled(struct ispsoftc *, int, lun_id_t); +static __inline int are_any_luns_enabled(struct ispsoftc *, int); +static __inline tstate_t *get_lun_statep(struct ispsoftc *, int, lun_id_t); static __inline void rls_lun_statep(struct ispsoftc *, tstate_t *); static __inline int isp_psema_sig_rqe(struct ispsoftc *); static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *, int); static __inline void isp_cv_signal_rqe(struct ispsoftc *, int); static __inline void isp_vsema_rqe(struct ispsoftc *); static cam_status -create_lun_state(struct ispsoftc *, struct cam_path *, tstate_t **); +create_lun_state(struct ispsoftc *, int, struct cam_path *, tstate_t **); static void destroy_lun_state(struct ispsoftc *, tstate_t *); static void isp_en_lun(struct ispsoftc *, union ccb *); static cam_status isp_abort_tgt_ccb(struct ispsoftc *, union ccb *); -static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *); -static cam_status isp_target_putback_atio(struct ispsoftc *, union ccb *); static timeout_t isp_refire_putback_atio; - +static void isp_complete_ctio(union ccb *); +static void isp_target_putback_atio(union ccb *); +static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *); static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *); static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *); static int isp_handle_platform_ctio(struct ispsoftc *, void *); -static void isp_handle_platform_ctio_part2(struct ispsoftc *, union ccb *); static __inline int -is_lun_enabled(struct ispsoftc *isp, lun_id_t lun) +is_lun_enabled(struct ispsoftc *isp, int bus, lun_id_t lun) { tstate_t *tptr; ISP_LOCK(isp); - if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) { + tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)]; + if (tptr == NULL) { ISP_UNLOCK(isp); return (0); } do { - if (tptr->lun == (lun_id_t) lun) { + if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) { ISP_UNLOCK(isp); return (1); } @@ -214,11 +215,18 @@ is_lun_enabled(struct ispsoftc *isp, lun_id_t lun) } static __inline int -are_any_luns_enabled(struct ispsoftc *isp) +are_any_luns_enabled(struct ispsoftc *isp, int port) { - int i; - for (i = 0; i < LUN_HASH_SIZE; i++) { - if (isp->isp_osinfo.lun_hash[i]) { + int lo, hi; + if (IS_DUALBUS(isp)) { + lo = (port * (LUN_HASH_SIZE >> 1)); + hi = lo + (LUN_HASH_SIZE >> 1); + } else { + lo = 0; + hi = LUN_HASH_SIZE; + } + for (lo = 0; lo < hi; lo++) { + if (isp->isp_osinfo.lun_hash[lo]) { return (1); } } @@ -226,18 +234,18 @@ are_any_luns_enabled(struct ispsoftc *isp) } static __inline tstate_t * -get_lun_statep(struct ispsoftc *isp, lun_id_t lun) +get_lun_statep(struct ispsoftc *isp, int bus, lun_id_t lun) { tstate_t *tptr; ISP_LOCK(isp); if (lun == CAM_LUN_WILDCARD) { - tptr = &isp->isp_osinfo.tsdflt; + tptr = &isp->isp_osinfo.tsdflt[bus]; tptr->hold++; ISP_UNLOCK(isp); return (tptr); } else { - tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]; + tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)]; } if (tptr == NULL) { ISP_UNLOCK(isp); @@ -245,7 +253,7 @@ get_lun_statep(struct ispsoftc *isp, lun_id_t lun) } do { - if (tptr->lun == lun) { + if (tptr->lun == lun && tptr->bus == bus) { tptr->hold++; ISP_UNLOCK(isp); return (tptr); @@ -310,17 +318,19 @@ isp_vsema_rqe(struct ispsoftc *isp) } static cam_status -create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt) +create_lun_state(struct ispsoftc *isp, int bus, + struct cam_path *path, tstate_t **rslt) { cam_status status; lun_id_t lun; + int hfx; tstate_t *tptr, *new; lun = xpt_path_lun_id(path); if (lun < 0) { return (CAM_LUN_INVALID); } - if (is_lun_enabled(isp, lun)) { + if (is_lun_enabled(isp, bus, lun)) { return (CAM_LUN_ALRDY_ENA); } new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO); @@ -334,14 +344,17 @@ create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt) free(new, M_DEVBUF); return (status); } + new->bus = bus; new->lun = lun; SLIST_INIT(&new->atios); SLIST_INIT(&new->inots); new->hold = 1; + hfx = LUN_HASH_FUNC(isp, new->bus, new->lun); ISP_LOCK(isp); - if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) { - isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)] = new; + tptr = isp->isp_osinfo.lun_hash[hfx]; + if (tptr == NULL) { + isp->isp_osinfo.lun_hash[hfx] = new; } else { while (tptr->next) tptr = tptr->next; @@ -355,24 +368,26 @@ create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt) static __inline void destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr) { + int hfx; tstate_t *lw, *pw; + hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun); ISP_LOCK(isp); if (tptr->hold) { ISP_UNLOCK(isp); return; } - pw = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)]; + pw = isp->isp_osinfo.lun_hash[hfx]; if (pw == NULL) { ISP_UNLOCK(isp); return; - } else if (pw->lun == tptr->lun) { - isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)] = pw->next; + } else if (pw->lun == tptr->lun && pw->bus == tptr->bus) { + isp->isp_osinfo.lun_hash[hfx] = pw->next; } else { lw = pw; pw = lw->next; while (pw) { - if (pw->lun == tptr->lun) { + if (pw->lun == tptr->lun && pw->bus == tptr->bus) { lw->next = pw->next; break; } @@ -391,7 +406,7 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr) static void isp_en_lun(struct ispsoftc *isp, union ccb *ccb) { - const char lfmt[] = "Lun now %sabled for target mode"; + const char lfmt[] = "Lun now %sabled for target mode on channel %d"; struct ccb_en_lun *cel = &ccb->cel; tstate_t *tptr; u_int16_t rstat; @@ -400,13 +415,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) target_id_t tgt; - bus = XS_CHANNEL(ccb); - if (bus != 0) { - isp_prt(isp, ISP_LOGERR, - "second channel target mode not supported"); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - return; - } + bus = XS_CHANNEL(ccb) & 0x1; tgt = ccb->ccb_h.target_id; lun = ccb->ccb_h.target_lun; @@ -420,8 +429,10 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) return; } if (IS_SCSI(isp)) { + sdparam *sdp = isp->isp_param; + sdp += bus; if (tgt != CAM_TARGET_WILDCARD && - tgt != SDPARAM(isp)->isp_initiator_id) { + tgt != sdp->isp_initiator_id) { ccb->ccb_h.status = CAM_TID_INVALID; return; } @@ -490,10 +501,10 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) * If so, we enable/disable target mode but don't do any lun enabling. */ if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) { - int av; - tptr = &isp->isp_osinfo.tsdflt; + int av = bus << 31; + tptr = &isp->isp_osinfo.tsdflt[bus]; if (cel->enable) { - if (isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) { + if (isp->isp_osinfo.tmflags & (1 << bus)) { ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; if (frozen) xpt_release_simq(isp->isp_sim, 1); @@ -511,7 +522,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) } SLIST_INIT(&tptr->atios); SLIST_INIT(&tptr->inots); - av = 1; + av |= ENABLE_TARGET_FLAG; ISP_LOCK(isp); av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); if (av) { @@ -522,22 +533,21 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) xpt_release_simq(isp->isp_sim, 1); return; } - isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED; + isp->isp_osinfo.tmflags |= (1 << bus); ISP_UNLOCK(isp); } else { - if ((isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) { + if ((isp->isp_osinfo.tmflags & (1 << bus)) == 0) { ccb->ccb_h.status = CAM_LUN_INVALID; if (frozen) xpt_release_simq(isp->isp_sim, 1); return; } - if (are_any_luns_enabled(isp)) { + if (are_any_luns_enabled(isp, bus)) { ccb->ccb_h.status = CAM_SCSI_BUSY; if (frozen) xpt_release_simq(isp->isp_sim, 1); return; } - av = 0; ISP_LOCK(isp); av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); if (av) { @@ -547,12 +557,13 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) xpt_release_simq(isp->isp_sim, 1); return; } - isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED; + isp->isp_osinfo.tmflags &= ~(1 << bus); ISP_UNLOCK(isp); ccb->ccb_h.status = CAM_REQ_CMP; } xpt_print_path(ccb->ccb_h.path); - isp_prt(isp, ISP_LOGINFO, lfmt, (cel->enable) ? "en" : "dis"); + isp_prt(isp, ISP_LOGINFO, "Target Mode %sabled on channel %d", + (cel->enable) ? "en" : "dis", bus); if (frozen) xpt_release_simq(isp->isp_sim, 1); return; @@ -568,12 +579,12 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) if (cel->enable) { ccb->ccb_h.status = - create_lun_state(isp, ccb->ccb_h.path, &tptr); + create_lun_state(isp, bus, ccb->ccb_h.path, &tptr); if (ccb->ccb_h.status != CAM_REQ_CMP) { return; } } else { - tptr = get_lun_statep(isp, lun); + tptr = get_lun_statep(isp, bus, lun); if (tptr == NULL) { ccb->ccb_h.status = CAM_LUN_INVALID; return; @@ -670,7 +681,8 @@ out: destroy_lun_state(isp, tptr); } else { xpt_print_path(ccb->ccb_h.path); - isp_prt(isp, ISP_LOGINFO, lfmt, (cel->enable) ? "en" : "dis"); + isp_prt(isp, ISP_LOGINFO, lfmt, + (cel->enable) ? "en" : "dis", bus); rls_lun_statep(isp, tptr); if (cel->enable == 0) { destroy_lun_state(isp, tptr); @@ -697,7 +709,7 @@ isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb) return (CAM_PATH_INVALID); } } - tptr = get_lun_statep(isp, accb->ccb_h.target_lun); + tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun); if (tptr == NULL) { return (CAM_PATH_INVALID); } @@ -778,10 +790,6 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) cto->ct_resid = atiop->ccb_h.spriv_field0; } - /* - * We always have to use the tag_id- it has the responder - * exchange id in it. - */ cto->ct_rxid = cso->tag_id; if (cso->dxfer_len == 0) { cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA; @@ -813,31 +821,26 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) ccb->ccb_h.flags &= ~CAM_SEND_SENSE; } if (cto->ct_flags & CT2_SENDSTATUS) { - isp_prt(isp, ISP_LOGTDEBUG2, + isp_prt(isp, ISP_LOGTDEBUG1, "CTIO2[%x] SCSI STATUS 0x%x datalength %u", cto->ct_rxid, cso->scsi_status, cto->ct_resid); } - cto->ct_timeout = 2; + if (cto->ct_flags & CT2_SENDSTATUS) + cto->ct_flags |= CT2_CCINCR; + cto->ct_timeout = 10; hp = &cto->ct_syshandle; } else { ct_entry_t *cto = qe; - /* - * We always have to use the tag_id- it has the handle - * for this command. - */ cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; cto->ct_header.rqs_entry_count = 1; cto->ct_iid = cso->init_id; + cto->ct_iid |= XS_CHANNEL(ccb) << 7; cto->ct_tgt = ccb->ccb_h.target_id; cto->ct_lun = ccb->ccb_h.target_lun; - cto->ct_fwhandle = cso->tag_id >> 8; - cto->ct_tag_val = cso->tag_id & 0xff; - if (cto->ct_tag_val && cso->tag_action) { - /* - * We don't specify a tag type for regular SCSI, - * just the tag value and set a flag. - */ + cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id); + if (AT_HAS_TAG(cso->tag_id)) { + cto->ct_tag_val = (u_int8_t) AT_GET_TAG(cso->tag_id); cto->ct_flags |= CT_TQAE; } if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { @@ -856,13 +859,16 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) cto->ct_resid = cso->resid; } if (cto->ct_flags & CT_SENDSTATUS) { - isp_prt(isp, ISP_LOGTDEBUG2, - "CTIO SCSI STATUS 0x%x resid %d", - cso->scsi_status, cso->resid); + isp_prt(isp, ISP_LOGTDEBUG1, + "CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x", + cto->ct_fwhandle, cso->scsi_status, cso->resid, + cso->tag_id); } - cto->ct_timeout = 2; + cto->ct_timeout = 10; hp = &cto->ct_syshandle; ccb->ccb_h.flags &= ~CAM_SEND_SENSE; + if (cto->ct_flags & CT_SENDSTATUS) + cto->ct_flags |= CT_CCINCR; } if (isp_save_xs(isp, (XS_T *)ccb, hp)) { @@ -882,6 +888,7 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) */ save_handle = *hp; + switch (ISP_DMASETUP(isp, cso, qe, &iptr, optr)) { case CMD_QUEUED: ISP_ADD_REQUEST(isp, iptr); @@ -898,63 +905,85 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb) } } -static cam_status -isp_target_putback_atio(struct ispsoftc *isp, union ccb *ccb) +static void +isp_refire_putback_atio(void *arg) { - void *qe; - struct ccb_accept_tio *atiop; + int s = splcam(); + isp_target_putback_atio(arg); + splx(s); +} + +static void +isp_target_putback_atio(union ccb *ccb) +{ + struct ispsoftc *isp; + struct ccb_scsiio *cso; u_int16_t iptr, optr; + void *qe; + + isp = XS_ISP(ccb); if (isp_getrqentry(isp, &iptr, &optr, &qe)) { - xpt_print_path(ccb->ccb_h.path); - printf("Request Queue Overflow in isp_target_putback_atio\n"); - return (CAM_RESRC_UNAVAIL); + (void) timeout(isp_refire_putback_atio, ccb, 10); + isp_prt(isp, ISP_LOGWARN, + "isp_target_putback_atio: Request Queue Overflow"); + return; } bzero(qe, QENTRY_LEN); - atiop = (struct ccb_accept_tio *) ccb; + cso = &ccb->csio; if (IS_FC(isp)) { at2_entry_t *at = qe; at->at_header.rqs_entry_type = RQSTYPE_ATIO2; at->at_header.rqs_entry_count = 1; if (isp->isp_maxluns > 16) { - at->at_scclun = (uint16_t) atiop->ccb_h.target_lun; + at->at_scclun = (uint16_t) ccb->ccb_h.target_lun; } else { - at->at_lun = (uint8_t) atiop->ccb_h.target_lun; + at->at_lun = (uint8_t) ccb->ccb_h.target_lun; } at->at_status = CT_OK; - at->at_rxid = atiop->tag_id; + at->at_rxid = cso->tag_id; ISP_SWIZ_ATIO2(isp, qe, qe); } else { at_entry_t *at = qe; at->at_header.rqs_entry_type = RQSTYPE_ATIO; at->at_header.rqs_entry_count = 1; - at->at_iid = atiop->init_id; - at->at_tgt = atiop->ccb_h.target_id; - at->at_lun = atiop->ccb_h.target_lun; + at->at_iid = cso->init_id; + at->at_iid |= XS_CHANNEL(ccb) << 7; + at->at_tgt = cso->ccb_h.target_id; + at->at_lun = cso->ccb_h.target_lun; at->at_status = CT_OK; - if (atiop->ccb_h.status & CAM_TAG_ACTION_VALID) { - at->at_tag_type = atiop->tag_action; - } - at->at_tag_val = atiop->tag_id & 0xff; - at->at_handle = atiop->tag_id >> 8; + at->at_tag_val = AT_GET_TAG(cso->tag_id); + at->at_handle = AT_GET_HANDLE(cso->tag_id); ISP_SWIZ_ATIO(isp, qe, qe); } ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe); ISP_ADD_REQUEST(isp, iptr); - return (CAM_REQ_CMP); + isp_complete_ctio(ccb); } static void -isp_refire_putback_atio(void *arg) +isp_complete_ctio(union ccb *ccb) { - union ccb *ccb = arg; - int s = splcam(); - if (isp_target_putback_atio(XS_ISP(ccb), ccb) != CAM_REQ_CMP) { - (void) timeout(isp_refire_putback_atio, ccb, 10); - } else { - isp_handle_platform_ctio_part2(XS_ISP(ccb), ccb); + struct ispsoftc *isp = XS_ISP(ccb); + if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + ccb->ccb_h.status |= CAM_REQ_CMP; } - splx(s); + ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) { + isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE; + if (isp->isp_osinfo.simqfrozen == 0) { + if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { + isp_prt(isp, ISP_LOGDEBUG2, "ctio->relsimq"); + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + } else { + isp_prt(isp, ISP_LOGWARN, "ctio->devqfrozen"); + } + } else { + isp_prt(isp, ISP_LOGWARN, + "ctio->simqfrozen(%x)", isp->isp_osinfo.simqfrozen); + } + } + xpt_done(ccb); } /* @@ -966,7 +995,7 @@ static int isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) { tstate_t *tptr; - int status; + int status, bus; struct ccb_accept_tio *atiop; /* @@ -999,9 +1028,11 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) return (0); } - tptr = get_lun_statep(isp, aep->at_lun); + bus = aep->at_iid >> 7; + aep->at_iid &= 0x7f; + tptr = get_lun_statep(isp, bus, aep->at_lun); if (tptr == NULL) { - tptr = get_lun_statep(isp, CAM_LUN_WILDCARD); + tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD); } if (tptr == NULL) { @@ -1030,8 +1061,8 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) */ xpt_print_path(tptr->owner); isp_prt(isp, ISP_LOGWARN, - "no ATIOS for lun %d from initiator %d", - aep->at_lun, aep->at_iid); + "no ATIOS for lun %d from initiator %d on channel %d", + aep->at_lun, aep->at_iid, bus); rls_lun_statep(isp, tptr); if (aep->at_flags & AT_TQAE) isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0); @@ -1040,7 +1071,7 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) return (0); } SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); - if (tptr == &isp->isp_osinfo.tsdflt) { + if (tptr == &isp->isp_osinfo.tsdflt[bus]) { atiop->ccb_h.target_id = aep->at_tgt; atiop->ccb_h.target_lun = aep->at_lun; } @@ -1058,16 +1089,21 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep) atiop->sense_len = 0; } - atiop->init_id = aep->at_iid; + atiop->init_id = aep->at_iid & 0x7f; atiop->cdb_len = aep->at_cdblen; MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen); atiop->ccb_h.status = CAM_CDB_RECVD; - atiop->tag_id = aep->at_tag_val | (aep->at_handle << 8); - if ((atiop->tag_action = aep->at_tag_type) != 0) { + /* + * Construct a tag 'id' based upon tag value (which may be 0..255) + * and the handle (which we have to preserve). + */ + AT_MAKE_TAGID(atiop->tag_id, aep); + if (aep->at_flags & AT_TQAE) { + atiop->tag_action = aep->at_tag_type; atiop->ccb_h.status |= CAM_TAG_ACTION_VALID; } xpt_done((union ccb*)atiop); - isp_prt(isp, ISP_LOGTDEBUG2, + isp_prt(isp, ISP_LOGTDEBUG1, "ATIO[%x] CDB=0x%x iid%d->lun%d tag 0x%x ttype 0x%x %s", aep->at_handle, aep->at_cdb[0] & 0xff, aep->at_iid, aep->at_lun, aep->at_tag_val & 0xff, aep->at_tag_type, @@ -1101,9 +1137,9 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep) } else { lun = aep->at_lun; } - tptr = get_lun_statep(isp, lun); + tptr = get_lun_statep(isp, 0, lun); if (tptr == NULL) { - tptr = get_lun_statep(isp, CAM_LUN_WILDCARD); + tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD); } if (tptr == NULL) { @@ -1168,7 +1204,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep) } SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); - if (tptr == &isp->isp_osinfo.tsdflt) { + if (tptr == &isp->isp_osinfo.tsdflt[0]) { atiop->ccb_h.target_id = ((fcparam *)isp->isp_param)->isp_loopid; atiop->ccb_h.target_lun = lun; @@ -1209,7 +1245,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep) atiop->ccb_h.spriv_field0 = aep->at_datalen; xpt_done((union ccb*)atiop); - isp_prt(isp, ISP_LOGTDEBUG2, + isp_prt(isp, ISP_LOGTDEBUG1, "ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u", aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid, lun, aep->at_taskflags, aep->at_datalen); @@ -1221,7 +1257,7 @@ static int isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) { union ccb *ccb; - int sentstatus, ok, notify_cam; + int sentstatus, ok, notify_cam, resid = 0; /* * CTIO and CTIO2 are close enough.... @@ -1235,82 +1271,75 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg) ct2_entry_t *ct = arg; sentstatus = ct->ct_flags & CT2_SENDSTATUS; ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK; - if (ok && (ccb->ccb_h.flags & CAM_SEND_SENSE)) { + if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) { ccb->ccb_h.status |= CAM_SENT_SENSE; } - isp_prt(isp, ISP_LOGTDEBUG2, - "CTIO2[%x] sts 0x%x flg 0x%x sns %d FIN", + isp_prt(isp, ISP_LOGTDEBUG1, + "CTIO2[%x] sts 0x%x flg 0x%x sns %d %s", ct->ct_rxid, ct->ct_status, ct->ct_flags, - (ccb->ccb_h.status & CAM_SENT_SENSE) != 0); - notify_cam = ct->ct_header.rqs_seqno; + (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, + sentstatus? "FIN" : "MID"); + notify_cam = ct->ct_header.rqs_seqno & 0x1; + if (ct->ct_flags & CT2_DATAMASK) + resid = ct->ct_resid; } else { ct_entry_t *ct = arg; sentstatus = ct->ct_flags & CT_SENDSTATUS; ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK; - isp_prt(isp, ISP_LOGTDEBUG2, - "CTIO tag 0x%x sts 0x%x flg 0x%x FIN", - ct->ct_tag_val, ct->ct_status, ct->ct_flags); - notify_cam = ct->ct_header.rqs_seqno; + isp_prt(isp, ISP_LOGTDEBUG1, + "CTIO[%x] tag %x iid %x tgt %d lun %d sts 0x%x flg %x %s", + ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_tgt, + ct->ct_lun, ct->ct_status, ct->ct_flags, + sentstatus? "FIN" : "MID"); + + /* + * We *ought* to be able to get back to the original ATIO + * here, but for some reason this gets lost. It's just as + * well because it's squirrelled away as part of periph + * private data. + * + * We can live without it as long as we continue to use + * the auto-replenish feature for CTIOs. + */ + notify_cam = ct->ct_header.rqs_seqno & 0x1; + if (ct->ct_status & QLTM_SVALID) { + char *sp = (char *)ct; + sp += CTIO_SENSE_OFFSET; + ccb->csio.sense_len = + min(sizeof (ccb->csio.sense_data), QLTM_SENSELEN); + MEMCPY(&ccb->csio.sense_data, sp, ccb->csio.sense_len); + ccb->ccb_h.status |= CAM_AUTOSNS_VALID; + } + if (ct->ct_flags & CT_DATAMASK) + resid = ct->ct_resid; } + ccb->csio.resid += resid; /* - * We're here either because data transfers are done (and - * it's time to send a final status CTIO) or because the final - * status CTIO is done. We don't get called for all intermediate - * CTIOs that happen for a large data transfer. + * We're here either because intermediate data transfers are done + * and/or the final status CTIO (which may have joined with a + * Data Transfer) is done. * * In any case, for this platform, the upper layers figure out * what to do next, so all we do here is collect status and - * pass information along. The exception is that we clear - * the notion of handling a non-disconnecting command here. + * pass information along. Any DMA handles have already been + * freed. */ - - if (sentstatus) { - /* - * Data transfer done. See if all went okay. - */ - if (ok) { - ccb->csio.resid = 0; - } else { - ccb->csio.resid = ccb->csio.dxfer_len; - } - } - if (notify_cam == 0) { - isp_prt(isp, ISP_LOGTDEBUG1, "Intermediate CTIO done"); + isp_prt(isp, ISP_LOGTDEBUG0, " INTER CTIO done"); return (0); } - isp_prt(isp, ISP_LOGTDEBUG1, "Final CTIO done"); - if (isp_target_putback_atio(isp, ccb) != CAM_REQ_CMP) { - (void) timeout(isp_refire_putback_atio, ccb, 10); + + isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO done (resid %d)", + (sentstatus)? " FINAL " : "MIDTERM ", ccb->csio.resid); + + if (!ok) { + isp_target_putback_atio(ccb); } else { - isp_handle_platform_ctio_part2(isp, ccb); - } - return (0); -} + isp_complete_ctio(ccb); -static void -isp_handle_platform_ctio_part2(struct ispsoftc *isp, union ccb *ccb) -{ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { - ccb->ccb_h.status |= CAM_REQ_CMP; - } - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) { - isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE; - if (isp->isp_osinfo.simqfrozen == 0) { - if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { - isp_prt(isp, ISP_LOGDEBUG2, "ctio->relsimq"); - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } else { - isp_prt(isp, ISP_LOGDEBUG2, "ctio->devqfrozen"); - } - } else { - isp_prt(isp, ISP_LOGDEBUG2, - "ctio->simqfrozen(%x)", isp->isp_osinfo.simqfrozen); - } } - xpt_done(ccb); + return (0); } #endif @@ -1327,22 +1356,27 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg) if (IS_SCSI(isp)) { u_int16_t oflags, nflags; sdparam *sdp = isp->isp_param; - int rvf, tgt; + int tgt; tgt = xpt_path_target_id(path); - rvf = ISP_FW_REVX(isp->isp_fwrev); ISP_LOCK(isp); sdp += cam_sim_bus(sim); - isp->isp_update |= (1 << cam_sim_bus(sim)); - nflags = DPARM_SAFE_DFLT; - if (rvf >= ISP_FW_REV(7, 55, 0) || - (ISP_FW_REV(4, 55, 0) <= rvf && - (rvf < ISP_FW_REV(5, 0, 0)))) { - nflags |= DPARM_NARROW | DPARM_ASYNC; +#ifndef ISP_TARGET_MODE + if (tgt == sdp->isp_initiator_id) { + nflags = DPARM_DEFAULT; + } else { + nflags = DPARM_SAFE_DFLT; + if (isp->isp_loaded_fw) { + nflags |= DPARM_NARROW | DPARM_ASYNC; + } } +#else + nflags = DPARM_DEFAULT; +#endif oflags = sdp->isp_devparam[tgt].dev_flags; sdp->isp_devparam[tgt].dev_flags = nflags; sdp->isp_devparam[tgt].dev_update = 1; + isp->isp_update |= (1 << cam_sim_bus(sim)); (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); sdp->isp_devparam[tgt].dev_flags = oflags; ISP_UNLOCK(isp); @@ -1590,7 +1624,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb) case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */ case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */ { - tstate_t *tptr = get_lun_statep(isp, ccb->ccb_h.target_lun); + tstate_t *tptr = + get_lun_statep(isp, XS_CHANNEL(ccb), ccb->ccb_h.target_lun); if (tptr == NULL) { ccb->ccb_h.status = CAM_LUN_INVALID; xpt_done(ccb); @@ -1600,9 +1635,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.sim_priv.entries[1].ptr = isp; ISP_LOCK(isp); if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { -#if 0 - (void) isp_target_putback_atio(isp, ccb); -#endif SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h, sim_links.sle); } else { @@ -1899,12 +1931,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) cpi->version_num = 1; #ifdef ISP_TARGET_MODE - /* XXX: we don't support 2nd bus target mode yet */ - if (cam_sim_bus(sim) == 0) - cpi->target_sprt = - PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; - else - cpi->target_sprt = 0; + cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; #else cpi->target_sprt = 0; #endif |