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

📄 i2o_core.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
			continue;		}		/*		 * Loop through all the devices on the IOP looking for their		 * LCT data in the LCT.  We assume that TIDs are not repeated.		 * as that is the only way to really tell.  It's been confirmed		 * by the IRTOS vendor(s?) that TIDs are not reused until they 		 * wrap arround(4096), and I doubt a system will up long enough		 * to create/delete that many devices.		 */		for(d = c->devices; d; )		{			found = 0;			d1 = d->next;						for(i = 0; i < entries; i++) 			{ 				if(d->lct_data.tid == c->dlct->lct_entry[i].tid) 				{ 					found = 1; 					break; 				} 			} 			if(!found) 			{				dprintk(KERN_INFO "i2o_core: Deleted device!\n"); 				spin_lock(&i2o_dev_lock);				i2o_delete_device(d); 				spin_unlock(&i2o_dev_lock);			} 			d = d1; 		}		/* 		 * Tell LCT to renotify us next time there is a change	 	 */		i2o_lct_notify(c);		/*		 * Copy new LCT into public LCT		 *		 * Possible race if someone is reading LCT while  we are copying 		 * over it. If this happens, we'll fix it then. but I doubt that		 * the LCT will get updated often enough or will get read by		 * a user often enough to worry.		 */		if(c->lct->table_size < c->dlct->table_size)		{			tmp = c->lct;			c->lct = kmalloc(c->dlct->table_size<<2, GFP_KERNEL);			if(!c->lct)			{				printk(KERN_ERR "%s: No memory for LCT!\n", c->name);				c->lct = tmp;				continue;			}			kfree(tmp);		}		memcpy(c->lct, c->dlct, c->dlct->table_size<<2);	}	return 0;}/** *	i2o_run_queue	-	process pending events on a controller *	@c: controller to process * *	This is called by the bus specific driver layer when an interrupt *	or poll of this card interface is desired. */ void i2o_run_queue(struct i2o_controller *c){	struct i2o_message *m;	u32 mv;	u32 *msg;	/*	 * Old 960 steppings had a bug in the I2O unit that caused	 * the queue to appear empty when it wasn't.	 */	if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)		mv=I2O_REPLY_READ32(c);	while(mv!=0xFFFFFFFF)	{		struct i2o_handler *i;		/* Map the message from the page frame map to kernel virtual */		/* m=(struct i2o_message *)(mv - (unsigned long)c->page_frame_map + (unsigned long)c->page_frame); */		m=(struct i2o_message *)bus_to_virt(mv);		msg=(u32*)m;		/*	 	 *	Ensure this message is seen coherently but cachably by		 *	the processor 	 	 */		pci_dma_sync_single(c->pdev, c->page_frame_map, MSG_FRAME_SIZE, PCI_DMA_FROMDEVICE);			/*		 *	Despatch it	 	 */		i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];		if(i && i->reply)			i->reply(i,c,m);		else		{			printk(KERN_WARNING "I2O: Spurious reply to handler %d\n", 				m->initiator_context&(MAX_I2O_MODULES-1));		}		 	i2o_flush_reply(c,mv);		mb();		/* That 960 bug again... */			if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)			mv=I2O_REPLY_READ32(c);	}		}/** *	i2o_get_class_name - 	do i2o class name lookup *	@class: class number * *	Return a descriptive string for an i2o class */ const char *i2o_get_class_name(int class){	int idx = 16;	static char *i2o_class_name[] = {		"Executive",		"Device Driver Module",		"Block Device",		"Tape Device",		"LAN Interface",		"WAN Interface",		"Fibre Channel Port",		"Fibre Channel Device",		"SCSI Device",		"ATE Port",		"ATE Device",		"Floppy Controller",		"Floppy Device",		"Secondary Bus Port",		"Peer Transport Agent",		"Peer Transport",		"Unknown"	};		switch(class&0xFFF)	{		case I2O_CLASS_EXECUTIVE:			idx = 0; break;		case I2O_CLASS_DDM:			idx = 1; break;		case I2O_CLASS_RANDOM_BLOCK_STORAGE:			idx = 2; break;		case I2O_CLASS_SEQUENTIAL_STORAGE:			idx = 3; break;		case I2O_CLASS_LAN:			idx = 4; break;		case I2O_CLASS_WAN:			idx = 5; break;		case I2O_CLASS_FIBRE_CHANNEL_PORT:			idx = 6; break;		case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:			idx = 7; break;		case I2O_CLASS_SCSI_PERIPHERAL:			idx = 8; break;		case I2O_CLASS_ATE_PORT:			idx = 9; break;		case I2O_CLASS_ATE_PERIPHERAL:			idx = 10; break;		case I2O_CLASS_FLOPPY_CONTROLLER:			idx = 11; break;		case I2O_CLASS_FLOPPY_DEVICE:			idx = 12; break;		case I2O_CLASS_BUS_ADAPTER_PORT:			idx = 13; break;		case I2O_CLASS_PEER_TRANSPORT_AGENT:			idx = 14; break;		case I2O_CLASS_PEER_TRANSPORT:			idx = 15; break;	}	return i2o_class_name[idx];}/** *	i2o_wait_message	-	obtain an i2o message from the IOP *	@c: controller *	@why: explanation  * *	This function waits up to 5 seconds for a message slot to be *	available. If no message is available it prints an error message *	that is expected to be what the message will be used for (eg *	"get_status"). 0xFFFFFFFF is returned on a failure. * *	On a success the message is returned. This is the physical page *	frame offset address from the read port. (See the i2o spec) */ u32 i2o_wait_message(struct i2o_controller *c, char *why){	long time=jiffies;	u32 m;	while((m=I2O_POST_READ32(c))==0xFFFFFFFF)	{		if((jiffies-time)>=5*HZ)		{			dprintk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n", 				c->name, why);			return 0xFFFFFFFF;		}		schedule();		barrier();	}	return m;}	/** *	i2o_report_controller_unit - print information about a tid *	@c: controller *	@d: device *	 *	Dump an information block associated with a given unit (TID). The *	tables are read and a block of text is output to printk that is *	formatted intended for the user. */ void i2o_report_controller_unit(struct i2o_controller *c, struct i2o_device *d){	char buf[64];	char str[22];	int ret;	int unit = d->lct_data.tid;	if(verbose==0)		return;			printk(KERN_INFO "Target ID %d.\n", unit);	if((ret=i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))>=0)	{		buf[16]=0;		printk(KERN_INFO "     Vendor: %s\n", buf);	}	if((ret=i2o_query_scalar(c, unit, 0xF100, 4, buf, 16))>=0)	{		buf[16]=0;		printk(KERN_INFO "     Device: %s\n", buf);	}	if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)	{		buf[16]=0;		printk(KERN_INFO "     Description: %s\n", buf);	}	if((ret=i2o_query_scalar(c, unit, 0xF100, 6, buf, 8))>=0)	{		buf[8]=0;		printk(KERN_INFO "        Rev: %s\n", buf);	}	printk(KERN_INFO "    Class: ");	sprintf(str, "%-21s", i2o_get_class_name(d->lct_data.class_id));	printk("%s\n", str);			printk(KERN_INFO "  Subclass: 0x%04X\n", d->lct_data.sub_class);	printk(KERN_INFO "     Flags: ");			if(d->lct_data.device_flags&(1<<0))		printk("C");		// ConfigDialog requested	if(d->lct_data.device_flags&(1<<1))		printk("U");		// Multi-user capable	if(!(d->lct_data.device_flags&(1<<4)))		printk("P");		// Peer service enabled!	if(!(d->lct_data.device_flags&(1<<5)))		printk("M");		// Mgmt service enabled!	printk("\n");			}/* *	Parse the hardware resource table. Right now we print it out *	and don't do a lot with it. We should collate these and then *	interact with the Linux resource allocation block. * *	Lets prove we can read it first eh ? * *	This is full of endianisms! */ static int i2o_parse_hrt(struct i2o_controller *c){#ifdef DRIVERDEBUG	u32 *rows=(u32*)c->hrt;	u8 *p=(u8 *)c->hrt;	u8 *d;	int count;	int length;	int i;	int state;		if(p[3]!=0)	{		printk(KERN_ERR "%s: HRT table for controller is too new a version.\n",			c->name);		return -1;	}			count=p[0]|(p[1]<<8);	length = p[2];		printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n",		c->name, count, length<<2);	rows+=2;		for(i=0;i<count;i++)	{		printk(KERN_INFO "Adapter %08X: ", rows[0]);		p=(u8 *)(rows+1);		d=(u8 *)(rows+2);		state=p[1]<<8|p[0];				printk("TID %04X:[", state&0xFFF);		state>>=12;		if(state&(1<<0))			printk("H");		/* Hidden */		if(state&(1<<2))		{			printk("P");		/* Present */			if(state&(1<<1))				printk("C");	/* Controlled */		}		if(state>9)			printk("*");		/* Hard */				printk("]:");				switch(p[3]&0xFFFF)		{			case 0:				/* Adapter private bus - easy */				printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", 					p[2], d[1]<<8|d[0], *(u32 *)(d+4));				break;			case 1:				/* ISA bus */				printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X",					p[2], d[2], d[1]<<8|d[0], *(u32 *)(d+4));				break;								case 2: /* EISA bus */				printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",					p[2], d[3], d[1]<<8|d[0], *(u32 *)(d+4));				break;			case 3: /* MCA bus */				printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X",					p[2], d[3], d[1]<<8|d[0], *(u32 *)(d+4));				break;			case 4: /* PCI bus */				printk("PCI %d: Bus %d Device %d Function %d",					p[2], d[2], d[1], d[0]);				break;			case 0x80: /* Other */			default:				printk("Unsupported bus type.");				break;		}		printk("\n");		rows+=length;	}#endif	return 0;}	/* *	The logical configuration table tells us what we can talk to *	on the board. Most of the stuff isn't interesting to us.  */static int i2o_parse_lct(struct i2o_controller *c){	int i;	int max;	int tid;	struct i2o_device *d;	i2o_lct *lct = c->lct;	if (lct == NULL) {		printk(KERN_ERR "%s: LCT is empty???\n", c->name);		return -1;	}	max = lct->table_size;	max -= 3;	max /= 9;		printk(KERN_INFO "%s: LCT has %d entries.\n", c->name, max);		if(lct->iop_flags&(1<<0))		printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);			for(i=0;i<max;i++)	{		d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);		if(d==NULL)		{			printk(KERN_CRIT "i2o_core: Out of memory for I2O device data.\n");			return -ENOMEM;		}				d->controller = c;		d->next = NULL;		memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));		d->flags = 0;		tid = d->lct_data.tid;				i2o_report_controller_unit(c, d);				i2o_install_device(c, d);	}	return 0;}/** *	i2o_quiesce_controller - quiesce controller *	@c: controller  * *	Quiesce an IOP. Causes IOP to make external operation quiescent *	(i2o 'READY' state). Internal operation of the IOP continues normally. */ int i2o_quiesce_controller(struct i2o_controller *c){	u32 msg[4];	int ret;	i2o_status_get(c);	/* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */	if ((c->status_block->iop_state != ADAPTER_STATE_READY) &&		(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))	{		return 0;	}	msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;	msg[3] = 0;	/* Long timeout needed for quiesce if lots of devices */	if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))		printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",			c->name, -ret);	else		dprintk(KERN_INFO "%s: Quiesced.\n", c->name);	i2o_status_get(c); // Entered READY state	return ret;}/** *	i2o_enable_controller - move controller from ready to operational *	@c: controller * *	Enable IOP. This allows the IOP to resume external operations and *	reverses the effect of a quiesce. In the event of an error a negative *	errno code is returned. */ int i2o_enable_controller(struct i2o_controller *c){	u32 msg[4];	int ret;	i2o_status_get(c);		/* Enable only allowed on READY state */		if(c->status_block->iop_state != ADAPTER_STATE_READY)		return -EINVAL;	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;	/* How long of a timeout do we need? */	if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))		printk(KERN_ERR "%s: Could not enable (status=%#x).\n",			c->name, -ret);	else		dprintk(KERN_INFO "%s: Enabled.\n", c->name);	i2o_status_get(c); // entered OPERATIONAL state	return ret;}/** *	i2o_clear_controller	-	clear a controller *	@c: controller * *	Clear an IOP to HOLD state, ie. terminate external operations, clear all *	input queues and prepare for a system restart. IOP's internal operation *	continues normally and the outbound queue is alive. *	The IOP is not expected to rebuild its LCT. */ int i2o_clear_controller(struct i2o_controller *c){	struct i2o_controller *iop;	u32 msg[4];	int ret;	/* Quiesce all IOPs first */	for (iop = i2o_controller_chain; iop; iop = iop->next)		i2o_quiesce_controller(iop);	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;	msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;	msg[3]=0;	if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))		printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",			c->name, -ret);	else		dprintk(KERN_INFO "%s: Cleared.\n",c->name);	i2o_status_get(c);	/* Enable other IOPs */	for (iop = i2o_controller_chain; iop; iop = iop->next)

⌨️ 快捷键说明

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