📄 isp_pci.c
字号:
return (1); } vid = isp_pci->pci_dev->vendor; did = isp_pci->pci_dev->device;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) io_base = pci_resource_start(isp_pci->pci_dev, 0); if (pci_resource_flags(isp_pci->pci_dev, 0) & PCI_BASE_ADDRESS_MEM_TYPE_64) irq = 2; else irq = 1; mem_base = pci_resource_start(isp_pci->pci_dev, irq); if (pci_resource_flags(isp_pci->pci_dev, irq) & PCI_BASE_ADDRESS_MEM_TYPE_64) {#if BITS_PER_LONG == 64 mem_base |= pci_resource_start(isp_pci->pci_dev, irq+1) << 32;#else isp_pci_mapmem &= ~(1 << isp->isp_unit);#endif }#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) */ io_base = isp_pci->pci_dev->base_address[0]; mem_base = isp_pci->pci_dev->base_address[1]; if (mem_base & PCI_BASE_ADDRESS_MEM_TYPE_64) {#if BITS_PER_LONG == 64 mem_base |= isp_pci->pci_dev->base_address[2] << 32;#else isp_pci_mapmem &= ~(1 << isp->isp_unit);#endif }#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) */ irq = isp_pci->pci_dev->irq; if (vid != PCI_VENDOR_ID_QLOGIC) { printk("%s: 0x%04x is not QLogic's PCI Vendor ID\n", loc, vid); return (1); } isp_pci->poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF; isp_pci->poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF; isp_pci->poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF; isp_pci->poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF; isp_pci->poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; switch (did) { case PCI_DEVICE_ID_QLOGIC_ISP1020: break; case PCI_DEVICE_ID_QLOGIC_ISP1080: case PCI_DEVICE_ID_QLOGIC_ISP1240: case PCI_DEVICE_ID_QLOGIC_ISP1280: case PCI_DEVICE_ID_QLOGIC_ISP12160: isp_pci->poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; break; case PCI_DEVICE_ID_QLOGIC_ISP2200: case PCI_DEVICE_ID_QLOGIC_ISP2100: isp_pci->poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; break; case PCI_DEVICE_ID_QLOGIC_ISP2300: pci_cmd_isp &= ~PCI_COMMAND_INVALIDATE; /* per errata */ isp_pci->poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; break; case PCI_DEVICE_ID_QLOGIC_ISP2312: isp->isp_port = PCI_FUNC(isp_pci->pci_dev->devfn); isp_pci->poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF; break; default: printk("%s: Device ID 0x%04x is not a known Qlogic Device", loc, did); return (1); } /* * Bump unit seed- we're here, whether we complete the attachment or not. */ isp->isp_unit = isp_unit_seed++; sprintf(isp->isp_name, "isp%d", isp->isp_unit); isp->isp_osinfo.device_id = ((isp_pci->pci_dev->bus->number) << 16) | (PCI_SLOT(isp_pci->pci_dev->devfn) << 8) | (PCI_FUNC(isp_pci->pci_dev->devfn)); if (isp_disable & (1 << isp->isp_unit)) { isp_prt(isp, ISP_LOGALL, "disabled at user request"); return (1); }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (pci_enable_device(isp_pci->pci_dev)) { printk("%s: fails to be PCI_ENABLEd\n", loc); return (1); } (void) PRDW(isp_pci, PCI_COMMAND, &cmd);#endif if ((cmd & PCI_CMD_ISP) != pci_cmd_isp) { if (isp_debug & ISP_LOGINFO) printk("%s: rewriting command register from 0x%x to 0x%x\n", loc, cmd, (cmd & ~PCI_CMD_ISP) | pci_cmd_isp); cmd &= ~PCI_CMD_ISP; cmd |= pci_cmd_isp; PWRW(isp_pci, PCI_COMMAND, cmd); } if (lnsz != PCI_DFLT_LNSZ) { if (isp_debug & ISP_LOGINFO) printk("%s: rewriting cache line size from 0x%x to 0x%x\n", loc, lnsz, PCI_DFLT_LNSZ); lnsz = PCI_DFLT_LNSZ; PWRB(isp_pci, PCI_CACHE_LINE_SIZE, lnsz); }#ifdef __sparc__ if (PRDB(isp_pci, PCI_MIN_GNT, &rev)) { printk("%s: unable to read min grant\n", loc); return (1); } if (rev) { rev = (rev << 3) & 0xff; } if (rev == 0) { rev = 64; } if (isp_debug & ISP_LOGINFO) { printk("%s: rewriting latency timer from 0x%x to 0x%x\n", loc, timer, rev); } PWRB(isp_pci, PCI_LATENCY_TIMER, rev);#else if (timer < PCI_DFLT_LTNCY) { if (isp_debug & ISP_LOGINFO) printk("%s: rewriting latency timer from 0x%x to 0x%x\n", loc, timer, PCI_DFLT_LTNCY); timer = PCI_DFLT_LTNCY; PWRB(isp_pci, PCI_LATENCY_TIMER, timer); }#endif if ((cmd & (PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) == 0) {#ifdef __powerpc__ if (io_base == 0 && mem_base == 0) { printk("%s: you lose- no register access defined.\n", loc); return (1); } if (io_base) cmd |= PCI_COMMAND_IO; if (mem_base) cmd |= PCI_COMMAND_MEMORY; PWRW(isp_pci, PCI_COMMAND, cmd);#else printk("%s: you lose- no register access defined.\n", loc); return (1);#endif } /* * Disable the ROM. */ PWRL(isp_pci, PCI_ROM_ADDRESS, 0); /* * Set up stuff... */ isp_pci->port = isp_pci->vaddr = 0; /* * If we prefer to map memory space over I/O, try that first. */ if (isp_pci_mapmem & (1 << isp->isp_unit)) { if (map_isp_mem(isp_pci, cmd, mem_base) == 0) { if (map_isp_io(isp_pci, cmd, io_base) == 0) { isp_prt(isp, ISP_LOGERR, nomap); return (1); } } } else { if (map_isp_io(isp_pci, cmd, io_base) == 0) { if (map_isp_mem(isp_pci, cmd, mem_base) == 0) { isp_prt(isp, ISP_LOGERR, nomap); return (1); } } } if (isp_pci->vaddr) { isp_prt(isp, ISP_LOGCONFIG, "mapped memory 0x%lx at 0x%lx\n", isp_pci->paddr, isp_pci->vaddr); host->io_port = isp_pci->paddr; } else { isp_prt(isp, ISP_LOGCONFIG, "mapped I/O space at 0x%lx\n", isp_pci->port); host->io_port = isp_pci->port; } host->irq = 0; isp_pci->pci_isp.isp_revision = rev;#ifndef ISP_DISABLE_1020_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP1020) { isp_pci->pci_isp.isp_mdvec = &mdvec; isp_pci->pci_isp.isp_type = ISP_HA_SCSI_UNKNOWN; } #endif#ifndef ISP_DISABLE_1080_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP1080) { isp_pci->pci_isp.isp_mdvec = &mdvec_1080; isp_pci->pci_isp.isp_type = ISP_HA_SCSI_1080; } if (did == PCI_DEVICE_ID_QLOGIC_ISP1240) { isp_pci->pci_isp.isp_mdvec = &mdvec_1080; isp_pci->pci_isp.isp_type = ISP_HA_SCSI_1240; host->max_channel = 1; } if (did == PCI_DEVICE_ID_QLOGIC_ISP1280) { isp_pci->pci_isp.isp_mdvec = &mdvec_1080; isp_pci->pci_isp.isp_type = ISP_HA_SCSI_1280; host->max_channel = 1; }#endif#ifndef ISP_DISABLE_12160_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP12160) { isp_pci->pci_isp.isp_mdvec = &mdvec_12160; isp_pci->pci_isp.isp_type = ISP_HA_SCSI_12160; host->max_channel = 1; }#endif#ifndef ISP_DISABLE_2100_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP2100) { isp_pci->pci_isp.isp_mdvec = &mdvec_2100; isp_pci->pci_isp.isp_type = ISP_HA_FC_2100; }#endif#ifndef ISP_DISABLE_2200_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP2200) { isp_pci->pci_isp.isp_mdvec = &mdvec_2200; isp_pci->pci_isp.isp_type = ISP_HA_FC_2200; }#endif#ifndef ISP_DISABLE_2300_SUPPORT if (did == PCI_DEVICE_ID_QLOGIC_ISP2300) { isp_pci->pci_isp.isp_mdvec = &mdvec_2300; isp_pci->pci_isp.isp_type = ISP_HA_FC_2300; } if (did == PCI_DEVICE_ID_QLOGIC_ISP2312) { isp_pci->pci_isp.isp_mdvec = &mdvec_2300; isp_pci->pci_isp.isp_type = ISP_HA_FC_2312; }#endif if (request_irq(irq, isplinux_intr, SA_SHIRQ, isp->isp_name, isp_pci)) { isp_prt(isp, ISP_LOGERR, "could not snag irq %u (0x%x)", irq, irq); goto bad; } host->irq = irq; host->select_queue_depths = isplinux_sqd; isp->isp_param = &isp_pci->params;#ifdef LINUX_ISP_TARGET_MODE isp->isp_osinfo.pool = isp_pci->rpool;#endif /* * At this point, we're committed to keeping this adapter around. */ isplinux_common_init(isp); return (0);bad: if (host->irq) { DISABLE_INTS(isp); free_irq(host->irq, isp_pci); host->irq = 0; } if (isp_pci->vaddr != 0) { unmap_pci_mem(isp_pci->vaddr, 0xff); isp_pci->vaddr = 0; } else { release_region(isp_pci->port, 0xff); isp_pci->port = 0; } return (1);}static INLINE u_int16_tispregrd(struct isp_pcisoftc *pcs, vm_offset_t offset){ u_int16_t rv; if (pcs->vaddr) { offset += pcs->vaddr; rv = readw(offset); } else { offset += pcs->port; rv = inw(offset); } return (rv);}static INLINE voidispregwr(struct isp_pcisoftc *pcs, vm_offset_t offset, u_int16_t val){ if (pcs->vaddr) { offset += pcs->vaddr; writew(val, offset); } else { offset += pcs->port; outw(val, offset); } MEMORYBARRIER(isp, SYNC_REG, offset, 2);}static INLINE intisp_pci_rd_debounced(struct isp_pcisoftc *pcs, vm_offset_t off, u_int16_t *rp){ u_int16_t val0, val1; int i = 0; do { val0 = ispregrd(pcs, off); val1 = ispregrd(pcs, off); } while (val0 != val1 && ++i < 1000); if (val0 != val1) { return (1); } *rp = val0; return (0);}#define IspVirt2Off(a, x) \ ((a)->poff[((x) & _BLK_REG_MASK) >> _BLK_REG_SHFT] + ((x) & 0xff))static intisp_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(pcs, IspVirt2Off(pcs, BIU_ISR), &isr)) { return (0); } if (isp_pci_rd_debounced(pcs, IspVirt2Off(pcs, BIU_SEMA), &sema)) { return (0); } } else { isr = ispregrd(pcs, IspVirt2Off(pcs, BIU_ISR)); sema = ispregrd(pcs, IspVirt2Off(pcs, 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(pcs, IspVirt2Off(pcs, OUTMAILBOX0), mbp)) { return (0); } } else { *mbp = ispregrd(pcs, IspVirt2Off(pcs, OUTMAILBOX0)); } } return (1);}#ifndef ISP_DISABLE_2300_SUPPORTstatic INLINE u_int32_tispregrd32(struct isp_pcisoftc *pcs, vm_offset_t offset){ u_int32_t rv; if (pcs->vaddr) { offset += pcs->vaddr; rv = readl(offset); } else { offset += pcs->port; rv = inl(offset); } return (rv);}static intisp_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; /* * Avoid parity errors on the 2312. */ if (!(ispregrd(pcs, IspVirt2Off(pcs, BIU_ISR)) & BIU2100_ISR_RISC_INT)) { *isrp = 0; return (0); } r2hisr = ispregrd32(pcs, 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_RIO_16: 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); }}#endifstatic u_int16_tisp_pci_rd_reg(struct ispsoftc *isp, int regoff){ u_int16_t rv, oldconf = 0; struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ oldconf = ispregrd(pcs, IspVirt2Off(pcs, BIU_CONF1)); ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); } rv = ispregrd(pcs, IspVirt2Off(pcs, regoff)); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf); } return (rv);}static voidisp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val){ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; u_int16_t oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ oldconf = ispregrd(pcs, IspVirt2Off(pcs, BIU_CONF1)); ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP); } ispregwr(pcs, IspVirt2Off(pcs, regoff), val); if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf); }}#if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT))static u_int16_tisp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff){ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; u_int16_t rv, oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { u_int16_t tmpconf; /* * We will assume that someone has paused the RISC processor. */ oldconf = ispregrd(pcs, IspVirt2Off(pcs, BIU_CONF1)); tmpconf = oldconf & ~BIU_PCI1080_CONF1_DMA; if (IS_1280(isp)) { if (regoff & SXP_BANK1_SELECT) { tmpconf |= BIU_PCI1080_CONF1_SXP0; } else { tmpconf |= BIU_PCI1080_CONF1_SXP1; } } else { tmpconf |= BIU_PCI1080_CONF1_SXP0; } ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), tmpconf); } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) { oldconf = ispregrd(pcs, IspVirt2Off(pcs, BIU_CONF1)); ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf | BIU_PCI1080_CONF1_DMA); } rv = ispregrd(pcs, IspVirt2Off(pcs, regoff)); if (oldconf) { ispregwr(pcs, IspVirt2Off(pcs, BIU_CONF1), oldconf); } return (rv);}static voidisp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val){ struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; u_int16_t oldconf = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK || (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) { u_int16_t tmpconf; /* * We will assume that someone has paused the RISC processor. */ oldconf = ispregrd(pcs, IspVirt2Off(pcs, BIU_CONF1)); tmpconf = oldconf & ~BIU_PCI1080_CONF1_DMA; if (IS_1280(isp)) { if (regoff & SXP_BANK1_SELECT) { tmpconf |= BIU_PCI1080_CONF1_SXP0; } else { tmpconf |= BIU_PCI1080_CONF1_SXP1; } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -