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.
This commit is contained in:
parent
7892febf24
commit
44f132def7
@ -28,6 +28,7 @@
|
|||||||
#include <dev/isp/isp_freebsd.h>
|
#include <dev/isp/isp_freebsd.h>
|
||||||
#include <machine/stdarg.h> /* for use by isp_prt below */
|
#include <machine/stdarg.h> /* for use by isp_prt below */
|
||||||
|
|
||||||
|
|
||||||
static void isp_intr_enable(void *);
|
static void isp_intr_enable(void *);
|
||||||
static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
|
static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
|
||||||
static void isp_poll(struct cam_sim *);
|
static void isp_poll(struct cam_sim *);
|
||||||
@ -172,39 +173,39 @@ isp_intr_enable(void *arg)
|
|||||||
|
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
|
|
||||||
static __inline int is_lun_enabled(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 *);
|
static __inline int are_any_luns_enabled(struct ispsoftc *, int);
|
||||||
static __inline tstate_t *get_lun_statep(struct ispsoftc *, lun_id_t);
|
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 void rls_lun_statep(struct ispsoftc *, tstate_t *);
|
||||||
static __inline int isp_psema_sig_rqe(struct ispsoftc *);
|
static __inline int isp_psema_sig_rqe(struct ispsoftc *);
|
||||||
static __inline int isp_cv_wait_timed_rqe(struct ispsoftc *, int);
|
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_cv_signal_rqe(struct ispsoftc *, int);
|
||||||
static __inline void isp_vsema_rqe(struct ispsoftc *);
|
static __inline void isp_vsema_rqe(struct ispsoftc *);
|
||||||
static cam_status
|
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 destroy_lun_state(struct ispsoftc *, tstate_t *);
|
||||||
static void isp_en_lun(struct ispsoftc *, union ccb *);
|
static void isp_en_lun(struct ispsoftc *, union ccb *);
|
||||||
static cam_status isp_abort_tgt_ccb(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 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_atio(struct ispsoftc *, at_entry_t *);
|
||||||
static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *);
|
static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *);
|
||||||
static int isp_handle_platform_ctio(struct ispsoftc *, void *);
|
static int isp_handle_platform_ctio(struct ispsoftc *, void *);
|
||||||
static void isp_handle_platform_ctio_part2(struct ispsoftc *, union ccb *);
|
|
||||||
|
|
||||||
static __inline int
|
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;
|
tstate_t *tptr;
|
||||||
ISP_LOCK(isp);
|
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);
|
ISP_UNLOCK(isp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if (tptr->lun == (lun_id_t) lun) {
|
if (tptr->lun == (lun_id_t) lun && tptr->bus == bus) {
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -214,11 +215,18 @@ is_lun_enabled(struct ispsoftc *isp, lun_id_t lun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __inline int
|
static __inline int
|
||||||
are_any_luns_enabled(struct ispsoftc *isp)
|
are_any_luns_enabled(struct ispsoftc *isp, int port)
|
||||||
{
|
{
|
||||||
int i;
|
int lo, hi;
|
||||||
for (i = 0; i < LUN_HASH_SIZE; i++) {
|
if (IS_DUALBUS(isp)) {
|
||||||
if (isp->isp_osinfo.lun_hash[i]) {
|
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);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,18 +234,18 @@ are_any_luns_enabled(struct ispsoftc *isp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __inline tstate_t *
|
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;
|
tstate_t *tptr;
|
||||||
|
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if (lun == CAM_LUN_WILDCARD) {
|
if (lun == CAM_LUN_WILDCARD) {
|
||||||
tptr = &isp->isp_osinfo.tsdflt;
|
tptr = &isp->isp_osinfo.tsdflt[bus];
|
||||||
tptr->hold++;
|
tptr->hold++;
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
return (tptr);
|
return (tptr);
|
||||||
} else {
|
} 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) {
|
if (tptr == NULL) {
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
@ -245,7 +253,7 @@ get_lun_statep(struct ispsoftc *isp, lun_id_t lun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (tptr->lun == lun) {
|
if (tptr->lun == lun && tptr->bus == bus) {
|
||||||
tptr->hold++;
|
tptr->hold++;
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
return (tptr);
|
return (tptr);
|
||||||
@ -310,17 +318,19 @@ isp_vsema_rqe(struct ispsoftc *isp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static cam_status
|
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;
|
cam_status status;
|
||||||
lun_id_t lun;
|
lun_id_t lun;
|
||||||
|
int hfx;
|
||||||
tstate_t *tptr, *new;
|
tstate_t *tptr, *new;
|
||||||
|
|
||||||
lun = xpt_path_lun_id(path);
|
lun = xpt_path_lun_id(path);
|
||||||
if (lun < 0) {
|
if (lun < 0) {
|
||||||
return (CAM_LUN_INVALID);
|
return (CAM_LUN_INVALID);
|
||||||
}
|
}
|
||||||
if (is_lun_enabled(isp, lun)) {
|
if (is_lun_enabled(isp, bus, lun)) {
|
||||||
return (CAM_LUN_ALRDY_ENA);
|
return (CAM_LUN_ALRDY_ENA);
|
||||||
}
|
}
|
||||||
new = (tstate_t *) malloc(sizeof (tstate_t), M_DEVBUF, M_NOWAIT|M_ZERO);
|
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);
|
free(new, M_DEVBUF);
|
||||||
return (status);
|
return (status);
|
||||||
}
|
}
|
||||||
|
new->bus = bus;
|
||||||
new->lun = lun;
|
new->lun = lun;
|
||||||
SLIST_INIT(&new->atios);
|
SLIST_INIT(&new->atios);
|
||||||
SLIST_INIT(&new->inots);
|
SLIST_INIT(&new->inots);
|
||||||
new->hold = 1;
|
new->hold = 1;
|
||||||
|
|
||||||
|
hfx = LUN_HASH_FUNC(isp, new->bus, new->lun);
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) {
|
tptr = isp->isp_osinfo.lun_hash[hfx];
|
||||||
isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)] = new;
|
if (tptr == NULL) {
|
||||||
|
isp->isp_osinfo.lun_hash[hfx] = new;
|
||||||
} else {
|
} else {
|
||||||
while (tptr->next)
|
while (tptr->next)
|
||||||
tptr = 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
|
static __inline void
|
||||||
destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
|
destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
|
||||||
{
|
{
|
||||||
|
int hfx;
|
||||||
tstate_t *lw, *pw;
|
tstate_t *lw, *pw;
|
||||||
|
|
||||||
|
hfx = LUN_HASH_FUNC(isp, tptr->bus, tptr->lun);
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if (tptr->hold) {
|
if (tptr->hold) {
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pw = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)];
|
pw = isp->isp_osinfo.lun_hash[hfx];
|
||||||
if (pw == NULL) {
|
if (pw == NULL) {
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
return;
|
return;
|
||||||
} else if (pw->lun == tptr->lun) {
|
} else if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
|
||||||
isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)] = pw->next;
|
isp->isp_osinfo.lun_hash[hfx] = pw->next;
|
||||||
} else {
|
} else {
|
||||||
lw = pw;
|
lw = pw;
|
||||||
pw = lw->next;
|
pw = lw->next;
|
||||||
while (pw) {
|
while (pw) {
|
||||||
if (pw->lun == tptr->lun) {
|
if (pw->lun == tptr->lun && pw->bus == tptr->bus) {
|
||||||
lw->next = pw->next;
|
lw->next = pw->next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -391,7 +406,7 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
|
|||||||
static void
|
static void
|
||||||
isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
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;
|
struct ccb_en_lun *cel = &ccb->cel;
|
||||||
tstate_t *tptr;
|
tstate_t *tptr;
|
||||||
u_int16_t rstat;
|
u_int16_t rstat;
|
||||||
@ -400,13 +415,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
target_id_t tgt;
|
target_id_t tgt;
|
||||||
|
|
||||||
|
|
||||||
bus = XS_CHANNEL(ccb);
|
bus = XS_CHANNEL(ccb) & 0x1;
|
||||||
if (bus != 0) {
|
|
||||||
isp_prt(isp, ISP_LOGERR,
|
|
||||||
"second channel target mode not supported");
|
|
||||||
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tgt = ccb->ccb_h.target_id;
|
tgt = ccb->ccb_h.target_id;
|
||||||
lun = ccb->ccb_h.target_lun;
|
lun = ccb->ccb_h.target_lun;
|
||||||
|
|
||||||
@ -420,8 +429,10 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (IS_SCSI(isp)) {
|
if (IS_SCSI(isp)) {
|
||||||
|
sdparam *sdp = isp->isp_param;
|
||||||
|
sdp += bus;
|
||||||
if (tgt != CAM_TARGET_WILDCARD &&
|
if (tgt != CAM_TARGET_WILDCARD &&
|
||||||
tgt != SDPARAM(isp)->isp_initiator_id) {
|
tgt != sdp->isp_initiator_id) {
|
||||||
ccb->ccb_h.status = CAM_TID_INVALID;
|
ccb->ccb_h.status = CAM_TID_INVALID;
|
||||||
return;
|
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 so, we enable/disable target mode but don't do any lun enabling.
|
||||||
*/
|
*/
|
||||||
if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) {
|
if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) {
|
||||||
int av;
|
int av = bus << 31;
|
||||||
tptr = &isp->isp_osinfo.tsdflt;
|
tptr = &isp->isp_osinfo.tsdflt[bus];
|
||||||
if (cel->enable) {
|
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;
|
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
|
||||||
if (frozen)
|
if (frozen)
|
||||||
xpt_release_simq(isp->isp_sim, 1);
|
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->atios);
|
||||||
SLIST_INIT(&tptr->inots);
|
SLIST_INIT(&tptr->inots);
|
||||||
av = 1;
|
av |= ENABLE_TARGET_FLAG;
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||||
if (av) {
|
if (av) {
|
||||||
@ -522,22 +533,21 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
xpt_release_simq(isp->isp_sim, 1);
|
xpt_release_simq(isp->isp_sim, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED;
|
isp->isp_osinfo.tmflags |= (1 << bus);
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
} else {
|
} 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;
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
||||||
if (frozen)
|
if (frozen)
|
||||||
xpt_release_simq(isp->isp_sim, 1);
|
xpt_release_simq(isp->isp_sim, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (are_any_luns_enabled(isp)) {
|
if (are_any_luns_enabled(isp, bus)) {
|
||||||
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
||||||
if (frozen)
|
if (frozen)
|
||||||
xpt_release_simq(isp->isp_sim, 1);
|
xpt_release_simq(isp->isp_sim, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
av = 0;
|
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||||
if (av) {
|
if (av) {
|
||||||
@ -547,12 +557,13 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
xpt_release_simq(isp->isp_sim, 1);
|
xpt_release_simq(isp->isp_sim, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED;
|
isp->isp_osinfo.tmflags &= ~(1 << bus);
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||||
}
|
}
|
||||||
xpt_print_path(ccb->ccb_h.path);
|
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)
|
if (frozen)
|
||||||
xpt_release_simq(isp->isp_sim, 1);
|
xpt_release_simq(isp->isp_sim, 1);
|
||||||
return;
|
return;
|
||||||
@ -568,12 +579,12 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
|
|
||||||
if (cel->enable) {
|
if (cel->enable) {
|
||||||
ccb->ccb_h.status =
|
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) {
|
if (ccb->ccb_h.status != CAM_REQ_CMP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tptr = get_lun_statep(isp, lun);
|
tptr = get_lun_statep(isp, bus, lun);
|
||||||
if (tptr == NULL) {
|
if (tptr == NULL) {
|
||||||
ccb->ccb_h.status = CAM_LUN_INVALID;
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
||||||
return;
|
return;
|
||||||
@ -670,7 +681,8 @@ out:
|
|||||||
destroy_lun_state(isp, tptr);
|
destroy_lun_state(isp, tptr);
|
||||||
} else {
|
} else {
|
||||||
xpt_print_path(ccb->ccb_h.path);
|
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);
|
rls_lun_statep(isp, tptr);
|
||||||
if (cel->enable == 0) {
|
if (cel->enable == 0) {
|
||||||
destroy_lun_state(isp, tptr);
|
destroy_lun_state(isp, tptr);
|
||||||
@ -697,7 +709,7 @@ isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
return (CAM_PATH_INVALID);
|
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) {
|
if (tptr == NULL) {
|
||||||
return (CAM_PATH_INVALID);
|
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;
|
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;
|
cto->ct_rxid = cso->tag_id;
|
||||||
if (cso->dxfer_len == 0) {
|
if (cso->dxfer_len == 0) {
|
||||||
cto->ct_flags |= CT2_FLAG_MODE1 | CT2_NO_DATA;
|
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;
|
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
|
||||||
}
|
}
|
||||||
if (cto->ct_flags & CT2_SENDSTATUS) {
|
if (cto->ct_flags & CT2_SENDSTATUS) {
|
||||||
isp_prt(isp, ISP_LOGTDEBUG2,
|
isp_prt(isp, ISP_LOGTDEBUG1,
|
||||||
"CTIO2[%x] SCSI STATUS 0x%x datalength %u",
|
"CTIO2[%x] SCSI STATUS 0x%x datalength %u",
|
||||||
cto->ct_rxid, cso->scsi_status, cto->ct_resid);
|
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;
|
hp = &cto->ct_syshandle;
|
||||||
} else {
|
} else {
|
||||||
ct_entry_t *cto = qe;
|
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_type = RQSTYPE_CTIO;
|
||||||
cto->ct_header.rqs_entry_count = 1;
|
cto->ct_header.rqs_entry_count = 1;
|
||||||
cto->ct_iid = cso->init_id;
|
cto->ct_iid = cso->init_id;
|
||||||
|
cto->ct_iid |= XS_CHANNEL(ccb) << 7;
|
||||||
cto->ct_tgt = ccb->ccb_h.target_id;
|
cto->ct_tgt = ccb->ccb_h.target_id;
|
||||||
cto->ct_lun = ccb->ccb_h.target_lun;
|
cto->ct_lun = ccb->ccb_h.target_lun;
|
||||||
cto->ct_fwhandle = cso->tag_id >> 8;
|
cto->ct_fwhandle = AT_GET_HANDLE(cso->tag_id);
|
||||||
cto->ct_tag_val = cso->tag_id & 0xff;
|
if (AT_HAS_TAG(cso->tag_id)) {
|
||||||
if (cto->ct_tag_val && cso->tag_action) {
|
cto->ct_tag_val = (u_int8_t) AT_GET_TAG(cso->tag_id);
|
||||||
/*
|
|
||||||
* We don't specify a tag type for regular SCSI,
|
|
||||||
* just the tag value and set a flag.
|
|
||||||
*/
|
|
||||||
cto->ct_flags |= CT_TQAE;
|
cto->ct_flags |= CT_TQAE;
|
||||||
}
|
}
|
||||||
if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) {
|
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;
|
cto->ct_resid = cso->resid;
|
||||||
}
|
}
|
||||||
if (cto->ct_flags & CT_SENDSTATUS) {
|
if (cto->ct_flags & CT_SENDSTATUS) {
|
||||||
isp_prt(isp, ISP_LOGTDEBUG2,
|
isp_prt(isp, ISP_LOGTDEBUG1,
|
||||||
"CTIO SCSI STATUS 0x%x resid %d",
|
"CTIO[%x] SCSI STATUS 0x%x resid %d tag_id %x",
|
||||||
cso->scsi_status, cso->resid);
|
cto->ct_fwhandle, cso->scsi_status, cso->resid,
|
||||||
|
cso->tag_id);
|
||||||
}
|
}
|
||||||
cto->ct_timeout = 2;
|
cto->ct_timeout = 10;
|
||||||
hp = &cto->ct_syshandle;
|
hp = &cto->ct_syshandle;
|
||||||
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
|
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)) {
|
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;
|
save_handle = *hp;
|
||||||
|
|
||||||
switch (ISP_DMASETUP(isp, cso, qe, &iptr, optr)) {
|
switch (ISP_DMASETUP(isp, cso, qe, &iptr, optr)) {
|
||||||
case CMD_QUEUED:
|
case CMD_QUEUED:
|
||||||
ISP_ADD_REQUEST(isp, iptr);
|
ISP_ADD_REQUEST(isp, iptr);
|
||||||
@ -898,63 +905,85 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cam_status
|
static void
|
||||||
isp_target_putback_atio(struct ispsoftc *isp, union ccb *ccb)
|
isp_refire_putback_atio(void *arg)
|
||||||
{
|
{
|
||||||
void *qe;
|
int s = splcam();
|
||||||
struct ccb_accept_tio *atiop;
|
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;
|
u_int16_t iptr, optr;
|
||||||
|
void *qe;
|
||||||
|
|
||||||
|
isp = XS_ISP(ccb);
|
||||||
|
|
||||||
if (isp_getrqentry(isp, &iptr, &optr, &qe)) {
|
if (isp_getrqentry(isp, &iptr, &optr, &qe)) {
|
||||||
xpt_print_path(ccb->ccb_h.path);
|
(void) timeout(isp_refire_putback_atio, ccb, 10);
|
||||||
printf("Request Queue Overflow in isp_target_putback_atio\n");
|
isp_prt(isp, ISP_LOGWARN,
|
||||||
return (CAM_RESRC_UNAVAIL);
|
"isp_target_putback_atio: Request Queue Overflow");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
bzero(qe, QENTRY_LEN);
|
bzero(qe, QENTRY_LEN);
|
||||||
atiop = (struct ccb_accept_tio *) ccb;
|
cso = &ccb->csio;
|
||||||
if (IS_FC(isp)) {
|
if (IS_FC(isp)) {
|
||||||
at2_entry_t *at = qe;
|
at2_entry_t *at = qe;
|
||||||
at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
|
at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
|
||||||
at->at_header.rqs_entry_count = 1;
|
at->at_header.rqs_entry_count = 1;
|
||||||
if (isp->isp_maxluns > 16) {
|
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 {
|
} 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_status = CT_OK;
|
||||||
at->at_rxid = atiop->tag_id;
|
at->at_rxid = cso->tag_id;
|
||||||
ISP_SWIZ_ATIO2(isp, qe, qe);
|
ISP_SWIZ_ATIO2(isp, qe, qe);
|
||||||
} else {
|
} else {
|
||||||
at_entry_t *at = qe;
|
at_entry_t *at = qe;
|
||||||
at->at_header.rqs_entry_type = RQSTYPE_ATIO;
|
at->at_header.rqs_entry_type = RQSTYPE_ATIO;
|
||||||
at->at_header.rqs_entry_count = 1;
|
at->at_header.rqs_entry_count = 1;
|
||||||
at->at_iid = atiop->init_id;
|
at->at_iid = cso->init_id;
|
||||||
at->at_tgt = atiop->ccb_h.target_id;
|
at->at_iid |= XS_CHANNEL(ccb) << 7;
|
||||||
at->at_lun = atiop->ccb_h.target_lun;
|
at->at_tgt = cso->ccb_h.target_id;
|
||||||
|
at->at_lun = cso->ccb_h.target_lun;
|
||||||
at->at_status = CT_OK;
|
at->at_status = CT_OK;
|
||||||
if (atiop->ccb_h.status & CAM_TAG_ACTION_VALID) {
|
at->at_tag_val = AT_GET_TAG(cso->tag_id);
|
||||||
at->at_tag_type = atiop->tag_action;
|
at->at_handle = AT_GET_HANDLE(cso->tag_id);
|
||||||
}
|
|
||||||
at->at_tag_val = atiop->tag_id & 0xff;
|
|
||||||
at->at_handle = atiop->tag_id >> 8;
|
|
||||||
ISP_SWIZ_ATIO(isp, qe, qe);
|
ISP_SWIZ_ATIO(isp, qe, qe);
|
||||||
}
|
}
|
||||||
ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
|
ISP_TDQE(isp, "isp_target_putback_atio", (int) optr, qe);
|
||||||
ISP_ADD_REQUEST(isp, iptr);
|
ISP_ADD_REQUEST(isp, iptr);
|
||||||
return (CAM_REQ_CMP);
|
isp_complete_ctio(ccb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
isp_refire_putback_atio(void *arg)
|
isp_complete_ctio(union ccb *ccb)
|
||||||
{
|
{
|
||||||
union ccb *ccb = arg;
|
struct ispsoftc *isp = XS_ISP(ccb);
|
||||||
int s = splcam();
|
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
|
||||||
if (isp_target_putback_atio(XS_ISP(ccb), ccb) != CAM_REQ_CMP) {
|
ccb->ccb_h.status |= CAM_REQ_CMP;
|
||||||
(void) timeout(isp_refire_putback_atio, ccb, 10);
|
|
||||||
} else {
|
|
||||||
isp_handle_platform_ctio_part2(XS_ISP(ccb), ccb);
|
|
||||||
}
|
}
|
||||||
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)
|
isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
|
||||||
{
|
{
|
||||||
tstate_t *tptr;
|
tstate_t *tptr;
|
||||||
int status;
|
int status, bus;
|
||||||
struct ccb_accept_tio *atiop;
|
struct ccb_accept_tio *atiop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -999,9 +1028,11 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
|
|||||||
return (0);
|
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) {
|
if (tptr == NULL) {
|
||||||
tptr = get_lun_statep(isp, CAM_LUN_WILDCARD);
|
tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tptr == NULL) {
|
if (tptr == NULL) {
|
||||||
@ -1030,8 +1061,8 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
|
|||||||
*/
|
*/
|
||||||
xpt_print_path(tptr->owner);
|
xpt_print_path(tptr->owner);
|
||||||
isp_prt(isp, ISP_LOGWARN,
|
isp_prt(isp, ISP_LOGWARN,
|
||||||
"no ATIOS for lun %d from initiator %d",
|
"no ATIOS for lun %d from initiator %d on channel %d",
|
||||||
aep->at_lun, aep->at_iid);
|
aep->at_lun, aep->at_iid, bus);
|
||||||
rls_lun_statep(isp, tptr);
|
rls_lun_statep(isp, tptr);
|
||||||
if (aep->at_flags & AT_TQAE)
|
if (aep->at_flags & AT_TQAE)
|
||||||
isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
|
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_id = aep->at_tgt;
|
||||||
atiop->ccb_h.target_lun = aep->at_lun;
|
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->sense_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
atiop->init_id = aep->at_iid;
|
atiop->init_id = aep->at_iid & 0x7f;
|
||||||
atiop->cdb_len = aep->at_cdblen;
|
atiop->cdb_len = aep->at_cdblen;
|
||||||
MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
|
MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen);
|
||||||
atiop->ccb_h.status = CAM_CDB_RECVD;
|
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;
|
atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
|
||||||
}
|
}
|
||||||
xpt_done((union ccb*)atiop);
|
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",
|
"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_handle, aep->at_cdb[0] & 0xff, aep->at_iid, aep->at_lun,
|
||||||
aep->at_tag_val & 0xff, aep->at_tag_type,
|
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 {
|
} else {
|
||||||
lun = aep->at_lun;
|
lun = aep->at_lun;
|
||||||
}
|
}
|
||||||
tptr = get_lun_statep(isp, lun);
|
tptr = get_lun_statep(isp, 0, lun);
|
||||||
if (tptr == NULL) {
|
if (tptr == NULL) {
|
||||||
tptr = get_lun_statep(isp, CAM_LUN_WILDCARD);
|
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tptr == NULL) {
|
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);
|
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 =
|
atiop->ccb_h.target_id =
|
||||||
((fcparam *)isp->isp_param)->isp_loopid;
|
((fcparam *)isp->isp_param)->isp_loopid;
|
||||||
atiop->ccb_h.target_lun = lun;
|
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;
|
atiop->ccb_h.spriv_field0 = aep->at_datalen;
|
||||||
|
|
||||||
xpt_done((union ccb*)atiop);
|
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",
|
"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,
|
aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
|
||||||
lun, aep->at_taskflags, aep->at_datalen);
|
lun, aep->at_taskflags, aep->at_datalen);
|
||||||
@ -1221,7 +1257,7 @@ static int
|
|||||||
isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
|
isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
|
||||||
{
|
{
|
||||||
union ccb *ccb;
|
union ccb *ccb;
|
||||||
int sentstatus, ok, notify_cam;
|
int sentstatus, ok, notify_cam, resid = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CTIO and CTIO2 are close enough....
|
* CTIO and CTIO2 are close enough....
|
||||||
@ -1235,83 +1271,76 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
|
|||||||
ct2_entry_t *ct = arg;
|
ct2_entry_t *ct = arg;
|
||||||
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
|
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
|
||||||
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
|
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;
|
ccb->ccb_h.status |= CAM_SENT_SENSE;
|
||||||
}
|
}
|
||||||
isp_prt(isp, ISP_LOGTDEBUG2,
|
isp_prt(isp, ISP_LOGTDEBUG1,
|
||||||
"CTIO2[%x] sts 0x%x flg 0x%x sns %d FIN",
|
"CTIO2[%x] sts 0x%x flg 0x%x sns %d %s",
|
||||||
ct->ct_rxid, ct->ct_status, ct->ct_flags,
|
ct->ct_rxid, ct->ct_status, ct->ct_flags,
|
||||||
(ccb->ccb_h.status & CAM_SENT_SENSE) != 0);
|
(ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
|
||||||
notify_cam = ct->ct_header.rqs_seqno;
|
sentstatus? "FIN" : "MID");
|
||||||
|
notify_cam = ct->ct_header.rqs_seqno & 0x1;
|
||||||
|
if (ct->ct_flags & CT2_DATAMASK)
|
||||||
|
resid = ct->ct_resid;
|
||||||
} else {
|
} else {
|
||||||
ct_entry_t *ct = arg;
|
ct_entry_t *ct = arg;
|
||||||
sentstatus = ct->ct_flags & CT_SENDSTATUS;
|
sentstatus = ct->ct_flags & CT_SENDSTATUS;
|
||||||
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
|
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
|
||||||
isp_prt(isp, ISP_LOGTDEBUG2,
|
isp_prt(isp, ISP_LOGTDEBUG1,
|
||||||
"CTIO tag 0x%x sts 0x%x flg 0x%x FIN",
|
"CTIO[%x] tag %x iid %x tgt %d lun %d sts 0x%x flg %x %s",
|
||||||
ct->ct_tag_val, ct->ct_status, ct->ct_flags);
|
ct->ct_fwhandle, ct->ct_tag_val, ct->ct_iid, ct->ct_tgt,
|
||||||
notify_cam = ct->ct_header.rqs_seqno;
|
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
|
* We're here either because intermediate data transfers are done
|
||||||
* it's time to send a final status CTIO) or because the final
|
* and/or the final status CTIO (which may have joined with a
|
||||||
* status CTIO is done. We don't get called for all intermediate
|
* Data Transfer) is done.
|
||||||
* CTIOs that happen for a large data transfer.
|
|
||||||
*
|
*
|
||||||
* In any case, for this platform, the upper layers figure out
|
* In any case, for this platform, the upper layers figure out
|
||||||
* what to do next, so all we do here is collect status and
|
* what to do next, so all we do here is collect status and
|
||||||
* pass information along. The exception is that we clear
|
* pass information along. Any DMA handles have already been
|
||||||
* the notion of handling a non-disconnecting command here.
|
* 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) {
|
if (notify_cam == 0) {
|
||||||
isp_prt(isp, ISP_LOGTDEBUG1, "Intermediate CTIO done");
|
isp_prt(isp, ISP_LOGTDEBUG0, " INTER CTIO done");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
isp_prt(isp, ISP_LOGTDEBUG1, "Final CTIO done");
|
|
||||||
if (isp_target_putback_atio(isp, ccb) != CAM_REQ_CMP) {
|
isp_prt(isp, ISP_LOGTDEBUG0, "%s CTIO done (resid %d)",
|
||||||
(void) timeout(isp_refire_putback_atio, ccb, 10);
|
(sentstatus)? " FINAL " : "MIDTERM ", ccb->csio.resid);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
isp_target_putback_atio(ccb);
|
||||||
} else {
|
} else {
|
||||||
isp_handle_platform_ctio_part2(isp, ccb);
|
isp_complete_ctio(ccb);
|
||||||
|
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1327,22 +1356,27 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
|
|||||||
if (IS_SCSI(isp)) {
|
if (IS_SCSI(isp)) {
|
||||||
u_int16_t oflags, nflags;
|
u_int16_t oflags, nflags;
|
||||||
sdparam *sdp = isp->isp_param;
|
sdparam *sdp = isp->isp_param;
|
||||||
int rvf, tgt;
|
int tgt;
|
||||||
|
|
||||||
tgt = xpt_path_target_id(path);
|
tgt = xpt_path_target_id(path);
|
||||||
rvf = ISP_FW_REVX(isp->isp_fwrev);
|
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
sdp += cam_sim_bus(sim);
|
sdp += cam_sim_bus(sim);
|
||||||
isp->isp_update |= (1 << cam_sim_bus(sim));
|
#ifndef ISP_TARGET_MODE
|
||||||
nflags = DPARM_SAFE_DFLT;
|
if (tgt == sdp->isp_initiator_id) {
|
||||||
if (rvf >= ISP_FW_REV(7, 55, 0) ||
|
nflags = DPARM_DEFAULT;
|
||||||
(ISP_FW_REV(4, 55, 0) <= rvf &&
|
} else {
|
||||||
(rvf < ISP_FW_REV(5, 0, 0)))) {
|
nflags = DPARM_SAFE_DFLT;
|
||||||
nflags |= DPARM_NARROW | DPARM_ASYNC;
|
if (isp->isp_loaded_fw) {
|
||||||
|
nflags |= DPARM_NARROW | DPARM_ASYNC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
nflags = DPARM_DEFAULT;
|
||||||
|
#endif
|
||||||
oflags = sdp->isp_devparam[tgt].dev_flags;
|
oflags = sdp->isp_devparam[tgt].dev_flags;
|
||||||
sdp->isp_devparam[tgt].dev_flags = nflags;
|
sdp->isp_devparam[tgt].dev_flags = nflags;
|
||||||
sdp->isp_devparam[tgt].dev_update = 1;
|
sdp->isp_devparam[tgt].dev_update = 1;
|
||||||
|
isp->isp_update |= (1 << cam_sim_bus(sim));
|
||||||
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
|
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
|
||||||
sdp->isp_devparam[tgt].dev_flags = oflags;
|
sdp->isp_devparam[tgt].dev_flags = oflags;
|
||||||
ISP_UNLOCK(isp);
|
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_IMMED_NOTIFY: /* Add Immediate Notify Resource */
|
||||||
case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO 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) {
|
if (tptr == NULL) {
|
||||||
ccb->ccb_h.status = CAM_LUN_INVALID;
|
ccb->ccb_h.status = CAM_LUN_INVALID;
|
||||||
xpt_done(ccb);
|
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;
|
ccb->ccb_h.sim_priv.entries[1].ptr = isp;
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
|
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,
|
SLIST_INSERT_HEAD(&tptr->atios,
|
||||||
&ccb->ccb_h, sim_links.sle);
|
&ccb->ccb_h, sim_links.sle);
|
||||||
} else {
|
} else {
|
||||||
@ -1899,12 +1931,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
|||||||
|
|
||||||
cpi->version_num = 1;
|
cpi->version_num = 1;
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
/* XXX: we don't support 2nd bus target mode yet */
|
cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
|
||||||
if (cam_sim_bus(sim) == 0)
|
|
||||||
cpi->target_sprt =
|
|
||||||
PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
|
|
||||||
else
|
|
||||||
cpi->target_sprt = 0;
|
|
||||||
#else
|
#else
|
||||||
cpi->target_sprt = 0;
|
cpi->target_sprt = 0;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user