patch-2.3.19 linux/drivers/i2o/i2o_config.c

Next file: linux/drivers/i2o/i2o_core.c
Previous file: linux/drivers/i2o/i2o_block.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.18/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
@@ -9,6 +9,9 @@
  *         - Added basic ioctl() support
  *      Modified 06/07/1999 by Deepak Saxena
  *         - Added software download ioctl (still testing)
+ *	Modified 09/10/1999 by Auvo Häkkinen
+ *	   - Changes to i2o_cfg_reply(), ioctl_parms()
+ *	   - Added ioct_validate() (not yet tested)
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -36,11 +39,6 @@
 static int i2o_cfg_context = -1;
 static void *page_buf;
 static void *i2o_buffer;
-static int i2o_ready;
-static int i2o_pagelen;
-static int i2o_error;
-static int cfg_inuse;
-static int i2o_eof;
 static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
 struct wait_queue *i2o_wait_queue;
 
@@ -52,6 +50,7 @@
 static int ioctl_swdl(unsigned long);
 static int ioctl_swul(unsigned long);
 static int ioctl_swdel(unsigned long);
+static int ioctl_validate(unsigned long); 
 
 /*
  *	This is the callback for any message we have posted. The message itself
@@ -61,8 +60,13 @@
  */
 static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
 {
-	i2o_cfg_token = I2O_POST_WAIT_OK;
-
+        u32 *msg = (u32 *)m;
+        
+	if (msg[4] >> 24) // RegStatus != SUCCESS
+        	i2o_cfg_token = -(msg[4] & 0xFFFF); // DetailedStatus
+        else
+		i2o_cfg_token = I2O_POST_WAIT_OK;
+               
 	return;
 }
 
@@ -84,7 +88,6 @@
 	return -ESPIPE;
 }
 
-/* i2ocontroller/i2odevice/page/?data */
 
 static ssize_t cfg_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
@@ -93,12 +96,15 @@
 	return 0;
 }
 
-/* To be written for event management support */
+
 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 *file, unsigned int cmd,
 	unsigned long arg)
 {
@@ -141,6 +147,10 @@
 			ret = ioctl_swdel(arg);
 			break;
 
+		case I2OVALIDATE:
+			ret = ioctl_validate(arg);
+			break;
+			
 		case I2OHTML:
 			ret = ioctl_html(arg);
 			break;
@@ -168,13 +178,11 @@
 		c = i2o_find_controller(i);
 		if(c)
 		{
-			printk(KERN_INFO "ioctl: iop%d found\n", i);
 			foo[i] = 1;
 			i2o_unlock_controller(c);
 		}
 		else
 		{
-			printk(KERN_INFO "ioctl: iop%d not found\n", i);
 			foo[i] = 0;
 		}
 	}
@@ -189,10 +197,7 @@
 	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	pi2o_hrt hrt;
-	u32 msg[6];
-	u32 *workspace;
 	int len;
-	int token;
 	u32 reslen;
 	int ret = 0;
 
@@ -208,42 +213,20 @@
 	c = i2o_find_controller(kcmd.iop);
 	if(!c)
 		return -ENXIO;
+		
+	hrt = (pi2o_hrt)c->hrt;
 
-	workspace = kmalloc(8192, GFP_KERNEL);
-	hrt = (pi2o_hrt)workspace;
-	if(workspace==NULL)
-	{
-		i2o_unlock_controller(c);
-		return -ENOMEM;
-	}
-
-	memset(workspace, 0, 8192);
-
-	msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
-	msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= (0xD0000000 | 8192);
-	msg[5]= virt_to_phys(workspace);
-
-	token = i2o_post_wait(c, ADAPTER_TID, msg, 6*4, &i2o_cfg_token,2);
-	if(token == I2O_POST_WAIT_TIMEOUT)
-	{
-		kfree(workspace);
-		i2o_unlock_controller(c);
-		return -ETIMEDOUT;
-	}
 	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 = -EINVAL;
+		ret = -EFAULT;
 
-	kfree(workspace);
 	return ret;
 }
 
@@ -253,10 +236,7 @@
 	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	pi2o_lct lct;
-	u32 msg[9];
-	u32 *workspace;
 	int len;
-	int token;
 	int ret = 0;
 	u32 reslen;
 
@@ -273,32 +253,7 @@
 	if(!c)
 		return -ENXIO;
 
-	workspace = kmalloc(8192, GFP_KERNEL);
-	lct = (pi2o_lct)workspace;
-	if(workspace==NULL)
-	{
-		i2o_unlock_controller(c);
-		return -ENOMEM;
-	}
-
-	memset(workspace, 0, 8192);
-
-	msg[0]= EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6;
-	msg[1]= I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= 0xFFFFFFFF;
-	msg[5]= 0;
-	msg[6]= (0xD0000000 | 8192);
-	msg[7]= virt_to_phys(workspace);
-
-	token = i2o_post_wait(c, ADAPTER_TID, msg, 8*4, &i2o_cfg_token,2);
-	if(token == I2O_POST_WAIT_TIMEOUT)
-	{
-		kfree(workspace);
-		i2o_unlock_controller(c);
-		return -ETIMEDOUT;
-	}
+	lct = (pi2o_lct)c->lct;
 	i2o_unlock_controller(c);
 
 	len = (unsigned int)lct->table_size << 2;
@@ -306,9 +261,8 @@
 	if(len > reslen)
 		ret = -ENOBUFS;	
 	else if(copy_to_user(kcmd.resbuf, (void*)lct, len))
-		ret = -EINVAL;
+		ret = -EFAULT;
 
-	kfree(workspace);
 	return ret;
 }
 
@@ -318,16 +272,10 @@
 	struct i2o_controller *c;
 	struct i2o_cmd_psetget *cmd = (struct i2o_cmd_psetget*)arg;
 	struct i2o_cmd_psetget kcmd;
-	u32 msg[9];
 	u32 reslen;
-	int token;
 	u8 *ops;
 	u8 *res;
-	u16 *res16;	
-	u32 *res32;
-	u16 count;
 	int len;
-	int i,j;
 
 	u32 i2o_cmd = (type == I2OPARMGET ? 
 				I2O_CMD_UTIL_PARAMS_GET :
@@ -369,47 +317,14 @@
 		return -ENOMEM;
 	}
 
-	res16 = (u16*)res;
-
-	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
-	msg[1]=i2o_cmd<<24|HOST_TID<<12|cmd->tid;
-	msg[2]=(u32)cfg_handler.context;
-	msg[3]=0;
-	msg[4]=0;
-	msg[5]=0x54000000|kcmd.oplen;
-	msg[6]=virt_to_bus(ops);
-	msg[7]=0xD0000000|(65536);
-	msg[8]=virt_to_bus(res);
-
-	/*
-	 * Parm set sometimes takes a little while for some reason
-	 */
-	token = i2o_post_wait(c, kcmd.tid, msg, 9*4, &i2o_cfg_token,10);
-	if(token == I2O_POST_WAIT_TIMEOUT)
-	{
-		i2o_unlock_controller(c);
-		kfree(ops);
-		kfree(res);
-		return -ETIMEDOUT;
-	}
-	i2o_unlock_controller(c);
+        len = i2o_issue_params(i2o_cmd, c, kcmd.tid, cfg_handler.context,
+        			ops, kcmd.oplen, res, 65536, &i2o_cfg_token);
+        i2o_unlock_controller(c);
 	kfree(ops);
-
-	/* 
-  	 * Determine required size...there's got to be a quicker way? 
-	 * Dump data to syslog for debugging failures
-	 */
-	count = res16[0];
-	printk(KERN_INFO "%0#6x\n%0#6x\n", res16[0], res16[1]);
-	len = 4;
-	res16 += 2;
-	for(i = 0; i < count; i++ )
-	{
-		len += res16[0] << 2;	/* BlockSize field in ResultBlock */
-		res32 = (u32*)res16;
-		for(j = 0; j < res16[0]; j++)
-			printk(KERN_INFO "%0#10x\n", res32[j]);
-		res16 += res16[0] << 1;	/* Shift to next block */
+        
+	if (len < 0) {
+		kfree(res);
+		return len; /* -DetailedStatus */
 	}
 
 	put_user(len, kcmd.reslen);
@@ -499,7 +414,7 @@
 	}
 
 	token = i2o_post_wait(c, cmd->tid, msg, 9*4, &i2o_cfg_token, 10);
-	if(token == I2O_POST_WAIT_TIMEOUT)
+	if(token != I2O_POST_WAIT_OK)
 	{
 		i2o_unlock_controller(c);
 		kfree(res);
@@ -529,7 +444,7 @@
 	struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg;
 	unsigned char maxfrag = 0, curfrag = 0;
 	unsigned char buffer[8192];
-	u32 msg[MSG_FRAME_SIZE/4];
+	u32 msg[9];
 	unsigned int token = 0, diff = 0, swlen = 0, swxfer = 0;
 	struct i2o_controller *c;
 	int foo = 0;
@@ -588,11 +503,11 @@
 		return -ENXIO;
 	printk("*** foo%d ***\n", foo++);
 
-	msg[0]= EIGHT_WORD_MSG_SIZE| SGL_OFFSET_7;
+	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
 	msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
 	msg[2]= (u32)cfg_handler.context;
 	msg[3]= 0;
-	msg[4]= ((u32)kxfer.dl_flags)<<24|((u32)kxfer.sw_type)<<16|((u32)maxfrag)<<8|((u32)curfrag);
+	msg[4]= ((u32)kxfer.flags)<<24|((u32)kxfer.sw_type)<<16|((u32)maxfrag)<<8|((u32)curfrag);
 	msg[5]= swlen;
 	msg[6]= kxfer.sw_id;
 	msg[7]= (0xD0000000 | 8192);
@@ -611,14 +526,15 @@
 		msg[4] |= (u32)curfrag;
 
 		__copy_from_user(buffer, kxfer.buf, 8192);
-		swxfer += 8129;
+		swxfer += 8192;
 
 		// Yes...that's one minute, but the spec states that
 		// transfers take a long time, and I've seen just how
 		// long they can take.
-		token = i2o_post_wait(c, ADAPTER_TID, msg, 6*4, &i2o_cfg_token,60);
-		if( token == I2O_POST_WAIT_TIMEOUT )	// Something very wrong
+		token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
+		if (token != I2O_POST_WAIT_OK )	// Something very wrong
 		{
+			i2o_unlock_controller(c);
 			printk("Timeout downloading software");
 			return -ETIMEDOUT;
 		}
@@ -631,13 +547,15 @@
 	msg[4] |= (u32)maxfrag;
 	msg[7] = (0xD0000000 | diff);
 	__copy_from_user(buffer, kxfer.buf, 8192);
-	token = i2o_post_wait(c, ADAPTER_TID, msg, 6*4, &i2o_cfg_token,60);
-	if( token == I2O_POST_WAIT_TIMEOUT )	// Something very wrong
+	token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
+	if( token != I2O_POST_WAIT_OK )	// Something very wrong
 	{
+		i2o_unlock_controller(c);
 		printk("Timeout downloading software");
 		return -ETIMEDOUT;
 	}
 	__put_user(curfrag, kxfer.curfrag);
+	i2o_unlock_controller(c);
 
 	return 0;
 }
@@ -651,9 +569,39 @@
 /* To be written */
 int ioctl_swdel(unsigned long arg)
 {
-	return 0;
+	return -EINVAL;
 }
 
+int ioctl_validate(unsigned long arg)
+{
+        int token;
+        int iop = (int)arg;
+        u32 msg[4];
+        struct i2o_controller *c;
+
+        c=i2o_find_controller(iop);
+        if (!c)
+                return -ENXIO;
+
+        msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+        msg[1] = I2O_CMD_CONFIG_VALIDATE<<24 | HOST_TID<<12 | iop;
+        msg[2] = (u32)i2o_cfg_context;
+        msg[3] = 0;
+
+        token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg),&i2o_cfg_token, 10);
+        i2o_unlock_controller(c);
+
+        if (token != I2O_POST_WAIT_OK)
+        {
+                printk("Can't validate configuration, ErrorStatus = %d\n",
+                	token);
+                return -ETIMEDOUT;
+        }
+
+        return 0;
+}   
+
+
 static int cfg_open(struct inode *inode, struct file *file)
 {
 	/* 
@@ -693,7 +641,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__init int i2o_config_init(void)
+int __init i2o_config_init(void)
 #endif
 {
 	printk(KERN_INFO "i2o configuration manager v 0.02\n");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)