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

📄 i2o_config.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		osm_warn("unable to copy user message\n");		return -EFAULT;	}	i2o_dump_message(msg);	if (get_user(reply_size, &user_reply[0]) < 0)		return -EFAULT;	reply_size >>= 16;	reply_size <<= 2;	reply = kmalloc(reply_size, GFP_KERNEL);	if (!reply) {		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",		       c->name);		return -ENOMEM;	}	memset(reply, 0, reply_size);	sg_offset = (msg->u.head[0] >> 4) & 0x0f;	writel(i2o_config_driver.context, &msg->u.s.icntxt);	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);	if (sg_offset) {		struct sg_simple_element *sg;		if (sg_offset * 4 >= size) {			rcode = -EFAULT;			goto cleanup;		}		// TODO 64bit fix		sg = (struct sg_simple_element *)((&msg->u.head[0]) +						  sg_offset);		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		if (sg_count > SG_TABLESIZE) {			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",			       c->name, sg_count);			rcode = -EINVAL;			goto cleanup;		}		for (i = 0; i < sg_count; i++) {			int sg_size;			struct i2o_dma *p;			if (!(sg[i].flag_count & 0x10000000			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {				printk(KERN_DEBUG				       "%s:Bad SG element %d - not simple (%x)\n",				       c->name, i, sg[i].flag_count);				rcode = -EINVAL;				goto cleanup;			}			sg_size = sg[i].flag_count & 0xffffff;			p = &(sg_list[sg_index++]);			/* Allocate memory for the transfer */			if (i2o_dma_alloc			    (&c->pdev->dev, p, sg_size,			     PCI_DMA_BIDIRECTIONAL)) {				printk(KERN_DEBUG				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",				       c->name, sg_size, i, sg_count);				rcode = -ENOMEM;				goto sg_list_cleanup;			}			/* Copy in the user's SG buffer if necessary */			if (sg[i].			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {				// TODO 64bit fix				if (copy_from_user				    (p->virt,				     (void __user *)(unsigned long)sg[i].				     addr_bus, sg_size)) {					printk(KERN_DEBUG					       "%s: Could not copy SG buf %d FROM user\n",					       c->name, i);					rcode = -EFAULT;					goto sg_list_cleanup;				}			}			//TODO 64bit fix			sg[i].addr_bus = (u32) p->phys;		}	}	rcode = i2o_msg_post_wait(c, m, 60);	if (rcode)		goto sg_list_cleanup;	if (sg_offset) {		u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];		/* Copy back the Scatter Gather buffers back to user space */		u32 j;		// TODO 64bit fix		struct sg_simple_element *sg;		int sg_size;		// re-acquire the original message to handle correctly the sg copy operation		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);		// get user msg size in u32s		if (get_user(size, &user_msg[0])) {			rcode = -EFAULT;			goto sg_list_cleanup;		}		size = size >> 16;		size *= 4;		/* Copy in the user's I2O command */		if (copy_from_user(msg, user_msg, size)) {			rcode = -EFAULT;			goto sg_list_cleanup;		}		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		// TODO 64bit fix		sg = (struct sg_simple_element *)(msg + sg_offset);		for (j = 0; j < sg_count; j++) {			/* Copy out the SG list to user's buffer if necessary */			if (!			    (sg[j].			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {				sg_size = sg[j].flag_count & 0xffffff;				// TODO 64bit fix				if (copy_to_user				    ((void __user *)(u64) sg[j].addr_bus,				     sg_list[j].virt, sg_size)) {					printk(KERN_WARNING					       "%s: Could not copy %p TO user %x\n",					       c->name, sg_list[j].virt,					       sg[j].addr_bus);					rcode = -EFAULT;					goto sg_list_cleanup;				}			}		}	}	/* Copy back the reply to user space */	if (reply_size) {		// we wrote our own values for context - now restore the user supplied ones		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {			printk(KERN_WARNING			       "%s: Could not copy message context FROM user\n",			       c->name);			rcode = -EFAULT;			goto sg_list_cleanup;		}		if (copy_to_user(user_reply, reply, reply_size)) {			printk(KERN_WARNING			       "%s: Could not copy reply TO user\n", c->name);			rcode = -EFAULT;		}	}      sg_list_cleanup:	for (i = 0; i < sg_index; i++)		i2o_dma_free(&c->pdev->dev, &sg_list[i]);      cleanup:	kfree(reply);	return rcode;}static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,				 unsigned long arg){	int ret;	lock_kernel();	switch (cmd) {	case I2OGETIOPS:		ret = i2o_cfg_ioctl(NULL, file, cmd, arg);		break;	case I2OPASSTHRU32:		ret = i2o_cfg_passthru32(file, cmd, arg);		break;	default:		ret = -ENOIOCTLCMD;		break;	}	unlock_kernel();	return ret;}#endifstatic int i2o_cfg_passthru(unsigned long arg){	struct i2o_cmd_passthru __user *cmd =	    (struct i2o_cmd_passthru __user *)arg;	struct i2o_controller *c;	u32 __user *user_msg;	u32 *reply = NULL;	u32 __user *user_reply = NULL;	u32 size = 0;	u32 reply_size = 0;	u32 rcode = 0;	void *sg_list[SG_TABLESIZE];	u32 sg_offset = 0;	u32 sg_count = 0;	int sg_index = 0;	u32 i = 0;	void *p = NULL;	i2o_status_block *sb;	struct i2o_message __iomem *msg;	u32 m;	unsigned int iop;	if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))		return -EFAULT;	c = i2o_find_iop(iop);	if (!c) {		osm_warn("controller %d not found\n", iop);		return -ENXIO;	}	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);	sb = c->status_block.virt;	if (get_user(size, &user_msg[0]))		return -EFAULT;	size = size >> 16;	if (size > sb->inbound_frame_size) {		osm_warn("size of message > inbound_frame_size");		return -EFAULT;	}	user_reply = &user_msg[size];	size <<= 2;		// Convert to bytes	/* Copy in the user's I2O command */	if (copy_from_user(msg, user_msg, size))		return -EFAULT;	if (get_user(reply_size, &user_reply[0]) < 0)		return -EFAULT;	reply_size >>= 16;	reply_size <<= 2;	reply = kmalloc(reply_size, GFP_KERNEL);	if (!reply) {		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",		       c->name);		return -ENOMEM;	}	memset(reply, 0, reply_size);	sg_offset = (msg->u.head[0] >> 4) & 0x0f;	writel(i2o_config_driver.context, &msg->u.s.icntxt);	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);	if (sg_offset) {		struct sg_simple_element *sg;		if (sg_offset * 4 >= size) {			rcode = -EFAULT;			goto cleanup;		}		// TODO 64bit fix		sg = (struct sg_simple_element *)((&msg->u.head[0]) +						  sg_offset);		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		if (sg_count > SG_TABLESIZE) {			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",			       c->name, sg_count);			rcode = -EINVAL;			goto cleanup;		}		for (i = 0; i < sg_count; i++) {			int sg_size;			if (!(sg[i].flag_count & 0x10000000			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {				printk(KERN_DEBUG				       "%s:Bad SG element %d - not simple (%x)\n",				       c->name, i, sg[i].flag_count);				rcode = -EINVAL;				goto sg_list_cleanup;			}			sg_size = sg[i].flag_count & 0xffffff;			/* Allocate memory for the transfer */			p = kmalloc(sg_size, GFP_KERNEL);			if (!p) {				printk(KERN_DEBUG				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",				       c->name, sg_size, i, sg_count);				rcode = -ENOMEM;				goto sg_list_cleanup;			}			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.			/* Copy in the user's SG buffer if necessary */			if (sg[i].			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {				// TODO 64bit fix				if (copy_from_user				    (p, (void __user *)sg[i].addr_bus,				     sg_size)) {					printk(KERN_DEBUG					       "%s: Could not copy SG buf %d FROM user\n",					       c->name, i);					rcode = -EFAULT;					goto sg_list_cleanup;				}			}			//TODO 64bit fix			sg[i].addr_bus = virt_to_bus(p);		}	}	rcode = i2o_msg_post_wait(c, m, 60);	if (rcode)		goto sg_list_cleanup;	if (sg_offset) {		u32 msg[128];		/* Copy back the Scatter Gather buffers back to user space */		u32 j;		// TODO 64bit fix		struct sg_simple_element *sg;		int sg_size;		// re-acquire the original message to handle correctly the sg copy operation		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);		// get user msg size in u32s		if (get_user(size, &user_msg[0])) {			rcode = -EFAULT;			goto sg_list_cleanup;		}		size = size >> 16;		size *= 4;		/* Copy in the user's I2O command */		if (copy_from_user(msg, user_msg, size)) {			rcode = -EFAULT;			goto sg_list_cleanup;		}		sg_count =		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);		// TODO 64bit fix		sg = (struct sg_simple_element *)(msg + sg_offset);		for (j = 0; j < sg_count; j++) {			/* Copy out the SG list to user's buffer if necessary */			if (!			    (sg[j].			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {				sg_size = sg[j].flag_count & 0xffffff;				// TODO 64bit fix				if (copy_to_user				    ((void __user *)sg[j].addr_bus, sg_list[j],				     sg_size)) {					printk(KERN_WARNING					       "%s: Could not copy %p TO user %x\n",					       c->name, sg_list[j],					       sg[j].addr_bus);					rcode = -EFAULT;					goto sg_list_cleanup;				}			}		}	}	/* Copy back the reply to user space */	if (reply_size) {		// we wrote our own values for context - now restore the user supplied ones		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {			printk(KERN_WARNING			       "%s: Could not copy message context FROM user\n",			       c->name);			rcode = -EFAULT;		}		if (copy_to_user(user_reply, reply, reply_size)) {			printk(KERN_WARNING			       "%s: Could not copy reply TO user\n", c->name);			rcode = -EFAULT;		}	}      sg_list_cleanup:	for (i = 0; i < sg_index; i++)		kfree(sg_list[i]);      cleanup:	kfree(reply);	return rcode;}#endif/* * IOCTL Handler */static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,			 unsigned long arg){	int ret;	switch (cmd) {	case I2OGETIOPS:		ret = i2o_cfg_getiops(arg);		break;	case I2OHRTGET:		ret = i2o_cfg_gethrt(arg);		break;	case I2OLCTGET:		ret = i2o_cfg_getlct(arg);		break;	case I2OPARMSET:		ret = i2o_cfg_parms(arg, I2OPARMSET);		break;	case I2OPARMGET:		ret = i2o_cfg_parms(arg, I2OPARMGET);		break;	case I2OSWDL:		ret = i2o_cfg_swdl(arg);		break;	case I2OSWUL:		ret = i2o_cfg_swul(arg);		break;	case I2OSWDEL:		ret = i2o_cfg_swdel(arg);		break;	case I2OVALIDATE:		ret = i2o_cfg_validate(arg);		break;	case I2OEVTREG:		ret = i2o_cfg_evt_reg(arg, fp);		break;	case I2OEVTGET:		ret = i2o_cfg_evt_get(arg, fp);		break;#ifdef CONFIG_I2O_EXT_ADAPTEC	case I2OPASSTHRU:		ret = i2o_cfg_passthru(arg);		break;#endif	default:		osm_debug("unknown ioctl called!\n");		ret = -EINVAL;	}	return ret;}static int cfg_open(struct inode *inode, struct file *file){	struct i2o_cfg_info *tmp =	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info),					   GFP_KERNEL);	unsigned long flags;	if (!tmp)		return -ENOMEM;	file->private_data = (void *)(i2o_cfg_info_id++);	tmp->fp = file;	tmp->fasync = NULL;	tmp->q_id = (ulong) file->private_data;	tmp->q_len = 0;	tmp->q_in = 0;	tmp->q_out = 0;	tmp->q_lost = 0;	tmp->next = open_files;	spin_lock_irqsave(&i2o_config_lock, flags);	open_files = tmp;	spin_unlock_irqrestore(&i2o_config_lock, flags);	return 0;}static int cfg_fasync(int fd, struct file *fp, int on){	ulong id = (ulong) fp->private_data;	struct i2o_cfg_info *p;	for (p = open_files; p; p = p->next)		if (p->q_id == id)			break;	if (!p)		return -EBADF;	return fasync_helper(fd, fp, on, &p->fasync);}static int cfg_release(struct inode *inode, struct file *file){	ulong id = (ulong) file->private_data;	struct i2o_cfg_info *p1, *p2;	unsigned long flags;	lock_kernel();	p1 = p2 = NULL;	spin_lock_irqsave(&i2o_config_lock, flags);	for (p1 = open_files; p1;) {		if (p1->q_id == id) {			if (p1->fasync)				cfg_fasync(-1, file, 0);			if (p2)				p2->next = p1->next;			else				open_files = p1->next;			kfree(p1);			break;		}		p2 = p1;		p1 = p1->next;	}	spin_unlock_irqrestore(&i2o_config_lock, flags);	unlock_kernel();	return 0;}static struct file_operations config_fops = {	.owner = THIS_MODULE,	.llseek = no_llseek,	.ioctl = i2o_cfg_ioctl,#ifdef CONFIG_COMPAT	.compat_ioctl = i2o_cfg_compat_ioctl,#endif	.open = cfg_open,	.release = cfg_release,	.fasync = cfg_fasync,};static struct miscdevice i2o_miscdev = {	I2O_MINOR,	"i2octl",	&config_fops};static int __init i2o_config_old_init(void){	spin_lock_init(&i2o_config_lock);	if (misc_register(&i2o_miscdev) < 0) {		osm_err("can't register device.\n");		return -EBUSY;	}	return 0;}static void i2o_config_old_exit(void){	misc_deregister(&i2o_miscdev);}MODULE_AUTHOR("Red Hat Software");

⌨️ 快捷键说明

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