diff options
Diffstat (limited to 'sys/pci/isp_pci.c')
-rw-r--r-- | sys/pci/isp_pci.c | 265 |
1 files changed, 185 insertions, 80 deletions
diff --git a/sys/pci/isp_pci.c b/sys/pci/isp_pci.c index 6f091d73..7508a0e 100644 --- a/sys/pci/isp_pci.c +++ b/sys/pci/isp_pci.c @@ -1,5 +1,5 @@ -/* $Id: isp_pci.c,v 1.14 1999/01/30 07:08:55 mjacob Exp $ */ -/* release_02_05_99 */ +/* $Id: isp_pci.c,v 1.15 1999/02/09 01:12:52 mjacob Exp $ */ +/* release_03_16_99 */ /* * PCI specific probe and attach routines for Qlogic ISP SCSI adapters. * FreeBSD Version. @@ -34,12 +34,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "opt_isp.h" - #include <dev/isp/isp_freebsd.h> #include <dev/isp/asm_pci.h> #include <sys/malloc.h> -#include <vm/vm.h> +#include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_extern.h> @@ -53,8 +51,14 @@ #include <machine/bus.h> #endif +#include "opt_isp.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)); +#ifndef ISP_DISABLE_1080_SUPPORT +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)); +#endif static int isp_pci_mbxdma __P((struct ispsoftc *)); static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *, ispreq_t *, u_int8_t *, u_int8_t)); @@ -68,6 +72,7 @@ isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t)); static void isp_pci_reset1 __P((struct ispsoftc *)); static void isp_pci_dumpregs __P((struct ispsoftc *)); +#ifndef ISP_DISABLE_1020_SUPPORT static struct ispmdvec mdvec = { isp_pci_rd_reg, isp_pci_wr_reg, @@ -84,7 +89,28 @@ static struct ispmdvec mdvec = { BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, 0 }; +#endif +#ifndef ISP_DISABLE_1080_SUPPORT +static struct ispmdvec mdvec_1080 = { + isp_pci_rd_reg_1080, + isp_pci_wr_reg_1080, + isp_pci_mbxdma, + isp_pci_dmasetup, + isp_pci_dmateardown, + NULL, + isp_pci_reset1, + isp_pci_dumpregs, + ISP_RISC_CODE, + ISP_CODE_LENGTH, + ISP_CODE_ORG, + ISP_CODE_VERSION, + BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64, + 0 +}; +#endif + +#ifndef ISP_DISABLE_2100_SUPPORT static struct ispmdvec mdvec_2100 = { isp_pci_rd_reg, isp_pci_wr_reg, @@ -101,6 +127,7 @@ static struct ispmdvec mdvec_2100 = { 0, /* Irrelevant to the 2100 */ 0 }; +#endif #ifndef SCSI_ISP_PREFER_MEM_MAP #ifdef __alpha__ @@ -135,27 +162,39 @@ static struct ispmdvec mdvec_2100 = { #define PCIR_LATTIMER 0x0d #endif - #ifndef PCI_VENDOR_QLOGIC -#define PCI_VENDOR_QLOGIC 0x1077 +#define PCI_VENDOR_QLOGIC 0x1077 #endif #ifndef PCI_PRODUCT_QLOGIC_ISP1020 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 #endif -#define PCI_QLOGIC_ISP \ - ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) +#ifndef PCI_PRODUCT_QLOGIC_ISP1080 +#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 +#endif + +#ifndef PCI_PRODUCT_QLOGIC_ISP1240 +#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 +#endif #ifndef PCI_PRODUCT_QLOGIC_ISP2100 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 #endif +#define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP1080 \ + ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC) + +#define PCI_QLOGIC_ISP1240 \ + ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC) + #define PCI_QLOGIC_ISP2100 \ ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC) -#define IO_MAP_REG 0x10 -#define MEM_MAP_REG 0x14 +#define IO_MAP_REG 0x10 +#define MEM_MAP_REG 0x14 #define PCI_DFLT_LTNCY 0x40 #define PCI_DFLT_LNSZ 0x10 @@ -172,7 +211,7 @@ typedef int bus_space_tag_t; typedef u_long bus_space_handle_t; #ifdef __alpha__ #define bus_space_read_2(st, sh, offset) \ - alpha_mb(), + alpha_mb(), (st == IO_SPACE_MAPPING)? \ inw((pci_port_t)sh + offset) : readw((pci_port_t)sh + offset) #define bus_space_write_2(st, sh, offset, val) \ @@ -201,6 +240,7 @@ struct isp_pcisoftc { pcici_t pci_id; bus_space_tag_t pci_st; bus_space_handle_t pci_sh; + int16_t pci_poff[_NREG_BLKS]; #if __FreeBSD_version >= 300004 bus_dma_tag_t parent_dmat; bus_dma_tag_t cntrol_dmat; @@ -230,17 +270,29 @@ DATA_SET (pcidevice_set, isp_pci_driver); static const char * isp_pci_probe(pcici_t tag, pcidi_t type) -{ +{ static int oneshot = 1; char *x; switch (type) { +#ifndef ISP_DISABLE_1020_SUPPORT case PCI_QLOGIC_ISP: - x = "Qlogic ISP 10X0 PCI SCSI Adapter"; + x = "Qlogic ISP 1020/1040 PCI SCSI Adapter"; + break; +#endif +#ifndef ISP_DISABLE_1080_SUPPORT + case PCI_QLOGIC_ISP1080: +#if 0 + case PCI_QLOGIC_ISP1240: /* 1240 not ready yet */ + x = "Qlogic ISP 1080/1240 PCI SCSI Adapter"; break; +#endif +#endif +#ifndef ISP_DISABLE_2100_SUPPORT case PCI_QLOGIC_ISP2100: x = "Qlogic ISP 2100 PCI FC-AL Adapter"; break; +#endif default: return (NULL); } @@ -254,7 +306,7 @@ isp_pci_probe(pcici_t tag, pcidi_t type) } -static void +static void isp_pci_attach(pcici_t config_id, int unit) { int mapped; @@ -320,36 +372,43 @@ isp_pci_attach(pcici_t config_id, int unit) isp = &pcs->pci_isp; #if __FreeBSD_version >= 300006 - (void) snprintf(isp->isp_name, sizeof(isp->isp_name), "isp%d", unit); + (void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit); #else (void) sprintf(isp->isp_name, "isp%d", unit); #endif isp->isp_osinfo.unit = unit; data = pci_conf_read(config_id, PCI_ID_REG); + pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; + pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; + pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; + pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; +#ifndef ISP_DISABLE_1020_SUPPORT if (data == PCI_QLOGIC_ISP) { isp->isp_mdvec = &mdvec; isp->isp_type = ISP_HA_SCSI_UNKNOWN; isp->isp_param = &pcs->_z._x; - } else if (data == PCI_QLOGIC_ISP2100) { + } +#endif +#ifndef ISP_DISABLE_1080_SUPPORT + if (data == PCI_QLOGIC_ISP1080 || data == PCI_QLOGIC_ISP1240) { + isp->isp_mdvec = &mdvec_1080; + isp->isp_type = ISP_HA_SCSI_1080; + isp->isp_param = &pcs->_z._x; + pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = + ISP1080_DMA_REGS_OFF; + } +#endif +#ifndef ISP_DISABLE_2100_SUPPORT + if (data == PCI_QLOGIC_ISP2100) { isp->isp_mdvec = &mdvec_2100; isp->isp_type = ISP_HA_FC_2100; isp->isp_param = &pcs->_z._y._a; - /* - * For some very early revisions, this dance had to occur. - */ -#ifdef NOT_NEEDED_ANY_MORE - ISP_LOCK(isp); - data = pci_conf_read(config_id, 0x30); - data &= ~1; - pci_conf_write(config_id, 0x30, data); - ISP_UNLOCK(isp); -#endif - } else { - printf("%s: unknown dev (%x)- punting\n", isp->isp_name, data); - free(pcs, M_DEVBUF); - return; + pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = + PCI_MBOX_REGS2100_OFF; } +#endif #if __FreeBSD_version >= 300004 ISP_LOCK(isp); @@ -417,15 +476,19 @@ isp_pci_attach(pcici_t config_id, int unit) } isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { - isp_uninit(isp); - ISP_UNLOCK(isp); - free(pcs, M_DEVBUF); - return; + /* If we're a Fibre Channel Card, we allow deferred attach */ + if (isp->isp_type & ISP_HA_SCSI) { + isp_uninit(isp); + free(pcs, M_DEVBUF); + } } isp_attach(isp); if (isp->isp_state != ISP_RUNSTATE) { - isp_uninit(isp); - free(pcs, M_DEVBUF); + /* If we're a Fibre Channel Card, we allow deferred attach */ + if (isp->isp_type & ISP_HA_SCSI) { + isp_uninit(isp); + free(pcs, M_DEVBUF); + } } ISP_UNLOCK(isp); #ifdef __alpha__ @@ -436,70 +499,114 @@ isp_pci_attach(pcici_t config_id, int unit) #endif } -#define PCI_BIU_REGS_OFF BIU_REGS_OFF +static u_int16_t +isp_pci_rd_reg(isp, regoff) + struct ispsoftc *isp; + int regoff; +{ + u_int16_t rv; + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + int offset, 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); + } + 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); + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { + isp_pci_wr_reg(isp, BIU_CONF1, oldconf); + } + return (rv); +} + +static void +isp_pci_wr_reg(isp, regoff, val) + struct ispsoftc *isp; + int regoff; + u_int16_t val; +{ + struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + int offset, 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); + } + 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); + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { + isp_pci_wr_reg(isp, BIU_CONF1, oldconf); + } +} + +#ifndef ISP_DISABLE_1080_SUPPORT static u_int16_t -isp_pci_rd_reg(struct ispsoftc *isp, int regoff) +isp_pci_rd_reg_1080(isp, regoff) + struct ispsoftc *isp; + int regoff; { u_int16_t rv; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset, oldsxp = 0; - - if ((regoff & BIU_BLOCK) != 0) { - offset = PCI_BIU_REGS_OFF; - } else if ((regoff & MBOX_BLOCK) != 0) { - if (isp->isp_type & ISP_HA_SCSI) - offset = PCI_MBOX_REGS_OFF; - else - offset = PCI_MBOX_REGS2100_OFF; - } else if ((regoff & SXP_BLOCK) != 0) { - offset = PCI_SXP_REGS_OFF; + int offset, oc = 0; + + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ - oldsxp = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP); - } else { - offset = PCI_RISC_REGS_OFF; + oc = isp_pci_rd_reg(isp, BIU_CONF1); + isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); + } 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); } - regoff &= 0xff; - offset += regoff; + 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); - if ((regoff & SXP_BLOCK) != 0) { - isp_pci_wr_reg(isp, BIU_CONF1, oldsxp); + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || + ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { + isp_pci_wr_reg(isp, BIU_CONF1, oc); } return (rv); } static void -isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val) +isp_pci_wr_reg_1080(isp, regoff, val) + struct ispsoftc *isp; + int regoff; + u_int16_t val; { struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; - int offset, oldsxp = 0; - if ((regoff & BIU_BLOCK) != 0) { - offset = PCI_BIU_REGS_OFF; - } else if ((regoff & MBOX_BLOCK) != 0) { - if (isp->isp_type & ISP_HA_SCSI) - offset = PCI_MBOX_REGS_OFF; - else - offset = PCI_MBOX_REGS2100_OFF; - } else if ((regoff & SXP_BLOCK) != 0) { - offset = PCI_SXP_REGS_OFF; + int offset, oc = 0; + + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ - oldsxp = isp_pci_rd_reg(isp, BIU_CONF1); - isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP); - } else { - offset = PCI_RISC_REGS_OFF; + oc = isp_pci_rd_reg(isp, BIU_CONF1); + isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP); + } 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); } - regoff &= 0xff; - offset += regoff; + 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); - if ((regoff & SXP_BLOCK) != 0) { - isp_pci_wr_reg(isp, BIU_CONF1, oldsxp); + if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || + ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { + isp_pci_wr_reg(isp, BIU_CONF1, oc); } } +#endif + #if __FreeBSD_version >= 300004 static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int)); @@ -770,7 +877,7 @@ isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, splx(s); } else { /* Pointer to physical buffer */ - struct bus_dma_segment seg; + struct bus_dma_segment seg; seg.ds_addr = (bus_addr_t)csio->data_ptr; seg.ds_len = csio->dxfer_len; dma2(mp, &seg, 1, 0); @@ -925,7 +1032,6 @@ isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, size = nextpaddr - paddr; if (size > datalen) size = datalen; - *(ctrp) += size; vaddr += size; datalen -= size; @@ -979,7 +1085,6 @@ isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, size = nextpaddr - paddr; if (size > datalen) size = datalen; - *(ctrp) += size; vaddr += size; datalen -= size; |