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

📄 mptctl.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
		ret = -EMLINK;		goto fwdl_out;	}	dprintk((KERN_INFO "DbG: sgl buffer  = %p, sgfrags = %d\n", sgl, numfrags));	/*	 * Parse SG list, copying sgl itself,	 * plus f/w image hunks from user space as we go...	 */	ret = -EFAULT;	sgIn = sgl;	bl = buflist;	for (i=0; i < numfrags; i++) {		nib = (le32_to_cpu(sgIn->FlagsLength) & 0xF0000000) >> 28;		/* skip ignore/chain. */		if (nib == 0 || nib == 3) {			;		} else if (sgIn->Address) {			*sgOut = *sgIn;			n++;			if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) {				printk(KERN_ERR "%s@%d::_ioctl_fwdl - "						"Unable to copy f/w buffer hunk#%d @ %p\n",						__FILE__, __LINE__, n, (void*)ufwbuf);				goto fwdl_out;			}			fw_bytes_copied += bl->len;		}		sgIn++;		bl++;		sgOut++;	}#ifdef MPT_DEBUG	{		u32 *m = (u32 *)mf;		printk(KERN_INFO MYNAM ": F/W download request:\n" KERN_INFO " ");		for (i=0; i < 7+numfrags*2; i++)			printk(" %08x", le32_to_cpu(m[i]));		printk("\n");	}#endif	/*	 * Finally, perform firmware download.	 */	ReplyMsg = NULL;	mpt_put_msg_frame(mptctl_id, ioc, mf);	/*	 *  Wait until the reply has been received	 */	{		int	 foo = 0;		while (ReplyMsg == NULL) {			if (!(foo%1000000)) {				dprintk((KERN_INFO "DbG::_do_fwdl: "					   "In ReplyMsg loop - iteration %d\n",					   foo)); //tc			}			ret = -ETIME;			if (++foo > 60000000)				goto fwdl_out;			mb();			schedule();			barrier();		}	}	if (sgl)        	kfree_sgl(sgl, sgl_dma, buflist, iocp);	iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;	if (iocstat == MPI_IOCSTATUS_SUCCESS) {		printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);		return 0;	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {		printk(KERN_WARNING MYNAM ": ?Hmmm...  %s says it doesn't support F/W download!?!\n",				iocp->name);		printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n");		return -EBADRQC;	} else if (iocstat == MPI_IOCSTATUS_BUSY) {		printk(KERN_WARNING MYNAM ": Warning!  %s says: IOC_BUSY!\n", iocp->name);		printk(KERN_WARNING MYNAM ": (try again later?)\n");		return -EBUSY;	} else {		printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR!  %s returned [bad] status = %04xh\n",				    iocp->name, iocstat);		printk(KERN_WARNING MYNAM ": (bad VooDoo)\n");		return -ENOMSG;	}	return 0;fwdl_out:        kfree_sgl(sgl, sgl_dma, buflist, iocp);	return ret;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  NEW rwperf (read/write performance) stuff starts here... *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static SGESimple32_t *kbuf_alloc_2_sgl(int bytes, u32 sgdir, int *frags,		 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc){	SGESimple32_t	*sglbuf = NULL;	struct buflist	*buflist = NULL;	int		 numfrags = 0;	int		 fragcnt = 0;	int		 alloc_sz = MIN(bytes,MAX_KMALLOC_SZ);	// avoid kernel warning msg!	int		 bytes_allocd = 0;	int		 this_alloc;	SGESimple32_t	*sgl;	u32		 pa;					// phys addr	SGEChain32_t	*last_chain = NULL;	SGEChain32_t	*old_chain = NULL;	int		 chaincnt = 0;	int		 i, buflist_ent;	int		 sg_spill = MAX_FRAGS_SPILL1;	int		 dir;	*frags = 0;	*blp = NULL;	i = MAX_SGL_BYTES / 8;	buflist = kmalloc(i, GFP_USER);	if (buflist == NULL)		return NULL;	memset(buflist, 0, i);	buflist_ent = 0;	sglbuf = pci_alloc_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf_dma);	if (sglbuf == NULL)		goto free_and_fail;	if (sgdir & 0x04000000)		dir = PCI_DMA_TODEVICE;	else		dir = PCI_DMA_FROMDEVICE;	sgl = sglbuf;	while (bytes_allocd < bytes) {		this_alloc = MIN(alloc_sz, bytes-bytes_allocd);		buflist[buflist_ent].len = this_alloc;		buflist[buflist_ent].kptr = pci_alloc_consistent(ioc->pcidev,								 this_alloc,								 &pa);		if (buflist[buflist_ent].kptr == NULL) {			alloc_sz = alloc_sz / 2;			if (alloc_sz == 0) {				printk(KERN_WARNING MYNAM "-SG: No can do - "						    "not enough memory!   :-(\n");				printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",						    numfrags);				goto free_and_fail;			}			continue;		} else {			dma_addr_t dma_addr;			bytes_allocd += this_alloc;			/* Write one SIMPLE sge */			sgl->FlagsLength = cpu_to_le32(0x10000000|sgdir|this_alloc);			dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);			sgl->Address = cpu_to_le32(dma_addr);			fragcnt++;			numfrags++;			sgl++;			buflist_ent++;		}		if (bytes_allocd >= bytes)			break;		/* Need to chain? */		if (fragcnt == sg_spill) {			dma_addr_t chain_link;			if (last_chain != NULL)				last_chain->NextChainOffset = 0x1E;			fragcnt = 0;			sg_spill = MAX_FRAGS_SPILL2;			/* fixup previous SIMPLE sge */			sgl[-1].FlagsLength |= cpu_to_le32(0x80000000);			chain_link = (*sglbuf_dma) +				((u8 *)(sgl+1) - (u8 *)sglbuf);			/* Write one CHAIN sge */			sgl->FlagsLength = cpu_to_le32(0x30000080);			sgl->Address = cpu_to_le32(chain_link);			old_chain = last_chain;			last_chain = (SGEChain32_t*)sgl;			chaincnt++;			numfrags++;			sgl++;		}		/* overflow check... */		if (numfrags*8 > MAX_SGL_BYTES) {			/* GRRRRR... */			printk(KERN_WARNING MYNAM "-SG: No can do - "					    "too many SG frags!   :-(\n");			printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n",					    numfrags);			goto free_and_fail;		}	}	/* Last sge fixup: set LE+eol+eob bits */	sgl[-1].FlagsLength |= cpu_to_le32(0xC1000000);	/* Chain fixup needed? */	if (last_chain != NULL && fragcnt < 16)		last_chain->Length = cpu_to_le16(fragcnt * 8);	*frags = numfrags;	*blp = buflist;	dprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "			   "%d SG frags generated!  (%d CHAIN%s)\n",			   numfrags, chaincnt, chaincnt>1?"s":""));	dprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "			   "last (big) alloc_sz=%d\n",			   alloc_sz));	return sglbuf;free_and_fail:	if (sglbuf != NULL) {		int i;		for (i = 0; i < numfrags; i++) {			dma_addr_t dma_addr;			u8 *kptr;			int len;			if ((le32_to_cpu(sglbuf[i].FlagsLength) >> 24) == 0x30)				continue;			dma_addr = le32_to_cpu(sglbuf[i].Address);			kptr = buflist[i].kptr;			len = buflist[i].len;			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);		}		pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf, *sglbuf_dma);	}	kfree(buflist);	return NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static voidkfree_sgl(SGESimple32_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc){	SGESimple32_t	*sg = sgl;	struct buflist	*bl = buflist;	u32		 nib;	int		 dir;	int		 n = 0;	if (le32_to_cpu(sg->FlagsLength) & 0x04000000)		dir = PCI_DMA_TODEVICE;	else		dir = PCI_DMA_FROMDEVICE;	nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28;	while (! (nib & 0x4)) { /* eob */		/* skip ignore/chain. */		if (nib == 0 || nib == 3) {			;		} else if (sg->Address) {			dma_addr_t dma_addr;			void *kptr;			int len;			dma_addr = le32_to_cpu(sg->Address);			kptr = bl->kptr;			len = bl->len;			pci_unmap_single(ioc->pcidev, dma_addr, len, dir);			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);			n++;		}		sg++;		bl++;		nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28;	}	/* we're at eob! */	if (sg->Address) {		dma_addr_t dma_addr;		void *kptr;		int len;		dma_addr = le32_to_cpu(sg->Address);		kptr = bl->kptr;		len = bl->len;		pci_unmap_single(ioc->pcidev, dma_addr, len, dir);		pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);		n++;	}	pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sgl, sgl_dma);	kfree(buflist);	dprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n));}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmpt_ioctl_rwperf_init(struct mpt_raw_r_w *dest, unsigned long src,		      char *caller, MPT_ADAPTER **iocpp){	char	*myname = "_rwperf_init()";	int	 ioc;	/* get copy of structure passed from user space */	if (copy_from_user(dest, (void*)src, sizeof(*dest))) {		printk(KERN_ERR MYNAM "::%s() @%d - Can't copy mpt_raw_r_w data @ %p\n",				myname, __LINE__, (void*)src);		return -EFAULT;				/* (-14) Bad address */	} else {		dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{ioc,targ,qd,iters,nblks}"				   ": %d %d %d %d %d\n",				   dest->iocnum, dest->target,				   (int)dest->qdepth, dest->iters, dest->nblks ));		dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{cache,skip,range,rdwr,seqran}"				   ": %d %d %d %d %d\n",				   dest->cache_sz, dest->skip, dest->range,				   dest->rdwr, dest->seqran ));		/* Get the MPT adapter id. */		if ((ioc = mpt_verify_adapter(dest->iocnum, iocpp)) < 0) {			printk(KERN_ERR MYNAM "::%s() @%d - ioc%d not found!\n",					myname, __LINE__, dest->iocnum);			return -ENXIO;			/* (-6) No such device or address */		} else {			dprintk((MYNAM "-perf: %s using mpt/ioc%x, target %02xh\n",					caller, dest->iocnum, dest->target));		}	}	return ioc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*  Treat first N blocks of disk as sacred!  */#define SACRED_BLOCKS	100/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmpt_ioctl_rwperf(unsigned long arg){	struct mpt_raw_r_w	 kPerfInfo;				/* NOTE: local copy, on stack==KERNEL_SPACE! */	u8		 target, targetM;	u8		 lun, lunM;	u8		 scsiop;	int		 qdepth;	int		 iters;	int		 cache_sz;	u32		 xferbytes;	u32		 scsidir;	u32		 qtag;	u32		 scsictl;	u32		 sgdir;	u32		 blkno;	u32		 sbphys;	SGESimple32_t	*sgl;	dma_addr_t	 sgl_dma;	struct buflist	*buflist;	SGESimple32_t	*sgOut, *sgIn;	int		 numfrags;	u32		*msg;	int		 i;	int		 ioc;	MPT_FRAME_HDR	*mf;	MPT_ADAPTER	*iocp;	int		 sgfragcpycnt;	int		 blklo, blkhi;	u8		 nextchainoffset;	u8		*SenseBuf;	dma_addr_t	 SenseBufDMA;	char		*myname = "_rwperf()";    dprintk((KERN_INFO "%s - starting...\n", myname));    /* Validate target device */    if ((ioc = mpt_ioctl_rwperf_init(&kPerfInfo, arg, myname, &iocp)) < 0)        return ioc;    /* Allocate DMA'able memory for the sense buffer. */    SenseBuf = pci_alloc_consistent(iocp->pcidev, 256, &SenseBufDMA);    /* set perf parameters from input */    target = kPerfInfo.target & 0x0FF;    targetM = target & myMAX_T_MASK;    lun = kPerfInfo.lun & 0x1F;			// LUN=31 max    lunM = lun & myMAX_L_MASK;    qdepth = kPerfInfo.qdepth;    iters = kPerfInfo.iters;    xferbytes = ((u32)kPerfInfo.nblks)<<9;    DevInUse[targetM][lunM] = 1;    DevIosCount[targetM][lunM] = 0;    cache_sz = kPerfInfo.cache_sz * 1024;	// CacheSz in kB!    /* ToDo: */    /* get capacity (?) */    // pre-build, one time, everything we can for speed in the loops below...    scsiop = 0x28;				// default to SCSI READ!    scsidir = MPI_SCSIIO_CONTROL_READ;		// DATA IN  (host<--ioc<--dev)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -