📄 isp_pci.c
字号:
} if (data == PCI_QLOGIC_ISP1240) { mdvp = &mdvec_1080; basetype = ISP_HA_SCSI_12X0; psize = 2 * sizeof (sdparam); pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF; }#endif#ifndef ISP_DISABLE_2100_SUPPORT if (data == PCI_QLOGIC_ISP2100) { mdvp = &mdvec_2100; basetype = ISP_HA_FC_2100; psize = sizeof (fcparam); pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF; data = pci_conf_read(config_id, PCI_CLASS_REG); if ((data & 0xff) < 3) { /* * XXX: Need to get the actual revision * XXX: number of the 2100 FB. At any rate, * XXX: lower cache line size for early revision * XXX; boards. */ linesz = 1; } }#endif isp = &pcs->pci_isp; isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT); if (isp->isp_param == NULL) { printf("isp%d: cannot allocate parameter data\n", unit); return; } bzero(isp->isp_param, psize); isp->isp_mdvec = mdvp; isp->isp_type = basetype;#if __FreeBSD_version >= 300006 (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;#if __FreeBSD_version >= 300004 ISP_LOCK(isp); /* * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER * are set. */ data = pci_cfgread(config_id, PCIR_COMMAND, 2); data |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; pci_cfgwrite(config_id, PCIR_COMMAND, 2, data); /* * Make sure the CACHE Line Size register is set sensibly. */ data = pci_cfgread(config_id, PCIR_CACHELNSZ, 1); if (data != linesz) { data = PCI_DFLT_LNSZ; printf("%s: set PCI line size to %d\n", isp->isp_name, data); pci_cfgwrite(config_id, PCIR_CACHELNSZ, data, 1); } /* * Make sure the Latency Timer is sane. */ data = pci_cfgread(config_id, PCIR_LATTIMER, 1); if (data < PCI_DFLT_LTNCY) { data = PCI_DFLT_LTNCY; printf("%s: set PCI latency to %d\n", isp->isp_name, data); pci_cfgwrite(config_id, PCIR_LATTIMER, data, 1); } /* * Make sure we've disabled the ROM. */ data = pci_cfgread(config_id, PCIR_ROMADDR, 4); data &= ~1; pci_cfgwrite(config_id, PCIR_ROMADDR, data, 4); ISP_UNLOCK(isp); if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1<<24, 255, 1<<24, 0, &pcs->parent_dmat) != 0) { printf("%s: could not create master dma tag\n", isp->isp_name); free(pcs, M_DEVBUF); return; }#else ISP_LOCK(isp); data = pci_conf_read(config_id, PCIR_COMMAND); data |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN; pci_conf_write(config_id, PCIR_COMMAND, data); data = pci_conf_read(config_id, PCIR_CACHELNSZ); if ((data & ~0xffff) != ((PCI_DFLT_LTNCY << 8) | linesz)) { data &= ~0xffff; data |= (PCI_DFLT_LTNCY << 8) | linesz; pci_conf_write(config_id, PCIR_CACHELNSZ, data); printf("%s: set PCI line size to %d\n", isp->isp_name, linesz); printf("%s: set PCI latency to %d\n", isp->isp_name, PCI_DFLT_LTNCY); } /* * Make sure we've disabled the ROM. */ data = pci_conf_read(config_id, PCIR_ROMADDR); data &= ~1; pci_conf_write(config_id, PCIR_ROMADDR, data); ISP_UNLOCK(isp);#endif if (pci_map_int(config_id, (void (*)(void *))isp_intr, (void *)isp, &IMASK) == 0) { printf("%s: could not map interrupt\n", isp->isp_name); free(pcs, M_DEVBUF); return; } pcs->pci_id = config_id;#ifdef SCSI_ISP_NO_FWLOAD_MASK if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit))) isp->isp_confopts |= ISP_CFG_NORELOAD;#endif#ifdef SCSI_ISP_NO_NVRAM_MASK if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) { printf("%s: ignoring NVRAM\n", isp->isp_name); isp->isp_confopts |= ISP_CFG_NONVRAM; }#endif ISP_LOCK(isp); isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { (void) pci_unmap_int(config_id); ISP_UNLOCK(isp); free(pcs, M_DEVBUF); return; } isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { /* If we're a Fibre Channel Card, we allow deferred attach */ if (isp->isp_type & ISP_HA_SCSI) { isp_uninit(isp); (void) pci_unmap_int(config_id); /* Does nothing */ ISP_UNLOCK(isp); free(pcs, M_DEVBUF); return; } } isp_attach(isp); if (isp->isp_state != ISP_RUNSTATE) { /* If we're a Fibre Channel Card, we allow deferred attach */ if (IS_SCSI(isp)) { isp_uninit(isp); (void) pci_unmap_int(config_id); /* Does nothing */ ISP_UNLOCK(isp); free(pcs, M_DEVBUF); return; } } ISP_UNLOCK(isp);#ifdef __alpha__ /* * THIS SHOULD NOT HAVE TO BE HERE */ alpha_register_pci_scsi(config_id->bus, config_id->slot, isp->isp_sim);#endif }static u_int16_tisp_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 voidisp_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_SUPPORTstatic u_int16_tisp_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, oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ 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); } 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 || ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { isp_pci_wr_reg(isp, BIU_CONF1, oc); } return (rv);}static voidisp_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, oc = 0; if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) { /* * We will assume that someone has paused the RISC processor. */ 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); } 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 || ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) { isp_pci_wr_reg(isp, BIU_CONF1, oc); }}#endif#if __FreeBSD_version >= 300004static 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 voidisp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error){ struct ispsoftc *isp = (struct ispsoftc *) arg; isp->isp_rquest_dma = segs->ds_addr;}static voidisp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error){ struct ispsoftc *isp = (struct ispsoftc *) arg; isp->isp_result_dma = segs->ds_addr;}static voidisp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error){ struct ispsoftc *isp = (struct ispsoftc *) arg; fcparam *fcp = isp->isp_param; fcp->isp_scdma = segs->ds_addr;}static intisp_pci_mbxdma(struct ispsoftc *isp){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; caddr_t base; u_int32_t len; int i, error; /* * Allocate and map the request, result queues, plus FC scratch area. */ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); if (isp->isp_type & ISP_HA_FC) { len += ISP2100_SCRLEN; } if (bus_dma_tag_create(pci->parent_dmat, 0, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) { printf("%s: cannot create a dma tag for control spaces\n", isp->isp_name); return (1); } if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base, BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) { printf("%s: cannot allocate %d bytes of CCB memory\n", isp->isp_name, len); return (1); } isp->isp_rquest = base; bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, pci, 0); isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result, ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, pci, 0); /* * Use this opportunity to initialize/create data DMA maps. */ for (i = 0; i < MAXISPREQUEST; i++) { error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]); if (error) { printf("%s: error %d creating mailbox DMA maps\n", isp->isp_name, error); return (1); } } if (isp->isp_type & ISP_HA_FC) { fcparam *fcp = (fcparam *) isp->isp_param; fcp->isp_scratch = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) + ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, pci, 0); } return (0);}static void dma2 __P((void *, bus_dma_segment_t *, int, int));typedef struct { struct ispsoftc *isp; ISP_SCSI_XFER_T *ccb; ispreq_t *rq; u_int8_t *iptrp; u_int8_t optr; u_int error;} mush_t;#define MUSHERR_NOQENTRIES -2static voiddma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error){ mush_t *mp; ISP_SCSI_XFER_T *ccb; struct ispsoftc *isp; struct isp_pcisoftc *pci; bus_dmamap_t *dp; bus_dma_segment_t *eseg; ispreq_t *rq; u_int8_t *iptrp; u_int8_t optr; ispcontreq_t *crq; int drq, seglim, datalen; mp = (mush_t *) arg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -