patch-2.3.39 linux/drivers/i2o/i2o_core.c

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

diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
@@ -18,7 +18,6 @@
  *		Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> 
  *		Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> 
  *		Deepak Saxena <deepak@plexity.net> 
- * 
  */
 
 #include <linux/config.h>
@@ -35,7 +34,6 @@
 
 #include <linux/bitops.h>
 #include <linux/wait.h>
-#include <linux/delay.h>
 #include <linux/timer.h>
 
 #include <asm/io.h>
@@ -53,19 +51,22 @@
  
 static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
 static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
+struct i2o_controller *i2o_controller_chain;
 int i2o_num_controllers = 0;
 static int core_context = 0;
 
-extern int i2o_online_controller(struct i2o_controller *c);
+static int i2o_activate_controller(struct i2o_controller *iop);
+static int i2o_online_controller(struct i2o_controller *c);
 static int i2o_init_outbound_q(struct i2o_controller *c);
 static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
 			   struct i2o_message *);
 static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
 static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
-static void i2o_dump_message(u32 *msg);
+void i2o_dump_message(u32 *msg);
 
 static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32);
 
+static int i2o_reset_controller(struct i2o_controller *);
 static int i2o_lct_get(struct i2o_controller *);
 static int i2o_hrt_get(struct i2o_controller *);
 
@@ -176,9 +177,7 @@
 	{
 		if (msg[4] >> 24)
 		{
-			/* 0x40000000 is used as an error report supress bit */
-			if(msg[2]&0x40000000)
-				i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
+			i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
 			status = -(msg[4] & 0xFFFF);
 		}
 		else
@@ -233,7 +232,6 @@
 	d->next=c->devices;
 	c->devices=d;
 	*d->dev_name = 0;
-	d->owner = NULL;
 
 	for(i = 0; i < I2O_MAX_MANAGERS; i++)
 		d->managers[i] = NULL;
@@ -307,12 +305,7 @@
 			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;
-//			printk(KERN_INFO "lct @ %p hrt @ %p status @ %p",
-//					c->lct, c->hrt, c->status_block);
+
 			sprintf(c->name, "i2o/iop%d", i);
 			i2o_num_controllers++;
 			spin_unlock(&i2o_configuration_lock);
@@ -328,15 +321,13 @@
 {
 	struct i2o_controller **p;
 	int users;
-
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "Deleting controller iop%d\n", c->unit);
-#endif
+	char name[16];
 
 	spin_lock(&i2o_configuration_lock);
 	if((users=atomic_read(&c->users)))
 	{
-		printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit);
+		printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users);
+		c->bus_disable(c); 
 		spin_unlock(&i2o_configuration_lock);
 		return -EBUSY;
 	}
@@ -345,6 +336,7 @@
 		if(__i2o_delete_device(c->devices)<0)
 		{
 			/* Shouldnt happen */
+			c->bus_disable(c); 
 			spin_unlock(&i2o_configuration_lock);
 			return -EBUSY;
 		}
@@ -356,8 +348,8 @@
 	{
 		if(*p==c)
 		{
-			/* Ask the IOP to switch to HOLD state */
-			i2o_clear_controller(c);
+			/* Ask the IOP to switch into RESET state */
+			i2o_reset_controller(c);
 
 			/* Release IRQ */
 			c->destructor(c);
@@ -365,8 +357,6 @@
 			*p=c->next;
 			spin_unlock(&i2o_configuration_lock);
 
-//			printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n",
-//				c->hrt, c->lct, c->page_frame, c->status_block);
 			if(c->page_frame)
 				kfree(c->page_frame);
 			if(c->hrt)
@@ -376,14 +366,13 @@
 			if(c->status_block)
 				kfree(c->status_block);
 
-			kfree(c);
-
 			i2o_controllers[c->unit]=NULL;
-
+			memcpy(name, c->name, strlen(c->name)+1);
+			kfree(c);
 			i2o_num_controllers--;
-#ifdef DRIVERDEBUG
-			printk(KERN_INFO "iop deleted\n");
-#endif
+			
+			dprintk((KERN_INFO "%s: Deleted from controller chain.\n", name));
+
 			return 0;
 		}
 		p=&((*p)->next);
@@ -540,17 +529,20 @@
 	u32 mv;
 
 #ifdef DEBUG_IRQ
-	printk(KERN_INFO "iop%d interrupt\n", c->unit);
+	printk(KERN_INFO "%s: interrupt\n", c->name);
 #endif
+	/* Sometimes we get here, but a message can't be read. Why? */
+	if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)
+		mv=I2O_REPLY_READ32(c);
 
-	while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF)
+	while (mv!=0xFFFFFFFF)
 	{
 		struct i2o_handler *i;
 		m=(struct i2o_message *)bus_to_virt(mv);
 		/*
 		 *	Temporary Debugging
 		 */
-		if(((m->function_addr>>24)&0xFF)==0x15)
+		if(m->function==0x15)
 			printk("UTFR!\n");
 
 #ifdef DEBUG_IRQ
@@ -562,12 +554,13 @@
 			i->reply(i,c,m);
 		else
 		{
-			printk("Spurious reply to handler %d\n", 
+			printk("i2o: Spurious reply to handler %d\n", 
 				m->initiator_context&(MAX_I2O_MODULES-1));
 			i2o_dump_message((u32*)m);
 		}	
 	 	i2o_flush_reply(c,mv);
 		mb();
+		mv=I2O_REPLY_READ32(c);
 	}
 }
 
@@ -699,7 +692,6 @@
 	}
 	if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)>=0)
 	{
-
 		buf[16]=0;
 		printk("     Device: %s", buf);
 	}
@@ -707,7 +699,7 @@
 	if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
 	{
 		buf[16]=0;
-		printk(KERN_INFO "Description: %s\n", buf);
+		printk("Description: %s", buf);
 	}
 #endif	
 	if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8)>=0)
@@ -831,25 +823,17 @@
 	char str[22];
 	i2o_lct *lct = c->lct;
 
-	max = lct->table_size;
+	if (lct == NULL) {
+		printk(KERN_ERR "%s: LCT is empty???\n",c->name);
+		return -1;
+	}
 	
+	max = lct->table_size;	
 	max -= 3;
 	max /= 9;
 
-	if(max==0)
-	{
-		printk(KERN_ERR "%s: LCT is empty????\n",c->name);
-		return -1;
-	}
-
 	printk(KERN_INFO "%s: LCT has %d entries.\n", c->name,max);
 	
-	if(max > 128)
-	{
-		printk(KERN_INFO "%s: LCT was truncated.\n",c->name);
-		max=128;
-	}
-	
 	if(lct->iop_flags&(1<<0))
 		printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);
 		
@@ -870,7 +854,7 @@
 		d->flags = 0;
 		tid = d->lct_data->tid;
 		
-		printk(KERN_INFO "Task ID %d.\n", tid);
+		printk(KERN_INFO "Target ID %d.\n", tid);
 
 		i2o_report_controller_unit(c, tid);
 		
@@ -880,10 +864,10 @@
 		
 		sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id));
 		printk("%s", str);
-		
-		printk(" Subclass: 0x%04X                Flags: ",
+
+		printk(" Subclass: 0x%04X                Flags: ", 
 			d->lct_data->sub_class);
-			
+
 		if(d->lct_data->device_flags&(1<<0))
 			printk("C");		// ConfigDialog requested
 		if(d->lct_data->device_flags&(1<<1))
@@ -899,37 +883,44 @@
 }
 
 
-/* Quiesce IOP */
+/* 
+ * Quiesce IOP. Causes IOP to make external operation quiescend. 
+ * Internal operation of the IOP continues normally.
+ */
 int i2o_quiesce_controller(struct i2o_controller *c)
 {
 	u32 msg[4];
 	int ret;
 
-	if ((c->status_block->iop_state != ADAPTER_STATE_READY) &
-	    (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)) 
+	/* 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))
 	{
-		dprintk((KERN_INFO "%s: Not in READY or OPERATIONAL state\n", 
-			c->name));
-		dprintk((KERN_INFO "%s: state = %d\n", 
-			c->name, c->status_block->iop_state));
-		return -EINVAL;
+		return 0;
 	}
 
 	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
 	msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
-	/* msg[2] and msg[3] filled in i2o_post_wait */
+	/* msg[2] filled in i2o_post_wait */
+	msg[3]=0;
 
 	/* Long timeout needed for quiesce if lots of devices */
 
 	if ((ret = i2o_post_wait(c, msg, sizeof(msg), 120)))
-		printk(KERN_INFO "%s: Unable to quiesce.\n", c->name);
+		printk(KERN_INFO "%s: Unable to quiesce (status=%#10x).\n", 
+			c->name, ret);
 	else
 		dprintk((KERN_INFO "%s: Quiesced.\n", c->name));
 
+	i2o_status_get(c); // Reread the Status Block
+
 	return ret;
 }
 
-/* Enable IOP */
+/* 
+ * Enable IOP. Allows the IOP to resume external operations.
+ */
 int i2o_enable_controller(struct i2o_controller *c)
 {
 	u32 msg[4];
@@ -937,44 +928,80 @@
 	
 	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
 	msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
-	/* msg[2] and msg[3] filled in i2o_post_wait */
+	/* msg[2] filled in i2o_post_wait */
 
 	/* 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, %d\n", c->name, ret);
+		printk(KERN_ERR "%s: Could not enable (status=%#10x).\n", 
+			c->name, ret);
+	else
+		dprintk((KERN_INFO "%s: Enabled.\n", c->name));
+
+	i2o_status_get(c);
 
 	return ret;
 }
 
-/* Reset an IOP, but keep message queues alive */
+/* 
+ * 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.
+ * 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[2] and msg[3] filled in i2o_post_wait */
+	/* msg[2] filled in i2o_post_wait */
+	msg[3]=0;
 
 	if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
-		printk(KERN_INFO "%s: Unable to clear, %#10x\n", 
+		printk(KERN_INFO "%s: Unable to clear (status=%#10x).\n", 
 			c->name, ret);
+	else
+		dprintk((KERN_INFO "%s: Cleared.\n",c->name));
 
-	i2o_status_get(c); // Reread the Status Block
+	i2o_status_get(c);
+
+	/* Enable other IOPs */
+
+	for (iop = i2o_controller_chain; iop; iop = iop->next)
+		if (iop != c)
+			i2o_enable_controller(iop);		
 
 	return ret;
 }
 
 
-/* Reset the IOP to sane state */
+/* 
+ * 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. 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)
+		i2o_quiesce_controller(iop);
+
 	m=i2o_wait_message(c, "AdapterReset");
 	if(m==0xFFFFFFFF)	
 		return -ETIMEDOUT;
@@ -1013,16 +1040,14 @@
 		barrier();
 	}
 
-	if (status[0]==0x02) 
-		printk(KERN_WARNING "%s: Reset rejected.\n",c->name); 
-	else 
+	if (status[0]==0x01) 
 	{
 		/* 
 		 * Once the reset is sent, the IOP goes into the INIT state 
-		 * which is inditerminate.  We need to wait until the IOP 
+		 * 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 
+		 * available.  If we can't read one in the given amount of 
 		 * time, we assume the IOP could not reboot properly.  
 		 */ 
 
@@ -1043,9 +1068,26 @@
 		} 
 
 		i2o_flush_reply(c,m);
-		printk(KERN_INFO "%s: Reset completed.\n", c->name);
+
+		dprintk((KERN_INFO "%s: Reset completed.\n", c->name));
 	}
 
+	/* If IopReset was rejected or didn't perform reset, try IopClear */
+
+	i2o_status_get(c);
+	if (status[0] == 0x02 || c->status_block->iop_state != ADAPTER_STATE_RESET)
+	{
+		printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name); 
+		i2o_clear_controller(c);
+
+	}
+
+	/* Enable other IOPs */
+
+	for (iop = i2o_controller_chain; iop; iop = iop->next)
+		if (iop != c)
+			i2o_enable_controller(iop);		
+
 	kfree(status);
 	return 0;
 }
@@ -1157,13 +1199,14 @@
 
 		msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
 		msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
-		/* msg[2] and msg[3] filled in i2o_post_wait */
+		/* msg[2] filled in i2o_post_wait */
+		msg[3]= 0;
 		msg[4]= (0xD0000000 | size);	/* Simple transaction */
 		msg[5]= virt_to_phys(c->hrt);	/* Dump it here */
 
 		if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
-			printk(KERN_ERR "%s: Unable to get HRT,"
-				" Status = %d.\n",c->name, ret);	
+			printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n",
+				c->name, ret);	
 			return ret;
 		}
 
@@ -1193,6 +1236,8 @@
         iop->status->current_io_base;
         iop->status->current_io_size;
 #endif
+
+/* FIXME */
         privmem[0]=iop->priv_mem;       /* Private memory space base address */
         privmem[1]=iop->priv_mem_size;
         privio[0]=iop->priv_io;         /* Private I/O address */
@@ -1200,7 +1245,8 @@
 
 	msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
         msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
-	/* [2] and [3] filled in i2o_post_wait */
+	/* msg[2] filled in i2o_post_wait */
+	msg[3] = 0;
         msg[4] = (0<<16) | ((iop->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
         msg[5] = 0;                               /* Segment 0 */
 
@@ -1217,8 +1263,10 @@
         msg[11] = virt_to_phys(privio);
 
 	if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
-		printk(KERN_INFO "%s: Unable to set SysTab, %d\n", 
-				iop->name, ret);
+		printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", 
+			iop->name, ret);
+	else
+		dprintk((KERN_INFO "%s: SysTab set.\n", iop->name));
 
 	return ret;	
 
@@ -1229,292 +1277,114 @@
  */
 static void __init i2o_sys_init()
 {
-	struct i2o_controller *iop, *niop;
-	int ret;
-	u32 m;
+	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");
 
-	/* Get the status for each IOP */
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
-		niop = iop->next;
-#ifdef DRIVERDEBUG
-		printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
-#endif
-		if(i2o_status_get(iop)<0)
-		{
-			printk("Unable to obtain status of IOP, attempting a reset.\n");
-			i2o_reset_controller(iop);
-			if(i2o_status_get(iop)<0)
-			{
-				printk("IOP not responding.\n");
-				i2o_delete_controller(iop);
-				continue;
-			}
-		}
-
-		if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
-		{
-			printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
-					iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-
-		if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
-	   	iop->status_block->iop_state == ADAPTER_STATE_READY ||
-	   	iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
-	   	iop->status_block->iop_state == ADAPTER_STATE_FAILED)
-		{
-			int msg[256];
-
-#ifdef DRIVERDEBUG
-			printk(KERN_INFO "iop%d already running...trying to reboot\n",
-					iop->unit);
-#endif
-			i2o_init_outbound_q(iop);
-			I2O_REPLY_WRITE32(iop,virt_to_phys(msg));
-			i2o_quiesce_controller(iop);
-			i2o_reset_controller(iop);
-			if(i2o_status_get(iop) || 
-				iop->status_block->iop_state != ADAPTER_STATE_RESET)
-			{
-				printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
-				i2o_delete_controller(iop);
-				continue;
-			}
-		}
-	}
+	/* In INIT state, Activate IOPs */
 
-	/*
-	 * Now init the outbound queue for each one.
-	 */
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
-		int i;
-		
+	for (iop = i2o_controller_chain; iop; iop = niop) {
 		niop = iop->next;
-
-		if((ret=i2o_init_outbound_q(iop)))
-		{
-			printk(KERN_ERR 
-				"IOP%d initialization failed: Could not initialize outbound q\n",
-				iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-		iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
-
-		if(iop->page_frame==NULL)
-		{
-			printk(KERN_CRIT "iop%d init failed: no memory for message page.\n", 
-						iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-	
-		m=virt_to_phys(iop->page_frame);
-	
-		for(i=0; i< NMBR_MSG_FRAMES; i++)
-		{
-			I2O_REPLY_WRITE32(iop,m);
-			mb();
-			m+=MSG_FRAME_SIZE;
-			mb();
-		}
+		i2o_activate_controller(iop);
 	}
 
-	/*
-	 * OK..parse the HRT
-	 */
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
-		niop = iop->next;
-		if(i2o_hrt_get(iop))
-		{
-			printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-		if(i2o_parse_hrt(iop))
-		{
-			printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-	}
+	/* Active IOPs in HOLD state */
+
+rebuild_sys_tab:
+	if (i2o_controller_chain == NULL)
+		return;
 
 	/*
-	 * Build and send the system table
-	 *
 	 * If build_sys_table fails, we kill everything and bail
 	 * as we can't init the IOPs w/o a system table
 	 */	
-	if(i2o_build_sys_table())
-	{
-		printk(KERN_CRIT "I2O: Error building system table. Aborting!\n");
+	if (i2o_build_sys_table() < 0) {
 		i2o_sys_shutdown();
 		return;
 	}
 
-	for(iop = i2o_controller_chain; iop; iop = niop)
-#ifdef DRIVERDEBUG
-	{
-		niop = iop->next;
-		printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
-#endif
-		if(i2o_systab_send(iop))
-		{
-			printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-#ifdef DRIVERDEBUG
-	}
-#endif
-
-	/*
-	 * Enable
-	 */
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
-		niop = iop->next;
-#ifdef DRIVERDEBUG
-		printk(KERN_INFO "Enabling iop%d\n", iop->unit);
-#endif
-		if(i2o_enable_controller(iop))
-		{
-			printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-	}
-
-	/*
-	 * OK..one last thing and we're ready to go!
-	 */
-	for(iop = i2o_controller_chain; iop; iop = niop)
-	{
+	/* If IOP don't get online, we need to rebuild the System table */
+	for (iop = i2o_controller_chain; iop; iop = niop) {
 		niop = iop->next;
-#ifdef DRIVERDEBUG
-		printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
-#endif
-		if(i2o_lct_get(iop))
-		{
-			printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
-			i2o_delete_controller(iop);
-			continue;
-		}
-		else	
-			i2o_parse_lct(iop);
+		if (i2o_online_controller(iop) < 0)
+			goto rebuild_sys_tab;
 	}
+	
+	/* Active IOPs now in OPERATIONAL state */
 }
 
 /*
  * Shutdown I2O system
- *
- * 1. Quiesce all controllers
- * 2. Delete all controllers
  */
 static void i2o_sys_shutdown(void)
 {
 	struct i2o_controller *iop, *niop;
 
-	for (iop = i2o_controller_chain; iop ; iop=iop->next) {
-		i2o_quiesce_controller(iop);			
-		i2o_status_get(iop);	// Update IOP status block
-	}
+	/* Delete all IOPs from the controller chain */
+	/* that will reset all IOPs too */
 
 	for (iop = i2o_controller_chain; iop; iop = niop) {
 		niop = iop->next;
-		if (i2o_delete_controller(iop))
-			iop->bus_disable(iop); 
+		i2o_delete_controller(iop);
 	}
 }
 
 /*
- *	Bring an I2O controller into HOLD state. See the 1.5
- *	spec. Basically we go
- *
- *	Wait for the message queue to initialise. 
- *	If it didnt -> controller is dead
- *	
- *	Send a get status using the message queue
- *	Poll for a reply block 88 bytes long
- *
- *	Send an initialise outbound queue
- *	Poll for a reply
- *
- *	Post our blank messages to the queue FIFO
- *
- *	Send GetHRT, Parse it
+ *	Bring an I2O controller into HOLD state. See the spec.
  */
-int i2o_activate_controller(struct i2o_controller *c)
+int i2o_activate_controller(struct i2o_controller *iop)
 {
-	return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
-	u32 m;
-	int i;
-	int ret;
-
-	printk(KERN_INFO "%s: Configuring I2O controller at 0x%08X.\n",
-	       c->name, (u32)c->mem_phys);
+	/* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */
+	/* In READY state, Get status */
 
-	if((ret=i2o_status_get(c)))
-		return ret;
+	if (i2o_status_get(iop) < 0) {
+		printk("Unable to obtain status of IOP, attempting a reset.\n");
+		i2o_reset_controller(iop);
+		if (i2o_status_get(iop) < 0) {
+			printk("IOP not responding.\n");
+			i2o_delete_controller(iop);
+			return -1;
+		}
+	}
 
-	/* not likely to be seen */
-	if(c->status_block->iop_state == ADAPTER_STATE_FAULTED) 
-	{
-		printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
-		       c->unit);
+	if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {
+		printk(KERN_CRIT "%s: hardware fault\n", iop->name);
+		i2o_delete_controller(iop);
 		return -1;
 	}
 
-	/*
-	 * If the board is running, reset it - we have no idea
-	 * what kind of a mess the previous owner left it in.
-	 * We need to feed the IOP a single outbound message
-	 * so that it can reply back to the ExecSysQuiesce.
-	 */
-	if(c->status_block->iop_state == ADAPTER_STATE_HOLD ||
-	   c->status_block->iop_state == ADAPTER_STATE_READY ||
-	   c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
-	   c->status_block->iop_state == ADAPTER_STATE_FAILED)
-	{
-		int msg[256];
-		printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit);
-
-		if(i2o_init_outbound_q(c));
-		I2O_REPLY_WRITE32(c,virt_to_phys(msg));
-
-		if((ret=i2o_reset_controller(c)))
-			return ret;
+//	if (iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
+	if (iop->status_block->iop_state == ADAPTER_STATE_READY ||
+	    iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+	    iop->status_block->iop_state == ADAPTER_STATE_FAILED)
+	{
+		dprintk((KERN_INFO "%s: already running...trying to reset\n",
+				iop->name));
+		i2o_reset_controller(iop);			
 
-		if((ret=i2o_status_get(c)))
-			return ret;
+		if (i2o_status_get(iop) < 0 || 
+			iop->status_block->iop_state != ADAPTER_STATE_RESET)
+		{
+			printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
+			i2o_delete_controller(iop);
+			return -1;
+		}
 	}
 
-	if ((ret=i2o_init_outbound_q(c))){
-		return ret;
+	if (i2o_init_outbound_q(iop) < 0) {
+		i2o_delete_controller(iop);
+		return -1;
 	}
 
-	/* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
-
-	/* 
-	 *	The outbound queue is initialised and loaded, 
-	 * 
-	 *	Now we need the Hardware Resource Table. We must ask for 
-	 *	this next we can't issue random messages yet.  
-	 */ 
-	 
-	if ((ret=i2o_hrt_get(c)))
-		return ret;
+	/* In HOLD state */
+	
+	if (i2o_hrt_get(iop) < 0) {
+		i2o_delete_controller(iop);
+		return -1;
+	}
 
-	return i2o_online_controller(c);
-#endif
+	return 0;
 }
 
 /*
@@ -1533,7 +1403,6 @@
 		return -ETIMEDOUT;
 	msg=(u32 *)(c->mem_offset+m);
 
-
 	status = kmalloc(4,GFP_KERNEL);
 	if (status==NULL) {
 		printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
@@ -1568,6 +1437,8 @@
 		barrier();
 	}
 
+	/* Alloc space for IOP's outbound queue message frames */
+
 	c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
 	if(c->page_frame==NULL) {
 		printk(KERN_CRIT "%s: Outbound Q initialize failed; out of memory.\n",
@@ -1577,6 +1448,8 @@
 	}	
 	m=virt_to_phys(c->page_frame);
 	
+	/* Post frames */
+
 	for(i=0; i< NMBR_MSG_FRAMES; i++) {
   		I2O_REPLY_WRITE32(c,m);
                 mb();
@@ -1608,15 +1481,16 @@
 
 		msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
 		msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
-		/* msg[2] and msg[3] filled in i2o_post_wait */
+		/* msg[2] filled in i2o_post_wait */
+		msg[3] = 0;
 		msg[4] = 0xFFFFFFFF;	/* All devices */
 		msg[5] = 0x00000000;	/* Report now */
 		msg[6] = 0xD0000000|size;
 		msg[7] = virt_to_bus(c->lct);
 
 		if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
-			printk(KERN_ERR "%s: Unable to get LCT,"
-				" Status = %d.\n", c->name,ret);	
+			printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", 
+				c->name, ret);	
 			return ret;
 		}
 
@@ -1627,83 +1501,39 @@
 		}
 	} while (c->lct == NULL);
 
+        if ((ret=i2o_parse_lct(c)) < 0)
+                return ret;
+
 	return 0;
 }
 
 
 /*
- *	Bring a controller online. Needs completing for multiple controllers
+ *	Bring a controller online into OPERATIONAL state. 
  */
  
-int i2o_online_controller(struct i2o_controller *c)
+int i2o_online_controller(struct i2o_controller *iop)
 {
-	return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
-	u32 msg[10];
-	u32 privmem[2];
-	u32 privio[2];
-	int ret;
+	if (i2o_systab_send(iop) < 0) {
+		i2o_delete_controller(iop);
+		return -1;
+	}
 
-	/*
-	 * Build and send the system table
-	 *
-	 * If build_sys_table fails, we kill everything and bail
-	 * as we can't init the IOPs w/o a system table
-	 */
-	 
-	if (i2o_build_sys_table()) {
-	 	i2o_sys_shutdown();
-	 	return;
-	 }
-	
-	privmem[0]=c->priv_mem;		/* Private memory space base address */
-	privmem[1]=c->priv_mem_size;
-	privio[0]=c->priv_io;		/* Private I/O address */
-	privio[1]=c->priv_io_size;
-
-        __raw_writel(TEN_WORD_MSG_SIZE|SGL_OFFSET_6, &msg[0]);
-        __raw_writel(I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID, &msg$
-        __raw_writel(0, &msg[2]);               /* Context not needed */
-        __raw_writel(0, &msg[3]);
-        __raw_writel((0<<16)|(2<<12), &msg[4]); /* Host 1 I2O 2 */
-        __raw_writel(0, &msg[5]);               /* Segment 1 */
-
-        /*
-         *      Scatter Gather List
-         */
-
-        __raw_writel(0x54000000|sys_tbl_len, &msg[6]);  /* One table for now */
-        __raw_writel(virt_to_phys(sys_tbl), &msg[[7]);
-        __raw_writel(0xD4000000|48, &msg[8]);   /* One table for now */
-        __raw_writel(virt_to_phys(privmem), &msg[9]);
-
-        ret = (i2o_post_wait(c, msg, sizeof(msg), 120);
-        if (ret)
-        	return ret; 
-
-        /*
-         *      Finally we go online
-         */
-        ret = i2o_enable_controller(c);
-        if(ret)
-                return ret;
+	/* In READY state */
 
-        /*
-         *      Grab the LCT, see what is attached
-         */
-        ret=i2o_lct_get(c);
-        if(ret)
-        {
-                /* Maybe we should do also do something else */
-                return ret;
-        }
+	if (i2o_enable_controller(iop) < 0) {
+		i2o_delete_controller(iop);
+		return -1;
+	}
 
-        ret=i2o_parse_lct(c);
-        if(ret)
-                return ret;
+	/* In OPERATIONAL state  */
 
-        return 0; 
-#endif
+	if (i2o_lct_get(iop) < 0){
+		i2o_delete_controller(iop);
+		return -1;
+	}
+
+	return 0;
 }
 
 static int i2o_build_sys_table(void)
@@ -1923,7 +1753,8 @@
 
         msg[0] = I2O_MESSAGE_SIZE(5 + evt_data_len / 4) | SGL_OFFSET_5;
         msg[1] = I2O_CMD_UTIL_EVT_ACK << 24 | HOST_TID << 12 | tid;
-	/* msg[2] and msg[3] filled in i2o_post_wait */
+	msg[2] = context;
+	msg[3] = 0;
         msg[4] = evt_indicator;
         memcpy(msg+5, evt_data, evt_data_len);
 
@@ -1947,9 +1778,10 @@
 	else	
 		msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid;
 
-	/* msg[2] and msg[3] filled in i2o_post_wait */	
+	/* msg[2] filled in i2o_post_wait */	
+	msg[3] = 0;
 	msg[4] = type;
-	
+
 	return i2o_post_wait(c, msg, sizeof(msg), 2);
 }
 
@@ -1970,6 +1802,8 @@
 
 	msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
 	msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
+	/* msg[2] filled in i2o_post_wait */
+	msg[3] = 0;
 	msg[4] = 0;
 	msg[5] = 0x54000000 | oplen;	/* OperationBlock */
 	msg[6] = virt_to_bus(opblk);
@@ -2515,7 +2349,7 @@
 }
 
 /* Used to dump a message to syslog during debugging */
-static void i2o_dump_message(u32 *msg)
+void i2o_dump_message(u32 *msg)
 {
 #ifdef DRIVERDEBUG
 	int i;
@@ -2531,10 +2365,7 @@
 
 EXPORT_SYMBOL(i2o_install_handler);
 EXPORT_SYMBOL(i2o_remove_handler);
-EXPORT_SYMBOL(i2o_install_device);
-EXPORT_SYMBOL(i2o_delete_device);
-EXPORT_SYMBOL(i2o_quiesce_controller);
-EXPORT_SYMBOL(i2o_clear_controller);
+
 EXPORT_SYMBOL(i2o_install_controller);
 EXPORT_SYMBOL(i2o_delete_controller);
 EXPORT_SYMBOL(i2o_unlock_controller);
@@ -2547,9 +2378,7 @@
 EXPORT_SYMBOL(i2o_claim_device);
 EXPORT_SYMBOL(i2o_release_device);
 EXPORT_SYMBOL(i2o_run_queue);
-EXPORT_SYMBOL(i2o_report_controller_unit);
 EXPORT_SYMBOL(i2o_activate_controller);
-EXPORT_SYMBOL(i2o_online_controller);
 EXPORT_SYMBOL(i2o_get_class_name);
 EXPORT_SYMBOL(i2o_status_get);
 
@@ -2558,7 +2387,6 @@
 EXPORT_SYMBOL(i2o_query_table);
 EXPORT_SYMBOL(i2o_clear_table);
 EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_row_delete_table);
 
 EXPORT_SYMBOL(i2o_post_this);
 EXPORT_SYMBOL(i2o_post_wait);

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