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

📄 i2o_core.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Core I2O structure management  *  * (C) Copyright 1999   Red Hat Software  * * Written by Alan Cox, Building Number Three Ltd  *  * 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.   *  * A lot of the I2O message side code from this is taken from the  * Red Creek RCPCI45 adapter driver by Red Creek Communications  *  * Fixes by:  *		Philipp Rumpf  *		Juha Siev鋘en <Juha.Sievanen@cs.Helsinki.FI>  *		Auvo H鋕kinen <Auvo.Hakkinen@cs.Helsinki.FI>  *		Deepak Saxena <deepak@plexity.net>  *		Boji T Kannanthanam <boji.t.kannanthanam@intel.com> *  */#include <linux/config.h>#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/spinlock.h>#include <linux/smp_lock.h>#include <linux/bitops.h>#include <linux/wait.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/tqueue.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <asm/semaphore.h>#include <linux/completion.h>#include <asm/io.h>#include <linux/reboot.h>#include "i2o_lan.h"//#define DRIVERDEBUG#ifdef DRIVERDEBUG#define dprintk(s, args...) printk(s, ## args)#else#define dprintk(s, args...)#endif/* OSM table */static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];/* Controller list */static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];struct i2o_controller *i2o_controller_chain;int i2o_num_controllers;/* Initiator Context for Core message */static int core_context;/* Initialization && shutdown functions */static void i2o_sys_init(void);static void i2o_sys_shutdown(void);static int i2o_reset_controller(struct i2o_controller *);static int i2o_reboot_event(struct notifier_block *, unsigned long , void *);static int i2o_online_controller(struct i2o_controller *);static int i2o_init_outbound_q(struct i2o_controller *);static int i2o_post_outbound_messages(struct i2o_controller *);/* Reply handler */static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,			   struct i2o_message *);/* Various helper functions */static int i2o_lct_get(struct i2o_controller *);static int i2o_lct_notify(struct i2o_controller *);static int i2o_hrt_get(struct i2o_controller *);static int i2o_build_sys_table(void);static int i2o_systab_send(struct i2o_controller *c);/* I2O core event handler */static int i2o_core_evt(void *);static int evt_pid;static int evt_running;/* Dynamic LCT update handler */static int i2o_dyn_lct(void *);void i2o_report_controller_unit(struct i2o_controller *, struct i2o_device *);/* * I2O System Table.  Contains information about * all the IOPs in the system.  Used to inform IOPs * about each other's existence. * * sys_tbl_ver is the CurrentChangeIndicator that is * used by IOPs to track changes. */static struct i2o_sys_tbl *sys_tbl;static int sys_tbl_ind;static int sys_tbl_len;/* * This spin lock is used to keep a device from being * added and deleted concurrently across CPUs or interrupts. * This can occur when a user creates a device and immediatelly * deletes it before the new_dev_notify() handler is called. */static spinlock_t i2o_dev_lock = SPIN_LOCK_UNLOCKED;#ifdef MODULE/*  * Function table to send to bus specific layers * See <include/linux/i2o.h> for explanation of this */static struct i2o_core_func_table i2o_core_functions ={	i2o_install_controller,	i2o_activate_controller,	i2o_find_controller,	i2o_unlock_controller,	i2o_run_queue,	i2o_delete_controller};#ifdef CONFIG_I2O_PCI_MODULEextern int i2o_pci_core_attach(struct i2o_core_func_table *);extern void i2o_pci_core_detach(void);#endif /* CONFIG_I2O_PCI_MODULE */#endif /* MODULE *//* * Structures and definitions for synchronous message posting. * See i2o_post_wait() for description. */ struct i2o_post_wait_data{	int *status;		/* Pointer to status block on caller stack */	int *complete;		/* Pointer to completion flag on caller stack */	u32 id;			/* Unique identifier */	wait_queue_head_t *wq;	/* Wake up for caller (NULL for dead) */	struct i2o_post_wait_data *next;	/* Chain */	void *mem[2];		/* Memory blocks to recover on failure path */};static struct i2o_post_wait_data *post_wait_queue;static u32 post_wait_id;	// Unique ID for each post_waitstatic spinlock_t post_wait_lock = SPIN_LOCK_UNLOCKED;static void i2o_post_wait_complete(u32, int);/* OSM descriptor handler */ static struct i2o_handler i2o_core_handler ={	(void *)i2o_core_reply,	NULL,	NULL,	NULL,	"I2O core layer",	0,	I2O_CLASS_EXECUTIVE};/* * Used when queueing a reply to be handled later */ struct reply_info{	struct i2o_controller *iop;	u32 msg[MSG_FRAME_SIZE];};static struct reply_info evt_reply;static struct reply_info events[I2O_EVT_Q_LEN];static int evt_in;static int evt_out;static int evt_q_len;#define MODINC(x,y) ((x) = ((x) + 1) % (y))/* * I2O configuration spinlock. This isnt a big deal for contention * so we have one only */static DECLARE_MUTEX(i2o_configuration_lock);/*  * Event spinlock.  Used to keep event queue sane and from * handling multiple events simultaneously. */static spinlock_t i2o_evt_lock = SPIN_LOCK_UNLOCKED;/* * Semaphore used to synchronize event handling thread with  * interrupt handler. */ static DECLARE_MUTEX(evt_sem);static DECLARE_COMPLETION(evt_dead);static DECLARE_WAIT_QUEUE_HEAD(evt_wait);static struct notifier_block i2o_reboot_notifier ={        i2o_reboot_event,        NULL,        0};/* *	Config options */static int verbose;MODULE_PARM(verbose, "i");/* * I2O Core reply handler */static void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,		    struct i2o_message *m){	u32 *msg=(u32 *)m;	u32 status;	u32 context = msg[2];	if (msg[0] & MSG_FAIL) // Fail bit is set	{		u32 *preserved_msg = (u32*)(c->mem_offset + msg[7]);		i2o_report_status(KERN_INFO, "i2o_core", msg);		i2o_dump_message(preserved_msg);		/* If the failed request needs special treatment,		 * it should be done here. */                /* Release the preserved msg by resubmitting it as a NOP */		preserved_msg[0] = cpu_to_le32(THREE_WORD_MSG_SIZE | SGL_OFFSET_0);		preserved_msg[1] = cpu_to_le32(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0);		preserved_msg[2] = 0;		i2o_post_message(c, msg[7]);		/* If reply to i2o_post_wait failed, return causes a timeout */		return;	}       #ifdef DRIVERDEBUG	i2o_report_status(KERN_INFO, "i2o_core", msg);#endif	if(msg[2]&0x80000000)	// Post wait message	{		if (msg[4] >> 24)			status = (msg[4] & 0xFFFF);		else			status = I2O_POST_WAIT_OK;			i2o_post_wait_complete(context, status);		return;	}	if(m->function == I2O_CMD_UTIL_EVT_REGISTER)	{		memcpy(events[evt_in].msg, msg, (msg[0]>>16)<<2);		events[evt_in].iop = c;		spin_lock(&i2o_evt_lock);		MODINC(evt_in, I2O_EVT_Q_LEN);		if(evt_q_len == I2O_EVT_Q_LEN)			MODINC(evt_out, I2O_EVT_Q_LEN);		else			evt_q_len++;		spin_unlock(&i2o_evt_lock);		up(&evt_sem);		wake_up_interruptible(&evt_wait);		return;	}	if(m->function == I2O_CMD_LCT_NOTIFY)	{		up(&c->lct_sem);		return;	}	/*	 * If this happens, we want to dump the message to the syslog so	 * it can be sent back to the card manufacturer by the end user	 * to aid in debugging.	 * 	 */	printk(KERN_WARNING "%s: Unsolicited message reply sent to core!"			"Message dumped to syslog\n", 			c->name);	i2o_dump_message(msg);	return;}/** *	i2o_install_handler - install a message handler *	@h: Handler structure * *	Install an I2O handler - these handle the asynchronous messaging *	from the card once it has initialised. If the table of handlers is *	full then -ENOSPC is returned. On a success 0 is returned and the *	context field is set by the function. The structure is part of the *	system from this time onwards. It must not be freed until it has *	been uninstalled */ int i2o_install_handler(struct i2o_handler *h){	int i;	down(&i2o_configuration_lock);	for(i=0;i<MAX_I2O_MODULES;i++)	{		if(i2o_handlers[i]==NULL)		{			h->context = i;			i2o_handlers[i]=h;			up(&i2o_configuration_lock);			return 0;		}	}	up(&i2o_configuration_lock);	return -ENOSPC;}/** *	i2o_remove_handler - remove an i2o message handler *	@h: handler * *	Remove a message handler previously installed with i2o_install_handler. *	After this function returns the handler object can be freed or re-used */ int i2o_remove_handler(struct i2o_handler *h){	i2o_handlers[h->context]=NULL;	return 0;}	/* *	Each I2O controller has a chain of devices on it. * Each device has a pointer to it's LCT entry to be used * for fun purposes. *//** *	i2o_install_device	-	attach a device to a controller *	@c: controller *	@d: device * 	 *	Add a new device to an i2o controller. This can be called from *	non interrupt contexts only. It adds the device and marks it as *	unclaimed. The device memory becomes part of the kernel and must *	be uninstalled before being freed or reused. Zero is returned *	on success. */ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d){	int i;	down(&i2o_configuration_lock);	d->controller=c;	d->owner=NULL;	d->next=c->devices;	d->prev=NULL;	if (c->devices != NULL)		c->devices->prev=d;	c->devices=d;	*d->dev_name = 0;	for(i = 0; i < I2O_MAX_MANAGERS; i++)		d->managers[i] = NULL;	up(&i2o_configuration_lock);	return 0;}/* we need this version to call out of i2o_delete_controller */int __i2o_delete_device(struct i2o_device *d){	struct i2o_device **p;	int i;	p=&(d->controller->devices);	/*	 *	Hey we have a driver!	 * Check to see if the driver wants us to notify it of 	 * device deletion. If it doesn't we assume that it	 * is unsafe to delete a device with an owner and 	 * fail.	 */	if(d->owner)	{		if(d->owner->dev_del_notify)		{			dprintk(KERN_INFO "Device has owner, notifying\n");			d->owner->dev_del_notify(d->controller, d);			if(d->owner)			{				printk(KERN_WARNING 					"Driver \"%s\" did not release device!\n", d->owner->name);				return -EBUSY;			}		}		else			return -EBUSY;	}	/*	 * Tell any other users who are talking to this device	 * that it's going away.  We assume that everything works.	 */	for(i=0; i < I2O_MAX_MANAGERS; i++)	{		if(d->managers[i] && d->managers[i]->dev_del_notify)			d->managers[i]->dev_del_notify(d->controller, d);	}	 				while(*p!=NULL)	{		if(*p==d)		{			/*			 *	Destroy			 */			*p=d->next;			kfree(d);			return 0;		}		p=&((*p)->next);	}	printk(KERN_ERR "i2o_delete_device: passed invalid device.\n");	return -EINVAL;}/** *	i2o_delete_device	-	remove an i2o device *	@d: device to remove * *	This function unhooks a device from a controller. The device *	will not be unhooked if it has an owner who does not wish to free *	it, or if the owner lacks a dev_del_notify function. In that case *	-EBUSY is returned. On success 0 is returned. Other errors cause *	negative errno values to be returned */ int i2o_delete_device(struct i2o_device *d){	int ret;	down(&i2o_configuration_lock);	/*	 *	Seek, locate	 */	ret = __i2o_delete_device(d);	up(&i2o_configuration_lock);	return ret;}/** *	i2o_install_controller	-	attach a controller *	@c: controller * 	 *	Add a new controller to the i2o layer. This can be called from *	non interrupt contexts only. It adds the controller and marks it as *	unused with no devices. If the tables are full or memory allocations *	fail then a negative errno code is returned. On success zero is *	returned and the controller is bound to the system. The structure *	must not be freed or reused until being uninstalled. */ int i2o_install_controller(struct i2o_controller *c){	int i;	down(&i2o_configuration_lock);	for(i=0;i<MAX_I2O_CONTROLLERS;i++)	{		if(i2o_controllers[i]==NULL)		{			c->dlct = (i2o_lct*)kmalloc(8192, GFP_KERNEL);			if(c->dlct==NULL)			{				up(&i2o_configuration_lock);				return -ENOMEM;			}			i2o_controllers[i]=c;			c->devices = NULL;			c->next=i2o_controller_chain;			i2o_controller_chain=c;			c->unit = i;			c->page_frame = NULL;			c->hrt = NULL;			c->lct = NULL;			c->status_block = NULL;			sprintf(c->name, "i2o/iop%d", i);			i2o_num_controllers++;			init_MUTEX_LOCKED(&c->lct_sem);			up(&i2o_configuration_lock);			return 0;		}	}	printk(KERN_ERR "No free i2o controller slots.\n");	up(&i2o_configuration_lock);	return -EBUSY;}/** *	i2o_delete_controller	- delete a controller *	@c: controller *	 *	Remove an i2o controller from the system. If the controller or its *	devices are busy then -EBUSY is returned. On a failure a negative *	errno code is returned. On success zero is returned. */  int i2o_delete_controller(struct i2o_controller *c){	struct i2o_controller **p;	int users;	char name[16];	int stat;	dprintk(KERN_INFO "Deleting controller %s\n", c->name);

⌨️ 快捷键说明

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