diff options
author | mjacob <mjacob@FreeBSD.org> | 1999-11-21 03:18:22 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 1999-11-21 03:18:22 +0000 |
commit | 0d75a5b4eba342471dab7a58b0b0c2174f6e341b (patch) | |
tree | a6dff8dbe2b38abe4e075e90258dcc7155545506 | |
parent | 1a6884ad3f584d66a116f9c5cddd835db47113b4 (diff) | |
download | FreeBSD-src-0d75a5b4eba342471dab7a58b0b0c2174f6e341b.zip FreeBSD-src-0d75a5b4eba342471dab7a58b0b0c2174f6e341b.tar.gz |
Clean up stupidity in the isp_handle_other_response function- indexes
of queue entries have to be at least 16 bits now! If we're running
a 2100 less than rev 5, turn off loop fairness (per Qlogic errata). Fix
typo in checking against 2200 F/W revision. Slightly fix/reorder fabric
login stuff. Change to usage of isp_getrqentry for code clarity. Add some
defensive dual bus assumptions. Various cleanups, etc...
-rw-r--r-- | sys/dev/isp/isp.c | 288 |
1 files changed, 169 insertions, 119 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index f268ab5..6f7dc07 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -70,7 +70,7 @@ */ static int isp_parse_async __P((struct ispsoftc *, int)); static int isp_handle_other_response -__P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *)); +__P((struct ispsoftc *, ispstatusreq_t *, u_int16_t *)); static void isp_parse_status __P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *)); static void isp_fastpost_complete __P((struct ispsoftc *, u_int32_t)); @@ -133,7 +133,7 @@ isp_reset(isp) * case, we don't really use this yet, but we may in * the future. */ - if (isp->isp_used == 0) { + if (isp->isp_touched == 0) { /* * Just in case it was paused... */ @@ -149,7 +149,7 @@ isp_reset(isp) isp->isp_romfw_rev[1] = mbs.param[2]; isp->isp_romfw_rev[2] = mbs.param[3]; } - isp->isp_used = 1; + isp->isp_touched = 1; } DISABLE_INTS(isp); @@ -959,7 +959,14 @@ isp_fibre_init(isp) #else fcp->isp_fwoptions = 0; #endif + fcp->isp_fwoptions |= ICBOPT_FAIRNESS; + /* + * If this is a 2100 < revision 5, we have to turn off FAIRNESS. + */ + if ((isp->isp_type == ISP_HA_FC_2100) && isp->isp_revision < 5) { + fcp->isp_fwoptions &= ~ICBOPT_FAIRNESS; + } fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; /* @@ -1076,12 +1083,6 @@ isp_fibre_init(isp) * Whatever happens, we're now committed to being here. */ isp->isp_state = ISP_INITSTATE; - -#ifdef ISP_TARGET_MODE - if (isp_modify_lun(isp, 0, 1, 1)) { - PRINTF("%s: failed to enable target mode\n", isp->isp_name); - } -#endif } /* @@ -1234,7 +1235,7 @@ isp_fclink_test(isp, waitdelay) return (-1); } fcp->isp_loopid = mbs.param[1]; - if (isp->isp_type == ISP_HA_FC_2100) { + if (isp->isp_type == ISP_HA_FC_2200) { if (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(2, 0, 14)) { topo = (int) mbs.param[6]; } @@ -1345,11 +1346,11 @@ isp_pdb_sync(isp, target) * FL_PORT_ID times). */ tport = fcp->tport; + /* + * make sure the temp port database is clean... + */ MEMZERO((void *) tport, sizeof (tport)); for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) { - /* - * make sure the temp port database is clean... - */ lp = &tport[loopid]; lp->node_wwn = isp_get_portname(isp, loopid, 1); if (lp->node_wwn == 0) @@ -1372,7 +1373,7 @@ isp_pdb_sync(isp, target) * asked for, restart the process entirely (up to a point...). */ if (pdb.pdb_loopid != loopid) { - IDPRINTF(0, ("%s: wankage (%d != %d)\n", + IDPRINTF(1, ("%s: wankage (%d != %d)\n", isp->isp_name, pdb.pdb_loopid, loopid)); loopid = 0; if (lim++ < FL_PORT_ID) { @@ -1575,7 +1576,7 @@ isp_pdb_sync(isp, target) continue; /* - * Tell the outside world we've gone away; + * Tell the outside world we've gone away. */ loopid = lp - fcp->portdb; (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); @@ -1619,48 +1620,94 @@ isp_pdb_sync(isp, target) mbs.param[2] = lp->portid >> 16; mbs.param[3] = lp->portid & 0xffff; isp_mboxcmd(isp, &mbs); - if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { - lp->valid = 1; - lp->fabdev = 1; - if (isp_getpdb(isp, loopid, &pdb) != 0) { - /* - * Be kind... - */ - lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); - PRINTF("%s: Faked PortID 0x%x into LoopID %d\n", - isp->isp_name, lp->portid, lp->loopid); - } else if (pdb.pdb_loopid != lp->loopid) { - lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); - PRINTF("%s: Wanked PortID 0x%x to LoopID %d\n", - isp->isp_name, lp->portid, lp->loopid); - } else { - lp->roles = - (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> - SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); - lp->loopid = pdb.pdb_loopid; - lp->node_wwn = - (((u_int64_t)pdb.pdb_nodename[0]) << 56) | - (((u_int64_t)pdb.pdb_nodename[1]) << 48) | - (((u_int64_t)pdb.pdb_nodename[2]) << 40) | - (((u_int64_t)pdb.pdb_nodename[3]) << 32) | - (((u_int64_t)pdb.pdb_nodename[4]) << 24) | - (((u_int64_t)pdb.pdb_nodename[5]) << 16) | - (((u_int64_t)pdb.pdb_nodename[6]) << 8) | - (((u_int64_t)pdb.pdb_nodename[7])); - lp->port_wwn = - (((u_int64_t)pdb.pdb_portname[0]) << 56) | - (((u_int64_t)pdb.pdb_portname[1]) << 48) | - (((u_int64_t)pdb.pdb_portname[2]) << 40) | - (((u_int64_t)pdb.pdb_portname[3]) << 32) | - (((u_int64_t)pdb.pdb_portname[4]) << 24) | - (((u_int64_t)pdb.pdb_portname[5]) << 16) | - (((u_int64_t)pdb.pdb_portname[6]) << 8) | - (((u_int64_t)pdb.pdb_portname[7])); - (void) isp_async(isp, ISPASYNC_PDB_CHANGED, - &loopid); + switch (mbs.param[0]) { + case MBOX_COMMAND_COMPLETE: + break; + case MBOX_COMMAND_ERROR: + switch (mbs.param[1]) { + case 1: + PRINTF("%s: no loop\n", isp->isp_name); + break; + case 2: + PRINTF("%s: IOCB buffer could not be alloced\n", + isp->isp_name); + break; + case 3: + PRINTF("%s: could not alloc xchange resource\n", + isp->isp_name); + break; + case 4: + PRINTF("%s: ELS timeout\n", isp->isp_name); + break; + case 5: + PRINTF("%s: no fabric port\n", isp->isp_name); + break; + case 6: + PRINTF("%s: remote device cannot be a target\n", + isp->isp_name); + break; + default: + break; } + continue; + default: + continue; + } + + lp->valid = 1; + lp->fabdev = 1; + if (isp_getpdb(isp, loopid, &pdb) != 0) { + /* + * Be kind... + */ + lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); + PRINTF("%s: Faked PortID 0x%x into LoopID %d\n", + isp->isp_name, lp->portid, lp->loopid); + continue; + } + if (pdb.pdb_loopid != lp->loopid) { + lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); + PRINTF("%s: Wanked PortID 0x%x to LoopID %d\n", + isp->isp_name, lp->portid, lp->loopid); + continue; } + lp->roles = + (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; + lp->portid = BITS2WORD(pdb.pdb_portid_bits); + lp->loopid = loopid; + lp->node_wwn = + (((u_int64_t)pdb.pdb_nodename[0]) << 56) | + (((u_int64_t)pdb.pdb_nodename[1]) << 48) | + (((u_int64_t)pdb.pdb_nodename[2]) << 40) | + (((u_int64_t)pdb.pdb_nodename[3]) << 32) | + (((u_int64_t)pdb.pdb_nodename[4]) << 24) | + (((u_int64_t)pdb.pdb_nodename[5]) << 16) | + (((u_int64_t)pdb.pdb_nodename[6]) << 8) | + (((u_int64_t)pdb.pdb_nodename[7])); + lp->port_wwn = + (((u_int64_t)pdb.pdb_portname[0]) << 56) | + (((u_int64_t)pdb.pdb_portname[1]) << 48) | + (((u_int64_t)pdb.pdb_portname[2]) << 40) | + (((u_int64_t)pdb.pdb_portname[3]) << 32) | + (((u_int64_t)pdb.pdb_portname[4]) << 24) | + (((u_int64_t)pdb.pdb_portname[5]) << 16) | + (((u_int64_t)pdb.pdb_portname[6]) << 8) | + (((u_int64_t)pdb.pdb_portname[7])); + /* + * Check to make sure this all makes sense. + */ + if (lp->node_wwn && lp->port_wwn) { + (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); + continue; + } + lp->fabdev = lp->valid = 0; + PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x lost its WWN\n", + isp->isp_name, loopid, lp->loopid, lp->portid); + mbs.param[0] = MBOX_FABRIC_LOGOUT; + mbs.param[1] = lp->loopid << 8; + mbs.param[2] = 0; + mbs.param[3] = 0; + isp_mboxcmd(isp, &mbs); } #endif return (0); @@ -1734,7 +1781,7 @@ ispscsicmd(xs) ISP_SCSI_XFER_T *xs; { struct ispsoftc *isp; - u_int8_t iptr, optr; + u_int16_t iptr, optr; union { ispreq_t *_reqp; ispreqt2_t *_t2reqp; @@ -1823,7 +1870,8 @@ ispscsicmd(xs) /* * If our loop state is now such that we've just now * received a Port Database Change notification, then - * we have to go off and (re)synchronize our + * we have to go off and (re)synchronize our port + * database. */ if (fcp->isp_loopstate == LOOP_PDB_RCVD) { if (isp_pdb_sync(isp, target)) { @@ -1860,13 +1908,8 @@ ispscsicmd(xs) isp_update(isp); } - optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); - iptr = isp->isp_reqidx; - - reqp = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); - iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); - if (iptr == optr) { - IDPRINTF(0, ("%s: Request Queue Overflow\n", isp->isp_name)); + if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) { + IDPRINTF(1, ("%s: Request Queue Overflow\n", isp->isp_name)); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } @@ -1877,7 +1920,7 @@ ispscsicmd(xs) * than which we got here to send a command to. */ if (isp->isp_sendmarker) { - u_int8_t niptr, n = (IS_12X0(isp)? 2: 1); + u_int8_t n = (IS_12X0(isp)? 2: 1); /* * Check ports to send markers for... */ @@ -1891,23 +1934,15 @@ ispscsicmd(xs) reqp->req_modifier = SYNC_ALL; reqp->req_target = i << 7; /* insert bus number */ ISP_SWIZZLE_REQUEST(isp, reqp); + MemoryBarrier(); + ISP_ADD_REQUEST(isp, iptr); - /* - * Unconditionally update the input pointer anyway. - */ - ISP_WRITE(isp, INMAILBOX4, iptr); - isp->isp_reqidx = iptr; - - niptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); - if (niptr == optr) { - IDPRINTF(0, ("%s: Request Queue Overflow+\n", + if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) { + IDPRINTF(1, ("%s: Request Queue Overflow+\n", isp->isp_name)); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } - reqp = (ispreq_t *) - ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); - iptr = niptr; } } @@ -1993,8 +2028,7 @@ ispscsicmd(xs) isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs), reqp->req_cdb[0], XS_XFRLEN(xs))); MemoryBarrier(); - ISP_WRITE(isp, INMAILBOX4, iptr); - isp->isp_reqidx = iptr; + ISP_ADD_REQUEST(isp, iptr); isp->isp_nactive++; if (isp->isp_sendmarker) isp->isp_sendmarker = 0; @@ -2110,6 +2144,13 @@ isp_control(isp, ctl, arg) case ISPCTL_FCLINK_TEST: return (isp_fclink_test(isp, FC_FW_READY_DELAY)); +#ifdef ISP_TARGET_MODE + case ISPCTL_ENABLE_LUN: + return (isp_modify_lun, 1, arg)); + + case ISPCTL_MODIFY_LUN: + return (isp_modify_lun, 0, arg)); +#endif } return (-1); } @@ -2127,7 +2168,7 @@ isp_intr(arg) { ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs; struct ispsoftc *isp = arg; - u_int8_t iptr, optr; + u_int16_t iptr, optr; u_int16_t isr, isrb, sema; int i, nlooked = 0, ndone = 0; @@ -2190,7 +2231,7 @@ isp_intr(arg) while (optr != iptr) { ispstatusreq_t *sp; - u_int8_t oop; + u_int16_t oop; int buddaboom = 0; sp = (ispstatusreq_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr); @@ -2402,26 +2443,30 @@ isp_parse_async(isp, mbox) struct ispsoftc *isp; int mbox; { + int bus; u_int32_t fast_post_handle = 0; + /* + * It is not documented anywhere that bus is always in OUTMAILBOX6 + * for dual bus cards- and we don't have the h/w to prove it either, + * So we'll just assume...... + */ + if (IS_1080(isp) || IS_12X0(isp)) { + bus = ISP_READ(isp, OUTMAILBOX6); + } else { + bus = 0; + } + switch (mbox) { case MBOX_COMMAND_COMPLETE: /* sometimes these show up */ break; case ASYNC_BUS_RESET: - { - int bus; - if (IS_1080(isp) || IS_12X0(isp)) { - bus = ISP_READ(isp, OUTMAILBOX6); - } else { - bus = 0; - } isp->isp_sendmarker = (1 << bus); - isp_async(isp, ISPASYNC_BUS_RESET, &bus); #ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); + isp_target_async(isp, bus, ASYNC_BUS_RESET); #endif + isp_async(isp, ISPASYNC_BUS_RESET, &bus); break; - } case ASYNC_SYSTEM_ERROR: mbox = ISP_READ(isp, OUTMAILBOX1); PRINTF("%s: Internal FW Error @ RISC Addr 0x%x\n", @@ -2439,26 +2484,28 @@ isp_parse_async(isp, mbox) break; case ASYNC_QWAKEUP: - /* don't need to be chatty */ + /* + * We've just been notified that the Queue has woken up. + * We don't need to be chatty about this- just unlatch things + * and move on. + */ mbox = ISP_READ(isp, OUTMAILBOX4); break; case ASYNC_TIMEOUT_RESET: - PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name); - isp->isp_sendmarker = 1; + PRINTF("%s: timeout initiated SCSI bus reset of bus %d\n", + isp->isp_name, bus); + isp->isp_sendmarker = (1 << bus); #ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); + isp_target_async(isp, bus, ASYNC_TIMEOUT_RESET); #endif break; case ASYNC_DEVICE_RESET: - /* - * XXX: WHICH BUS? - */ - isp->isp_sendmarker = 1; - PRINTF("%s: device reset\n", isp->isp_name); + PRINTF("%s: device reset on bus %d\n", isp->isp_name, bus); + isp->isp_sendmarker = 1 << bus; #ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); + isp_target_async(isp, bus, ASYNC_DEVICE_RESET); #endif break; @@ -2482,9 +2529,6 @@ isp_parse_async(isp, mbox) break; case ASYNC_BUS_TRANSIT: - /* - * XXX: WHICH BUS? - */ mbox = ISP_READ(isp, OUTMAILBOX2); switch (mbox & 0x1c00) { case SXP_PINS_LVD_MODE: @@ -2516,7 +2560,7 @@ isp_parse_async(isp, mbox) * XXX: Set up to renegotiate again! */ /* Can only be for a 1080... */ - isp->isp_sendmarker = (1 << ISP_READ(isp, OUTMAILBOX6)); + isp->isp_sendmarker = (1 << bus); break; case ASYNC_CMD_CMPLT: @@ -2558,13 +2602,13 @@ isp_parse_async(isp, mbox) break; case ASYNC_LOOP_RESET: - isp->isp_sendmarker = 1; + isp->isp_sendmarker = 1 << bus; ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); PRINTF("%s: Loop RESET\n", isp->isp_name); #ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); + isp_target_async(isp, bus, ASYNC_LOOP_RESET); #endif break; @@ -2591,11 +2635,17 @@ isp_parse_async(isp, mbox) return (fast_post_handle); } +/* + * Handle other response entries. A pointer to the request queue output + * index is here in case we want to eat several entries at once, although + * this is not used currently. + */ + static int isp_handle_other_response(isp, sp, optrp) struct ispsoftc *isp; ispstatusreq_t *sp; - u_int8_t *optrp; + u_int16_t *optrp; { switch (sp->req_header.rqs_entry_type) { case RQSTYPE_ATIO: @@ -2609,12 +2659,14 @@ isp_handle_other_response(isp, sp, optrp) case RQSTYPE_CTIO2: case RQSTYPE_CTIO3: #ifdef ISP_TARGET_MODE - return(isp_target_notify(isp, sp, optrp)); + return (isp_target_entry(isp, sp)); #else /* FALLTHROUGH */ #endif case RQSTYPE_REQUEST: default: + PRINTF("%s: unhandled response type 0x%x\n", isp->isp_name, + sp->req_header.rqs_entry_type); return (-1); } } @@ -3023,7 +3075,7 @@ static u_int8_t mbpcnt[] = { MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */ MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */ MAKNIB(0, 0), /* 0x6d: */ - MAKNIB(8, 1), /* 0x6e: MBOX_SEND_SNS */ + MAKNIB(8, 2), /* 0x6e: MBOX_SEND_SNS */ MAKNIB(4, 3), /* 0x6f: MBOX_FABRIC_LOGIN */ MAKNIB(2, 1), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ MAKNIB(2, 1), /* 0x71: MBOX_FABRIC_LOGOUT */ @@ -3484,7 +3536,7 @@ again: mbs.param[0] = MBOX_GET_FW_STATE; isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - IDPRINTF(0, ("%s: isp_fw_state 0x%x\n", isp->isp_name, + IDPRINTF(1, ("%s: isp_fw_state 0x%x\n", isp->isp_name, mbs.param[0])); switch (mbs.param[0]) { case ASYNC_PDB_CHANGED: @@ -3657,17 +3709,15 @@ isp_setdfltparm(isp, channel) /* Platform specific.... */ fcp->isp_loopid = DEFAULT_LOOPID(isp); fcp->isp_nodewwn = DEFAULT_WWN(isp); - fcp->isp_portwwn = DEFAULT_WWN(isp); + fcp->isp_portwwn = 0; /* * Now try and read NVRAM */ - if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { - if (isp_read_nvram(isp)) { - PRINTF("%s: using default WWN 0x%08x%08x\n", - isp->isp_name, - (u_int32_t)(fcp->isp_portwwn >> 32), - (u_int32_t)(fcp->isp_portwwn & 0xffffffff)); - } + if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) || + (isp_read_nvram(isp))) { + PRINTF("%s: using Node WWN 0x%08x%08x\n", + isp->isp_name, (u_int32_t)(fcp->isp_nodewwn >> 32), + (u_int32_t)(fcp->isp_nodewwn & 0xffffffff)); } return; } |