📄 isp_pci.c
字号:
if (error) { mp->error = error; return; } isp = mp->isp; if (nseg < 1) { printf("%s: zero or negative segment count\n", isp->isp_name); mp->error = EFAULT; return; } ccb = mp->ccb; rq = mp->rq; iptrp = mp->iptrp; optr = mp->optr; pci = (struct isp_pcisoftc *)isp; dp = &pci->dmaps[rq->req_handle - 1]; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD); drq = REQFLAG_DATA_IN; } else { bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE); drq = REQFLAG_DATA_OUT; } datalen = XS_XFRLEN(ccb); if (isp->isp_type & ISP_HA_FC) { seglim = ISP_RQDSEG_T2; ((ispreqt2_t *)rq)->req_totalcnt = datalen; ((ispreqt2_t *)rq)->req_flags |= drq; } else { seglim = ISP_RQDSEG; rq->req_flags |= drq; } eseg = dm_segs + nseg; while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) { if (isp->isp_type & ISP_HA_FC) { ispreqt2_t *rq2 = (ispreqt2_t *)rq; rq2->req_dataseg[rq2->req_seg_count].ds_base = dm_segs->ds_addr; rq2->req_dataseg[rq2->req_seg_count].ds_count = dm_segs->ds_len; } else { rq->req_dataseg[rq->req_seg_count].ds_base = dm_segs->ds_addr; rq->req_dataseg[rq->req_seg_count].ds_count = dm_segs->ds_len; } datalen -= dm_segs->ds_len;#if 0 if (isp->isp_type & ISP_HA_FC) { ispreqt2_t *rq2 = (ispreqt2_t *)rq; printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_seg_count, rq2->req_dataseg[rq2->req_seg_count].ds_count, rq2->req_dataseg[rq2->req_seg_count].ds_base); } else { printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_seg_count, rq->req_dataseg[rq->req_seg_count].ds_count, rq->req_dataseg[rq->req_seg_count].ds_base); }#endif rq->req_seg_count++; dm_segs++; } while (datalen > 0 && dm_segs != eseg) { crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); if (*iptrp == optr) {#if 0 printf("%s: Request Queue Overflow++\n", isp->isp_name);#endif mp->error = MUSHERR_NOQENTRIES; return; } rq->req_header.rqs_entry_count++; bzero((void *)crq, sizeof (*crq)); crq->req_header.rqs_entry_count = 1; crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; seglim = 0; while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) { crq->req_dataseg[seglim].ds_base = dm_segs->ds_addr; crq->req_dataseg[seglim].ds_count = dm_segs->ds_len;#if 0 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_header.rqs_entry_count-1, seglim, crq->req_dataseg[seglim].ds_count, crq->req_dataseg[seglim].ds_base);#endif rq->req_seg_count++; dm_segs++; seglim++; datalen -= dm_segs->ds_len; } }}static intisp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq, u_int8_t *iptrp, u_int8_t optr){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; struct ccb_hdr *ccb_h; struct ccb_scsiio *csio; bus_dmamap_t *dp; mush_t mush, *mp; csio = (struct ccb_scsiio *) ccb; ccb_h = &csio->ccb_h; if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { rq->req_seg_count = 1; return (CMD_QUEUED); } dp = &pci->dmaps[rq->req_handle - 1]; /* * Do a virtual grapevine step to collect info for * the callback dma allocation that we have to use... */ mp = &mush; mp->isp = isp; mp->ccb = ccb; mp->rq = rq; mp->iptrp = iptrp; mp->optr = optr; mp->error = 0; if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { int error, s; s = splsoftvm(); error = bus_dmamap_load(pci->parent_dmat, *dp, csio->data_ptr, csio->dxfer_len, dma2, mp, 0); if (error == EINPROGRESS) { bus_dmamap_unload(pci->parent_dmat, *dp); mp->error = EINVAL; printf("%s: deferred dma allocation not " "supported\n", isp->isp_name); } else if (error && mp->error == 0) { mp->error = error; } splx(s); } else { /* Pointer to physical buffer */ 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); } } else { struct bus_dma_segment *segs; if ((ccb_h->flags & CAM_DATA_PHYS) != 0) { printf("%s: Physical segment pointers unsupported", isp->isp_name); mp->error = EINVAL; } else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) { printf("%s: Virtual segment addresses unsupported", isp->isp_name); mp->error = EINVAL; } else { /* Just use the segments provided */ segs = (struct bus_dma_segment *) csio->data_ptr; dma2(mp, segs, csio->sglist_cnt, 0); } } if (mp->error) { int retval = CMD_COMPLETE; if (mp->error == MUSHERR_NOQENTRIES) { retval = CMD_EAGAIN; ccb_h->status = CAM_UNREC_HBA_ERROR; } else if (mp->error == EFBIG) { ccb_h->status = CAM_REQ_TOO_BIG; } else if (mp->error == EINVAL) { ccb_h->status = CAM_REQ_INVALID; } else { ccb_h->status = CAM_UNREC_HBA_ERROR; } return (retval); } else { return (CMD_QUEUED); }}static voidisp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, u_int32_t handle){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; bus_dmamap_t *dp = &pci->dmaps[handle]; if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD); } else { bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE); } bus_dmamap_unload(pci->parent_dmat, *dp);}#else /* __FreeBSD_version >= 300004 */static intisp_pci_mbxdma(struct ispsoftc *isp){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; u_int32_t len; int rseg; /* XXXX CHECK FOR ALIGNMENT */ /* * Allocate and map the request queue. */ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN); isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT); if (isp->isp_rquest == NULL) { printf("%s: cannot malloc request queue\n", isp->isp_name); return (1); } isp->isp_rquest_dma = vtophys(isp->isp_rquest);#if 0 printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma);#endif /* * Allocate and map the result queue. */ len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN); isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT); if (isp->isp_result == NULL) { free(isp->isp_rquest, M_DEVBUF); printf("%s: cannot malloc result queue\n", isp->isp_name); return (1); } isp->isp_result_dma = vtophys(isp->isp_result);#if 0 printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma);#endif if (isp->isp_type & ISP_HA_FC) { fcparam *fcp = isp->isp_param; len = ISP2100_SCRLEN; fcp->isp_scratch = (volatile caddr_t) malloc(ISP2100_SCRLEN, M_DEVBUF, M_NOWAIT); if (fcp->isp_scratch == NULL) { printf("%s: cannot alloc scratch\n", isp->isp_name); return (1); } fcp->isp_scdma = vtophys(fcp->isp_scratch); } return (0);}static intisp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, ispreq_t *rq, u_int8_t *iptrp, u_int8_t optr){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; ispcontreq_t *crq; vm_offset_t vaddr; int drq, seglim; u_int32_t paddr, nextpaddr, datalen, size, *ctrp; if (xs->datalen == 0) { rq->req_seg_count = 1; return (CMD_QUEUED); } if (xs->flags & SCSI_DATA_IN) { drq = REQFLAG_DATA_IN; } else { drq = REQFLAG_DATA_OUT; } if (isp->isp_type & ISP_HA_FC) { seglim = ISP_RQDSEG_T2; ((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs); ((ispreqt2_t *)rq)->req_flags |= drq; } else { seglim = ISP_RQDSEG; rq->req_flags |= drq; } datalen = XS_XFRLEN(xs); vaddr = (vm_offset_t) xs->data; paddr = vtophys(vaddr); while (datalen != 0 && rq->req_seg_count < seglim) { if (isp->isp_type & ISP_HA_FC) { ispreqt2_t *rq2 = (ispreqt2_t *)rq; rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr; ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count; } else { rq->req_dataseg[rq->req_seg_count].ds_base = paddr; ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count; } nextpaddr = paddr; *(ctrp) = 0; while (datalen != 0 && paddr == nextpaddr) { nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; size = nextpaddr - paddr; if (size > datalen) size = datalen; *(ctrp) += size; vaddr += size; datalen -= size; if (datalen != 0) paddr = vtophys(vaddr); }#if 0 if (isp->isp_type & ISP_HA_FC) { ispreqt2_t *rq2 = (ispreqt2_t *)rq; printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_seg_count, rq2->req_dataseg[rq2->req_seg_count].ds_count, rq2->req_dataseg[rq2->req_seg_count].ds_base); } else { printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_seg_count, rq->req_dataseg[rq->req_seg_count].ds_count, rq->req_dataseg[rq->req_seg_count].ds_base); }#endif rq->req_seg_count++; } if (datalen == 0) return (CMD_QUEUED); paddr = vtophys(vaddr); while (datalen > 0) { crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp); *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN); if (*iptrp == optr) { printf("%s: Request Queue Overflow\n", isp->isp_name); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } rq->req_header.rqs_entry_count++; bzero((void *)crq, sizeof (*crq)); crq->req_header.rqs_entry_count = 1; crq->req_header.rqs_entry_type = RQSTYPE_DATASEG; for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) { crq->req_dataseg[seglim].ds_base = paddr; ctrp = &crq->req_dataseg[seglim].ds_count; *(ctrp) = 0; nextpaddr = paddr; while (datalen != 0 && paddr == nextpaddr) { nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE; size = nextpaddr - paddr; if (size > datalen) size = datalen; *(ctrp) += size; vaddr += size; datalen -= size; if (datalen != 0) paddr = vtophys(vaddr); }#if 0 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n", isp->isp_name, rq->req_header.rqs_entry_count-1, seglim, crq->req_dataseg[seglim].ds_count, crq->req_dataseg[seglim].ds_base);#endif rq->req_seg_count++; } } return (CMD_QUEUED);}#endifstatic voidisp_pci_reset1(struct ispsoftc *isp){ /* Make sure the BIOS is disabled */ isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);}static voidisp_pci_dumpregs(struct ispsoftc *isp){ struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp; printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name, pci_conf_read(pci->pci_id, PCIR_COMMAND));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -