⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp_pci.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -