diff options
author | mjacob <mjacob@cvs.openbsd.org> | 2001-09-01 07:16:41 +0000 |
---|---|---|
committer | mjacob <mjacob@cvs.openbsd.org> | 2001-09-01 07:16:41 +0000 |
commit | 12d884abf1047520b53d046341e7575af4e4b3b3 (patch) | |
tree | 1758d469abfa46037bcdc4f646333a7e06c66dfd /sys/dev/pci | |
parent | 62aed17c49c1b0d9f5091657be7fa35f73271aac (diff) |
Catch up with mainline of code development.
Add support for 2 Gigabit cards (2300/2312). This necessitated a change
in how interrupts are down- the 23XX has not only a different place to check
for an interrupt, but unlike all other QLogic cards, you have to read the
status as a 32 bit word- not 16 bit words. Rather than have device specific
functions as called from the core module (in isp_intr), it makes more sense
to have the platform/bus modules do the gruntwork of splitting out the
isr, semaphore register and the first outgoing mailbox register (if needed)
*prior* to calling isp_intr (if calling isp_intr is necessary at all).
Rearchitect how regular SCSI parameters are stored or used.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/isp_pci.c | 289 |
1 files changed, 221 insertions, 68 deletions
diff --git a/sys/dev/pci/isp_pci.c b/sys/dev/pci/isp_pci.c index 62288a04e62..2c77441df7a 100644 --- a/sys/dev/pci/isp_pci.c +++ b/sys/dev/pci/isp_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_pci.c,v 1.22 2001/08/26 03:32:22 jason Exp $ */ +/* $OpenBSD: isp_pci.c,v 1.23 2001/09/01 07:16:40 mjacob Exp $ */ /* * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. * @@ -46,6 +46,12 @@ 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); #endif +static int +isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); +#ifndef ISP_DISABLE_2300_SUPPORT +static int +isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *); +#endif static int isp_pci_mbxdma(struct ispsoftc *); static int isp_pci_dmasetup(struct ispsoftc *, struct scsi_xfer *, ispreq_t *, u_int16_t *, u_int16_t); @@ -61,6 +67,7 @@ static int isp_pci_intr (void *); #define ISP_COMPILE_12160_FW 1 #define ISP_COMPILE_2100_FW 1 #define ISP_COMPILE_2200_FW 1 +#define ISP_COMPILE_2300_FW 1 #endif #if defined(ISP_DISABLE_1040_SUPPORT) || !defined(ISP_COMPILE_1040_FW) @@ -98,8 +105,16 @@ static int isp_pci_intr (void *); #include <dev/microcode/isp/asm_2200.h> #endif +#if defined(ISP_DISABLE_2300_SUPPORT) || !defined(ISP_COMPILE_2300_FW) +#define ISP_2300_RISC_CODE NULL +#else +#define ISP_2300_RISC_CODE isp_2300_risc_code +#include <dev/microcode/isp/asm_2300.h> +#endif + #ifndef ISP_DISABLE_1020_SUPPORT static struct ispmdvec mdvec = { + isp_pci_rd_isr, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -115,6 +130,7 @@ static struct ispmdvec mdvec = { #ifndef ISP_DISABLE_1080_SUPPORT static struct ispmdvec mdvec_1080 = { + isp_pci_rd_isr, isp_pci_rd_reg_1080, isp_pci_wr_reg_1080, isp_pci_mbxdma, @@ -130,6 +146,7 @@ static struct ispmdvec mdvec_1080 = { #ifndef ISP_DISABLE_12160_SUPPORT static struct ispmdvec mdvec_12160 = { + isp_pci_rd_isr, isp_pci_rd_reg_1080, isp_pci_wr_reg_1080, isp_pci_mbxdma, @@ -145,6 +162,7 @@ static struct ispmdvec mdvec_12160 = { #ifndef ISP_DISABLE_2100_SUPPORT static struct ispmdvec mdvec_2100 = { + isp_pci_rd_isr, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -159,6 +177,7 @@ static struct ispmdvec mdvec_2100 = { #ifndef ISP_DISABLE_2200_SUPPORT static struct ispmdvec mdvec_2200 = { + isp_pci_rd_isr, isp_pci_rd_reg, isp_pci_wr_reg, isp_pci_mbxdma, @@ -171,6 +190,21 @@ static struct ispmdvec mdvec_2200 = { }; #endif +#ifndef ISP_DISABLE_2300_SUPPORT +static struct ispmdvec mdvec_2300 = { + isp_pci_rd_isr_2300, + isp_pci_rd_reg, + isp_pci_wr_reg, + isp_pci_mbxdma, + isp_pci_dmasetup, + isp_pci_dmateardown, + NULL, + isp_pci_reset1, + isp_pci_dumpregs, + ISP_2300_RISC_CODE +}; +#endif + #ifndef PCI_VENDOR_QLOGIC #define PCI_VENDOR_QLOGIC 0x1077 #endif @@ -203,6 +237,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_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) #define PCI_QLOGIC_ISP1080 \ @@ -223,6 +265,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) + #define IO_MAP_REG 0x10 #define MEM_MAP_REG 0x14 #define PCIR_ROMADDR 0x30 @@ -305,6 +353,11 @@ isp_pci_probe(struct device *parent, void *match, void *aux) case PCI_QLOGIC_ISP2200: return (1); #endif +#ifndef ISP_DISABLE_2300_SUPPORT + case PCI_QLOGIC_ISP2300: + case PCI_QLOGIC_ISP2312: + return (1); +#endif default: return (0); } @@ -506,6 +559,22 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG); } #endif +#ifndef ISP_DISABLE_2300_SUPPORT + if (pa->pa_id == PCI_QLOGIC_ISP2300 || + pa->pa_id == PCI_QLOGIC_ISP2312) { + isp->isp_mdvec = &mdvec_2300; + isp->isp_type = ISP_HA_FC_2300; + isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT); + if (isp->isp_param == NULL) { + printf(nomem); + return; + } + bzero(isp->isp_param, sizeof (fcparam)); + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2300_OFF; + data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG); + } +#endif /* * Set up logging levels. */ @@ -632,27 +701,127 @@ isp_pci_attach(struct device *parent, struct device *self, void *aux) } } +#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); +} + +#ifndef ISP_DISABLE_2300_SUPPORT +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); + } +} +#endif + static u_int16_t 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); - delay(250); + 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); - delay(250); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); } return (rv); } @@ -661,22 +830,19 @@ static void 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); - delay(250); + 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); - delay(250); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf); } } @@ -686,7 +852,6 @@ 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)) { @@ -694,29 +859,21 @@ isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) /* * We will assume that someone has paused the RISC processor. */ - oc = isp_pci_rd_reg(isp, BIU_CONF1); - tc = oc & ~(BIU_PCI1080_CONF1_DMA|BIU_PCI_CONF1_SXP); - if (IS_12X0(isp)) { - if (regoff & SXP_BANK1_SELECT) - tc |= BIU_PCI1080_CONF1_SXP0; - else - tc |= BIU_PCI1080_CONF1_SXP1; - } else { + 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); - delay(250); + 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); - delay(250); + 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); - delay(250); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); } return (rv); } @@ -724,9 +881,8 @@ isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff) static void isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) { - u_int16_t oc = 0; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset; + int oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { @@ -734,29 +890,21 @@ isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val) /* * We will assume that someone has paused the RISC processor. */ - oc = isp_pci_rd_reg(isp, BIU_CONF1); - tc = oc & ~(BIU_PCI1080_CONF1_DMA|BIU_PCI_CONF1_SXP); - if (IS_12X0(isp)) { - if (regoff & SXP_BANK1_SELECT) - tc |= BIU_PCI1080_CONF1_SXP0; - else - tc |= BIU_PCI1080_CONF1_SXP1; - } else { + 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); - delay(250); + 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); - delay(250); + 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); - delay(250); + BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc); } } #endif @@ -929,17 +1077,22 @@ mbxsync: static int isp_pci_intr(void *arg) { - int r; + u_int16_t isr, sema, mbox; struct ispsoftc *isp = (struct ispsoftc *)arg; struct isp_pcisoftc *p = (struct isp_pcisoftc *)isp; - isp_bus_dmamap_sync(p->pci_dmat, p->pci_result_dmap, 0, - p->pci_result_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD); - - isp->isp_osinfo.onintstack = 1; - r = isp_intr(arg); - isp->isp_osinfo.onintstack = 0; - return (r); + isp->isp_intcnt++; + if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) { + isp->isp_intbogus++; + return (0); + } else { + isp_bus_dmamap_sync(p->pci_dmat, p->pci_result_dmap, 0, + p->pci_result_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD); + isp->isp_osinfo.onintstack = 1; + isp_intr(isp, isr, sema, mbox); + isp->isp_osinfo.onintstack = 0; + return (0); + } } static void |