diff options
| -rw-r--r-- | sys/dev/isp/isp.c | 310 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.c | 166 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.h | 12 | ||||
| -rw-r--r-- | sys/dev/isp/isp_pci.c | 269 | ||||
| -rw-r--r-- | sys/dev/isp/ispmbox.h | 45 | ||||
| -rw-r--r-- | sys/dev/isp/ispreg.h | 32 | ||||
| -rw-r--r-- | sys/dev/isp/ispvar.h | 59 |
7 files changed, 599 insertions, 294 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 6dd14e03a7cc..783fcea62b94 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -150,12 +150,14 @@ static void isp_parse_nvram_2100 __P((struct ispsoftc *, u_int8_t *)); * * Locking done elsewhere. */ + void isp_reset(struct ispsoftc *isp) { mbreg_t mbs; + u_int16_t code_org; int loops, i, touched, dodnld = 1; - char *revname = "????"; + char *btype = "????"; isp->isp_state = ISP_NILSTATE; @@ -163,7 +165,8 @@ isp_reset(struct ispsoftc *isp) /* * Basic types (SCSI, FibreChannel and PCI or SBus) * have been set in the MD code. We figure out more - * here. + * here. Possibly more refined types based upon PCI + * identification. Chip revision has been gathered. * * After we've fired this chip up, zero out the conf1 register * for SCSI adapters and do other settings for the 2100. @@ -205,6 +208,14 @@ isp_reset(struct ispsoftc *isp) } DISABLE_INTS(isp); + /* + * Set up default request/response queue in-pointer/out-pointer + * register indices. + */ + isp->isp_rqstinrp = INMAILBOX4; + isp->isp_rqstoutrp = OUTMAILBOX4; + isp->isp_respinrp = OUTMAILBOX5; + isp->isp_respoutrp = INMAILBOX5; /* * Put the board into PAUSE mode (so we can read the SXP registers @@ -215,13 +226,17 @@ isp_reset(struct ispsoftc *isp) if (IS_FC(isp)) { switch (isp->isp_type) { case ISP_HA_FC_2100: - revname = "2100"; + btype = "2100"; break; case ISP_HA_FC_2200: - revname = "2200"; + btype = "2200"; break; case ISP_HA_FC_2300: - revname = "2300"; + isp->isp_rqstinrp = BIU_REQINP; + isp->isp_rqstoutrp = BIU_REQOUTP; + isp->isp_respinrp = BIU_RSPINP; + isp->isp_respoutrp = BIU_RSPOUTP; + btype = "2300"; break; default: break; @@ -236,7 +251,7 @@ isp_reset(struct ispsoftc *isp) ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); } else if (IS_1240(isp)) { sdparam *sdp = isp->isp_param; - revname = "1240"; + btype = "1240"; isp->isp_clock = 60; sdp->isp_ultramode = 1; sdp++; @@ -252,13 +267,13 @@ isp_reset(struct ispsoftc *isp) isp->isp_clock = 100; if (IS_1280(isp)) - revname = "1280"; + btype = "1280"; else if (IS_1080(isp)) - revname = "1080"; + btype = "1080"; else if (IS_12160(isp)) - revname = "12160"; + btype = "12160"; else - revname = "<UNKLVD>"; + btype = "<UNKLVD>"; l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK; switch (l) { @@ -313,7 +328,7 @@ isp_reset(struct ispsoftc *isp) isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i); /* FALLTHROUGH */ case 1: - revname = "1020"; + btype = "1020"; isp->isp_type = ISP_HA_SCSI_1020; isp->isp_clock = 40; break; @@ -323,27 +338,27 @@ isp_reset(struct ispsoftc *isp) * run the clock rate up for that unless told to * do so by the Ultra Capable bits being set. */ - revname = "1020A"; + btype = "1020A"; isp->isp_type = ISP_HA_SCSI_1020A; isp->isp_clock = 40; break; case 3: - revname = "1040"; + btype = "1040"; isp->isp_type = ISP_HA_SCSI_1040; isp->isp_clock = 60; break; case 4: - revname = "1040A"; + btype = "1040A"; isp->isp_type = ISP_HA_SCSI_1040A; isp->isp_clock = 60; break; case 5: - revname = "1040B"; + btype = "1040B"; isp->isp_type = ISP_HA_SCSI_1040B; isp->isp_clock = 60; break; case 6: - revname = "1040C"; + btype = "1040C"; isp->isp_type = ISP_HA_SCSI_1040C; isp->isp_clock = 60; break; @@ -593,11 +608,16 @@ again: dodnld = 0; } + if (IS_2300(isp)) + code_org = ISP_CODE_ORG_2300; + else + code_org = ISP_CODE_ORG; + if (dodnld) { u_int16_t fwlen = isp->isp_mdvec->dv_ispfw[3]; for (i = 0; i < fwlen; i++) { mbs.param[0] = MBOX_WRITE_RAM_WORD; - mbs.param[1] = ISP_CODE_ORG + i; + mbs.param[1] = code_org + i; mbs.param[2] = isp->isp_mdvec->dv_ispfw[i]; isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { @@ -612,7 +632,7 @@ again: * Verify that it downloaded correctly. */ mbs.param[0] = MBOX_VERIFY_CHECKSUM; - mbs.param[1] = ISP_CODE_ORG; + mbs.param[1] = code_org; isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure"); @@ -631,8 +651,9 @@ again: * we still need to (re)start it. */ + mbs.param[0] = MBOX_EXEC_FIRMWARE; - mbs.param[1] = ISP_CODE_ORG; + mbs.param[1] = code_org; isp_mboxcmd(isp, &mbs, MBLOGNONE); /* give it a chance to start */ USEC_SLEEP(isp, 500); @@ -655,9 +676,9 @@ again: return; } isp_prt(isp, ISP_LOGCONFIG, - "Board Revision %s, %s F/W Revision %d.%d.%d", revname, - dodnld? "loaded" : "resident", mbs.param[1], mbs.param[2], - mbs.param[3]); + "Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d", + btype, isp->isp_revision, dodnld? "loaded" : "resident", + mbs.param[1], mbs.param[2], mbs.param[3]); if (IS_FC(isp)) { isp_prt(isp, ISP_LOGCONFIG, "Firmware Attributes = 0x%x", mbs.param[6]); @@ -871,8 +892,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[0] = MBOX_INIT_RES_QUEUE; mbs.param[1] = RESULT_QUEUE_LEN(isp); - mbs.param[2] = DMA_MSW(isp->isp_result_dma); - mbs.param[3] = DMA_LSW(isp->isp_result_dma); + mbs.param[2] = DMA_WD1(isp->isp_result_dma); + mbs.param[3] = DMA_WD0(isp->isp_result_dma); mbs.param[4] = 0; mbs.param[5] = 0; isp_mboxcmd(isp, &mbs, MBLOGALL); @@ -883,8 +904,8 @@ isp_scsi_init(struct ispsoftc *isp) mbs.param[0] = MBOX_INIT_REQ_QUEUE; mbs.param[1] = RQUEST_QUEUE_LEN(isp); - mbs.param[2] = DMA_MSW(isp->isp_rquest_dma); - mbs.param[3] = DMA_LSW(isp->isp_rquest_dma); + mbs.param[2] = DMA_WD1(isp->isp_rquest_dma); + mbs.param[3] = DMA_WD0(isp->isp_rquest_dma); mbs.param[4] = 0; isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { @@ -1142,6 +1163,8 @@ isp_fibre_init(struct ispsoftc *isp) /* * Right now we just set extended options to prefer point-to-point * over loop based upon some soft config options. + * + * NB: for the 2300, ICBOPT_EXTENDED is required. */ if (IS_2200(isp) || IS_2300(isp)) { icbp->icb_fwoptions |= ICBOPT_EXTENDED; @@ -1162,6 +1185,15 @@ isp_fibre_init(struct ispsoftc *isp) icbp->icb_xfwoptions = ICBXOPT_LOOP_2_PTP; break; } + if (IS_2300(isp)) { + if (isp->isp_revision < 2) { + icbp->icb_fwoptions &= ~ICBOPT_FAST_POST; + } + icbp->icb_xfwoptions |= ICBXOPT_RATE_AUTO; + } + } + + if (IS_2200(isp) || IS_2300(isp)) { /* * Turn on LIP F8 async event (1) * Turn on generate AE 8013 on all LIP Resets (2) @@ -1173,7 +1205,14 @@ isp_fibre_init(struct ispsoftc *isp) mbs.param[3] = 0; isp_mboxcmd(isp, &mbs, MBLOGALL); } - icbp->icb_logintime = 60; /* 60 second login timeout */ + icbp->icb_logintime = 30; /* 30 second login timeout */ + + if (IS_2300(isp)) { + ISP_WRITE(isp, isp->isp_rqstinrp, 0); + ISP_WRITE(isp, isp->isp_rqstoutrp, 0); + ISP_WRITE(isp, isp->isp_respinrp, 0); + ISP_WRITE(isp, isp->isp_respoutrp, 0); + } nwwn = ISP_NODEWWN(isp); pwwn = ISP_PORTWWN(isp); @@ -1193,10 +1232,14 @@ isp_fibre_init(struct ispsoftc *isp) } icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp); icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp); - icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_rquest_dma); - icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_rquest_dma); - icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_result_dma); - icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma); + icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma); + icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma); + icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); + icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); isp_prt(isp, ISP_LOGDEBUG1, "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions); ISP_SWIZZLE_ICB(isp, icbp); @@ -1207,12 +1250,12 @@ isp_fibre_init(struct ispsoftc *isp) */ mbs.param[0] = MBOX_INIT_FIRMWARE; mbs.param[1] = 0; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); mbs.param[4] = 0; mbs.param[5] = 0; - mbs.param[6] = 0; - mbs.param[7] = 0; + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { return; @@ -1242,8 +1285,8 @@ isp_getmap(struct ispsoftc *isp, fcpos_map_t *map) mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP; mbs.param[1] = 0; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); /* * Unneeded. For the 2100, except for initializing f/w, registers * 4/5 have to not be written to. @@ -1280,8 +1323,8 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp) mbs.param[0] = MBOX_GET_PORT_DB; mbs.param[1] = id << 8; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); /* * Unneeded. For the 2100, except for initializing f/w, registers * 4/5 have to not be written to. @@ -1289,8 +1332,8 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp) * mbs.param[5] = 0; * */ - mbs.param[6] = 0; - mbs.param[7] = 0; + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { ISP_UNSWIZZLE_AND_COPY_PDBP(isp, pdbp, fcp->isp_scratch); @@ -2183,9 +2226,13 @@ isp_scan_fabric(struct ispsoftc *isp) MEMZERO((void *) reqp, SNS_GAN_REQ_SIZE); reqp->snscb_rblen = SNS_GAN_RESP_SIZE >> 1; reqp->snscb_addr[RQRSP_ADDR0015] = - DMA_LSW(fcp->isp_scdma + 0x100); + DMA_WD0(fcp->isp_scdma + 0x100); reqp->snscb_addr[RQRSP_ADDR1631] = - DMA_MSW(fcp->isp_scdma + 0x100); + DMA_WD1(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR3247] = + DMA_WD2(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR4863] = + DMA_WD3(fcp->isp_scdma + 0x100); reqp->snscb_sblen = 6; reqp->snscb_data[0] = SNS_GAN; reqp->snscb_data[4] = portid & 0xffff; @@ -2193,10 +2240,13 @@ isp_scan_fabric(struct ispsoftc *isp) ISP_SWIZZLE_SNS_REQ(isp, reqp); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_GAN_REQ_SIZE >> 1; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); - mbs.param[6] = 0; - mbs.param[7] = 0; + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); + /* + * Leave 4 and 5 alone + */ + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); isp_mboxcmd(isp, &mbs, MBLOGNONE); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC) { @@ -2268,8 +2318,10 @@ isp_register_fc4_type(struct ispsoftc *isp) reqp = (sns_screq_t *) fcp->isp_scratch; MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE); reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1; - reqp->snscb_addr[RQRSP_ADDR0015] = DMA_LSW(fcp->isp_scdma + 0x100); - reqp->snscb_addr[RQRSP_ADDR1631] = DMA_MSW(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100); reqp->snscb_sblen = 22; reqp->snscb_data[0] = SNS_RFT; reqp->snscb_data[4] = fcp->isp_portid & 0xffff; @@ -2281,10 +2333,13 @@ isp_register_fc4_type(struct ispsoftc *isp) ISP_SWIZZLE_SNS_REQ(isp, reqp); mbs.param[0] = MBOX_SEND_SNS; mbs.param[1] = SNS_RFT_REQ_SIZE >> 1; - mbs.param[2] = DMA_MSW(fcp->isp_scdma); - mbs.param[3] = DMA_LSW(fcp->isp_scdma); - mbs.param[6] = 0; - mbs.param[7] = 0; + mbs.param[2] = DMA_WD1(fcp->isp_scdma); + mbs.param[3] = DMA_WD0(fcp->isp_scdma); + /* + * Leave 4 and 5 alone + */ + mbs.param[6] = DMA_WD3(fcp->isp_scdma); + mbs.param[7] = DMA_WD2(fcp->isp_scdma); isp_mboxcmd(isp, &mbs, MBLOGALL); if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded"); @@ -2603,12 +2658,12 @@ isp_start(XS_T *xs) } else { /* * If we don't know what tag to use, use HEAD OF QUEUE - * for Request Sense or Ordered (for safety's sake). + * for Request Sense or Simple. */ if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */ t2reqp->req_flags = REQFLAG_HTAG; else - t2reqp->req_flags = REQFLAG_OTAG; + t2reqp->req_flags = REQFLAG_STAG; } } else { sdparam *sdp = (sdparam *)isp->isp_param; @@ -2865,65 +2920,18 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg) */ #define MAX_REQUESTQ_COMPLETIONS 32 -int -isp_intr(void *arg) +void +isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox) { - struct ispsoftc *isp = arg; XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs; - u_int16_t iptr, optr, isr, sema, junk; + u_int16_t iptr, optr, junk; int i, nlooked = 0, ndone = 0; - if (IS_2100(isp)) { - i = 0; - do { - isr = ISP_READ(isp, BIU_ISR); - junk = ISP_READ(isp, BIU_ISR); - } while (isr != junk && ++i < 1000); - if (isr != junk) { - isp_prt(isp, ISP_LOGWARN, - "isr unsteady (%x, %x)", isr, junk); - } - i = 0; - do { - sema = ISP_READ(isp, BIU_SEMA); - junk = ISP_READ(isp, BIU_SEMA); - } while (sema != junk && ++i < 1000); - if (sema != junk) { - isp_prt(isp, ISP_LOGWARN, - "sema unsteady (%x, %x)", sema, junk); - } - } else { - isr = ISP_READ(isp, BIU_ISR); - sema = ISP_READ(isp, BIU_SEMA); - } - isp_prt(isp, ISP_LOGDEBUG3, "isp_intr isr %x sem %x", isr, sema); - isr &= INT_PENDING_MASK(isp); - sema &= BIU_SEMA_LOCK; - isp->isp_intcnt++; - if (isr == 0 && sema == 0) { - isp->isp_intbogus++; - return (0); - } - + /* + * Is this a mailbox related interrupt? + * The mailbox semaphore will be nonzero if so. + */ if (sema) { - u_int16_t mbox; - - if (IS_2100(isp)) { - i = 0; - do { - mbox = ISP_READ(isp, OUTMAILBOX0); - junk = ISP_READ(isp, OUTMAILBOX0);; - } while (junk != mbox && ++i < 1000); - if (mbox != junk) { - isp_prt(isp, ISP_LOGWARN, - "mailbox0 unsteady (%x, %x)", mbox, junk); - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - return (1); - } - } else { - mbox = ISP_READ(isp, OUTMAILBOX0); - } if (mbox & 0x4000) { int obits, i = 0; if ((obits = isp->isp_mboxbsy) != 0) { @@ -2949,9 +2957,9 @@ isp_intr(void *arg) } } if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) { - ISP_WRITE(isp, BIU_SEMA, 0); ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - return (1); + ISP_WRITE(isp, BIU_SEMA, 0); + return; } } @@ -2960,41 +2968,55 @@ isp_intr(void *arg) */ if (isp->isp_state != ISP_RUNSTATE) { isp_prt(isp, ISP_LOGWARN, - "interrupt (isr=%x, sema=%x) when not ready", isr, sema); - WRITE_RESPONSE_QUEUE_IN_POINTER(isp, - READ_RESPONSE_QUEUE_OUT_POINTER(isp)); + "interrupt (ISR=%x SEMA=%x) when not ready", isr, sema); + /* + * Thank you very much! *Burrrp*! + */ + WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, + READ_RESPONSE_QUEUE_IN_POINTER(isp)); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); ISP_WRITE(isp, BIU_SEMA, 0); - return (1); + return; } /* - * You *must* read the Response Queue Out Pointer - * prior to clearing the RISC interrupt. + * Get the current Response Queue Out Pointer. + * + * If we're a 2300, we can ask what hardware what it thinks. */ - optr = isp->isp_residx; + if (IS_2300(isp)) { + optr = ISP_READ(isp, isp->isp_respoutrp); + if (isp->isp_residx != optr) { + isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x", + optr, isp->isp_residx); + } + } else { + optr = isp->isp_residx; + } - if (IS_2100(isp)) { + /* + * You *must* read the Response Queue In Pointer + * prior to clearing the RISC interrupt. + */ + if (IS_2100(isp) || IS_2300(isp)) { i = 0; do { - iptr = READ_RESPONSE_QUEUE_OUT_POINTER(isp); - junk = READ_RESPONSE_QUEUE_OUT_POINTER(isp); + iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + junk = READ_RESPONSE_QUEUE_IN_POINTER(isp); } while (junk != iptr && ++i < 1000); if (iptr != junk) { ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); isp_prt(isp, ISP_LOGWARN, - "mailbox5 unsteady (%x, %x)", iptr, junk); - return (1); + "Response Queue Out Pointer Unstable (%x, %x)", + iptr, junk); + return; } } else { - iptr = READ_RESPONSE_QUEUE_OUT_POINTER(isp); + iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); } - if (sema) { - ISP_WRITE(isp, BIU_SEMA, 0); - } - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); if (optr == iptr && sema == 0) { /* @@ -3005,12 +3027,22 @@ isp_intr(void *arg) * make sure the old interrupt went away (to avoid 'ringing' * effects), but that didn't stop this from occurring. */ - junk = ISP_READ(isp, BIU_ISR); - isp_prt(isp, ISP_LOGDEBUG2, - "bogus intr- isr %x (%x) iptr %x optr %x", - isr, junk, iptr, optr); - isp->isp_intbogus++; + if (IS_2300(isp)) { + USEC_DELAY(100); + iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); + junk = ISP_READ(isp, BIU_R2HSTSLO); + } else { + junk = ISP_READ(isp, BIU_ISR); + } + if (optr == iptr) { + isp_prt(isp, ISP_LOGDEBUG0, + "bogus intr- isr %x (%x) iptr %x optr %x", + isr, junk, iptr, optr); + isp->isp_intbogus++; + } } + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); while (optr != iptr) { ispstatusreq_t *sp; @@ -3057,7 +3089,7 @@ isp_intr(void *arg) if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) { isp_prt(isp, ISP_LOGWARN, "continuation segment"); - WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr); + WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); continue; } if (sp->req_header.rqs_flags & RQSFLAG_FULL) { @@ -3089,7 +3121,7 @@ isp_intr(void *arg) "bad request handle %d (type 0x%x, flags 0x%x)", sp->req_handle, sp->req_header.rqs_entry_type, sp->req_header.rqs_flags); - WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr); + WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); continue; } xs = isp_find_xs(isp, sp->req_handle); @@ -3098,7 +3130,7 @@ isp_intr(void *arg) isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x in xflist", sp->req_handle); - WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr); + WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); continue; } isp_destroy_handle(isp, sp->req_handle); @@ -3233,7 +3265,10 @@ isp_intr(void *arg) * ISP's notion of what we've seen so far. */ if (nlooked) { - WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr); + WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); + /* + * While we're at it, reqad the requst queue out pointer. + */ isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); } @@ -3244,7 +3279,6 @@ isp_intr(void *arg) isp_done(xs); } } - return (1); } /* diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index a2a53750bd3a..d4bb57fa7b38 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -390,15 +390,16 @@ get_lun_statep(struct ispsoftc *isp, int bus, lun_id_t lun) tstate_t *tptr; if (lun == CAM_LUN_WILDCARD) { - tptr = &isp->isp_osinfo.tsdflt[bus]; - tptr->hold++; - return (tptr); + if (isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED) { + tptr = &isp->isp_osinfo.tsdflt[bus]; + tptr->hold++; + return (tptr); + } else { + return (NULL); + } } else { tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)]; } - if (tptr == NULL) { - return (NULL); - } do { if (tptr->lun == lun && tptr->bus == bus) { @@ -546,7 +547,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) struct ccb_en_lun *cel = &ccb->cel; tstate_t *tptr; u_int16_t rstat; - int bus, cmd, frozen = 0; + int bus, cmd, av, wildcard, frozen = 0; lun_id_t lun; target_id_t tgt; @@ -630,23 +631,23 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) } } + if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) { + wildcard = 1; + } else { + wildcard = 0; + } /* * Next check to see whether this is a target/lun wildcard action. - * - * If so, we enable/disable target mode but don't do any lun enabling. + * If so, we know that we can accept commands and send them + * upstream. Otherwise, we have to handle them locally. */ - if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) { - int av = bus << 31; + + if (wildcard) { tptr = &isp->isp_osinfo.tsdflt[bus]; if (cel->enable) { - if (isp->isp_osinfo.tmflags & (1 << bus)) { + if (isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED) { ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; - if (frozen) { - ISPLOCK_2_CAMLOCK(isp); - xpt_release_simq(isp->isp_sim, 1); - CAMLOCK_2_ISPLOCK(isp); - } return; } ccb->ccb_h.status = @@ -664,54 +665,72 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) } SLIST_INIT(&tptr->atios); SLIST_INIT(&tptr->inots); - av |= ENABLE_TARGET_FLAG; - av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); - if (av) { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_free_path(tptr->owner); - if (frozen) { - ISPLOCK_2_CAMLOCK(isp); - xpt_release_simq(isp->isp_sim, 1); - CAMLOCK_2_ISPLOCK(isp); - } - return; - } - isp->isp_osinfo.tmflags |= (1 << bus); + isp->isp_osinfo.tmflags |= TM_WILDCARD_ENABLED; } else { - if ((isp->isp_osinfo.tmflags & (1 << bus)) == 0) { - ccb->ccb_h.status = CAM_LUN_INVALID; - if (frozen) { - ISPLOCK_2_CAMLOCK(isp); - xpt_release_simq(isp->isp_sim, 1); - CAMLOCK_2_ISPLOCK(isp); - } + if (!(isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED)) { + ccb->ccb_h.status = CAM_REQ_CMP; return; } - if (are_any_luns_enabled(isp, bus)) { + if (tptr->hold) { ccb->ccb_h.status = CAM_SCSI_BUSY; - if (frozen) { - ISPLOCK_2_CAMLOCK(isp); - xpt_release_simq(isp->isp_sim, 1); - CAMLOCK_2_ISPLOCK(isp); - } return; } - av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); - if (av) { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - if (frozen) { - ISPLOCK_2_CAMLOCK(isp); - xpt_release_simq(isp->isp_sim, 1); - CAMLOCK_2_ISPLOCK(isp); - } - return; + xpt_free_path(tptr->owner); + isp->isp_osinfo.tmflags &= ~TM_WILDCARD_ENABLED; + } + } + + /* + * Now check to see whether this bus needs to be + * enabled/disabled with respect to target mode. + */ + + av = bus << 31; + if (cel->enable && (isp->isp_osinfo.tmflags & (1 << bus)) == 0) { + av |= ENABLE_TARGET_FLAG; + av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); + if (av) { + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + ISPLOCK_2_CAMLOCK(isp); + xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + if (wildcard) { + isp->isp_osinfo.tmflags &= ~TM_WILDCARD_ENABLED; + xpt_free_path(tptr->owner); } - isp->isp_osinfo.tmflags &= ~(1 << bus); - ccb->ccb_h.status = CAM_REQ_CMP; + return; + } + isp_prt(isp, ISP_LOGINFO, + "Target Mode enabled on channel %d", bus); + } else if (cel->enable == 0 && (isp->isp_osinfo.tmflags & (1 << bus)) && + wildcard) { + if (are_any_luns_enabled(isp, bus)) { + ccb->ccb_h.status = CAM_SCSI_BUSY; + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); + xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + return; } + av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); + if (av) { + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + if (frozen) { + ISPLOCK_2_CAMLOCK(isp); + xpt_release_simq(isp->isp_sim, 1); + CAMLOCK_2_ISPLOCK(isp); + } + return; + } + isp->isp_osinfo.tmflags &= ~(1 << bus); + ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); - isp_prt(isp, ISP_LOGINFO, "Target Mode %sabled on channel %d", - (cel->enable) ? "en" : "dis", bus); + isp_prt(isp, ISP_LOGINFO, + "Target Mode disabled on channel %d", bus); + } + + if (wildcard) { if (frozen) { ISPLOCK_2_CAMLOCK(isp); xpt_release_simq(isp->isp_sim, 1); @@ -850,7 +869,21 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb) "DISABLE LUN returned 0x%x", rstat); goto out; } + if (are_any_luns_enabled(isp, bus) == 0) { + av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av); + if (av) { + isp_prt(isp, ISP_LOGWARN, + "disable target mode on channel %d failed", + bus); + goto out; + } + isp->isp_osinfo.tmflags &= ~(1 << bus); + xpt_print_path(ccb->ccb_h.path); + isp_prt(isp, ISP_LOGINFO, + "Target Mode disabled on channel %d", bus); + } } + out: isp_vsema_rqe(isp); @@ -1571,8 +1604,12 @@ static void isp_poll(struct cam_sim *sim) { struct ispsoftc *isp = cam_sim_softc(sim); + u_int16_t isr, sema, mbox; + ISP_LOCK(isp); - (void) isp_intr(isp); + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + } ISP_UNLOCK(isp); } @@ -1609,7 +1646,8 @@ isp_watchdog(void *arg) ISP_LOCK(isp); handle = isp_find_handle(isp, xs); if (handle) { - u_int16_t r; + u_int16_t isr, sema, mbox; + if (XS_CMD_DONE_P(xs)) { isp_prt(isp, ISP_LOGDEBUG1, @@ -1626,12 +1664,12 @@ isp_watchdog(void *arg) } XS_CMD_S_WDOG(xs); - - r = ISP_READ(isp, BIU_ISR); - - if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) { + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + } + if (XS_CMD_DONE_P(xs)) { isp_prt(isp, ISP_LOGDEBUG2, - "watchdog cleanup (%x, %x)", handle, r); + "watchdog cleanup for handle 0x%x", handle); xpt_done((union ccb *) xs); } else if (XS_CMD_GRACE_P(xs)) { /* @@ -1649,7 +1687,7 @@ isp_watchdog(void *arg) isp_destroy_handle(isp, handle); xpt_print_path(xs->ccb_h.path); isp_prt(isp, ISP_LOGWARN, - "watchdog timeout (%x, %x)", handle, r); + "watchdog timeout for handle %x", handle); XS_SETERR(xs, CAM_CMD_TIMEOUT); XS_CMD_C_WDOG(xs); isp_done(xs); diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 46bec0d5dafb..b3110ce5ff12 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -103,6 +103,7 @@ struct isposinfo { #ifdef ISP_TARGET_MODE #define TM_WANTED 0x80 #define TM_BUSY 0x40 +#define TM_WILDCARD_ENABLED 0x20 #define TM_TMODE_ENABLED 0x03 u_int8_t tmflags; u_int8_t rstatus; @@ -328,12 +329,17 @@ isp_mbox_wait_complete(struct ispsoftc *isp) } else { int j; for (j = 0; j < 60 * 10000; j++) { - if (isp_intr(isp) == 0) { - USEC_DELAY(500); - } + u_int16_t isr, sema, mbox; if (isp->isp_mboxbsy == 0) { break; } + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + if (isp->isp_mboxbsy == 0) { + break; + } + } + USEC_DELAY(500); } if (isp->isp_mboxbsy != 0) { isp_prt(isp, ISP_LOGWARN, diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index 887841c18183..0341b10a21f1 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -45,24 +45,29 @@ #include <dev/isp/isp_freebsd.h> -static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int)); -static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t)); -static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int)); -static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t)); -static int isp_pci_mbxdma __P((struct ispsoftc *)); -static int isp_pci_dmasetup __P((struct ispsoftc *, XS_T *, - ispreq_t *, u_int16_t *, u_int16_t)); +static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int); +static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t); +static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int); +static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t); +static int +isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); +static int +isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); +static int isp_pci_mbxdma(struct ispsoftc *); +static int +isp_pci_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *, u_int16_t); static void -isp_pci_dmateardown __P((struct ispsoftc *, XS_T *, u_int16_t)); +isp_pci_dmateardown(struct ispsoftc *, XS_T *, u_int16_t); -static void isp_pci_reset1 __P((struct ispsoftc *)); -static void isp_pci_dumpregs __P((struct ispsoftc *, const char *)); +static void isp_pci_reset1(struct ispsoftc *); +static void isp_pci_dumpregs(struct ispsoftc *, const char *); #ifndef ISP_CODE_ORG #define ISP_CODE_ORG 0x1000 #endif static struct ispmdvec mdvec = { + isp_pci_rd_isr, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -76,6 +81,7 @@ static struct ispmdvec mdvec = { }; static struct ispmdvec mdvec_1080 = { + isp_pci_rd_isr, isp_pci_rd_reg_1080, isp_pci_wr_reg_1080, isp_pci_mbxdma, @@ -89,6 +95,7 @@ static struct ispmdvec mdvec_1080 = { }; static struct ispmdvec mdvec_12160 = { + isp_pci_rd_isr, isp_pci_rd_reg_1080, isp_pci_wr_reg_1080, isp_pci_mbxdma, @@ -102,6 +109,7 @@ static struct ispmdvec mdvec_12160 = { }; static struct ispmdvec mdvec_2100 = { + isp_pci_rd_isr, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -113,6 +121,19 @@ static struct ispmdvec mdvec_2100 = { }; static struct ispmdvec mdvec_2200 = { + isp_pci_rd_isr, + isp_pci_rd_reg, + isp_pci_wr_reg, + isp_pci_mbxdma, + isp_pci_dmasetup, + isp_pci_dmateardown, + NULL, + isp_pci_reset1, + isp_pci_dumpregs +}; + +static struct ispmdvec mdvec_2300 = { + isp_pci_rd_isr_2300, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -184,6 +205,14 @@ static struct ispmdvec mdvec_2200 = { #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 #endif +#ifndef PCI_PRODUCT_QLOGIC_ISP2300 +#define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 +#endif + +#ifndef PCI_PRODUCT_QLOGIC_ISP2312 +#define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 +#endif + #define PCI_QLOGIC_ISP1020 \ ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) @@ -205,6 +234,12 @@ static struct ispmdvec mdvec_2200 = { #define PCI_QLOGIC_ISP2200 \ ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC) +#define PCI_QLOGIC_ISP2300 \ + ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP2312 \ + ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC) + /* * Odd case for some AMI raid cards... We need to *not* attach to this. */ @@ -240,7 +275,7 @@ static device_method_t isp_pci_methods[] = { DEVMETHOD(device_attach, isp_pci_attach), { 0, 0 } }; -static void isp_pci_intr __P((void *)); +static void isp_pci_intr(void *); static driver_t isp_pci_driver = { "isp", isp_pci_methods, sizeof (struct isp_pcisoftc) @@ -277,6 +312,12 @@ isp_pci_probe(device_t dev) case PCI_QLOGIC_ISP2200: device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter"); break; + case PCI_QLOGIC_ISP2300: + device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter"); + break; + case PCI_QLOGIC_ISP2312: + device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter"); + break; default: return (ENXIO); } @@ -455,6 +496,14 @@ isp_pci_attach(device_t dev) pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; } + if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300 || + pci_get_devid(dev) == PCI_QLOGIC_ISP2312) { + mdvp = &mdvec_2300; + basetype = ISP_HA_FC_2300; + psize = sizeof (fcparam); + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2300_OFF; + } isp = &pcs->pci_isp; isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO); if (isp->isp_param == NULL) { @@ -698,68 +747,167 @@ static void isp_pci_intr(void *arg) { struct ispsoftc *isp = arg; + u_int16_t isr, sema, mbox; + ISP_LOCK(isp); - (void) isp_intr(isp); + isp->isp_intcnt++; + if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { + isp->isp_intbogus++; + } else { + isp_intr(isp, isr, sema, mbox); + } ISP_UNLOCK(isp); } + +#define IspVirt2Off(a, x) \ + (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \ + _BLK_REG_SHFT] + ((x) & 0xff)) + +#define BXR2(pcs, off) \ + bus_space_read_2(pcs->pci_st, pcs->pci_sh, off) +#define BXW2(pcs, off, v) \ + bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v) + + +static INLINE int +isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + u_int16_t val0, val1; + int i = 0; + + do { + val0 = BXR2(pcs, IspVirt2Off(isp, off)); + val1 = BXR2(pcs, IspVirt2Off(isp, off)); + } while (val0 != val1 && ++i < 1000); + if (val0 != val1) { + return (1); + } + *rp = val0; + return (0); +} + +static int +isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp, + u_int16_t *semap, u_int16_t *mbp) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + u_int16_t isr, sema; + + if (IS_2100(isp)) { + if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) { + return (0); + } + if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) { + return (0); + } + } else { + isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR)); + sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA)); + } + isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema); + isr &= INT_PENDING_MASK(isp); + sema &= BIU_SEMA_LOCK; + if (isr == 0 && sema == 0) { + return (0); + } + *isrp = isr; + if ((*semap = sema) != 0) { + if (IS_2100(isp)) { + if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) { + return (0); + } + } else { + *mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0)); + } + } + return (1); +} + +static int +isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp, + u_int16_t *semap, u_int16_t *mbox0p) +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + u_int32_t r2hisr; + + r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh, + IspVirt2Off(pcs, BIU_R2HSTSLO)); + isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr); + if ((r2hisr & BIU_R2HST_INTR) == 0) { + *isrp = 0; + return (0); + } + switch (r2hisr & BIU_R2HST_ISTAT_MASK) { + case ISPR2HST_ROM_MBX_OK: + case ISPR2HST_ROM_MBX_FAIL: + case ISPR2HST_MBX_OK: + case ISPR2HST_MBX_FAIL: + case ISPR2HST_ASYNC_EVENT: + case ISPR2HST_FPOST: + case ISPR2HST_FPOST_CTIO: + *isrp = r2hisr & 0xffff; + *mbox0p = (r2hisr >> 16); + *semap = 1; + return (1); + case ISPR2HST_RSPQ_UPDATE: + *isrp = r2hisr & 0xffff; + *mbox0p = 0; + *semap = 0; + return (1); + default: + return (0); + } +} + static u_int16_t -isp_pci_rd_reg(isp, regoff) - struct ispsoftc *isp; - int regoff; +isp_pci_rd_reg(struct ispsoftc *isp, int regoff) { u_int16_t rv; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset, oldconf = 0; + int oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ - oldconf = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); + oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), + oldconf | BIU_PCI_CONF1_SXP); } - offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; - offset += (regoff & 0xff); - rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); + rv = BXR2(pcs, IspVirt2Off(isp, regoff)); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { - isp_pci_wr_reg(isp, BIU_CONF1, oldconf); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); } return (rv); } static void -isp_pci_wr_reg(isp, regoff, val) - struct ispsoftc *isp; - int regoff; - u_int16_t val; +isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset, oldconf = 0; + int oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ - oldconf = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP); + oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), + oldconf | BIU_PCI_CONF1_SXP); } - offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; - offset += (regoff & 0xff); - bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); + BXW2(pcs, IspVirt2Off(isp, regoff), val); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { - isp_pci_wr_reg(isp, BIU_CONF1, oldconf); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); } } static u_int16_t -isp_pci_rd_reg_1080(isp, regoff) - struct ispsoftc *isp; - int regoff; +isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) { u_int16_t rv, oc = 0; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { @@ -767,34 +915,30 @@ isp_pci_rd_reg_1080(isp, regoff) /* * We will assume that someone has paused the RISC processor. */ - oc = isp_pci_rd_reg(isp, BIU_CONF1); + oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); tc = oc & ~BIU_PCI1080_CONF1_DMA; if (regoff & SXP_BANK1_SELECT) tc |= BIU_PCI1080_CONF1_SXP1; else tc |= BIU_PCI1080_CONF1_SXP0; - isp_pci_wr_reg(isp, BIU_CONF1, tc); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { - oc = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); + oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), + oc | BIU_PCI1080_CONF1_DMA); } - offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; - offset += (regoff & 0xff); - rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset); + rv = BXR2(pcs, IspVirt2Off(isp, regoff)); if (oc) { - isp_pci_wr_reg(isp, BIU_CONF1, oc); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); } return (rv); } static void -isp_pci_wr_reg_1080(isp, regoff, val) - struct ispsoftc *isp; - int regoff; - u_int16_t val; +isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset, oc = 0; + int oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { @@ -802,28 +946,27 @@ isp_pci_wr_reg_1080(isp, regoff, val) /* * We will assume that someone has paused the RISC processor. */ - oc = isp_pci_rd_reg(isp, BIU_CONF1); + oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); tc = oc & ~BIU_PCI1080_CONF1_DMA; if (regoff & SXP_BANK1_SELECT) tc |= BIU_PCI1080_CONF1_SXP1; else tc |= BIU_PCI1080_CONF1_SXP0; - isp_pci_wr_reg(isp, BIU_CONF1, tc); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { - oc = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA); + oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1)); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), + oc | BIU_PCI1080_CONF1_DMA); } - offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT]; - offset += (regoff & 0xff); - bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val); + BXW2(pcs, IspVirt2Off(isp, regoff), val); if (oc) { - isp_pci_wr_reg(isp, BIU_CONF1, oc); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); } } -static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); -static void isp_map_result __P((void *, bus_dma_segment_t *, int, int)); -static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int)); +static void isp_map_rquest(void *, bus_dma_segment_t *, int, int); +static void isp_map_result(void *, bus_dma_segment_t *, int, int); +static void isp_map_fcscrt(void *, bus_dma_segment_t *, int, int); struct imush { struct ispsoftc *isp; @@ -1552,7 +1695,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } #endif -static void dma2 __P((void *, bus_dma_segment_t *, int, int)); +static void dma2(void *, bus_dma_segment_t *, int, int); static void dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) @@ -1700,7 +1843,7 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq, struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; bus_dmamap_t *dp = NULL; mush_t mush, *mp; - void (*eptr) __P((void *, bus_dma_segment_t *, int, int)); + void (*eptr)(void *, bus_dma_segment_t *, int, int); #ifdef ISP_TARGET_MODE if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) { diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h index a69a272e7906..5c4b632bc933 100644 --- a/sys/dev/isp/ispmbox.h +++ b/sys/dev/isp/ispmbox.h @@ -219,16 +219,16 @@ typedef struct { */ #define WRITE_REQUEST_QUEUE_IN_POINTER(isp, value) \ - ISP_WRITE(isp, INMAILBOX4, value) + ISP_WRITE(isp, isp->isp_rqstinrp, value) -#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \ - ISP_READ(isp, OUTMAILBOX4) +#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \ + ISP_READ(isp, isp->isp_rqstoutrp) -#define WRITE_RESPONSE_QUEUE_IN_POINTER(isp, value) \ - ISP_WRITE(isp, INMAILBOX5, value) +#define READ_RESPONSE_QUEUE_IN_POINTER(isp) \ + ISP_READ(isp, isp->isp_respinrp) -#define READ_RESPONSE_QUEUE_OUT_POINTER(isp) \ - ISP_READ(isp, OUTMAILBOX5) +#define WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value) \ + ISP_WRITE(isp, isp->isp_respoutrp, value) /* * Command Structure Definitions @@ -240,7 +240,8 @@ typedef struct { } ispds_t; typedef struct { - u_int64_t ds_base; + u_int32_t ds_base; + u_int32_t ds_basehi; u_int32_t ds_count; } ispds64_t; @@ -353,7 +354,7 @@ typedef struct { #define ISP_SBUSIFY_ISPREQ(a, b) #endif -#define ISP_RQDSEG_T2 3 +#define ISP_RQDSEG_T2 3 typedef struct { isphdr_t req_header; u_int32_t req_handle; @@ -369,6 +370,22 @@ typedef struct { ispds_t req_dataseg[ISP_RQDSEG_T2]; } ispreqt2_t; +#define ISP_RQDSEG_T3 2 +typedef struct { + isphdr_t req_header; + u_int32_t req_handle; + u_int8_t req_lun_trn; + u_int8_t req_target; + u_int16_t req_scclun; + u_int16_t req_flags; + u_int16_t _res2; + u_int16_t req_time; + u_int16_t req_seg_count; + u_int32_t req_cdb[4]; + u_int32_t req_totalcnt; + ispds64_t req_dataseg[ISP_RQDSEG_T3]; +} ispreqt3_t; + /* req_flag values */ #define REQFLAG_NODISCON 0x0001 #define REQFLAG_HTAG 0x0002 @@ -410,6 +427,12 @@ typedef struct { ispds_t req_dataseg[ISP_CDSEG]; } ispcontreq_t; +#define ISP_CDSEG64 5 +typedef struct { + isphdr_t req_header; + ispds64_t req_dataseg[ISP_CDSEG64]; +} ispcontreq64_t; + typedef struct { isphdr_t req_header; u_int32_t req_handle; @@ -630,6 +653,10 @@ typedef struct isp_icb { #define ICBXOPT_RIO_16BIT_DELAY 3 #define ICBXOPT_RIO_32BIT_DELAY 4 +/* These 3 only apply to the 2300 */ +#define ICBXOPT_RATE_ONEGB (0 << 14) +#define ICBXOPT_RATE_TWOGB (1 << 14) +#define ICBXOPT_RATE_AUTO (2 << 14) #define ICB_MIN_FRMLEN 256 diff --git a/sys/dev/isp/ispreg.h b/sys/dev/isp/ispreg.h index d50cdf76cb0d..390452553775 100644 --- a/sys/dev/isp/ispreg.h +++ b/sys/dev/isp/ispreg.h @@ -63,6 +63,7 @@ #define PCI_MBOX_REGS_OFF 0x70 #define PCI_MBOX_REGS2100_OFF 0x10 +#define PCI_MBOX_REGS2300_OFF 0x40 #define SBUS_MBOX_REGS_OFF 0x80 #define PCI_SXP_REGS_OFF 0x80 @@ -107,6 +108,37 @@ #define BIU_ISR (BIU_BLOCK+0xA) /* R : Bus Interface Status */ #define BIU_SEMA (BIU_BLOCK+0xC) /* RW : Bus Semaphore */ #define BIU_NVRAM (BIU_BLOCK+0xE) /* RW : Bus NVRAM */ +/* + * These are specific to the 2300. + * + * They *claim* you can read BIU_R2HSTSLO with a full 32 bit access + * and get both registers, but I'm a bit dubious about that. But the + * point here is that the top 16 bits are firmware defined bits that + * the RISC processor uses to inform the host about something- usually + * something which was nominally in a mailbox register. + */ +#define BIU_REQINP (BIU_BLOCK+0x10) /* Request Queue In */ +#define BIU_REQOUTP (BIU_BLOCK+0x12) /* Request Queue Out */ +#define BIU_RSPINP (BIU_BLOCK+0x14) /* Response Queue In */ +#define BIU_RSPOUTP (BIU_BLOCK+0x16) /* Response Queue Out */ + +#define BIU_R2HSTSLO (BIU_BLOCK+0x18) +#define BIU_R2HSTSHI (BIU_BLOCK+0x1A) + +#define BIU_R2HST_INTR (1 << 15) /* RISC to Host Interrupt */ +#define BIU_R2HST_PAUSED (1 << 8) /* RISC paused */ +#define BIU_R2HST_ISTAT_MASK 0x3f /* intr information && status */ +#define ISPR2HST_ROM_MBX_OK 0x1 /* ROM mailbox cmd done ok */ +#define ISPR2HST_ROM_MBX_FAIL 0x2 /* ROM mailbox cmd done fail */ +#define ISPR2HST_MBX_OK 0x10 /* mailbox cmd done ok */ +#define ISPR2HST_MBX_FAIL 0x11 /* mailbox cmd done fail */ +#define ISPR2HST_ASYNC_EVENT 0x12 /* Async Event */ +#define ISPR2HST_RSPQ_UPDATE 0x13 /* Response Queue Update */ +#define ISPR2HST_RQST_UPDATE 0x14 /* Resquest Queue Update */ +#define ISPR2HST_RIO_16 0x15 /* RIO 1-16 */ +#define ISPR2HST_FPOST 0x16 /* Low 16 bits fast post */ +#define ISPR2HST_FPOST_CTIO 0x17 /* Low 16 bits fast post ctio */ + #define DFIFO_COMMAND (BIU_BLOCK+0x60) /* RW : Command FIFO Port */ #define RDMA2100_CONTROL DFIFO_COMMAND #define DFIFO_DATA (BIU_BLOCK+0x62) /* RW : Data FIFO Port */ diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 8526866bff91..833f99ba0912 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -54,20 +54,22 @@ #endif #define ISP_CORE_VERSION_MAJOR 2 -#define ISP_CORE_VERSION_MINOR 2 +#define ISP_CORE_VERSION_MINOR 4 /* * Vector for bus specific code to provide specific services. */ struct ispsoftc; struct ispmdvec { + int (*dv_rd_isr) + (struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); u_int16_t (*dv_rd_reg) (struct ispsoftc *, int); void (*dv_wr_reg) (struct ispsoftc *, int, u_int16_t); int (*dv_mbxdma) (struct ispsoftc *); int (*dv_dmaset) (struct ispsoftc *, - XS_T *, ispreq_t *, u_int16_t *, u_int16_t); + XS_T *, ispreq_t *, u_int16_t *, u_int16_t); void (*dv_dmaclr) - (struct ispsoftc *, XS_T *, u_int16_t); + (struct ispsoftc *, XS_T *, u_int16_t); void (*dv_reset0) (struct ispsoftc *); void (*dv_reset1) (struct ispsoftc *); void (*dv_dregs) (struct ispsoftc *, const char *); @@ -79,16 +81,24 @@ struct ispmdvec { /* * Overall parameters */ -#define MAX_TARGETS 16 -#define MAX_FC_TARG 256 +#define MAX_TARGETS 16 +#define MAX_FC_TARG 256 #define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS) #define ISP_MAX_LUNS(isp) (isp)->isp_maxluns +/* + * 'Types' + */ +#ifndef ISP_DMA_ADDR_T +#define ISP_DMA_ADDR_T u_int32_t +#endif /* * Macros to access ISP registers through bus specific layers- * mostly wrappers to vector through the mdvec structure. */ +#define ISP_READ_ISR(isp, isrp, semap, mbox0p) \ + (*(isp)->isp_mdvec->dv_rd_isr)(isp, isrp, semap, mbox0p) #define ISP_READ(isp, reg) \ (*(isp)->isp_mdvec->dv_rd_reg)((isp), (reg)) @@ -152,7 +162,7 @@ struct ispmdvec { #define ISP_ADD_REQUEST(isp, iptr) \ MEMORYBARRIER(isp, SYNC_REQUEST, iptr, QENTRY_LEN); \ - ISP_WRITE(isp, INMAILBOX4, iptr); \ + WRITE_REQUEST_QUEUE_IN_POINTER(isp, iptr); \ isp->isp_reqidx = iptr /* @@ -284,7 +294,7 @@ typedef struct { * Scratch DMA mapped in area to fetch Port Database stuff, etc. */ caddr_t isp_scratch; - u_int32_t isp_scdma; + ISP_DMA_ADDR_T isp_scdma; } fcparam; #define FW_CONFIG_WAIT 0 @@ -350,6 +360,11 @@ typedef struct ispsoftc { u_int32_t isp_confopts; /* config options */ + u_int16_t isp_rqstinrp; /* register for REQINP */ + u_int16_t isp_rqstoutrp; /* register for REQOUTP */ + u_int16_t isp_respinrp; /* register for RESINP */ + u_int16_t isp_respoutrp; /* register for RESOUTP */ + /* * Instrumentation */ @@ -384,8 +399,8 @@ typedef struct ispsoftc { */ caddr_t isp_rquest; caddr_t isp_result; - u_int32_t isp_rquest_dma; - u_int32_t isp_result_dma; + ISP_DMA_ADDR_T isp_rquest_dma; + ISP_DMA_ADDR_T isp_result_dma; } ispsoftc_t; #define SDPARAM(isp) ((sdparam *) (isp)->isp_param) @@ -447,6 +462,7 @@ typedef struct ispsoftc { * Firmware related defines */ #define ISP_CODE_ORG 0x1000 /* default f/w code start */ +#define ISP_CODE_ORG_2300 0x0800 /* ..except for 2300s */ #define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic) #define ISP_FW_REVX(xp) ((xp[0]<<24) | (xp[1] << 16) | xp[2]) @@ -490,16 +506,15 @@ typedef struct ispsoftc { #define IS_FC(isp) ((isp)->isp_type & ISP_HA_FC) #define IS_2100(isp) ((isp)->isp_type == ISP_HA_FC_2100) #define IS_2200(isp) ((isp)->isp_type == ISP_HA_FC_2200) -#define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300) - -/* 2300 Support isn't ready yet */ -#define ISP_DISABLE_2300_SUPPORT 1 +#define IS_2300(isp) ((isp)->isp_type >= ISP_HA_FC_2300) /* * DMA cookie macros */ -#define DMA_MSW(x) (((x) >> 16) & 0xffff) -#define DMA_LSW(x) (((x) & 0xffff)) +#define DMA_WD3(x) 0 +#define DMA_WD2(x) 0 +#define DMA_WD1(x) (((x) >> 16) & 0xffff) +#define DMA_WD0(x) (((x) & 0xffff)) /* * Core System Function Prototypes @@ -522,9 +537,14 @@ void isp_init(struct ispsoftc *); void isp_reinit(struct ispsoftc *); /* - * Interrupt Service Routine + * Internal Interrupt Service Routine + * + * The outer layers do the spade work to get the appropriate status register, + * semaphore register and first mailbox register (if appropriate). This also + * means that most spurious/bogus interrupts not for us can be filtered first. */ -int isp_intr(void *); +void isp_intr(struct ispsoftc *, u_int16_t, u_int16_t, u_int16_t); + /* * Command Entry Point- Platform Dependent layers call into this @@ -689,6 +709,11 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...); * * INLINE - platform specific define for 'inline' functions * + * ISP_DMA_ADDR_T - platform specific dma address coookie- basically + * the largest integer that can hold the 32 or + * 64 bit value appropriate for the QLogic's DMA + * addressing. Defaults to u_int32_t. + * * ISP2100_SCRLEN - length for the Fibre Channel scratch DMA area * * MEMZERO(dst, src) platform zeroing function |
