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

📄 i2o_config.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * I2O Configuration Interface Driver * * (C) Copyright 1999   Red Hat Software *	 * Written by Alan Cox, Building Number Three Ltd * * Modified 04/20/1999 by Deepak Saxena *   - Added basic ioctl() support * Modified 06/07/1999 by Deepak Saxena *   - Added software download ioctl (still testing) * Modified 09/10/1999 by Auvo H鋕kinen *   - Changes to i2o_cfg_reply(), ioctl_parms() *   - Added ioct_validate() * Modified 09/30/1999 by Taneli V鋒鋕angas *   - Fixed ioctl_swdl() * Modified 10/04/1999 by Taneli V鋒鋕angas *   - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() * Modified 11/18/199 by Deepak Saxena *   - Added event managmenet support * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/i2o.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/miscdevice.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/io.h>static int i2o_cfg_context = -1;static void *page_buf;static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;struct wait_queue *i2o_wait_queue;#define MODINC(x,y) ((x) = ((x) + 1) % (y))struct i2o_cfg_info{	struct file* fp;	struct fasync_struct *fasync;	struct i2o_evt_info event_q[I2O_EVT_Q_LEN];	u16		q_in;		// Queue head index	u16		q_out;		// Queue tail index	u16		q_len;		// Queue length	u16		q_lost;		// Number of lost events	u32		q_id;		// Event queue ID...used as tx_context	struct	i2o_cfg_info *next;};static struct i2o_cfg_info *open_files = NULL;static int i2o_cfg_info_id = 0;static int ioctl_getiops(unsigned long);static int ioctl_gethrt(unsigned long);static int ioctl_getlct(unsigned long);static int ioctl_parms(unsigned long, unsigned int);static int ioctl_html(unsigned long);static int ioctl_swdl(unsigned long);static int ioctl_swul(unsigned long);static int ioctl_swdel(unsigned long);static int ioctl_validate(unsigned long); static int ioctl_evt_reg(unsigned long, struct file *);static int ioctl_evt_get(unsigned long, struct file *);static int cfg_fasync(int, struct file*, int);/* *	This is the callback for any message we have posted. The message itself *	will be returned to the message pool when we return from the IRQ * *	This runs in irq context so be short and sweet. */static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m){	u32 *msg = (u32 *)m;	if (msg[0] & MSG_FAIL) {		u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);		printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");		/* Release the preserved msg frame by resubmitting it as a NOP */		preserved_msg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;		preserved_msg[1] = I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0;		preserved_msg[2] = 0;		i2o_post_message(c, msg[7]);	}	if (msg[4] >> 24)  // ReqStatus != SUCCESS		i2o_report_status(KERN_INFO,"i2o_config", msg);	if(m->function == I2O_CMD_UTIL_EVT_REGISTER)	{		struct i2o_cfg_info *inf;		for(inf = open_files; inf; inf = inf->next)			if(inf->q_id == msg[3])				break;		//		// If this is the case, it means that we're getting		// events for a file descriptor that's been close()'d		// w/o the user unregistering for events first.		// The code currently assumes that the user will 		// take care of unregistering for events before closing		// a file.		// 		// TODO: 		// Should we track event registartion and deregister		// for events when a file is close()'d so this doesn't		// happen? That would get rid of the search through		// the linked list since file->private_data could point		// directly to the i2o_config_info data structure...but		// it would mean having all sorts of tables to track		// what each file is registered for...I think the		// current method is simpler. - DS		//					if(!inf)			return;		inf->event_q[inf->q_in].id.iop = c->unit;		inf->event_q[inf->q_in].id.tid = m->target_tid;		inf->event_q[inf->q_in].id.evt_mask = msg[4];		//		// Data size = msg size - reply header		//		inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;		if(inf->event_q[inf->q_in].data_size)			memcpy(inf->event_q[inf->q_in].evt_data, 				(unsigned char *)(msg + 5),				inf->event_q[inf->q_in].data_size);		spin_lock(&i2o_config_lock);		MODINC(inf->q_in, I2O_EVT_Q_LEN);		if(inf->q_len == I2O_EVT_Q_LEN)		{			MODINC(inf->q_out, I2O_EVT_Q_LEN);			inf->q_lost++;		}		else		{			// Keep I2OEVTGET on another CPU from touching this			inf->q_len++;		}		spin_unlock(&i2o_config_lock);		//		printk(KERN_INFO "File %p w/id %d has %d events\n",//			inf->fp, inf->q_id, inf->q_len);			kill_fasync(&inf->fasync, SIGIO, POLL_IN);	}	return;}/* *	Each of these describes an i2o message handler. They are *	multiplexed by the i2o_core code */ struct i2o_handler cfg_handler={	i2o_cfg_reply,	NULL,	NULL,	NULL,	"Configuration",	0,	0xffffffff	// All classes};static ssize_t cfg_write(struct file *file, const char *buf, size_t count, loff_t *ppos){	printk(KERN_INFO "i2o_config write not yet supported\n");	return 0;}static ssize_t cfg_read(struct file *file, char *buf, size_t count, loff_t *ptr){	return 0;}/* * IOCTL Handler */static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,	unsigned long arg){	int ret;	switch(cmd)	{			case I2OGETIOPS:			ret = ioctl_getiops(arg);			break;		case I2OHRTGET:			ret = ioctl_gethrt(arg);			break;		case I2OLCTGET:			ret = ioctl_getlct(arg);			break;		case I2OPARMSET:			ret = ioctl_parms(arg, I2OPARMSET);			break;		case I2OPARMGET:			ret = ioctl_parms(arg, I2OPARMGET);			break;		case I2OSWDL:			ret = ioctl_swdl(arg);			break;		case I2OSWUL:			ret = ioctl_swul(arg);			break;		case I2OSWDEL:			ret = ioctl_swdel(arg);			break;		case I2OVALIDATE:			ret = ioctl_validate(arg);			break;					case I2OHTML:			ret = ioctl_html(arg);			break;		case I2OEVTREG:			ret = ioctl_evt_reg(arg, fp);			break;		case I2OEVTGET:			ret = ioctl_evt_get(arg, fp);			break;		default:			ret = -EINVAL;	}	return ret;}int ioctl_getiops(unsigned long arg){	u8 *user_iop_table = (u8*)arg;	struct i2o_controller *c = NULL;	int i;	u8 foo[MAX_I2O_CONTROLLERS];	if(!access_ok(VERIFY_WRITE, user_iop_table,  MAX_I2O_CONTROLLERS))		return -EFAULT;	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)	{		c = i2o_find_controller(i);		if(c)		{			foo[i] = 1;			i2o_unlock_controller(c);		}		else		{			foo[i] = 0;		}	}	__copy_to_user(user_iop_table, foo, MAX_I2O_CONTROLLERS);	return 0;}int ioctl_gethrt(unsigned long arg){	struct i2o_controller *c;	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;	struct i2o_cmd_hrtlct kcmd;	i2o_hrt *hrt;	int len;	u32 reslen;	int ret = 0;	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))		return -EFAULT;	if(get_user(reslen, kcmd.reslen) < 0)		return -EFAULT;	if(kcmd.resbuf == NULL)		return -EFAULT;	c = i2o_find_controller(kcmd.iop);	if(!c)		return -ENXIO;			hrt = (i2o_hrt *)c->hrt;	i2o_unlock_controller(c);	len = 8 + ((hrt->entry_len * hrt->num_entries) << 2);		/* We did a get user...so assuming mem is ok...is this bad? */	put_user(len, kcmd.reslen);	if(len > reslen)		ret = -ENOBUFS;		if(copy_to_user(kcmd.resbuf, (void*)hrt, len))		ret = -EFAULT;	return ret;}int ioctl_getlct(unsigned long arg){	struct i2o_controller *c;	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;	struct i2o_cmd_hrtlct kcmd;	i2o_lct *lct;	int len;	int ret = 0;	u32 reslen;	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))		return -EFAULT;	if(get_user(reslen, kcmd.reslen) < 0)		return -EFAULT;	if(kcmd.resbuf == NULL)		return -EFAULT;	c = i2o_find_controller(kcmd.iop);	if(!c)		return -ENXIO;	lct = (i2o_lct *)c->lct;	i2o_unlock_controller(c);	len = (unsigned int)lct->table_size << 2;	put_user(len, kcmd.reslen);	if(len > reslen)		ret = -ENOBUFS;		else if(copy_to_user(kcmd.resbuf, (void*)lct, len))		ret = -EFAULT;	return ret;}static int ioctl_parms(unsigned long arg, unsigned int type){	int ret = 0;	struct i2o_controller *c;	struct i2o_cmd_psetget *cmd = (struct i2o_cmd_psetget*)arg;	struct i2o_cmd_psetget kcmd;	u32 reslen;	u8 *ops;	u8 *res;	int len;	u32 i2o_cmd = (type == I2OPARMGET ? 				I2O_CMD_UTIL_PARAMS_GET :				I2O_CMD_UTIL_PARAMS_SET);	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))		return -EFAULT;	if(get_user(reslen, kcmd.reslen))		return -EFAULT;	c = i2o_find_controller(kcmd.iop);	if(!c)		return -ENXIO;	ops = (u8*)kmalloc(kcmd.oplen, GFP_KERNEL);	if(!ops)	{		i2o_unlock_controller(c);		return -ENOMEM;	}	if(copy_from_user(ops, kcmd.opbuf, kcmd.oplen))	{		i2o_unlock_controller(c);		kfree(ops);		return -EFAULT;	}	/*	 * It's possible to have a _very_ large table	 * and that the user asks for all of it at once...	 */	res = (u8*)kmalloc(65536, GFP_KERNEL);	if(!res)	{		i2o_unlock_controller(c);		kfree(ops);		return -ENOMEM;	}	len = i2o_issue_params(i2o_cmd, c, kcmd.tid, 				ops, kcmd.oplen, res, 65536);	i2o_unlock_controller(c);	kfree(ops);        	if (len < 0) {		kfree(res);		return -EAGAIN;	}	put_user(len, kcmd.reslen);	if(len > reslen)		ret = -ENOBUFS;	else if(copy_to_user(cmd->resbuf, res, len))		ret = -EFAULT;	kfree(res);	return ret;}int ioctl_html(unsigned long arg){	struct i2o_html *cmd = (struct i2o_html*)arg;	struct i2o_html kcmd;	struct i2o_controller *c;	u8 *res = NULL;	void *query = NULL;	int ret = 0;	int token;	u32 len;	u32 reslen;	u32 msg[MSG_FRAME_SIZE/4];	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_html)))	{		printk(KERN_INFO "i2o_config: can't copy html cmd\n");		return -EFAULT;	}	if(get_user(reslen, kcmd.reslen) < 0)	{		printk(KERN_INFO "i2o_config: can't copy html reslen\n");		return -EFAULT;	}	if(!kcmd.resbuf)			{		printk(KERN_INFO "i2o_config: NULL html buffer\n");		return -EFAULT;	}	c = i2o_find_controller(kcmd.iop);	if(!c)		return -ENXIO;	if(kcmd.qlen) /* Check for post data */	{		query = kmalloc(kcmd.qlen, GFP_KERNEL);		if(!query)		{			i2o_unlock_controller(c);			return -ENOMEM;		}		if(copy_from_user(query, kcmd.qbuf, kcmd.qlen))		{			i2o_unlock_controller(c);

⌨️ 快捷键说明

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