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

📄 mptctl.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	} 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 __user *uarg = (void __user *) 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"));	/* Add of PCI INFO results in unaligned access for	 * IA64 and Sparc. Reset long to int. Return no PCI	 * data for obsolete format.	 */	if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0))		cim_rev = 0;	else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1))		cim_rev = 1;	else if (data_size == sizeof(struct mpt_ioctl_iocinfo))		cim_rev = 2;	else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))		cim_rev = 0;	/* obsolete */	else		return -EFAULT;		karg = kmalloc(data_size, GFP_KERNEL);	if (karg == NULL) {		printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",				__FILE__, __LINE__);		return -ENOMEM;	}			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__, uarg);		kfree(karg);		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));		kfree(karg);		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__);		kfree(karg);		return -EFAULT;	}	/* Fill in the data and return the structure to the calling	 * program	 */	if (ioc->bus_type == FC)		karg->adapterType = MPT_IOCTL_INTERFACE_FC;	else		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;	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;	karg->subSystemDevice = pdev->subsystem_device;	karg->subSystemVendor = pdev->subsystem_vendor;	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 );	} else if (cim_rev == 2) {		/* Get the PCI bus, device, function and segment ID 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 );		karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );		karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);	}	/* 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->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0';	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 __user *)arg, karg, data_size)) {		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",				__FILE__, __LINE__, uarg);		kfree(karg);		return -EFAULT;	}	kfree(karg);	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 __user *uarg = (void __user *) arg;	struct mpt_ioctl_targetinfo karg;	MPT_ADAPTER		*ioc;	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	VirtDevice		*vdev;	char			*pmem;	int			*pdata;	IOCPage2_t		*pIoc2;	IOCPage3_t		*pIoc3;	int			iocnum;	int			numDevices = 0;	unsigned int		max_id;	int			id, jj, indexed_lun, lun_index;	u32			lun;	int			maxWordsLeft;	int			numBytes;	u8			port, devType, bus_id;	dctlprintk(("mptctl_gettargetinfo called.\n"));	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {		printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - "			"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",				__FILE__, __LINE__, uarg);		return -EFAULT;	}	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||	    (ioc == NULL)) {		dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",				__FILE__, __LINE__, iocnum));		return -ENODEV;	}	/* Get the port number and set the maximum number of bytes	 * in the returned structure.	 * Ignore the port setting.	 */	numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);	maxWordsLeft = numBytes/sizeof(int);	port = karg.hdr.port;	if (maxWordsLeft <= 0) {

⌨️ 快捷键说明

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