diff options
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r-- | sys/dev/isp/isp.c | 813 |
1 files changed, 198 insertions, 615 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 1b8b9d893a7e..b93775007e83 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1,5 +1,4 @@ -/* $Id: isp.c,v 1.10 1999/01/10 02:55:10 mjacob Exp $ */ -/* release_12_28_98_A+ */ +/* $FreeBSD$ */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -52,7 +51,7 @@ #include <dev/isp/isp_freebsd.h> #endif #ifdef __linux__ -#include "isp_linux.h" +#include <isp_linux.h> #endif /* @@ -64,7 +63,7 @@ /* * Local static data */ -#ifdef ISP_TARGET_MODE +#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) static const char tgtiqd[36] = { 0x03, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x51, 0x4C, 0x4F, 0x47, 0x49, 0x43, 0x20, 0x20, @@ -89,16 +88,11 @@ static const char tgtiqd[36] = { /* * Local function prototypes. */ -static int isp_parse_async __P((struct ispsoftc *, int)); +static int isp_parse_async __P((struct ispsoftc *, u_int16_t)); static int isp_handle_other_response __P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *)); -#ifdef ISP_TARGET_MODE +#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) static int isp_modify_lun __P((struct ispsoftc *, int, int, int)); -static void isp_notify_ack __P((struct ispsoftc *, void *)); -static void isp_handle_atio __P((struct ispsoftc *, void *)); -static void isp_handle_atio2 __P((struct ispsoftc *, void *)); -static void isp_handle_ctio __P((struct ispsoftc *, void *)); -static void isp_handle_ctio2 __P((struct ispsoftc *, void *)); #endif static void isp_parse_status __P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *)); @@ -107,7 +101,7 @@ static void isp_fw_state __P((struct ispsoftc *)); static void isp_dumpregs __P((struct ispsoftc *, const char *)); static void isp_dumpxflist __P((struct ispsoftc *)); static void isp_prtstst __P((ispstatusreq_t *)); -static char *isp2100_fw_statename __P((int)); +static char *isp2100_fw_statename __P((u_int8_t)); static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *)); static void isp_update __P((struct ispsoftc *)); @@ -128,7 +122,7 @@ isp_reset(isp) { static char once = 1; mbreg_t mbs; - int loops, i, dodnld = 1, deadchip; + int loops, i, dodnld = 1; char *revname; isp->isp_state = ISP_NILSTATE; @@ -139,26 +133,16 @@ isp_reset(isp) * here. */ isp->isp_dblev = DFLT_DBLEVEL; - deadchip = ISP_READ(isp, HCCR) & HCCR_RESET; - if (deadchip) { - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); - if (ISP_READ(isp, HCCR) & HCCR_RESET) { - isp_dumpregs(isp, "still reset after release"); - SYS_DELAY(1000); - } else { - deadchip = 1; - } - } - if (isp->isp_type & ISP_HA_FC) { revname = "2100"; } else { sdparam *sdp = isp->isp_param; - i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK; - switch (i) { + + int rev = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK; + switch (rev) { default: PRINTF("%s: unknown chip rev. 0x%x- assuming a 1020\n", - isp->isp_name, i); + isp->isp_name, rev); /* FALLTHROUGH */ case 1: revname = "1020"; @@ -195,20 +179,16 @@ isp_reset(isp) * Try and figure out if we're connected to a differential bus. * You have to pause the RISC processor to read SXP registers. */ - if (deadchip == 0) { - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); - i = 100; - while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) { - SYS_DELAY(20); - if (--i == 0) { - isp_dumpregs(isp, - "cannot stop RISC processor"); - i = -1; - break; - } + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + i = 100; + while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) { + SYS_DELAY(20); + if (--i == 0) { + PRINTF("%s: unable to pause RISC processor\n", + isp->isp_name); + i = -1; + break; } - } else { - i = 0; } if (i > 0) { if (isp->isp_bustype != ISP_BT_SBUS) { @@ -243,10 +223,9 @@ isp_reset(isp) sdp->isp_clock = 40; } /* - * Restart processor, if necessary. + * Restart processor */ - if (deadchip == 0) - ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); + ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } /* * Machine dependent clock (if set) overrides @@ -264,7 +243,7 @@ isp_reset(isp) */ ISP_RESET0(isp); - if (once == 1 && deadchip == 0) { + if (once == 1) { once = 0; /* * Get the current running firmware revision out of the @@ -285,7 +264,6 @@ isp_reset(isp) } } - /* * Hit the chip over the head with hammer, * and give the ISP a chance to recover. @@ -353,21 +331,9 @@ isp_reset(isp) ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); SYS_DELAY(100); - /* - * Establish some initial burst rate thingies - * (only for the 1XX0 boards). This really should - * be done later after fetching from NVRAM. - */ if (isp->isp_type & ISP_HA_SCSI) { - u_int16_t conf1 = isp->isp_mdvec->dv_conf1; - /* - * Busted FIFO. Turn off all but burst enables. - */ - if (isp->isp_type == ISP_HA_SCSI_1040A) { - conf1 &= BIU_BURST_ENABLE; - } - ISP_SETBITS(isp, BIU_CONF1, conf1); - if (conf1 & BIU_BURST_ENABLE) { + ISP_SETBITS(isp, BIU_CONF1, isp->isp_mdvec->dv_conf1); + if (isp->isp_mdvec->dv_conf1 & BIU_BURST_ENABLE) { ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST); ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST); } @@ -740,7 +706,7 @@ isp_fibre_init(isp) fcparam *fcp; isp_icb_t *icbp; mbreg_t mbs; - int count, loopid; + int count; u_int8_t lwfs; fcp = isp->isp_param; @@ -749,41 +715,16 @@ isp_fibre_init(isp) PRINTF("%s: can't setup DMA for mailboxes\n", isp->isp_name); return; } - /* - * For systems that don't have BIOS methods for which - * we can easily change the NVRAM based loopid, we'll - * override that here. Note that when we initialize - * the firmware we may get back a different loopid than - * we asked for anyway. XXX This is probably not the - * best way to figure this out XXX - */ -#ifndef __i386__ - loopid = DEFAULT_LOOPID; -#else - loopid = fcp->isp_loopid; -#endif - icbp = (isp_icb_t *) fcp->isp_scratch; - MEMZERO(icbp, sizeof (*icbp)); + bzero(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; -#ifdef ISP_TARGET_MODE - fcp->isp_fwoptions = ICBOPT_TGT_ENABLE|ICBOPT_INI_TGTTYPE; -#else + fcp->isp_fwoptions = 0; -#endif - fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS; - fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; - fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; -#ifdef CHECKME - fcp->isp_fwoptions |= ICBOPT_USE_PORTNAME; -#endif -#ifdef THIS_WORKED - /* - * This has unhappiness in target mode - */ - fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; +#ifdef ISP2100_TARGET_MODE + fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE | ICBOPT_INI_TGTTYPE; + icbp->icb_iqdevtype = 0x23; /* DPQ_SUPPORTED/PROCESSOR */ #endif icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; @@ -796,13 +737,9 @@ isp_fibre_init(isp) icbp->icb_execthrottle = fcp->isp_execthrottle; icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; - icbp->icb_hardaddr = loopid; MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwn); - if (icbp->icb_fwoptions & ICBOPT_USE_PORTNAME) { - u_int64_t portname = fcp->isp_wwn | (2LL << 56); - MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, portname); - } + icbp->icb_rqstqlen = RQUEST_QUEUE_LEN; icbp->icb_rsltqlen = RESULT_QUEUE_LEN; icbp->icb_rqstaddr[RQRSP_ADDR0015] = @@ -851,15 +788,24 @@ isp_fibre_init(isp) isp->isp_residx = 0; /* - * Wait up to 5 seconds for FW to go to READY state. + * Wait up to 12 seconds for FW to go to READY state. + * This used to be 3 seconds, but that lost. + * + * This is all very much not right. The problem here + * is that the cable may not be plugged in, or there + * may be many many members of the loop that haven't + * been logged into. + * + * This model of doing things doesn't support dynamic + * attachment, so we just plain lose (for now). */ lwfs = FW_CONFIG_WAIT; for (count = 0; count < 12000; count++) { isp_fw_state(isp); if (lwfs != fcp->isp_fwstate) { PRINTF("%s: Firmware State %s -> %s\n", - isp->isp_name, isp2100_fw_statename((int)lwfs), - isp2100_fw_statename((int)fcp->isp_fwstate)); + isp->isp_name, isp2100_fw_statename(lwfs), + isp2100_fw_statename(fcp->isp_fwstate)); lwfs = fcp->isp_fwstate; } if (fcp->isp_fwstate == FW_READY) { @@ -882,14 +828,16 @@ isp_fibre_init(isp) } fcp->isp_loopid = mbs.param[1]; fcp->isp_alpa = mbs.param[2]; - PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name, + PRINTF("%s: Loop ID 0x%x, ALPA 0x%x\n", isp->isp_name, fcp->isp_loopid, fcp->isp_alpa); isp->isp_state = ISP_INITSTATE; -#ifdef ISP_TARGET_MODE +#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) DISABLE_INTS(isp); - if (isp_modify_lun(isp, 0, 1, 1)) { - PRINTF("%s: failed to enable target mode\n", - isp->isp_name); + if (isp->isp_fwrev >= ISP_FW_REV(1, 13)) { + if (isp_modify_lun(isp, 0, 1, 1)) { + PRINTF("%s: failed to establish target mode\n", + isp->isp_name); + } } ENABLE_INTS(isp); #endif @@ -900,6 +848,29 @@ isp_fibre_init(isp) } /* + * Free any associated resources prior to decommissioning and + * set the card to a known state (so it doesn't wake up and kick + * us when we aren't expecting it to). + * + * Locks are held before coming here. + */ +void +isp_uninit(isp) + struct ispsoftc *isp; +{ + /* + * Leave with interrupts disabled. + */ + DISABLE_INTS(isp); + + /* + * Stop the watchdog timer (if started). + */ + STOP_WATCHDOG(isp_watch, isp); +} + + +/* * Start a command. Locking is assumed done in the caller. */ @@ -964,7 +935,7 @@ ispscsicmd(xs) u_int8_t niptr; ispmarkreq_t *marker = (ispmarkreq_t *) reqp; - MEMZERO((void *) marker, sizeof (*marker)); + bzero((void *) marker, sizeof (*marker)); marker->req_header.rqs_entry_count = 1; marker->req_header.rqs_entry_type = RQSTYPE_MARKER; marker->req_modifier = SYNC_ALL; @@ -991,7 +962,7 @@ ispscsicmd(xs) iptr = niptr; } - MEMZERO((void *) reqp, UZSIZE); + bzero((void *) reqp, UZSIZE); reqp->req_header.rqs_entry_count = 1; if (isp->isp_type & ISP_HA_FC) { reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; @@ -1046,19 +1017,12 @@ ispscsicmd(xs) reqp->req_flags = 0; } } + reqp->req_lun_trn = XS_LUN(xs); reqp->req_target = XS_TGT(xs); if (isp->isp_type & ISP_HA_SCSI) { - reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); - } else { -#ifdef SCCLUN - reqp->req_scclun = XS_LUN(xs); -#else - reqp->req_lun_trn = XS_LUN(xs); -#endif - } - MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); + bcopy((void *)XS_CDBP(xs), reqp->req_cdb, XS_CDBLEN(xs)); IDPRINTF(5, ("%s(%d.%d): START%d cmd 0x%x datalen %d\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs), reqp->req_header.rqs_seqno, @@ -1158,18 +1122,7 @@ isp_control(isp, ctl, arg) break; } mbs.param[0] = MBOX_ABORT; -#ifdef SCCLUN - if (isp->isp_type & ISP_HA_FC) { - mbs.param[1] = XS_TGT(xs) << 8; - mbs.param[4] = 0; - mbs.param[5] = 0; - mbs.param[6] = XS_LUN(xs); - } else { - mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); - } -#else - mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); -#endif + mbs.param[1] = XS_TGT(xs) | XS_LUN(xs); mbs.param[2] = (i+1) >> 16; mbs.param[3] = (i+1) & 0xffff; isp_mboxcmd(isp, &mbs); @@ -1227,7 +1180,7 @@ isp_intr(arg) if (ISP_READ(isp, BIU_SEMA) & 1) { u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (isp_parse_async(isp, (int) mbox)) + if (isp_parse_async(isp, mbox)) return (1); ISP_WRITE(isp, BIU_SEMA, 0); } @@ -1319,14 +1272,14 @@ isp_intr(arg) XS_STS(xs) = sp->req_scsi_status & 0xff; if (isp->isp_type & ISP_HA_SCSI) { if (sp->req_state_flags & RQSF_GOT_SENSE) { - MEMCPY(XS_SNSP(xs), sp->req_sense_data, + bcopy(sp->req_sense_data, XS_SNSP(xs), XS_SNSLEN(xs)); XS_SNS_IS_VALID(xs); } } else { if (XS_STS(xs) == SCSI_CHECK) { XS_SNS_IS_VALID(xs); - MEMCPY(XS_SNSP(xs), sp->req_sense_data, + bcopy(sp->req_sense_data, XS_SNSP(xs), XS_SNSLEN(xs)); sp->req_state_flags |= RQSF_GOT_SENSE; } @@ -1346,9 +1299,8 @@ isp_intr(arg) } else { PRINTF("%s: unknown return %x\n", isp->isp_name, sp->req_header.rqs_entry_type); - if (XS_NOERR(xs)) { + if (XS_NOERR(xs)) XS_SETERR(xs, HBA_BOTCH); - } } if (isp->isp_type & ISP_HA_SCSI) { XS_RESID(xs) = sp->req_resid; @@ -1368,8 +1320,7 @@ isp_intr(arg) */ if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) { if (XS_NOERR(xs)) { - PRINTF("%s: ARQ failure for target %d lun %d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs)); + PRINTF("%s: ARQ Failure\n", isp->isp_name); XS_SETERR(xs, HBA_ARQFAIL); } } @@ -1389,8 +1340,9 @@ isp_intr(arg) } ISP_WRITE(isp, INMAILBOX5, optr); - if (isp->isp_nactive > 0) - isp->isp_nactive--; + isp->isp_nactive--; + if (isp->isp_nactive < 0) + isp->isp_nactive = 0; complist[ndone++] = xs; /* defer completion call until later */ } /* @@ -1417,15 +1369,12 @@ isp_intr(arg) static int isp_parse_async(isp, mbox) struct ispsoftc *isp; - int mbox; + u_int16_t mbox; { switch (mbox) { case ASYNC_BUS_RESET: PRINTF("%s: SCSI bus reset detected\n", isp->isp_name); isp->isp_sendmarker = 1; -#ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); -#endif break; case ASYNC_SYSTEM_ERROR: @@ -1452,16 +1401,10 @@ isp_parse_async(isp, mbox) case ASYNC_TIMEOUT_RESET: PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name); isp->isp_sendmarker = 1; -#ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); -#endif break; - case ASYNC_DEVICE_RESET: - PRINTF("%s: device reset\n", isp->isp_name); -#ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); -#endif + case ASYNC_UNSPEC_TMODE: + PRINTF("%s: mystery async target completion\n", isp->isp_name); break; case ASYNC_EXTMSG_UNDERRUN: @@ -1497,7 +1440,6 @@ isp_parse_async(isp, mbox) break; case ASYNC_CTIO_DONE: - /* Should only occur when Fast Posting Set for 2100s */ PRINTF("%s: CTIO done\n", isp->isp_name); break; @@ -1515,9 +1457,6 @@ isp_parse_async(isp, mbox) case ASYNC_LOOP_RESET: PRINTF("%s: Loop RESET\n", isp->isp_name); -#ifdef ISP_TARGET_MODE - isp_notify_ack(isp, NULL); -#endif break; case ASYNC_PDB_CHANGED: @@ -1544,122 +1483,62 @@ isp_handle_other_response(isp, sp, optrp) u_int8_t iptr, optr; int reqsize = 0; void *ireqp = NULL; -#ifdef ISP_TARGET_MODE - union { - at_entry_t *atio; - at2_entry_t *at2io; - ct_entry_t *ctio; - ct2_entry_t *ct2io; - lun_entry_t *lunen; - in_entry_t *inot; - in_fcentry_t *inot_fc; - na_entry_t *nack; - na_fcentry_t *nack_fc; - void *voidp; -#define atio un.atio -#define at2io un.at2io -#define ctio un.ctio -#define ct2io un.ct2io -#define lunen un.lunen -#define inot un.inot -#define inot_fc un.inot_fc -#define nack un.nack -#define nack_fc un.nack_fc - } un; - - un.voidp = sp; -#endif - switch (sp->req_header.rqs_entry_type) { case RQSTYPE_REQUEST: return (-1); -#ifdef ISP_TARGET_MODE +#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) case RQSTYPE_NOTIFY_ACK: { - static const char *f = - "%s: Notify Ack Status 0x%x Sequence Id 0x%x\n" - /* - * The ISP is acknowleding our ack of an Immediate Notify. - */ - if (isp->isp_type & ISP_HA_FC) { - PRINTF(f, isp->isp_name, - nack_fc->na-status, nack_fc->na_seqid); - } else { - PRINTF(f, isp->isp_name, - nack->na_status, nack->na_seqid); - } + ispnotify_t *spx = (ispnotify_t *) sp; + PRINTF("%s: Immediate Notify Ack %d.%d Status 0x%x Sequence " + "0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, + spx->req_status, spx->req_sequence); break; } case RQSTYPE_NOTIFY: { - u_int16_t seqid, status; - - /* - * Either the ISP received a SCSI message it cannot handle - * or some other out of band condition (e.g., Port Logout) - * or it is returning an Immediate Notify entry we sent. - */ - if (isp->isp_type & ISP_HA_FC) { - status = inot_fc->status; - seqid = inot_fc->in_seqid; - } else { - status = inot->status; - seqid = inot->seqid & 0xff; - } - PRINTF("%s: Immediate Notify Status 0x%x Sequence Id 0x%x\n", - isp->isp_name, status, seqid); - - switch (status) { - case IN_MSG_RECEIVED: - case IN_IDE_RECEIVED: - ptisp_got_msg(ptp, &inot); - break; - case IN_RSRC_UNAVAIL: - PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name); - break; - case IN_ABORT_TASK: - PRINTF("%s: Abort Task iid %d rx_id 0x%x\n", - inot_fc->in_iid, seqid); - break; - case IN_PORT_LOGOUT: - PRINTF("%s: Port Logout for Initiator %d\n", - isp->isp_name, inot_fc->in_iid); - break; - default: - PRINTF("%s: bad status (0x%x) in Immediate Notify\n", - isp->isp_name, status); - break; - - } - isp_notify_ack(isp, un.voidp); - reqsize = 0; + ispnotify_t *spx = (ispnotify_t *) sp; + + PRINTF("%s: Notify loopid %d to lun %d req_status 0x%x " + "req_task_flags 0x%x seq 0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, spx->req_status, + spx->req_task_flags, spx->req_sequence); + reqsize = sizeof (*spx); + spx->req_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + spx->req_header.rqs_entry_count = 1; + spx->req_header.rqs_flags = 0; + spx->req_header.rqs_seqno = isp->isp_seqno++; + spx->req_handle = (spx->req_initiator<<16) | RQSTYPE_NOTIFY_ACK; + if (spx->req_status == IN_RSRC_UNAVAIL) + spx->req_flags = LUN_INCR_CMD; + else if (spx->req_status == IN_NOCAP) + spx->req_flags = LUN_INCR_IMMED; + else { + reqsize = 0; + } + ireqp = spx; break; } case RQSTYPE_ENABLE_LUN: - case RQSTYPE_MODIFY_LUN: - if (lunen->req_status != 1) { - PRINTF("%s: ENABLE/MODIFY LUN returned status 0x%x\n", - isp->isp_name, lunen->req_status); + { + isplun_t *ip = (isplun_t *) sp; + if (ip->req_status != 1) { + PRINTF("%s: ENABLE LUN returned status 0x%x\n", + isp->isp_name, ip->req_status); } break; + } case RQSTYPE_ATIO2: { fcparam *fcp = isp->isp_param; ispctiot2_t local, *ct2 = NULL; ispatiot2_t *at2 = (ispatiot2_t *) sp; - int s, lun; + int s; -#ifdef SCCLUN - lun = at2->req_scclun; -#else - lun = at2->req_lun; -#endif - PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags0x%x " - "tflags0x%x ecodes0x%x rqstatus0x%x\n", isp->isp_name, - at2->req_initiator, lun, at2->req_rxid, - at2->req_flags, at2->req_taskflags, at2->req_execodes, - at2->req_status); + PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags 0x%x " + "task flags 0x%x exec codes 0x%x\n", isp->isp_name, + at2->req_initiator, at2->req_lun, at2->req_rxid, + at2->req_flags, at2->req_taskflags, at2->req_execodes); switch (at2->req_status & ~ATIO_SENSEVALID) { case ATIO_PATH_INVALID: @@ -1692,15 +1571,13 @@ isp_handle_other_response(isp, sp, optrp) } PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name, at2->req_datalen, at2->req_cdb[0]); - MEMZERO((void *) ct2, sizeof (*ct2)); + bzero ((void *) ct2, sizeof (*ct2)); ct2->req_header.rqs_entry_type = RQSTYPE_CTIO2; ct2->req_header.rqs_entry_count = 1; ct2->req_header.rqs_flags = 0; ct2->req_header.rqs_seqno = isp->isp_seqno++; - ct2->req_handle = (at2->req_initiator << 16) | lun; -#ifndef SCCLUN - ct2->req_lun = lun; -#endif + ct2->req_handle = (at2->req_initiator << 16) | at2->req_lun; + ct2->req_lun = at2->req_lun; ct2->req_initiator = at2->req_initiator; ct2->req_rxid = at2->req_rxid; @@ -1718,16 +1595,16 @@ isp_handle_other_response(isp, sp, optrp) ct2->req_seg_count = 1; if (at2->req_cdb[0] == 0x12) { s = sizeof(tgtiqd); - MEMCPY(fcp->isp_scratch, tgtiqd, s); + bcopy((void *)tgtiqd, fcp->isp_scratch, s); } else { s = at2->req_datalen; - MEMZERO(fcp->isp_scratch, s); + bzero(fcp->isp_scratch, s); } ct2->req_m.mode0.req_dataseg[0].ds_base = fcp->isp_scdma; ct2->req_m.mode0.req_dataseg[0].ds_count = s; ct2->req_m.mode0.req_datalen = s; -#if 1 +#if 0 if (at2->req_datalen < s) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RESP_VALID|CTIO2_RSPOVERUN; @@ -1741,7 +1618,7 @@ isp_handle_other_response(isp, sp, optrp) default: /* ALL OTHERS */ ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1; ct2->req_m.mode1.req_scsi_status = 0; -#if 1 +#if 0 if (at2->req_datalen) { ct2->req_m.mode1.req_scsi_status |= CTIO2_RSPUNDERUN; @@ -1773,8 +1650,9 @@ isp_handle_other_response(isp, sp, optrp) ct2->req_m.mode1.req_sense_len = 18; ct2->req_m.mode1.req_scsi_status |= at2->req_scsi_status; - MEMCPY(ct2->req_m.mode1.req_response, - at2->req_sense, sizeof (at2->req_sense)); + bcopy((void *)at2->req_sense, + (void *)ct2->req_m.mode1.req_response, + sizeof (at2->req_sense)); } break; } @@ -1801,15 +1679,6 @@ isp_handle_other_response(isp, sp, optrp) ireqp = at2; break; } -#undef atio -#undef at2io -#undef ctio -#undef ct2io -#undef lunen -#undef inot -#undef inot_fc -#undef nack -#undef nack_fc #endif default: PRINTF("%s: other response type %x\n", isp->isp_name, @@ -1826,7 +1695,7 @@ isp_handle_other_response(isp, sp, optrp) PRINTF("%s: Request Queue Overflow other response\n", isp->isp_name); } else { - MEMCPY(reqp, ireqp, reqsize); + bcopy(ireqp, reqp, reqsize); ISP_WRITE(isp, INMAILBOX4, iptr); isp->isp_reqidx = iptr; } @@ -1834,37 +1703,7 @@ isp_handle_other_response(isp, sp, optrp) return (0); } -#ifdef ISP_TARGET_MODE - -static void isp_tmd_newcmd_dflt __P((void *, tmd_cmd_t *)); -static void isp_tmd_event_dflt __P((void *, int)); -static void isp_tmd_notify_dflt __P((void *, tmd_notify_t *)); - -static void isp_tgt_data_xfer __P ((tmd_cmd_t *)); -static void isp_tgt_endcmd __P ((tmd_cmd_t *, u_int8_t)); -static void isp_tgt_done __P ((tmd_cmd_t *)); - -static void -isp_tmd_newcmd_dflt(arg0, cmdp) - void *arg0; - tmd_cmd_t *cmdp; -{ -} - -static void -isp_tmd_event_dflt(arg0, event) - void *arg0; - int event; -{ -} - -static void -isp_tmd_notify_dflt(arg0, npt) - void *arg0; - tmd_notify_t *npt; -{ -} - +#if defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE) /* * Locks held, and ints disabled (if FC). * @@ -1890,14 +1729,13 @@ isp_modify_lun(isp, lun, icnt, ccnt) return (-1); } - MEMZERO((void *) ip, sizeof (*ip)); + bzero((void *) ip, sizeof (*ip)); ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN; ip->req_header.rqs_entry_count = 1; + ip->req_header.rqs_flags = 0; ip->req_header.rqs_seqno = isp->isp_seqno++; ip->req_handle = RQSTYPE_ENABLE_LUN; - if (isp->isp_type & ISP_HA_SCSI) { - ip->req_lun = lun; - } + ip->req_lun = lun; ip->req_cmdcount = ccnt; ip->req_imcount = icnt; ip->req_timeout = 0; /* default 30 seconds */ @@ -1905,263 +1743,6 @@ isp_modify_lun(isp, lun, icnt, ccnt) isp->isp_reqidx = iptr; return (0); } - -static void -isp_notify_ack(isp, ptrp) - struct ispsoftc *isp; - void *ptrp; -{ - void *reqp; - u_int8_t iptr, optr; - union { - na_fcentry_t _naf; - na_entry_t _nas; - } un; - - MEMZERO((caddr_t)&un, sizeof (un)); - un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; - un._nas.na_header.rqs_entry_count = 1; - - if (isp->isp_type & ISP_HA_FC) { - na_fcentry_t *na = &un._nas; - if (ptrp) { - in_fcentry_t *inp = ptrp; - na->na_iid = inp->in_iid; - na->na_lun = inp->in_lun; - na->na_task_flags = inp->in_task_flags; - na->na_seqid = inp->in_seqid; - na->na_status = inp->in_status; - } else { - na->na_flags = NAFC_RST_CLRD; - } - } else { - na_entry_t *na = &un._nas; - if (ptrp) { - in_entry_t *inp = ptrp; - na->na_iid = inp->in_iid; - na->na_lun = inp->in_lun; - na->na_tgt = inp->in_tgt; - na->na_seqid = inp->in_seqid; - } else { - na->na_flags = NA_RST_CLRD; - } - } - optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); - iptr = isp->isp_reqidx; - reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); - iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); - if (iptr == optr) { - PRINTF("%s: Request Queue Overflow For isp_notify_ack\n", - isp->isp_name); - } else { - MEMCPY(reqp, ireqp, sizeof (un)); - ISP_WRITE(isp, INMAILBOX4, iptr); - isp->isp_reqidx = iptr; - } -} - -/* - * These are dummy stubs for now until the outside framework is plugged in. - */ - -static void -isp_handle_atio (isp, aep) - struct ispsoftc *isp; - at_entry_t *aep; -{ - int status, connected; - tmd_cmd_t local, *cdp = &local; - - /* - * Get the ATIO status and see if we're still connected. - */ - status = aep->at_status; - connected = ((aep->at_flags & AT_NODISC) != 0); - - PRINTF("%s: ATIO status=0x%x, connected=%d\n", isp->isp_name, - status, connected); - - /* - * The firmware status (except for the SenseValid bit) indicates - * why this ATIO was sent to us. - * If SenseValid is set, the firware has recommended Sense Data. - * If the Disconnects Disabled bit is set in the flags field, - * we're still connected on the SCSI bus - i.e. the initiator - * did not set DiscPriv in the identify message. We don't care - * about this so it's ignored. - */ - switch(status & ~TGTSVALID) { - case AT_PATH_INVALID: - /* - * ATIO rejected by the firmware due to disabled lun. - */ - PRINTF("%s: Firmware rejected ATIO for disabled lun %d\n", - isp->isp_name, aep->at_lun); - break; - - case AT_PHASE_ERROR: - /* - * Bus Pase Sequence error. - * - * The firmware should have filled in the correct - * sense data. - */ - - - if (status & TGTSVALID) { - MEMCPY(&cdp->cd_sensedata, aep->at_sense, - sizeof (cdp->cd_sensedata)); - PRINTF("%s: Bus Phase Sequence error key 0x%x\n", - isp->isp_name, cdp->cd_sensedata[2] & 0xf); - } else { - PRINTF("%s: Bus Phase Sequence With No Sense\n", - isp->isp_name); - } - (*isp->isp_tmd_newcmd)(isp, cdp); - break; - - case AT_NOCAP: - /* - * Requested Capability not available - * We sent an ATIO that overflowed the firmware's - * command resource count. - */ - PRINTF("%s: Firmware rejected ATIO, command count overflow\n", - isp->isp_name); - break; - - case AT_BDR_MSG: - /* - * If we send an ATIO to the firmware to increment - * its command resource count, and the firmware is - * recovering from a Bus Device Reset, it returns - * the ATIO with this status. - */ - PRINTF("%s: ATIO returned with BDR received\n", isp->isp_name); - break; - - case AT_CDB: - /* - * New CDB - */ - cdp->cd_hba = isp; - cdp->cd_iid = aep->at_iid; - cdp->cd_tgt = aep->at_tgt; - cdp->cd_lun = aep->at_lun; - cdp->cd_tagtype = aep->at_tag_type; - cdp->cd_tagval = aep->at_tag_val; - MEMCPY(cdp->cd_cdb, aep->at_cdb, 16); - PRINTF("%s: CDB 0x%x itl %d/%d/%d\n", isp->isp_name, - cdp->cd_cdb[0], cdp->cd_iid, cdp->cd_tgt, cdp->cd_lun); - (*isp->isp_tmd_newcmd)(isp, cdp); - break; - - default: - PRINTF("%s: Unknown status (0x%x) in ATIO\n", - isp->isp_name, status); - cdp->cd_hba = isp; - cdp->cd_iid = aep->at_iid; - cdp->cd_tgt = aep->at_tgt; - cdp->cd_lun = aep->at_lun; - cdp->cd_tagtype = aep->at_tag_type; - cdp->cd_tagval = aep->at_tag_val; - isp_tgtcmd_done(cdp); - break; - } -} - -static void -isp_handle_atio2(isp, aep) - struct ispsoftc *isp; - at2_entry_t *aep; -{ - int status; - tmd_cmd_t local, *cdp = &local; - - /* - * Get the ATIO2 status. - */ - status = aep->at_status; - PRINTD("%s: ATIO2 status=0x%x\n", status); - - /* - * The firmware status (except for the SenseValid bit) indicates - * why this ATIO was sent to us. - * If SenseValid is set, the firware has recommended Sense Data. - */ - switch(status & ~TGTSVALID) { - case AT_PATH_INVALID: - /* - * ATIO rejected by the firmware due to disabled lun. - */ - PRINTF("%s: Firmware rejected ATIO2 for disabled lun %d\n", - isp->isp_name, aep->at_lun); - break; - - case AT_NOCAP: - /* - * Requested Capability not available - * We sent an ATIO that overflowed the firmware's - * command resource count. - */ - PRINTF("%s: Firmware rejected ATIO2, command count overflow\n", - isp->isp_name); - break; - - case AT_BDR_MSG: - /* - * If we send an ATIO to the firmware to increment - * its command resource count, and the firmware is - * recovering from a Bus Device Reset, it returns - * the ATIO with this status. - */ - PRINTF("%s: ATIO2 returned with BDR rcvd\n", isp->isp_name); - break; - - case AT_CDB: - /* - * New CDB - */ - cdp->cd_hba = isp; - cdp->cd_iid = aep->at_iid; - cdp->cd_tgt = 0; - cdp->cd_lun = aep->at_lun; - MEMCPY(cdp->cd_cdb, aep->at_cdb, 16); - cdp->cd_rxid = aep->at_rxid; - cdp->cp_origdlen = aep->at_datalen; - cdp->cp_totbytes = 0; - PRINTF("%s: CDB 0x%x rx_id 0x%x itl %d/%d/%d dlen %d\n", - isp->isp_name, cdp->cd_cdb[0], cdp->cd_tagval, cdp->cd_iid, - cdp->cd_tgt, cdp->cd_lun, aep->at_datalen); - (*isp->isp_tmd_newcmd)(isp, cdp); - break; - - default: - PRINTF("%s: Unknown status (0x%x) in ATIO2\n", - isp->isp_name, status); - cdp->cd_hba = isp; - cdp->cd_iid = aep->at_iid; - cdp->cd_tgt = aep->at_tgt; - cdp->cd_lun = aep->at_lun; - cdp->cp_rxid = aep->at_rxid; - isp_tgtcmd_done(cdp); - break; - } -} - -static void -isp_handle_ctio(isp, cep) - struct ispsoftc *isp; - ct_entry_t *aep; -{ -} - -static void -isp_handle_ctio2(isp, cep) - struct ispsoftc *isp; - at2_entry_t *aep; -{ -} #endif static void @@ -2288,7 +1869,7 @@ isp_parse_status(isp, sp, xs) break; case RQCS_UNEXP_BUS_FREE: - PRINTF("%s: target %d lun %d had an unexpected bus free\n", + PRINTF("%s: target %d lun %d had unexeptected bus free\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs)); break; @@ -2323,17 +1904,8 @@ isp_parse_status(isp, sp, xs) break; case RQCS_QUEUE_FULL: - PRINTF("%s: internal queues full for target %d lun %d " - "status 0x%x\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs), - XS_STS(xs)); - /* - * If QFULL or some other status byte is set, then this - * isn't an error, per se. - */ - if (XS_STS(xs) != 0) { - XS_SETERR(xs, HBA_NOERROR); - return; - } + PRINTF("%s: internal queues full for target %d lun %d\n", + isp->isp_name, XS_TGT(xs), XS_LUN(xs)); break; case RQCS_PHASE_SKIPPED: @@ -2556,29 +2128,6 @@ isp_mboxcmd(isp, mbp) } - /* - * Check for variants - */ -#ifdef SCCLUN - if (isp->isp_type & ISP_HA_FC) { - switch (mbp->param[0]) { - case MBOX_ABORT: - inparam = 7; - break; - case MBOX_ABORT_DEVICE: - case MBOX_START_QUEUE: - case MBOX_STOP_QUEUE: - case MBOX_SINGLE_STEP_QUEUE: - case MBOX_ABORT_QUEUE: - case MBOX_GET_DEV_QUEUE_STATUS: - inparam = 3; - break; - default: - break; - } - } -#endif - command_known: /* @@ -2597,7 +2146,7 @@ command_known: isp->isp_name, ISP_READ(isp, BIU_ISR)); if (ISP_READ(isp, BIU_SEMA) & 1) { u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (isp_parse_async(isp, (int) mbox)) + if (isp_parse_async(isp, mbox)) return; ISP_WRITE(isp, BIU_SEMA, 0); } @@ -2726,13 +2275,8 @@ command_known: isp->isp_name, opcode); break; - /* - * Be silent about these... - */ - case ASYNC_LOOP_UP: case ASYNC_LIP_OCCURRED: - case ASYNC_PDB_CHANGED: break; default: @@ -2850,7 +2394,6 @@ again: isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { if (mbs.param[0] == ASYNC_LIP_OCCURRED || - mbs.param[0] == ASYNC_PDB_CHANGED || mbs.param[0] == ASYNC_LOOP_UP) { if (once++ < 2) { goto again; @@ -3106,14 +2649,59 @@ isp_restart(isp) if (XS_NULL(xs)) { continue; } - if (isp->isp_nactive > 0) - isp->isp_nactive--; + isp->isp_nactive--; + if (isp->isp_nactive < 0) { + isp->isp_nactive = 0; + } XS_RESID(xs) = XS_XFRLEN(xs); XS_SETERR(xs, HBA_BUSRESET); XS_CMD_DONE(xs); } } +void +isp_watch(arg) + void *arg; +{ + int i; + struct ispsoftc *isp = arg; + ISP_SCSI_XFER_T *xs; + ISP_LOCKVAL_DECL; + + /* + * Look for completely dead commands (but not polled ones). + */ + ISP_ILOCK(isp); + for (i = 0; i < RQUEST_QUEUE_LEN; i++) { + if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) { + continue; + } + if (XS_TIME(xs) == 0) { + continue; + } + XS_TIME(xs) -= (WATCH_INTERVAL * 1000); + /* + * Avoid later thinking that this + * transaction is not being timed. + * Then give ourselves to watchdog + * periods of grace. + */ + if (XS_TIME(xs) == 0) + XS_TIME(xs) = 1; + else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) { + continue; + } + if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { + PRINTF("%s: isp_watch failed to abort command\n", + isp->isp_name); + isp_restart(isp); + break; + } + } + ISP_IUNLOCK(isp); + RESTART_WATCHDOG(isp_watch, isp); +} + /* * Miscellaneous debug statements. */ @@ -3159,7 +2747,7 @@ isp_prtstst(sp) static char * isp2100_fw_statename(state) - int state; + u_int8_t state; { switch(state) { case FW_CONFIG_WAIT: return "Config Wait"; @@ -3232,9 +2820,9 @@ isp_read_nvram(isp) if (isp->isp_type & ISP_HA_SCSI) { sdparam *sdp = (sdparam *) isp->isp_param; + /* XXX CHECK THIS FOR SANITY XXX */ sdp->isp_fifo_threshold = - ISP_NVRAM_FIFO_THRESHOLD(nvram_data) | - (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2); + ISP_NVRAM_FIFO_THRESHOLD(nvram_data); sdp->isp_initiator_id = ISP_NVRAM_INITIATOR_ID(nvram_data); @@ -3276,6 +2864,8 @@ isp_read_nvram(isp) sdp->isp_tag_aging = ISP_NVRAM_TAG_AGE_LIMIT(nvram_data); + /* XXX ISP_NVRAM_FIFO_THRESHOLD_128 XXX */ + sdp->isp_selection_timeout = ISP_NVRAM_SELECTION_TIMEOUT(nvram_data); @@ -3284,12 +2874,6 @@ isp_read_nvram(isp) sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data); -#if 0 - PRINTF("%s: fifo_threshold = 0x%x cbena%d dbena%d\n", - isp->isp_name, sdp->isp_fifo_threshold, - sdp->isp_cmd_dma_burst_enable, - sdp->isp_data_dma_burst_enabl); -#endif for (i = 0; i < 16; i++) { sdp->isp_devparam[i].dev_enable = ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i); @@ -3364,9 +2948,8 @@ isp_read_nvram(isp) fcp->isp_wwn = wwnstore.full64; wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data); if (wwnstore.full64 != 0) { - PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", - isp->isp_name, wwnstore.wds.hi32, - wwnstore.wds.lo32); + PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", isp->isp_name, + wwnstore.wds.hi32, wwnstore.wds.lo32); } fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); |