diff options
| author | Matt Jacob <mjacob@FreeBSD.org> | 2001-08-31 21:39:04 +0000 |
|---|---|---|
| committer | Matt Jacob <mjacob@FreeBSD.org> | 2001-08-31 21:39:04 +0000 |
| commit | 126ec86486d4ed90e89f9aa760fdfc3d8a21ada3 (patch) | |
| tree | 27923f611af7ff56dad91ea26a66018b0045b5ae /sys/dev/isp/isp_pci.c | |
| parent | a2f1799115337d912cab193a43edb86eef3acd39 (diff) | |
Notes
Diffstat (limited to 'sys/dev/isp/isp_pci.c')
| -rw-r--r-- | sys/dev/isp/isp_pci.c | 269 |
1 files changed, 206 insertions, 63 deletions
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) { |
