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

📄 mptctl.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
			mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address);			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 += (sizeof(dma_addr_t) + sizeof(u32));	}#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	 */	for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) {		if (!cntdn) {			ret = -ETIME;			goto fwdl_out;		}		if (!(i%HZ)) {			dctlprintk((KERN_INFO "DbG::_do_fwdl: "				   "In ReplyMsg loop - iteration %d\n",				   i));		}		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(1);	}	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;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * SGE Allocation routine * * Inputs:	bytes - number of bytes to be transferred *		sgdir - data direction *		sge_offset - offset (in bytes) from the start of the request *			frame to the first SGE *		ioc - pointer to the mptadapter * Outputs:	frags - number of scatter gather elements *		blp - point to the buflist pointer *		sglbuf_dma - pointer to the (dma) sgl * Returns:	Null if failes *		pointer to the (virtual) sgl if successful. */static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,		 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc){	MptSge_t	*sglbuf = NULL;		/* pointer to array of SGE */						/* and chain buffers */	struct buflist	*buflist = NULL;	/* kernel routine */	MptSge_t	*sgl;	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;	dma_addr_t	 pa;					// phys addr	int		 i, buflist_ent;	int		 sg_spill = MAX_FRAGS_SPILL1;	int		 dir;	/* initialization */	*frags = 0;	*blp = NULL;	/* Allocate and initialize an array of kernel	 * structures for the SG elements.	 */	i = MAX_SGL_BYTES / 8;	buflist = kmalloc(i, GFP_USER);	if (buflist == NULL)		return NULL;	memset(buflist, 0, i);	buflist_ent = 0;	/* Allocate a single block of memory to store the sg elements and	 * the chain buffers.  The calling routine is responsible for	 * copying the data in this array into the correct place in the	 * request and chain buffers.	 */	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;	/* At start:	 *	sgl = sglbuf = point to beginning of sg buffer	 *	buflist_ent = 0 = first kernel structure	 *	sg_spill = number of SGE that can be written before the first	 *		chain element.	 *	 */	sgl = sglbuf;	sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1;	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;			sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc);			dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);			sgl->Address = dma_addr;			fragcnt++;			numfrags++;			sgl++;			buflist_ent++;		}		if (bytes_allocd >= bytes)			break;		/* Need to chain? */		if (fragcnt == sg_spill) {			printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required!   :-(\n");			printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags);			goto free_and_fail;		}		/* 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 |= 0xC1000000;	*frags = numfrags;	*blp = buflist;	dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - "			   "%d SG frags generated!\n",			   numfrags));	dctlprintk((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 ((sglbuf[i].FlagsLength >> 24) == 0x30)				continue;			dma_addr = 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;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * Routine to free the SGL elements. */static voidkfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc){	MptSge_t	*sg = sgl;	struct buflist	*bl = buflist;	u32		 nib;	int		 dir;	int		 n = 0;	if (sg->FlagsLength & 0x04000000)		dir = PCI_DMA_TODEVICE;	else		dir = PCI_DMA_FROMDEVICE;	nib = (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 = 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 = 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);	dctlprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n));}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptctl_getiocinfo - Query the host adapter for IOC information. *	@arg: User space argument * * Outputs:	None. * Return:	0 if successful *		-EFAULT if data unavailable *		-ENODEV  if no such device/adapter */static intmptctl_getiocinfo (unsigned long arg, unsigned int data_size){	struct mpt_ioctl_iocinfo *uarg = (struct mpt_ioctl_iocinfo *) arg;	struct mpt_ioctl_iocinfo karg;	MPT_ADAPTER		*ioc;	struct pci_dev		*pdev;	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	int			iocnum;	int			numDevices = 0;	unsigned int		max_id;	int			ii;	int			port;	int			cim_rev;	u8			revision;	dctlprintk((": mptctl_getiocinfo called.\n"));	if (data_size == sizeof(struct mpt_ioctl_iocinfo))		cim_rev = 1;	else if (data_size == (sizeof(struct mpt_ioctl_iocinfo) - sizeof(struct mpt_ioctl_pci_info)))		cim_rev = 0;	else		return -EFAULT;	if (copy_from_user(&karg, uarg, data_size)) {		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",				__FILE__, __LINE__, (void*)uarg);		return -EFAULT;	}	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||	    (ioc == NULL)) {		dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",				__FILE__, __LINE__, iocnum));		return -ENODEV;	}	/* Verify the data transfer size is correct.	 * Ignore the port setting.	 */	if (karg.hdr.maxDataSize != data_size) {		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "			"Structure size mismatch. Command not completed.\n",				__FILE__, __LINE__);		return -EFAULT;	}	/* Fill in the data and return the structure to the calling	 * program	 */	if (ioc->chip_type == C1030)		karg.adapterType = MPT_IOCTL_INTERFACE_SCSI;	else		karg.adapterType = MPT_IOCTL_INTERFACE_FC;	port = karg.hdr.port;	karg.port = port;	pdev = (struct pci_dev *) ioc->pcidev;	karg.pciId = pdev->device;	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);	karg.hwRev = revision;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	karg.subSystemDevice = pdev->subsystem_device;	karg.subSystemVendor = pdev->subsystem_vendor;#endif	if (cim_rev == 1) {		/* Get the PCI bus, device, and function numbers for the IOC		 */		karg.pciInfo.u.bits.busNumber = pdev->bus->number;		karg.pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );		karg.pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );	}	/* Get number of devices         */	if ((sh = ioc->sh) != NULL) {		 /* sh->max_id = maximum target ID + 1		 */		max_id = sh->max_id - 1;		hd = (MPT_SCSI_HOST *) sh->hostdata;		/* Check all of the target structures and		 * keep a counter.		 */		if (hd && hd->Targets) {			for (ii = 0; ii <= max_id; ii++) {				if (hd->Targets[ii])					numDevices++;			}		}	}	karg.numDevices = numDevices;	/* Set the BIOS and FW Version	 */	karg.FWVersion = ioc->facts.FWVersion.Word;	karg.BIOSVersion = ioc->biosVersion;	/* Set the Version Strings.	 */	strncpy (karg.driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH);	karg.busChangeEvent = 0;	karg.hostId = ioc->pfacts[port].PortSCSIID;	karg.rsvd[0] = karg.rsvd[1] = 0;	/* Copy the data from kernel memory to user memory	 */	if (copy_to_user((char *)arg, &karg, data_size)) {		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",				__FILE__, __LINE__, (void*)uarg);		return -EFAULT;	}	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptctl_gettargetinfo - Query the host adapter for target information. *	@arg: User space argument * * Outputs:	None. * Return:	0 if successful *		-EFAULT if data unavailable *		-ENODEV  if no such device/adapter */static intmptctl_gettargetinfo (unsigned long arg){	struct mpt_ioctl_targetinfo *uarg = (struct mpt_ioctl_targetinfo *) arg;	struct mpt_ioctl_targetinfo karg;	MPT_ADAPTER		*ioc;	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	char			*pmem;	int			*pdata;	int			iocnum;	int			numDevices = 0;	unsigned int		max_id;	int			ii, jj, lun;	int			maxWordsLeft;	int			numBytes;	u8			port;	dctlprintk(("mptctl_gettargetinfo called.\n"));

⌨️ 快捷键说明

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