aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2002-03-21 23:22:21 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2002-03-21 23:22:21 +0000
commit9971f53bf62c52de8c4ef9c8c1b4aa841254119b (patch)
tree57053634841a21ea9feed9bf11e6194569ef7130 /sys/dev/isp
parent3e211ac1e426b9280594d803319f962bd24222a5 (diff)
Notes
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp.c65
-rw-r--r--sys/dev/isp/isp_freebsd.h2
-rw-r--r--sys/dev/isp/isp_target.h6
-rw-r--r--sys/dev/isp/ispvar.h4
4 files changed, 54 insertions, 23 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 8f0ddaacd2dd..b6b9d4d7b838 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -1250,9 +1250,20 @@ isp_fibre_init(struct ispsoftc *isp)
}
#ifndef ISP_NO_RIO_FC
- if ((isp->isp_role & ISP_ROLE_TARGET) == 0 &&
- ((IS_2100(isp) && ISP_FW_REVX(isp->isp_fwrev) >=
- ISP_FW_REV(1, 17, 0)) || IS_2200(isp) || IS_23XX(isp))) {
+ /*
+ * RIO seems to be enabled in 2100s for fw >= 1.17.0.
+ *
+ * I've had some questionable problems with RIO on 2200.
+ * More specifically, on a 2204 I had problems with RIO
+ * on a Linux system where I was dropping commands right
+ * and left. It's not clear to me what the actual problem
+ * was, but it seems safer to only support this on the
+ * 23XX cards.
+ *
+ * I have it disabled if we support a target mode role for
+ * reasons I can't now remember.
+ */
+ if ((isp->isp_role & ISP_ROLE_TARGET) == 0 && IS_23XX(isp)) {
icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT;
icbp->icb_racctimer = 4;
icbp->icb_idelaytimer = 8;
@@ -2287,6 +2298,9 @@ isp_scan_loop(struct ispsoftc *isp)
return (0);
}
+#ifndef HICAP_MAX
+#define HICAP_MAX 256
+#endif
static int
isp_scan_fabric(struct ispsoftc *isp)
{
@@ -2309,7 +2323,7 @@ isp_scan_fabric(struct ispsoftc *isp)
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
- for (first_portid_seen = hicap = 0; hicap < 65535; hicap++) {
+ for (first_portid_seen = hicap = 0; hicap < HICAP_MAX; hicap++) {
mbreg_t mbs;
sns_screq_t *rq;
sns_ganrsp_t *rs0, *rs1;
@@ -3122,6 +3136,7 @@ again:
} else {
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
}
+ isp->isp_resodx = iptr;
if (optr == iptr && sema == 0) {
@@ -3156,9 +3171,15 @@ again:
isr, junk, iptr, optr);
}
}
+ isp->isp_resodx = iptr;
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
ISP_WRITE(isp, BIU_SEMA, 0);
+ if (isp->isp_rspbsy) {
+ return;
+ }
+ isp->isp_rspbsy = 1;
+
while (optr != iptr) {
ispstatusreq_t local, *sp = &local;
isphdr_t *hp;
@@ -3187,9 +3208,16 @@ again:
}
if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
+ MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
} else {
- if (!isp_handle_other_response(isp, type, hp, &optr)) {
+ /*
+ * Somebody reachable via isp_handle_other_response
+ * may have updated the response queue pointers for
+ * us, so we reload our goal index.
+ */
+ if (isp_handle_other_response(isp, type, hp, &optr)) {
+ iptr = isp->isp_resodx;
MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
}
@@ -3410,7 +3438,7 @@ again:
if (nlooked) {
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
/*
- * While we're at it, reqad the requst queue out pointer.
+ * While we're at it, read the requst queue out pointer.
*/
isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
if (isp->isp_rscchiwater < ndone)
@@ -3418,6 +3446,7 @@ again:
}
isp->isp_residx = optr;
+ isp->isp_rspbsy = 0;
for (i = 0; i < ndone; i++) {
xs = complist[i];
if (xs) {
@@ -3767,7 +3796,7 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
switch (type) {
case RQSTYPE_STATUS_CONT:
isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
- return (0);
+ return (1);
case RQSTYPE_ATIO:
case RQSTYPE_CTIO:
case RQSTYPE_ENABLE_LUN:
@@ -3780,7 +3809,9 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
case RQSTYPE_CTIO3:
isp->isp_rsltccmplt++; /* count as a response completion */
#ifdef ISP_TARGET_MODE
- return (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp));
+ if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
+ return (1);
+ }
#else
optrp = optrp;
/* FALLTHROUGH */
@@ -3788,11 +3819,11 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
case RQSTYPE_REQUEST:
default:
if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) {
- return (0);
+ return (1);
}
isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
isp_get_response_type(isp, hp));
- return (-1);
+ return (0);
}
}
@@ -4096,18 +4127,16 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
/*
* No such port on the loop. Moral equivalent of SELTIMEO
*/
- isp_prt(isp, ISP_LOGINFO,
- "Port Unavailable for target %d", XS_TGT(xs));
- if (XS_NOERR(xs)) {
- XS_SETERR(xs, HBA_SELTIMEOUT);
- }
- return;
case RQCS_PORT_LOGGED_OUT:
/*
* It was there (maybe)- treat as a selection timeout.
*/
- isp_prt(isp, ISP_LOGINFO,
- "port logout for target %d", XS_TGT(xs));
+ if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
+ isp_prt(isp, ISP_LOGINFO,
+ "Port Unavailable for target %d", XS_TGT(xs));
+ else
+ isp_prt(isp, ISP_LOGINFO,
+ "port logout for target %d", XS_TGT(xs));
/*
* If we're on a local loop, force a LIP (which is overkill)
* to force a re-login of this unit.
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 04c4972fd42f..2735d135a0a5 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -68,7 +68,7 @@
#define HANDLE_LOOPSTATE_IN_OUTER_LAYERS 1
-typedef void ispfwfunc __P((int, int, int, const u_int16_t **));
+typedef void ispfwfunc __P((int, int, int, u_int16_t **));
#ifdef ISP_TARGET_MODE
#define ISP_TARGET_FUNCTIONS 1
diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h
index f911a17a75b4..5362987af071 100644
--- a/sys/dev/isp/isp_target.h
+++ b/sys/dev/isp/isp_target.h
@@ -409,9 +409,9 @@ typedef struct {
isphdr_t ct_header;
u_int16_t ct_reserved;
u_int16_t ct_fwhandle; /* just to match CTIO */
- u_int8_t ct_lun; /* lun */
- u_int8_t ct_iid; /* initiator id */
- u_int16_t ct_rxid; /* response ID */
+ u_int8_t ct_lun; /* lun */
+ u_int8_t ct_iid; /* initiator id */
+ u_int16_t ct_rxid; /* response ID */
u_int16_t ct_flags;
u_int16_t ct_status; /* isp status */
u_int16_t ct_timeout;
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index c89f7d06207c..53025f1f27b8 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -73,7 +73,7 @@ struct ispmdvec {
void (*dv_reset0) (struct ispsoftc *);
void (*dv_reset1) (struct ispsoftc *);
void (*dv_dregs) (struct ispsoftc *, const char *);
- const u_int16_t *dv_ispfw; /* ptr to f/w */
+ u_int16_t *dv_ispfw; /* ptr to f/w */
u_int16_t dv_conf1;
u_int16_t dv_clock; /* clock frequency */
};
@@ -396,6 +396,8 @@ typedef struct ispsoftc {
volatile u_int16_t isp_reqodx; /* index of last ISP pickup */
volatile u_int16_t isp_reqidx; /* index of next request */
volatile u_int16_t isp_residx; /* index of next result */
+ volatile u_int16_t isp_resodx; /* index of next result */
+ volatile u_int16_t isp_rspbsy;
volatile u_int16_t isp_lasthdls; /* last handle seed */
volatile u_int16_t isp_mboxtmp[MAX_MAILBOX];
volatile u_int16_t isp_lastmbxcmd; /* last mbox command sent */