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

📄 mptctl.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			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;	unsigned 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. */	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;	if (karg->hdr.port > 1)		return -EINVAL;	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) {		printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",				__FILE__, __LINE__);		return -ENOMEM;	}	/* Fill in the data and return the structure to the calling	 * program	 */	/* struct mpt_ioctl_targetinfo does not contain sufficient space	 * for the target structures so when the IOCTL is called, there is	 * not sufficient stack space for the structure. Allocate memory,	 * populate the memory, copy back to the user, then free memory.	 * targetInfo format:	 * bits 31-24: reserved	 *      23-16: LUN	 *      15- 8: Bus Number	 *       7- 0: Target ID	 */	pmem = kmalloc(numBytes, GFP_KERNEL);	if (pmem == NULL) {		printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n",				__FILE__, __LINE__);		return -ENOMEM;	}	memset(pmem, 0, numBytes);	pdata =  (int *) pmem;	/* Get number of devices         */	if ((sh = ioc->sh) != NULL) {		max_id = sh->max_id - 1;		hd = (MPT_SCSI_HOST *) sh->hostdata;		/* Check all of the target structures.		 * Save the Id and increment the counter,		 * if ptr non-null.		 * sh->max_id = maximum target ID + 1		 */		if (hd && hd->Targets) {			mpt_findImVolumes(ioc);			pIoc2 = ioc->raid_data.pIocPg2;			for ( id = 0; id <= max_id; ) {				if ( pIoc2 && pIoc2->NumActiveVolumes ) {					if ( id == pIoc2->RaidVolume[0].VolumeID ) {						if (maxWordsLeft <= 0) {							printk(KERN_ERR "mptctl_gettargetinfo - "			"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);							goto data_space_full;						}						if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )                        				devType = 0x80;                    				else                        				devType = 0xC0;						bus_id = pIoc2->RaidVolume[0].VolumeBus;	            				numDevices++;                    				*pdata = ( (devType << 24) | (bus_id << 8) | id );						dctlprintk((KERN_ERR "mptctl_gettargetinfo - "		"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));                    				pdata++;						--maxWordsLeft;						goto next_id;					} else {						pIoc3 = ioc->raid_data.pIocPg3;            					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {                    					if ( pIoc3->PhysDisk[jj].PhysDiskID == id )								goto next_id;						}					}				}				if ( (vdev = hd->Targets[id]) ) {					for (jj = 0; jj <= MPT_LAST_LUN; jj++) {						lun_index = (jj >> 5);						indexed_lun = (jj % 32);						lun = (1 << indexed_lun);						if (vdev->luns[lun_index] & lun) {							if (maxWordsLeft <= 0) {								printk(KERN_ERR "mptctl_gettargetinfo - "			"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);								goto data_space_full;							}							bus_id = vdev->bus_id;							numDevices++;                            				*pdata = ( (jj << 16) | (bus_id << 8) | id );							dctlprintk((KERN_ERR "mptctl_gettargetinfo - "		"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));							pdata++;							--maxWordsLeft;						}					}				}next_id:				id++;			}		}	}data_space_full:	karg.numDevices = numDevices;	/* Copy part of the data from kernel memory to user memory	 */	if (copy_to_user((char __user *)arg, &karg,				sizeof(struct mpt_ioctl_targetinfo))) {

⌨️ 快捷键说明

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