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

📄 i2o_core.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (iop != c)			i2o_enable_controller(iop);	return ret;}/** *	i2o_reset_controller	-	reset an IOP *	@c: controller to reset * *	Reset the IOP into INIT state and wait until IOP gets into RESET state. *	Terminate all external operations, clear IOP's inbound and outbound *	queues, terminate all DDMs, and reload the IOP's operating environment *	and all local DDMs. The IOP rebuilds its LCT. */ static int i2o_reset_controller(struct i2o_controller *c){	struct i2o_controller *iop;	u32 m;	u8 *status;	u32 *msg;	long time;	/* Quiesce all IOPs first */	for (iop = i2o_controller_chain; iop; iop = iop->next)	{		if(iop->type != I2O_TYPE_PCI || !iop->bus.pci.dpt)			i2o_quiesce_controller(iop);	}	m=i2o_wait_message(c, "AdapterReset");	if(m==0xFFFFFFFF)			return -ETIMEDOUT;	msg=(u32 *)(c->mem_offset+m);		status=(void *)kmalloc(4, GFP_KERNEL);	if(status==NULL) {		printk(KERN_ERR "IOP reset failed - no free memory.\n");		return -ENOMEM;	}	memset(status, 0, 4);		msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;	msg[2]=core_context;	msg[3]=0;	msg[4]=0;	msg[5]=0;	msg[6]=virt_to_bus(status);	msg[7]=0;	/* 64bit host FIXME */	i2o_post_message(c,m);	/* Wait for a reply */	time=jiffies;	while(*status==0)	{		if((jiffies-time)>=20*HZ)		{			printk(KERN_ERR "IOP reset timeout.\n");			// Better to leak this for safety: kfree(status);			return -ETIMEDOUT;		}		schedule();		barrier();	}	if (*status==I2O_CMD_IN_PROGRESS)	{ 		/* 		 * Once the reset is sent, the IOP goes into the INIT state 		 * which is indeterminate.  We need to wait until the IOP 		 * has rebooted before we can let the system talk to 		 * it. We read the inbound Free_List until a message is 		 * available.  If we can't read one in the given ammount of 		 * time, we assume the IOP could not reboot properly.  		 */ 		dprintk(KERN_INFO "%s: Reset in progress, waiting for reboot...\n",			c->name); 		time = jiffies; 		m = I2O_POST_READ32(c); 		while(m == 0XFFFFFFFF) 		{ 			if((jiffies-time) >= 30*HZ)			{				printk(KERN_ERR "%s: Timeout waiting for IOP reset.\n", 						c->name); 				return -ETIMEDOUT; 			} 			schedule(); 			barrier(); 			m = I2O_POST_READ32(c); 		}		i2o_flush_reply(c,m);	}	/* If IopReset was rejected or didn't perform reset, try IopClear */	i2o_status_get(c);	if (status[0] == I2O_CMD_REJECTED || 		c->status_block->iop_state != ADAPTER_STATE_RESET)	{		printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name);		i2o_clear_controller(c);	}	else		dprintk(KERN_INFO "%s: Reset completed.\n", c->name);	/* Enable other IOPs */	for (iop = i2o_controller_chain; iop; iop = iop->next)		if (iop != c)			i2o_enable_controller(iop);	kfree(status);	return 0;}/** * 	i2o_status_get	-	get the status block for the IOP *	@c: controller * *	Issue a status query on the controller. This updates the *	attached status_block. If the controller fails to reply or an *	error occurs then a negative errno code is returned. On success *	zero is returned and the status_blok is updated. */ int i2o_status_get(struct i2o_controller *c){	long time;	u32 m;	u32 *msg;	u8 *status_block;	if (c->status_block == NULL) 	{		c->status_block = (i2o_status_block *)			kmalloc(sizeof(i2o_status_block),GFP_KERNEL);		if (c->status_block == NULL)		{			printk(KERN_CRIT "%s: Get Status Block failed; Out of memory.\n",				c->name);			return -ENOMEM;		}	}	status_block = (u8*)c->status_block;	memset(c->status_block,0,sizeof(i2o_status_block));		m=i2o_wait_message(c, "StatusGet");	if(m==0xFFFFFFFF)		return -ETIMEDOUT;		msg=(u32 *)(c->mem_offset+m);	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;	msg[2]=core_context;	msg[3]=0;	msg[4]=0;	msg[5]=0;	msg[6]=virt_to_bus(c->status_block);	msg[7]=0;   /* 64bit host FIXME */	msg[8]=sizeof(i2o_status_block); /* always 88 bytes */	i2o_post_message(c,m);	/* Wait for a reply */	time=jiffies;	while(status_block[87]!=0xFF)	{		if((jiffies-time)>=5*HZ)		{			printk(KERN_ERR "%s: Get status timeout.\n",c->name);			return -ETIMEDOUT;		}		schedule();		barrier();	}#ifdef DRIVERDEBUG	printk(KERN_INFO "%s: State = ", c->name);	switch (c->status_block->iop_state) {		case 0x01:  			printk("INIT\n");			break;		case 0x02:			printk("RESET\n");			break;		case 0x04:			printk("HOLD\n");			break;		case 0x05:			printk("READY\n");			break;		case 0x08:			printk("OPERATIONAL\n");			break;		case 0x10:			printk("FAILED\n");			break;		case 0x11:			printk("FAULTED\n");			break;		default: 			printk("%x (unknown !!)\n",c->status_block->iop_state);}     #endif   	return 0;}/* * Get the Hardware Resource Table for the device. * The HRT contains information about possible hidden devices * but is mostly useless to us  */int i2o_hrt_get(struct i2o_controller *c){	u32 msg[6];	int ret, size = sizeof(i2o_hrt);	/* First read just the header to figure out the real size */	do  {		if (c->hrt == NULL) {			c->hrt=kmalloc(size, GFP_KERNEL);			if (c->hrt == NULL) {				printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", c->name);				return -ENOMEM;			}		}		msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;		msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;		msg[3]= 0;		msg[4]= (0xD0000000 | size);	/* Simple transaction */		msg[5]= virt_to_bus(c->hrt);	/* Dump it here */		ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL);				if(ret == -ETIMEDOUT)		{			/* The HRT block we used is in limbo somewhere. When the iop wakes up			   we will recover it */			c->hrt = NULL;			return ret;		}				if(ret<0)		{			printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",				c->name, -ret);				return ret;		}		if (c->hrt->num_entries * c->hrt->entry_len << 2 > size) {			size = c->hrt->num_entries * c->hrt->entry_len << 2;			kfree(c->hrt);			c->hrt = NULL;		}	} while (c->hrt == NULL);	i2o_parse_hrt(c); // just for debugging	return 0;}/* * Send the I2O System Table to the specified IOP * * The system table contains information about all the IOPs in the * system.  It is build and then sent to each IOP so that IOPs can * establish connections between each other. * */static int i2o_systab_send(struct i2o_controller *iop){	u32 msg[12];	int ret;	u32 *privbuf = kmalloc(16, GFP_KERNEL);	if(privbuf == NULL)		return -ENOMEM;		if(iop->type == I2O_TYPE_PCI)	{		struct resource *root;				if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size)		{			struct resource *res = &iop->mem_resource;			res->name = iop->pdev->bus->name;			res->flags = IORESOURCE_MEM;			res->start = 0;			res->end = 0;			printk("%s: requires private memory resources.\n", iop->name);			root = pci_find_parent_resource(iop->pdev, res);			if(root==NULL)				printk("Can't find parent resource!\n");			if(root && allocate_resource(root, res, 					iop->status_block->desired_mem_size,					iop->status_block->desired_mem_size,					iop->status_block->desired_mem_size,					1<<20,	/* Unspecified, so use 1Mb and play safe */					NULL,					NULL)>=0)			{				iop->mem_alloc = 1;				iop->status_block->current_mem_size = 1 + res->end - res->start;				iop->status_block->current_mem_base = res->start;				printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", 					iop->name, 1+res->end-res->start, res->start);			}		}		if(iop->status_block->current_io_size < iop->status_block->desired_io_size)		{			struct resource *res = &iop->io_resource;			res->name = iop->pdev->bus->name;			res->flags = IORESOURCE_IO;			res->start = 0;			res->end = 0;			printk("%s: requires private memory resources.\n", iop->name);			root = pci_find_parent_resource(iop->pdev, res);			if(root==NULL)				printk("Can't find parent resource!\n");			if(root &&  allocate_resource(root, res, 					iop->status_block->desired_io_size,					iop->status_block->desired_io_size,					iop->status_block->desired_io_size,					1<<20,	/* Unspecified, so use 1Mb and play safe */					NULL,					NULL)>=0)			{				iop->io_alloc = 1;				iop->status_block->current_io_size = 1 + res->end - res->start;				iop->status_block->current_mem_base = res->start;				printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", 					iop->name, 1+res->end-res->start, res->start);			}		}	}	else	{			privbuf[0] = iop->status_block->current_mem_base;		privbuf[1] = iop->status_block->current_mem_size;		privbuf[2] = iop->status_block->current_io_base;		privbuf[3] = iop->status_block->current_io_size;	}	msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;	msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;	msg[3] = 0;	msg[4] = (0<<16) | ((iop->unit+2) );      /* Host 0 IOP ID (unit + 2) */	msg[5] = 0;                               /* Segment 0 */	/*  	 * Provide three SGL-elements: 	 * System table (SysTab), Private memory space declaration and  	 * Private i/o space declaration   	 * 	 * FIXME: provide these for controllers needing them 	 */	msg[6] = 0x54000000 | sys_tbl_len;	msg[7] = virt_to_bus(sys_tbl);	msg[8] = 0x54000000 | 8;	msg[9] = virt_to_bus(privbuf);	msg[10] = 0xD4000000 | 8;	msg[11] = virt_to_bus(privbuf+2);	ret=i2o_post_wait_mem(iop, msg, sizeof(msg), 120, privbuf, NULL);		if(ret==-ETIMEDOUT)	{		printk(KERN_ERR "%s: SysTab setup timed out.\n", iop->name);	}	else if(ret<0)	{		printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", 			iop->name, -ret);		kfree(privbuf);	}	else	{		dprintk(KERN_INFO "%s: SysTab set.\n", iop->name);		kfree(privbuf);	}	i2o_status_get(iop); // Entered READY state	return ret;	 }/* * Initialize I2O subsystem. */static void __init i2o_sys_init(void){	struct i2o_controller *iop, *niop = NULL;	printk(KERN_INFO "Activating I2O controllers...\n");	printk(KERN_INFO "This may take a few minutes if there are many devices\n");		/* In INIT state, Activate IOPs */	for (iop = i2o_controller_chain; iop; iop = niop) {		dprintk(KERN_INFO "Calling i2o_activate_controller for %s...\n", 			iop->name);		niop = iop->next;		if (i2o_activate_controller(iop) < 0)			i2o_delete_controller(iop);	}	/* Active IOPs in HOLD state */rebuild_sys_tab:	if (i2o_controller_chain == NULL)		return;	/*	 * If build_sys_table fails, we kill everything and bail	 * as we can't init the IOPs w/o a system table	 */		dprintk(KERN_INFO "i2o_core: Calling i2o_build_sys_table...\n");	if (i2o_build_sys_table() < 0) {		i2o_sys_shutdown();		return;	}	/* If IOP don't get online, we need to rebuild the System table */	for (iop = i2o_controller_chain; iop; iop = niop) {		niop = iop->next;		dprintk(KERN_INFO "Calling i2o_online_controller for %s...\n", iop->name);		if (i2o_online_controller(iop) < 0) {			i2o_delete_controller(iop);				goto rebuild_sys_tab;		}	}		/* Active IOPs now in OPERATIONAL state */	/*	 * Register for status updates from all IOPs	 */	for(iop = i2o_controller_chain; iop; iop=iop->next) {		/* Create a kernel thread to deal with dynamic LCT updates */		iop->lct_pid = kernel_thread(i2o_dyn_lct, iop, CLONE_SIGHAND);			/* Update change ind on DLCT */		iop->dlct->change_ind = iop->lct->change_ind;		/* Start dynamic LCT updates */		i2o_lct_notify(iop);		/* Register for all events from IRTOS */		i2o_event_register(iop, core_context, 0, 0, 0xFFFFFFFF);	}}/** *	i2o_sys_shutdown - shutdown I2O system * *	Bring down each i2o controller and then return. Each controller *	is taken through an orderly shutdown */ static void i2o_sys_shutdown(void){	struct i2o_controller *iop, *niop;	/* Delete all IOPs from the controller chain */	/* that will reset all IOPs too */	for (iop = i2o_controller_chain; iop; iop = niop) {		niop = iop->next;		i2o_delete_controller(iop);	}}/** *	i2o_activate_controller	-	bring controller up to HOLD *	@iop: controller * *	This function brings an I2O controller into HOLD state. The adapter *	is reset if neccessary and then the queues and resource table *	are read. -1 is returned on a failure, 0 on success. *	 */ int i2o_activate_controller(struct i2o_controller *iop){	/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */	/* In READY state, Get status */	if (i2o_status_get(iop) < 0) {		printk(KERN_INFO "Unable to obtain status of %s, "			"attempting a reset.\n", iop->name);		if (i2o_reset_controller(iop) < 0)			return -1;	}	if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {		printk(KERN_CRIT "%s: hardware fault\n", iop->name);		return -1;	}	if (iop->status_block->i2o_version > I2OVER15) {		printk(KERN_ERR "%s: Not running vrs. 1.5. of the I2O Specification.\n",			iop->name);		return -1;	}	if (iop->status_block->iop_state == ADAPTER_STATE_READY ||	    iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||	    iop->status_block->iop_state == ADAPTER_STATE_HOLD ||	    iop->status_block->iop_state == ADAPTER_STATE_FAILED)	{		dprintk(KERN_INFO "%s: Already running, trying to reset...\n",			iop->name);		if (i2o_reset_controller(iop) < 0)			return -1;	}	if (i2o_init_outbound_q(iop) < 0)		return -1;	if (i2o_post_outbound_messages(iop)) 		return -1;	/* In HOLD state */		if (i2o_hrt_get(iop) < 0)		return -1;	return 0;}/** *	i2o_init_outbound_queue	- setup the outbound queue *	@c: controller *

⌨️ 快捷键说明

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