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

📄 i2o_core.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 */int i2o_lct_notify(struct i2o_controller *c){	u32 msg[8];	msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;	msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;	msg[2] = core_context;	msg[3] = 0xDEADBEEF;		msg[4] = 0xFFFFFFFF;	/* All devices */	msg[5] = c->dlct->change_ind+1;	/* Next change */	msg[6] = 0xD0000000|8192;	msg[7] = virt_to_bus(c->dlct);	return i2o_post_this(c, msg, sizeof(msg));}		/* *	Bring a controller online into OPERATIONAL state.  */int i2o_online_controller(struct i2o_controller *iop){	if (i2o_systab_send(iop) < 0)		return -1;	/* In READY state */	dprintk(KERN_INFO "%s: Attempting to enable...\n", iop->name);	if (i2o_enable_controller(iop) < 0)		return -1;	/* In OPERATIONAL state  */	dprintk(KERN_INFO "%s: Attempting to get/parse lct...\n", iop->name);	if (i2o_lct_get(iop) < 0)		return -1;	return 0;}/* * Build system table * * The system table contains information about all the IOPs in the * system (duh) and is used by the Executives on the IOPs to establish * peer2peer connections.  We're not supporting peer2peer at the moment, * but this will be needed down the road for things like lan2lan forwarding. */static int i2o_build_sys_table(void){	struct i2o_controller *iop = NULL;	struct i2o_controller *niop = NULL;	int count = 0;	sys_tbl_len = sizeof(struct i2o_sys_tbl) +	// Header + IOPs				(i2o_num_controllers) *					sizeof(struct i2o_sys_tbl_entry);	if(sys_tbl)		kfree(sys_tbl);	sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL);	if(!sys_tbl) {		printk(KERN_CRIT "SysTab Set failed. Out of memory.\n");		return -ENOMEM;	}	memset((void*)sys_tbl, 0, sys_tbl_len);	sys_tbl->num_entries = i2o_num_controllers;	sys_tbl->version = I2OVERSION; /* TODO: Version 2.0 */	sys_tbl->change_ind = sys_tbl_ind++;	for(iop = i2o_controller_chain; iop; iop = niop)	{		niop = iop->next;		/* 		 * Get updated IOP state so we have the latest information		 *		 * We should delete the controller at this point if it		 * doesn't respond since  if it's not on the system table 		 * it is techninically not part of the I2O subsy遲em...		 */		if(i2o_status_get(iop)) {			printk(KERN_ERR "%s: Deleting b/c could not get status while"				"attempting to build system table\n", iop->name);			i2o_delete_controller(iop);					sys_tbl->num_entries--;			continue; // try the next one		}		sys_tbl->iops[count].org_id = iop->status_block->org_id;		sys_tbl->iops[count].iop_id = iop->unit + 2;		sys_tbl->iops[count].seg_num = 0;		sys_tbl->iops[count].i2o_version = 				iop->status_block->i2o_version;		sys_tbl->iops[count].iop_state = 				iop->status_block->iop_state;		sys_tbl->iops[count].msg_type = 				iop->status_block->msg_type;		sys_tbl->iops[count].frame_size = 				iop->status_block->inbound_frame_size;		sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??		sys_tbl->iops[count].iop_capabilities = 				iop->status_block->iop_capabilities;		sys_tbl->iops[count].inbound_low = 				(u32)virt_to_bus(iop->post_port);		sys_tbl->iops[count].inbound_high = 0;	// TODO: 64-bit support		count++;	}#ifdef DRIVERDEBUG{	u32 *table;	table = (u32*)sys_tbl;	for(count = 0; count < (sys_tbl_len >>2); count++)		printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);}#endif	return 0;}/* *	Run time support routines */ /* *	Generic "post and forget" helpers. This is less efficient - we do *	a memcpy for example that isnt strictly needed, but for most uses *	this is simply not worth optimising */int i2o_post_this(struct i2o_controller *c, u32 *data, int len){	u32 m;	u32 *msg;	unsigned long t=jiffies;	do	{		mb();		m = I2O_POST_READ32(c);	}	while(m==0xFFFFFFFF && (jiffies-t)<HZ);		if(m==0xFFFFFFFF)	{		printk(KERN_ERR "%s: Timeout waiting for message frame!\n",		       c->name);		return -ETIMEDOUT;	}	msg = (u32 *)(c->mem_offset + m); 	memcpy_toio(msg, data, len);	i2o_post_message(c,m);	return 0;}/* * This core API allows an OSM to post a message and then be told whether * or not the system received a successful reply.  It is useful when * the OSM does not want to know the exact 3 */int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout){	DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);	int status = 0;	int flags = 0;	struct i2o_post_wait_data *p1, *p2;	struct i2o_post_wait_data *wait_data =		kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);	if(!wait_data)		return -ENOMEM;	/* 	 * The spin locking is needed to keep anyone from playing 	 * with the queue pointers and id while we do the same	 */	spin_lock_irqsave(&post_wait_lock, flags);	wait_data->next = post_wait_queue;	post_wait_queue = wait_data;	wait_data->id = (++post_wait_id) & 0x7fff;	spin_unlock_irqrestore(&post_wait_lock, flags);	wait_data->wq = &wq_i2o_post;	wait_data->status = -ETIMEDOUT;	msg[2] = 0x80000000|(u32)core_context|((u32)wait_data->id<<16);		if ((status = i2o_post_this(c, msg, len))==0) {		interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);		status = wait_data->status;	}  #ifdef DRIVERDEBUG	if(status == -ETIMEDOUT)		printk(KERN_INFO "%s: POST WAIT TIMEOUT\n",c->name);#endif	/* 	 * Remove the entry from the queue.	 * Since i2o_post_wait() may have been called again by	 * a different thread while we were waiting for this 	 * instance to complete, we're not guaranteed that 	 * this entry is at the head of the queue anymore, so 	 * we need to search for it, find it, and delete it.	 */	p2 = NULL;	spin_lock_irqsave(&post_wait_lock, flags);	for(p1 = post_wait_queue; p1; p2 = p1, p1 = p1->next) {		if(p1 == wait_data) {			if(p2)				p2->next = p1->next;			else				post_wait_queue = p1->next;			break;		}	}	spin_unlock_irqrestore(&post_wait_lock, flags);		kfree(wait_data);	return status;}/* * i2o_post_wait is completed and we want to wake up the  * sleeping proccess. Called by core's reply handler. */static void i2o_post_wait_complete(u32 context, int status){	struct i2o_post_wait_data *p1 = NULL;	/* 	 * We need to search through the post_wait 	 * queue to see if the given message is still	 * outstanding.  If not, it means that the IOP 	 * took longer to respond to the message than we 	 * had allowed and timer has already expired.  	 * Not much we can do about that except log	 * it for debug purposes, increase timeout, and recompile	 *	 * Lock needed to keep anyone from moving queue pointers 	 * around while we're looking through them.	 */	spin_lock(&post_wait_lock);	for(p1 = post_wait_queue; p1; p1 = p1->next) {		if(p1->id == ((context >> 16) & 0x7fff)) {			p1->status = status;			wake_up_interruptible(p1->wq);			spin_unlock(&post_wait_lock);			return;		}	}	spin_unlock(&post_wait_lock);	printk(KERN_DEBUG "i2o_post_wait reply after timeout!\n");}/*	Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET * *	This function can be used for all UtilParamsGet/Set operations. *	The OperationList is given in oplist-buffer,  *	and results are returned in reslist-buffer. *	Note that the minimum sized reslist is 8 bytes and contains *	ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,                 void *oplist, int oplen, void *reslist, int reslen){	u32 msg[9]; 	u8 *res = (u8 *)reslist;	u32 *res32 = (u32*)reslist;	u32 *restmp = (u32*)reslist;	int len = 0;	int i = 0;	int wait_status;	msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;	msg[1] = cmd << 24 | HOST_TID << 12 | tid; 	msg[3] = 0;	msg[4] = 0;	msg[5] = 0x54000000 | oplen;	/* OperationList */	msg[6] = virt_to_bus(oplist);	msg[7] = 0xD0000000 | reslen;	/* ResultList */	msg[8] = virt_to_bus(reslist);	if((wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10)))		return wait_status; 	/* -DetailedStatus */	/*	 * Calculate number of bytes of Result LIST	 * We need to loop through each Result BLOCK and grab the length	 */	restmp = res32 + 1;	len = 1;	for(i = 0; i < (res32[0]&0X0000FFFF); i++)	{		if(restmp[0]&0x00FF0000)	/* BlockStatus != SUCCESS */		{			printk(KERN_WARNING "%s - Error:\n  ErrorInfoSize = 0x%02x, " 					"BlockStatus = 0x%02x, BlockSize = 0x%04x\n",					(cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"					: "PARAMS_GET",   					res32[1]>>24, (res32[1]>>16)&0xFF, res32[1]&0xFFFF);				/*			 *	If this is the only request,than we return an error			 */			if((res32[0]&0x0000FFFF) == 1)				return -((res[1] >> 16) & 0xFF); /* -BlockStatus */		}		len += restmp[0] & 0x0000FFFF;	/* Length of res BLOCK */		restmp += restmp[0] & 0x0000FFFF;	/* Skip to next BLOCK */	}	return (len << 2);  /* bytes used by result list */}/* *	 Query one scalar group value or a whole scalar group. */                  	int i2o_query_scalar(struct i2o_controller *iop, int tid,                      int group, int field, void *buf, int buflen){	u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };	u8  resblk[8+buflen]; /* 8 bytes for header */	int size;	if (field == -1)  		/* whole group */       		opblk[4] = -1;              	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, 		opblk, sizeof(opblk), resblk, sizeof(resblk));			if (size < 0)		return size;		memcpy(buf, resblk+8, buflen);  /* cut off header */	return size;}/* *	Set a scalar group value or a whole group. */int i2o_set_scalar(struct i2o_controller *iop, int tid, 		   int group, int field, void *buf, int buflen){	u16 *opblk;	u8  resblk[8+buflen]; /* 8 bytes for header */        int size;	opblk = kmalloc(buflen+64, GFP_KERNEL);	if (opblk == NULL)	{		printk(KERN_ERR "i2o: no memory for operation buffer.\n");		return -ENOMEM;	}	opblk[0] = 1;                        /* operation count */	opblk[1] = 0;                        /* pad */	opblk[2] = I2O_PARAMS_FIELD_SET;	opblk[3] = group;	if(field == -1) {               /* whole group */		opblk[4] = -1;		memcpy(opblk+5, buf, buflen);	}	else                            /* single field */	{		opblk[4] = 1;		opblk[5] = field;		memcpy(opblk+6, buf, buflen);	}   	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 				opblk, 12+buflen, resblk, sizeof(resblk));	kfree(opblk);	return size;}/*  * 	if oper == I2O_PARAMS_TABLE_GET, get from all rows  * 		if fieldcount == -1 return all fields *			ibuf and ibuflen are unused (use NULL, 0) * 		else return specific fields *  			ibuf contains fieldindexes * * 	if oper == I2O_PARAMS_LIST_GET, get from specific rows * 		if fieldcount == -1 return all fields *			ibuf contains rowcount, keyvalues * 		else return specific fields *			fieldcount is # of fieldindexes *  			ibuf contains fieldindexes, rowcount, keyvalues * *	You could also use directly function i2o_issue_params(). */int i2o_query_table(int oper, struct i2o_controller *iop, int tid, int group,		int fieldcount, void *ibuf, int ibuflen,		void *resblk, int reslen) {	u16 *opblk;	int size;	opblk = kmalloc(10 + ibuflen, GFP_KERNEL);	if (opblk == NULL)	{		printk(KERN_ERR "i2o: no memory for query buffer.\n");		return -ENOMEM;	}	opblk[0] = 1;				/* operation count */	opblk[1] = 0;				/* pad */	opblk[2] = oper;	opblk[3] = group;			opblk[4] = fieldcount;	memcpy(opblk+5, ibuf, ibuflen);		/* other params */	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, 				opblk, 10+ibuflen, resblk, reslen);	kfree(opblk);	return size;}/* * 	Clear table group, i.e. delete all rows. */int i2o_clear_table(struct i2o_controller *iop, int tid, int group){	u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group };	u8  resblk[32]; /* min 8 bytes for result header */	return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 				opblk, sizeof(opblk), resblk, sizeof(resblk));}/* * 	Add a new row into a table group. * * 	if fieldcount==-1 then we add whole rows *		buf contains rowcount, keyvalues * 	else just specific fields are given, rest use defaults *  		buf contains fieldindexes, rowcount, keyvalues */	int i2o_row_add_table(struct i2o_controller *iop, int tid,		    int group, int fieldcount, void *buf, int buflen){	u16 *opblk;	u8  resblk[32]; /* min 8 bytes for header */	int size;	opblk = kmalloc(buflen+64, GFP_KERNEL);	if (opblk == NULL)	{		printk(KERN_ERR "i2o: no memory for operation buffer.\n");		return -ENOMEM;	}	opblk[0] = 1;			/* operation count */	opblk[1] = 0;			/* pad */	opblk[2] = I2O_PARAMS_ROW_ADD;	opblk[3] = group;		opblk[4] = fieldcount;	memcpy(opblk+5, buf, buflen);	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 				opblk, 10+buflen, resblk, sizeof(resblk));	kfree(opblk);	return size;}/* * Used for error reporting/debugging purposes. * Following fail status are common to all classes. * The preserved message must be handled in the reply handler.  */void i2o_report_fail_status(u8 req_status, u32* msg){	static char *FAIL_STATUS[] = { 		"0x80",				/* not used */		"SERVICE_SUSPENDED", 		/* 0x81 */		"SERVICE_TERMINATED", 		/* 0x82 */		"CONGESTION",		"FAILURE",		"STATE_ERROR",		"TIME_OUT",		"ROUTING_FAILURE",		"INVALID_VERSION",		"INVALID_OFFSET",		"INVALID_MSG_FLAGS",		"FRAME_TOO_SMALL",		"FRAME_TOO_LARGE",		"INVALID_TARGET_ID",		"INVALID_INITIATOR_ID",		"INVALID_INITIATOR_CONTEX",	/* 0x8F */		"UNKNOWN_FAILURE"		/* 0xFF */	};	if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)		printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x)\n.", req_status);	else		printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]);	/* Dump some details */	printk(KERN_ERR "  InitiatorId = %d, TargetId = %d\n",		(msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); 	printk(KERN_ERR "  LowestVersion = 0x%02X, HighestVersion = 0x%02X\n",		(msg[4] >> 8) & 0xFF, msg[4] & 0xFF);	printk(KERN_ERR "  FailingHostUnit = 0x%04X,  FailingIOP = 0x%03X\n",		msg[5] >> 16, msg[5] & 0xFFF);	printk(KERN_ERR "  Severity:  0x%02X ", (msg[4] >> 16) & 0xFF); 	if (msg[4] & (1<<16))		printk("(FormatError), "			"this msg can never be delivered/processed.\n");	if (msg[4] & (1<<17))		printk("(PathError), "			"this msg can no longer be delivered/processed.\n");	if (msg[4] & (1<<18))		printk("(PathState), "			"the system state does not allow delivery.\n");	if (msg[4] & (1<<19))		printk("(Congestion), resources temporarily not available;"			"do not retry immediately.\n");}/* * Used for error reporting/debugging purposes. * Following reply status are common to all classes. */void i2o_report_common_status(u8 req_status){	static char *REPLY_STATUS[] = { 		"SUCCESS", 		"ABORT_DIRTY", 		"ABORT_NO_

⌨️ 快捷键说明

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