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

📄 commctrl.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		}		entry = entry->next;		fibctx = NULL;	}	if (!fibctx)		return 0; /* Already gone */	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||		 (fibctx->size != sizeof(struct aac_fib_context)))		return -EINVAL;	spin_lock_irqsave(&dev->fib_lock, flags);	status = aac_close_fib_context(dev, fibctx);	spin_unlock_irqrestore(&dev->fib_lock, flags);	return status;}/** *	check_revision	-	close down user fib context *	@dev: adapter *	@arg: ioctl arguments * *	This routine returns the driver version. *      Under Linux, there have been no version incompatibilities, so this is  *      simple! */static int check_revision(struct aac_dev *dev, void __user *arg){	struct revision response;	char *driver_version = aac_driver_version;	u32 version;	response.compat = 1;	version = (simple_strtol(driver_version, 				&driver_version, 10) << 24) | 0x00000400;	version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;	version += simple_strtol(driver_version + 1, NULL, 10);	response.version = cpu_to_le32(version);#	if (defined(AAC_DRIVER_BUILD))		response.build = cpu_to_le32(AAC_DRIVER_BUILD);#	else		response.build = cpu_to_le32(9999);#	endif	if (copy_to_user(arg, &response, sizeof(response)))		return -EFAULT;	return 0;}/** * * aac_send_raw_scb * */static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg){	struct fib* srbfib;	int status;	struct aac_srb *srbcmd = NULL;	struct user_aac_srb *user_srbcmd = NULL;	struct user_aac_srb __user *user_srb = arg;	struct aac_srb_reply __user *user_reply;	struct aac_srb_reply* reply;	u32 fibsize = 0;	u32 flags = 0;	s32 rcode = 0;	u32 data_dir;	void __user *sg_user[32];	void *sg_list[32];	u32   sg_indx = 0;	u32 byte_count = 0;	u32 actual_fibsize = 0;	int i;	if (!capable(CAP_SYS_ADMIN)){		dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 		return -EPERM;	}	/*	 *	Allocate and initialize a Fib then setup a BlockWrite command	 */	if (!(srbfib = fib_alloc(dev))) {		return -ENOMEM;	}	fib_init(srbfib);	srbcmd = (struct aac_srb*) fib_data(srbfib);	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){		dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n")); 		rcode = -EFAULT;		goto cleanup;	}	if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {		rcode = -EINVAL;		goto cleanup;	}	user_srbcmd = kmalloc(fibsize, GFP_KERNEL);	if (!user_srbcmd) {		dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));		rcode = -ENOMEM;		goto cleanup;	}	if(copy_from_user(user_srbcmd, user_srb,fibsize)){		dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n")); 		rcode = -EFAULT;		goto cleanup;	}	user_reply = arg+fibsize;	flags = user_srbcmd->flags; /* from user in cpu order */	// Fix up srb for endian and force some values	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);	// Force this	srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);	srbcmd->id	 = cpu_to_le32(user_srbcmd->id);	srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);	srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);	srbcmd->flags    = cpu_to_le32(flags);	srbcmd->retry_limit = 0; // Obsolete parameter	srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);	memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));		switch (flags & (SRB_DataIn | SRB_DataOut)) {	case SRB_DataOut:		data_dir = DMA_TO_DEVICE;		break;	case (SRB_DataIn | SRB_DataOut):		data_dir = DMA_BIDIRECTIONAL;		break;	case SRB_DataIn:		data_dir = DMA_FROM_DEVICE;		break;	default:		data_dir = DMA_NONE;	}	if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",		  le32_to_cpu(srbcmd->sg.count)));		rcode = -EINVAL;		goto cleanup;	}	if (dev->dac_support == 1) {		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;		struct user_sgmap* usg;		byte_count = 0;		/*		 * This should also catch if user used the 32 bit sgmap		 */		actual_fibsize = sizeof(struct aac_srb) - 			sizeof(struct sgentry) +			((upsg->count & 0xff) * 		 	sizeof(struct sgentry));		if(actual_fibsize != fibsize){ // User made a mistake - should not continue			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));			rcode = -EINVAL;			goto cleanup;		}		usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)		  + sizeof(struct sgmap), GFP_KERNEL);		if (!usg) {			dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));			rcode = -ENOMEM;			goto cleanup;		}		memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)		  + sizeof(struct sgmap));		actual_fibsize = sizeof(struct aac_srb) - 			sizeof(struct sgentry) + ((usg->count & 0xff) * 			 	sizeof(struct sgentry64));		if ((data_dir == DMA_NONE) && upsg->count) {			kfree (usg);			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));			rcode = -EINVAL;			goto cleanup;		}		for (i = 0; i < usg->count; i++) {			u64 addr;			void* p;			/* Does this really need to be GFP_DMA? */			p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);			if(p == 0) {				kfree (usg);				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",				  usg->sg[i].count,i,usg->count));				rcode = -ENOMEM;				goto cleanup;			}			sg_user[i] = (void __user *)(long)usg->sg[i].addr;			sg_list[i] = p; // save so we can clean up later			sg_indx = i;			if( flags & SRB_DataOut ){				if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){					kfree (usg);					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 					rcode = -EFAULT;					goto cleanup;				}			}			addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);			psg->sg[i].count = cpu_to_le32(usg->sg[i].count);  			byte_count += usg->sg[i].count;		}		kfree (usg);		srbcmd->count = cpu_to_le32(byte_count);		psg->count = cpu_to_le32(sg_indx+1);		status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);	} else {		struct user_sgmap* upsg = &user_srbcmd->sg;		struct sgmap* psg = &srbcmd->sg;		byte_count = 0;		actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));		if(actual_fibsize != fibsize){ // User made a mistake - should not continue			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));			rcode = -EINVAL;			goto cleanup;		}		if ((data_dir == DMA_NONE) && upsg->count) {			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));			rcode = -EINVAL;			goto cleanup;		}		for (i = 0; i < upsg->count; i++) {			dma_addr_t addr; 			void* p;			p = kmalloc(upsg->sg[i].count, GFP_KERNEL);			if(p == 0) {				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",				  upsg->sg[i].count, i, upsg->count));				rcode = -ENOMEM;				goto cleanup;			}			sg_user[i] = (void __user *)(long)upsg->sg[i].addr;			sg_list[i] = p; // save so we can clean up later			sg_indx = i;			if( flags & SRB_DataOut ){				if(copy_from_user(p, sg_user[i],						upsg->sg[i].count)) {					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 					rcode = -EFAULT;					goto cleanup;				}			}			addr = pci_map_single(dev->pdev, p,				upsg->sg[i].count, data_dir);			psg->sg[i].addr = cpu_to_le32(addr);			psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  			byte_count += upsg->sg[i].count;		}		srbcmd->count = cpu_to_le32(byte_count);		psg->count = cpu_to_le32(sg_indx+1);		status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);	}	if (status != 0){		dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); 		rcode = -ENXIO;		goto cleanup;	}	if( flags & SRB_DataIn ) {		for(i = 0 ; i <= sg_indx; i++){			byte_count = le32_to_cpu((dev->dac_support == 1)			      ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count			      : srbcmd->sg.sg[i].count);			if(copy_to_user(sg_user[i], sg_list[i], byte_count)){				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); 				rcode = -EFAULT;				goto cleanup;			}		}	}	reply = (struct aac_srb_reply *) fib_data(srbfib);	if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){		dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); 		rcode = -EFAULT;		goto cleanup;	}cleanup:	kfree(user_srbcmd);	for(i=0; i <= sg_indx; i++){		kfree(sg_list[i]);	}	fib_complete(srbfib);	fib_free(srbfib);	return rcode;}struct aac_pci_info {        u32 bus;        u32 slot;};static int aac_get_pci_info(struct aac_dev* dev, void __user *arg){        struct aac_pci_info pci_info;	pci_info.bus = dev->pdev->bus->number;	pci_info.slot = PCI_SLOT(dev->pdev->devfn);       if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {               dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));               return -EFAULT;	}        return 0;} int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg){	int status;		/*	 *	HBA gets first crack	 */	 	status = aac_dev_ioctl(dev, cmd, arg);	if(status != -ENOTTY)		return status;	switch (cmd) {	case FSACTL_MINIPORT_REV_CHECK:		status = check_revision(dev, arg);		break;	case FSACTL_SEND_LARGE_FIB:	case FSACTL_SENDFIB:		status = ioctl_send_fib(dev, arg);		break;	case FSACTL_OPEN_GET_ADAPTER_FIB:		status = open_getadapter_fib(dev, arg);		break;	case FSACTL_GET_NEXT_ADAPTER_FIB:		status = next_getadapter_fib(dev, arg);		break;	case FSACTL_CLOSE_GET_ADAPTER_FIB:		status = close_getadapter_fib(dev, arg);		break;	case FSACTL_SEND_RAW_SRB:		status = aac_send_raw_srb(dev,arg);		break;	case FSACTL_GET_PCI_INFO:		status = aac_get_pci_info(dev,arg);		break;	default:		status = -ENOTTY;	  	break;		}	return status;}

⌨️ 快捷键说明

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