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
- Lines: 1068
- Date:
Mon Jan 10 14:05:32 2000
- Orig file:
v2.3.38/linux/drivers/i2o/i2o_core.c
- Orig date:
Tue Jan 4 13:57:17 2000
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)