patch-2.3.10 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: 1731
- Date:
Tue Jul 6 10:11:40 1999
- Orig file:
v2.3.9/linux/drivers/i2o/i2o_core.c
- Orig date:
Wed Jun 30 13:38:19 1999
diff -u --recursive --new-file v2.3.9/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
@@ -13,12 +13,12 @@
* A lot of the I2O message side code from this is taken from the
* Red Creek RCPCI45 adapter driver by Red Creek Communications
*
- * Some fixes and cleanup by Philipp Rumpf
- *
- * Additional fixes by Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- *
+ * Fixes by Philipp Rumpf
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -32,26 +32,69 @@
#include "i2o_lan.h"
+
/*
* Size of the I2O module table
*/
-
static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
int i2o_num_controllers = 0;
-
+static int core_context = 0;
+static int reply_flag = 0;
extern int i2o_online_controller(struct i2o_controller *c);
+static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
+ struct i2o_message *);
+
+/* Message handler */
+static struct i2o_handler i2o_core_handler =
+{
+ (void *)i2o_core_reply,
+ "I2O core layer",
+ 0
+};
/*
* I2O configuration spinlock. This isnt a big deal for contention
* so we have one only
*/
-#ifdef __SMP__
static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED;
+
+void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
+ struct i2o_message *m)
+{
+ u32 *msg=(u32 *)m;
+ u32 *flag = (u32 *)msg[3];
+
+#if 0
+ i2o_report_status(KERN_INFO, "i2o_core", msg);
#endif
+
+ if (msg[0] & (1<<13)) // Fail bit is set
+ {
+ printk(KERN_ERR "IOP failed to process the msg:\n");
+ printk(KERN_ERR " Cmd = 0x%02X, InitiatorTid = %d, TargetTid =%d\n",
+ (msg[1] >> 24) & 0xFF, (msg[1] >> 12) & 0xFFF, msg[1] &
+ 0xFFF);
+ printk(KERN_ERR " FailureCode = 0x%02X\n Severity = 0x%02X\n"
+ "LowestVersion = 0x%02X\n HighestVersion = 0x%02X\n",
+ msg[4] >> 24, (msg[4] >> 16) & 0xFF,
+ (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
+ printk(KERN_ERR " FailingHostUnit = 0x%04X\n FailingIOP = 0x%03X\n",
+ msg[5] >> 16, msg[5] & 0xFFF);
+ return;
+ }
+
+ if (msg[4] >> 24)
+ {
+ i2o_report_status(KERN_WARNING, "i2o_core", msg);
+ *flag = -(msg[4] & 0xFFFF);
+ }
+ else
+ *flag = I2O_POST_WAIT_OK;
+}
/*
* Install an I2O handler - these handle the asynchronous messaging
@@ -179,10 +222,11 @@
int i2o_delete_controller(struct i2o_controller *c)
{
struct i2o_controller **p;
-
+
spin_lock(&i2o_configuration_lock);
if(atomic_read(&c->users))
{
+ printk("Someones using controller iop%d\n", c->unit);
spin_unlock(&i2o_configuration_lock);
return -EBUSY;
}
@@ -195,21 +239,41 @@
return -EBUSY;
}
}
- c->destructor(c);
-
+// c->destructor(c); /* We dont want to free the IRQ yet */
+
p=&i2o_controller_chain;
-
+
+ /* Send first SysQuiesce to other IOPs */
+ while(*p)
+ {
+ if(*p!=c)
+ if(i2o_quiesce_controller(*p)<0)
+ printk(KERN_INFO "Unable to quiesce iop%d\n",
+ (*p)->unit);
+ p=&((*p)->next);
+ }
+
+ p=&i2o_controller_chain;
+
while(*p)
{
if(*p==c)
{
- /* Prepare for restart */
-// i2o_clear_controller(c);
+ /* Ask the IOP to switch to HOLD state */
+ if (i2o_clear_controller(c) < 0)
+ printk("Unable to clear iop%d\n", c->unit);
+
+ /* Release IRQ */
+ c->destructor(c);
*p=c->next;
spin_unlock(&i2o_configuration_lock);
if(c->page_frame);
kfree(c->page_frame);
+ if(c->hrt)
+ kfree(c->hrt);
+ if(c->lct)
+ kfree(c->lct);
i2o_controllers[c->unit]=NULL;
kfree(c);
i2o_num_controllers--;
@@ -317,7 +381,7 @@
"Device Driver Module",
"Block Device",
"Tape Device",
- "LAN Inteface",
+ "LAN Interface",
"WAN Interface",
"Fibre Channel Port",
"Fibre Channel Device",
@@ -384,7 +448,7 @@
{
if((jiffies-time)>=5*HZ)
{
- printk(KERN_ERR "%s: Timeout waiting for message to send %s.\n",
+ printk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n",
c->name, why);
return 0xFFFFFFFF;
}
@@ -396,7 +460,7 @@
/*
- * Wait up to 5 seconds for a reply to be available.
+ * Wait up to timeout seconds for a reply to be available.
*/
u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout)
@@ -418,173 +482,6 @@
}
-
-/* Quiesce and clear IOP */
-int i2o_quiesce_controller(struct i2o_controller *c)
-{
- u32 m;
- u32 *msg;
-
- /* now we stop receiving messages to this IOP */
- m=i2o_wait_message(c, "Quiesce IOP");
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
- msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
- msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=0;
- msg[3]=0;
-
- printk(KERN_DEBUG "Sending SysQuiesce to %s\n", c->name);
- i2o_post_message(c,m);
-
- m=i2o_wait_reply(c, "System Quiesce", 20);
-
- if (m==0xFFFFFFFF)
- return -ETIMEDOUT;
- /* Someday we should check return status... */
-
- return 0;
-}
-
-int i2o_clear_controller(struct i2o_controller *c)
-{
- u32 m;
- u32 *msg;
-
- m=i2o_wait_message(c, "IOP Clear");
- if (m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
- msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
- msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=0;
- msg[3]=0;
-
- printk(KERN_DEBUG "Sending IOPClear to %s\n", c->name);
- i2o_post_message(c, m);
-
- m=i2o_wait_reply(c, "IOP Clear timeout", 5);
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- return 0;
-}
-
-
-/*
- * i2o table walking. We just provide a single element retrieve. You can
- * all sorts of fancy lookups in I2O but we have no performance critical
- * lookups so why write all the code for it.
- */
-
-#if 0
-static int i2o_query_table_polled(struct i2o_controller *c, int tid, void *buf, int buflen,
- int group, int field, u32 *key, int keylen)
-{
- u32 m;
- u32 *msg;
- u16 op[64];
- u32 *p;
- int i;
- u32 *rbuf;
-
- op[0]=1; /* One Operation */
- op[1]=0; /* PAD */
- op[2]=2; /* LIST_GET */
- op[3]=group; /* group number */
- op[4]=1; /* 1 field */
- op[5]=field; /* Field number */
- op[6]=1; /* Key count */
- memcpy(op+7, key, keylen); /* Key */
-
- m=i2o_wait_message(c, "I2O query table.");
- if(m==0xFFFFFFFF)
- {
- return -ETIMEDOUT;
- }
-
- msg=(u32 *)(c->mem_offset+m);
-
- rbuf=kmalloc(buflen+32, GFP_KERNEL);
- if(rbuf==NULL)
- {
- printk(KERN_ERR "No free memory for table read.\n");
- return -ENOMEM;
- }
- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
- msg[1]=I2O_CMD_UTIL_PARAMS_GET<<24|HOST_TID<<12|tid;
- msg[2]=0; /* Context */
- msg[3]=0;
- msg[4]=0;
- msg[5]=0x54000000|(14);
- msg[6]=virt_to_bus(op);
- msg[7]=0xD0000000|(32+buflen);
- msg[8]=virt_to_bus(rbuf);
-
- i2o_post_message(c,m);
- barrier();
-
- /*
- * Now wait for a reply
- */
-
-
- m=i2o_wait_reply(c, "Table read timeout", 5);
-
- if(m==0xFFFFFFFF)
- {
- kfree(rbuf);
- return -ETIMEDOUT;
- }
-
- msg = (u32 *)bus_to_virt(m);
-
- if(msg[4]>>24)
- {
- i2o_report_status(KERN_WARNING, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
- }
-
- p=rbuf;
-
- /* Ok 'p' is the reply block - lets see what happened */
- /* p0->p2 are the header */
-
- /* FIXME: endians - turn p3 to little endian */
-
- i=(p[0]&0xFFFF)<<2; /* Message size */
- if(i<buflen)
- buflen=i;
-
- /* Do we have an error block ? */
- if(p[0]&0xFF000000)
- {
- printk(KERN_ERR "%s: error in field read.\n",
- c->name);
- kfree(rbuf);
- return -EBADR;
- }
-
- /* p[1] holds the more flag and row count - we dont care */
-
- /* Ok it worked p[2]-> hold the data */
- memcpy(buf, p+2, buflen);
-
- kfree(rbuf);
-
- /* Finally return the message */
- I2O_REPLY_WRITE32(c,m);
- return buflen;
-}
-#endif
-
static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf, int buflen,
int group, int field)
{
@@ -602,7 +499,7 @@
op[4]=1; /* 1 field */
op[5]=field; /* Field number */
- m=i2o_wait_message(c, "I2O query scalar.");
+ m=i2o_wait_message(c, "ParamsGet");
if(m==0xFFFFFFFF)
{
return -ETIMEDOUT;
@@ -634,8 +531,7 @@
* Now wait for a reply
*/
-
- m=i2o_wait_reply(c, "Scalar read timeout", 5);
+ m=i2o_wait_reply(c, "ParamsGet", 5);
if(m==0xFFFFFFFF)
{
@@ -646,9 +542,7 @@
msg = (u32 *)bus_to_virt(m);
if(msg[4]>>24)
{
- i2o_report_status(KERN_WARNING, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
+ i2o_report_status(KERN_WARNING, "i2o_core", msg);
}
p=rbuf;
@@ -729,9 +623,10 @@
* This is full of endianisms!
*/
-static int i2o_parse_hrt(struct i2o_controller *c, u8 *p)
+static int i2o_parse_hrt(struct i2o_controller *c)
{
- u32 *rows=(u32 *)p;
+ u32 *rows=c->hrt;
+ u8 *p=(u8 *)c->hrt;
u8 *d;
int count;
int length;
@@ -818,7 +713,7 @@
* on the board. Most of the stuff isn't interesting to us.
*/
-static int i2o_parse_lct(struct i2o_controller *c, u32 *lct)
+static int i2o_parse_lct(struct i2o_controller *c)
{
int i;
int max;
@@ -826,11 +721,18 @@
u32 *p;
struct i2o_device *d;
char str[22];
+ u32 *lct=(u32 *)c->lct;
max=lct[0]&0xFFFF;
max-=3;
max/=9;
+
+ if(max==0)
+ {
+ printk(KERN_ERR "LCT is empty????\n");
+ return -1;
+ }
printk(KERN_INFO "LCT has %d entries.\n", max);
@@ -891,37 +793,61 @@
return 0;
}
-#if 0
-/* Reset the IOP to sane state */
-/* I think we need handler for core (or executive class in I2O terms) */
-static int i2o_reset_adapter(struct i2o_controller *c)
+/* Quiesce IOP */
+int i2o_quiesce_controller(struct i2o_controller *c)
{
- u32 m;
- u8 *work8;
- u32 *msg;
- long time;
+ u32 msg[4];
- /* First stop extral operations */
- m=i2o_wait_message(c, "quiesce IOP");
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=0;
- msg[3]=0;
+ msg[2]=core_context;
+ msg[3]=(u32)&reply_flag;
- i2o_post_message(c,m);
+ return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10);
+}
- m=i2o_wait_reply(c, "System Quiesce timeout", 5);
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
+int i2o_clear_controller(struct i2o_controller *c)
+{
+ u32 msg[4];
+
+ /* First stop external operations for this IOP */
+ if(i2o_quiesce_controller(c)<0)
+ printk(KERN_INFO "Unable to quiesce iop%d\n", c->unit);
+ else
+ printk(KERN_INFO "Iop%d quiesced\n", c->unit);
+
+ /* Then clear the IOP */
+ msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
+ msg[2]=core_context;
+ msg[3]=(u32)&reply_flag;
+
+ return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10);
+}
+
+
+/* Reset the IOP to sane state */
+static int i2o_reset_controller(struct i2o_controller *c)
+{
+ u32 m;
+ u8 *work8;
+ u32 *msg;
+ long time;
+ struct i2o_controller *iop;
+
+ /* First stop external operations */
+ for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
+ {
+ if(i2o_quiesce_controller(iop)<0)
+ printk(KERN_INFO "Unable to quiesce iop%d\n",
+ iop->unit);
+ else
+ printk(KERN_DEBUG "%s quiesced\n", iop->name);
+ }
/* Then reset the IOP */
- m=i2o_wait_message(c, "reset IOP");
+ m=i2o_wait_message(c, "AdapterReset");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -937,8 +863,8 @@
msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=0;
- msg[3]=0;
+ msg[2]=core_context;
+ msg[3]=(u32)&reply_flag;
msg[4]=0;
msg[5]=0;
msg[6]=virt_to_phys(work8);
@@ -949,8 +875,10 @@
/* Wait for a reply */
time=jiffies;
- while(work8[0]==0x01) {
- if((jiffies-time)>=5*HZ) {
+ while(work8[0]==0x01)
+ {
+ if((jiffies-time)>=5*HZ)
+ {
printk(KERN_ERR "IOP reset timeout.\n");
kfree(work8);
return -ETIMEDOUT;
@@ -964,113 +892,186 @@
return 0;
}
-#endif
-/*
- * 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
- */
-int i2o_activate_controller(struct i2o_controller *c)
+int i2o_status_get(struct i2o_controller *c)
{
long time;
u32 m;
- u8 *workspace;
u32 *msg;
- int i;
-
- printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n", (u32)c->mem_phys);
+ u8 *status_block;
- /* First reset the IOP to sane state */
-// i2o_reset_adapter(c)
-
- m=i2o_wait_message(c, "initialise");
+ status_block=(void *)kmalloc(88, GFP_KERNEL);
+ if(status_block==NULL)
+ {
+ printk(KERN_ERR "StatusGet failed - no free memory.\n");
+ return -ENOMEM;
+ }
+
+ m=i2o_wait_message(c, "StatusGet");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
msg=(u32 *)(c->mem_offset+m);
-
- workspace = (void *)kmalloc(88, GFP_KERNEL);
- if(workspace==NULL)
- {
- printk(KERN_ERR "IOP initialisation failed - no free memory.\n");
- return -ENOMEM;
- }
-
- memset(workspace, 0, 88);
-
+
msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=0;
+ msg[2]=core_context;
msg[3]=0;
msg[4]=0;
msg[5]=0;
- msg[6]=virt_to_phys(workspace);
+ msg[6]=virt_to_phys(status_block);
msg[7]=0; /* 64bit host FIXME */
msg[8]=88;
i2o_post_message(c,m);
- /*
- * Wait for a reply
- */
-
+ /* Wait for a reply */
time=jiffies;
- while(workspace[87]!=0xFF)
+ while(status_block[87]!=0xFF)
{
if((jiffies-time)>=5*HZ)
{
printk(KERN_ERR "IOP get status timeout.\n");
- kfree(workspace);
return -ETIMEDOUT;
}
schedule();
barrier();
}
- /*
- * Ok the reply has arrived. Fill in the important stuff
- */
-
- c->status = workspace[10];
- c->i2oversion = (workspace[9]>>4)&0xFF;
- c->inbound_size = (workspace[12]|(workspace[13]<<8))*4; /* 32bit words */
-
+ /* Ok the reply has arrived. Fill in the important stuff */
+ c->status = status_block[10];
+ c->i2oversion = (status_block[9]>>4)&0xFF;
+ c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
+
+ return 0;
+}
+
+
+int i2o_hrt_get(struct i2o_controller *c)
+{
+ u32 m;
+ u32 *msg;
+
+ c->hrt=kmalloc(2048, GFP_KERNEL);
+ if(c->hrt==NULL)
+ {
+ printk(KERN_ERR "IOP init failed; no memory.\n");
+ return -ENOMEM;
+ }
+
+ m=i2o_wait_message(c, "HRTGet");
+ if(m==0xFFFFFFFF)
+ return -ETIMEDOUT;
+
+ msg=(u32 *)(c->mem_offset+m);
+
+ msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
+ msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
+ msg[2]= core_context;
+ msg[3]= 0x0; /* Transaction context */
+ msg[4]= (0xD0000000 | 2048); /* Simple transaction , 2K */
+ msg[5]= virt_to_phys(c->hrt); /* Dump it here */
+
+ i2o_post_message(c,m);
+
+ barrier();
+
+ /* Now wait for a reply */
+ m=i2o_wait_reply(c, "HRTGet", 5);
+
+ if(m==0xFFFFFFFF)
+ return -ETIMEDOUT;
+
+ msg=(u32 *)bus_to_virt(m);
+
+ if(msg[4]>>24)
+ i2o_report_status(KERN_WARNING, "i2o_core", msg);
+
+ I2O_REPLY_WRITE32(c,m);
+
+ return 0;
+}
+
+
+/*
+ * 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
+ */
+
+int i2o_activate_controller(struct i2o_controller *c)
+{
+ long time;
+ u32 m;
+ u8 *workspace;
+ u32 *msg;
+ int i;
+ int ret;
+
+ printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n",
+ (u32)c->mem_phys);
+
+ if((ret=i2o_status_get(c)))
+ return ret;
+
+ if(c->status == ADAPTER_STATE_FAULTED) /* not likely to be seen */
+ {
+ printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
+ c->unit);
+ return -1;
+ }
+
/*
* If the board is running, reset it - we have no idea
* what kind of a mess the previous owner left it in.
*/
-
-// if(c->status == ADAPTER_STATE_OPERATIONAL)
-// i2o_reset_device(c);
+ if(c->status == ADAPTER_STATE_HOLD ||
+ c->status == ADAPTER_STATE_READY ||
+ c->status == ADAPTER_STATE_OPERATIONAL ||
+ c->status == ADAPTER_STATE_FAILED)
+ {
+ if((ret=i2o_reset_controller(c)))
+ return ret;
-
- m=i2o_wait_message(c, "initqueue");
+ if((ret=i2o_status_get(c)))
+ return ret;
+ }
+
+ workspace = (void *)kmalloc(88, GFP_KERNEL);
+ if(workspace==NULL)
+ {
+ printk(KERN_ERR "IOP initialisation failed - no free memory.\n");
+ return -ENOMEM;
+ }
+
+ memset(workspace, 0, 88);
+
+ m=i2o_wait_message(c, "OutboundInit");
if(m==0xFFFFFFFF)
{
kfree(workspace);
return -ETIMEDOUT;
}
-
+
msg=(u32 *)(c->mem_offset+m);
msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2]= 0;
+ msg[2]= core_context;
msg[3]= 0x0106; /* Transaction context */
msg[4]= 4096; /* Host page frame size */
msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size and Initcode */
@@ -1099,9 +1100,11 @@
schedule();
barrier();
}
-
+
kfree(workspace);
+ /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
+
c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
if(c->page_frame==NULL)
{
@@ -1124,64 +1127,71 @@
* Now we need the Hardware Resource Table. We must ask for
* this next we can't issue random messages yet.
*/
+ ret=i2o_hrt_get(c);
+ if(ret)
+ return ret;
+
+ ret=i2o_parse_hrt(c);
+ if(ret)
+ return ret;
+
+ return i2o_online_controller(c);
+// i2o_report_controller_unit(c, ADAPTER_TID);
+}
- workspace=kmalloc(2048, GFP_KERNEL);
- if(workspace==NULL)
+int i2o_lct_get(struct i2o_controller *c)
+{
+ u32 m;
+ u32 *msg;
+
+ m=i2o_wait_message(c, "LCTNotify");
+
+ if(m==0xFFFFFFFF)
+ return -ETIMEDOUT;
+
+ msg=(u32 *)(c->mem_offset+m);
+
+ c->lct = kmalloc(8192, GFP_KERNEL);
+ if(c->lct==NULL)
{
- printk(KERN_ERR "IOP init failed; no memory.\n");
+ msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1]= HOST_TID<<12|ADAPTER_TID; /* NOP */
+ i2o_post_message(c,m);
+ printk(KERN_ERR "No free memory for i2o controller buffer.\n");
return -ENOMEM;
}
- m=i2o_wait_message(c, "I2O HRT timeout.");
- if(m==0xFFFFFFFF)
- {
- kfree(workspace);
- return -ETIMEDOUT;
- }
+ memset(c->lct, 0, 8192);
- msg=(u32 *)(c->mem_offset+m);
+ msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
+ msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
+ msg[2] = 0; /* Context not needed */
+ msg[3] = 0;
+ msg[4] = 0xFFFFFFFF; /* All devices */
+ msg[5] = 0x00000000; /* Report now */
+ msg[6] = 0xD0000000|8192;
+ msg[7] = virt_to_bus(c->lct);
- msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
- msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2]= 0x0;
- msg[3]= 0x0; /* Transaction context */
- msg[4]= (0xD0000000 | 2048); /* Simple transaction , 2K */
- msg[5]= virt_to_phys(workspace); /* Dump it here */
- *((u32 *)workspace)=0xFFFFFFFF;
-
i2o_post_message(c,m);
-
+
barrier();
-
- /*
- * Now wait for a reply
- */
-
- m=i2o_wait_reply(c, "HRT table", 5);
-
+
+ /* Now wait for a reply */
+ m=i2o_wait_reply(c, "LCTNotify", 5);
+
if(m==0xFFFFFFFF)
- {
- kfree(workspace);
return -ETIMEDOUT;
- }
-
+
msg=(u32 *)bus_to_virt(m);
-
+
+ /* TODO: Check TableSize for big LCTs and send new ExecLctNotify
+ * with bigger workspace */
+
if(msg[4]>>24)
- {
- i2o_report_status(KERN_WARNING, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
- }
- I2O_REPLY_WRITE32(c,m);
-
- i2o_parse_hrt(c, workspace);
-
- kfree(workspace);
-
- return i2o_online_controller(c);
-// i2o_report_controller_unit(c, ADAPTER_TID);
+ i2o_report_status(KERN_ERR, "i2o_core", msg);
+
+ return 0;
}
@@ -1196,7 +1206,7 @@
u32 systab[32];
u32 privmem[2];
u32 privio[2];
- u32 *workspace;
+ int ret;
systab[0]=1;
systab[1]=0;
@@ -1216,7 +1226,7 @@
privio[0]=c->priv_io; /* Private I/O address */
privio[1]=c->priv_io_size;
- m=i2o_wait_message(c, "SetSysTab");
+ m=i2o_wait_message(c, "SysTabSet");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1249,7 +1259,7 @@
*/
- m=i2o_wait_reply(c, "Systab read", 5);
+ m=i2o_wait_reply(c, "SysTabSet", 5);
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1258,9 +1268,7 @@
if(msg[4]>>24)
{
- i2o_report_status(KERN_ERR, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
+ i2o_report_status(KERN_ERR, "i2o_core", msg);
}
I2O_REPLY_WRITE32(c,m);
@@ -1268,7 +1276,7 @@
* Finally we go online
*/
- m=i2o_wait_message(c, "No message for SysEnable");
+ m=i2o_wait_message(c, "SysEnable");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1289,7 +1297,7 @@
*/
- m=i2o_wait_reply(c, "Enable", 240);
+ m=i2o_wait_reply(c, "SysEnable", 240);
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1298,73 +1306,25 @@
if(msg[4]>>24)
{
- i2o_report_status(KERN_ERR, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
+ i2o_report_status(KERN_ERR, "i2o_core", msg);
}
I2O_REPLY_WRITE32(c,m);
/*
* Grab the LCT, see what is attached
*/
-
- m=i2o_wait_message(c, "No message for LCT");
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
-
- workspace = kmalloc(8192, GFP_KERNEL);
- if(workspace==NULL)
- {
- msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
- msg[1]= HOST_TID<<12|ADAPTER_TID; /* NOP */
- i2o_post_message(c,m);
- printk(KERN_ERR "No free memory for i2o controller buffer.\n");
- return -ENOMEM;
- }
-
- memset(workspace, 0, 8192);
-
- msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_6;
- msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2] = 0; /* Context not needed */
- msg[3] = 0;
- msg[4] = 0xFFFFFFFF; /* All devices */
- msg[5] = 0x00000000; /* Report now */
- msg[6] = 0xD0000000|8192;
- msg[7] = virt_to_bus(workspace);
-
- i2o_post_message(c,m);
-
- barrier();
- /*
- * Now wait for a reply
- */
-
- m=i2o_wait_reply(c, "LCT", 5);
-
- if(m==0xFFFFFFFF)
+ ret=i2o_lct_get(c);
+ if(ret)
{
- kfree(workspace);
- return -ETIMEDOUT;
+ /* Maybe we should do also sthg else */
+ return ret;
}
-
- msg=(u32 *)bus_to_virt(m);
-
- if(msg[4]>>24)
- {
- i2o_report_status(KERN_ERR, "i2o_core",
- (msg[1]>>24)&0xFF, (msg[4]>>24)&0xFF,
- msg[4]&0xFFFF);
- }
-
- i2o_parse_lct(c, workspace);
- kfree(workspace);
-
+
+ ret=i2o_parse_lct(c);
+ if(ret)
+ return ret;
+
I2O_REPLY_WRITE32(c,m);
return 0;
@@ -1417,16 +1377,21 @@
*flag = 0;
if(i2o_post_this(c, tid, data, len))
- return -1;
+ return I2O_POST_WAIT_TIMEOUT;
while(!*flag && (jiffies-t)<timeout*HZ)
{
schedule();
mb();
}
- if(*flag <= 0)
- return -1;
- return 0;
+
+ if (*flag < 0)
+ return *flag; /* DetailedStatus */
+
+ if (*flag == 0)
+ return I2O_POST_WAIT_TIMEOUT;
+
+ return I2O_POST_WAIT_OK;
}
/*
@@ -1452,247 +1417,262 @@
return i2o_post_wait(c, tid, msg, 20, flag,2);
}
+/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
+ *
+ * This function can be used for all UtilParamsGet/Set operations.
+ * The OperationBlock is given in opblk-buffer,
+ * and results are returned in resblk-buffer.
+ * Note that the minimum sized resblk is 8 bytes and contains
+ * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
+ */
+int i2o_issue_params(int cmd,
+ struct i2o_controller *iop, int tid, int context,
+ void *opblk, int oplen, void *resblk, int reslen,
+ int *flag)
+{
+ u32 msg[9];
+ u8 *res = (u8 *)resblk;
+ int res_count;
+ int blk_size;
+ int bytes;
+ int wait_status;
+
+ msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
+ msg[1] = cmd << 24 | HOST_TID << 12 | tid;
+ msg[2] = context | 0x80000000;
+ msg[3] = (u32)flag;
+ msg[4] = 0;
+ msg[5] = 0x54000000 | oplen; /* OperationBlock */
+ msg[6] = virt_to_bus(opblk);
+ msg[7] = 0xD0000000 | reslen; /* ResultBlock */
+ msg[8] = virt_to_bus(resblk);
+
+ wait_status = i2o_post_wait(iop, tid, msg, sizeof(msg), flag, 10);
+ if (wait_status < 0)
+ return wait_status; /* -DetailedStatus */
+
+ if (res[1]&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",
+ res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
+ return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
+ }
+
+ res_count = res[0] & 0xFFFF; /* # of resultblocks */
+ bytes = 4;
+ res += 4;
+ while (res_count--)
+ {
+ blk_size = (res[0] & 0xFFFF) << 2;
+ bytes += blk_size;
+ res += blk_size;
+ }
+
+ return bytes; /* total sizeof Result List in bytes */
+}
+
+/*
+ * Query one scalar group value or a whole scalar group.
+ */
+int i2o_query_scalar(struct i2o_controller *iop, int tid, int context,
+ int group, int field, void *buf, int buflen, int *flag)
+{
+ 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, context,
+ opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
+
+ if (size < 0)
+ return size;
+
+ memcpy(buf, resblk+8, buflen); /* cut off header */
+ return buflen;
+}
+
/*
- * Query a scalar value
+ * Set a scalar group value or a whole group.
*/
-
-int i2o_query_scalar(struct i2o_controller *c, int tid, int context,
- int group, int field, void *buf, int buflen, int *flag)
+int i2o_set_scalar(struct i2o_controller *iop, int tid, int context,
+ int group, int field, void *buf, int buflen, int *flag)
{
- u16 *op;
- u32 *bl;
- u32 msg[9];
-
- bl=kmalloc(buflen+64, GFP_KERNEL); /* Enough space for error replys */
- if(bl==NULL)
- {
- printk(KERN_ERR "i2o: no memory for query buffer.\n");
- return -ENOMEM;
- }
-
- op = (u16*)bl;
- op[0]=1; /* One Operation */
- op[1]=0; /* PAD */
- op[2]=1; /* FIELD_GET */
- op[3]=group; /* group number */
- op[4]=1; /* field count, default = 1 */
- op[5]=field; /* field index */
+ 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);
+ }
- if(field == -1)
- /* Single value or the whole group? */
- {
- op[4]=-1;
- op[5]=0;
- }
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
+ opblk, 12+buflen, resblk, sizeof(resblk), flag);
- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
- msg[1]=I2O_CMD_UTIL_PARAMS_GET<<24|HOST_TID<<12|tid;
- msg[2]=context|0x80000000; /* So we can pick it out */
- msg[3]=(u32)flag;
- msg[4]=0;
- msg[5]=0x54000000|12;
- msg[6]=virt_to_bus(bl);
- /*
- * There are 8 bytes of "overhead" required to pull in
- * a Params ResultsList; 2 bytes for ResultCount
- * (which should have value=1), plus 2 bytes for pad,
- * plus 2 bytes for BlockSize, plus 1 byte BlockStatus,
- * plus 1 byte ErrorInfoSize (8 bytes total overhead).
- * This is followed finally by actual result value(s).
- *
- * Tell the IOP to return 8 + buflen bytes.
- */
- msg[7]=0xD0000000|(8+buflen);
- msg[8]=virt_to_bus(bl+3);
-
- bl[3]=0xFCFCFCFC; // Pad,ResultCount
- bl[4]=0xFAFAFCFC; // ErrorInfoSize,BlockStatus,BlockSize
-
- /*
- * Post the message and await a reply
- */
-
- if (i2o_post_wait(c, tid, msg, sizeof(msg), flag,2) < 0)
- {
- kfree(bl);
- return -1;
- }
-
- if(bl[4]&0x00FF00000) /* BlockStatus != SUCCESS */
- {
- printk(KERN_WARNING "i2o_query_scalar - Error\n"
- "ErrorInfoSize = 0x%02x, BlockStatus = 0x%02x, "
- "BlockSize = 0x%04x\n",
- bl[4]>>24, (bl[4]>>16)&0xFF, bl[4]&0xFFFF);
- kfree(bl);
- return -1;
- }
- if((bl[3] & 0xFFFF) != 1)
- {
- printk(KERN_ERR "i2o: query ResultCount = 0x%04x\n", bl[3]&0xFFFF);
- }
-
- memcpy(buf, bl+5, buflen);
- kfree(bl);
- return 0;
+ kfree(opblk);
+ return size;
}
-
-#if 0
/*
- * Query a table field
- * FIXME: NOT TESTED!
+ * if oper == I2O_PARAMS_TABLE_GET:
+ * Get all table group fields from all rows or
+ * get specific table group fields from all rows.
+ *
+ * if fieldcount == -1 we query all fields from all rows
+ * ibuf is NULL and ibuflen is 0
+ * else we query specific fields from all rows
+ * ibuf contains fieldindexes
+ *
+ * if oper == I2O_PARAMS_LIST_GET:
+ * Get all table group fields from specified rows or
+ * get specific table group fields from specified rows.
+ *
+ * if fieldcount == -1 we query all fields from specified rows
+ * ibuf contains rowcount, keyvalues
+ * else we query specific fields from specified rows
+ * ibuf contains fieldindexes, rowcount, keyvalues
+ *
+ * You could also use directly function i2o_issue_params().
*/
-int i2o_query_table(struct i2o_controller *c, int tid, int context,
- void *buf, int buflen,
- int table,
- int *field, int fieldlen,
- u32 *key, int keylen,
- int *flag)
+int i2o_query_table(int oper,
+ struct i2o_controller *iop, int tid, int context, int group,
+ int fieldcount, void *ibuf, int ibuflen,
+ void *resblk, int reslen, int *flag)
{
- static u16 op[32];
- u32 *bl;
- u32 msg[9];
- int i;
+ u16 *opblk;
+ int size;
- bl=kmalloc(buflen+64, GFP_KERNEL);
- if(bl==NULL)
+ opblk = kmalloc(10 + ibuflen, GFP_KERNEL);
+ if (opblk == NULL)
{
printk(KERN_ERR "i2o: no memory for query buffer.\n");
return -ENOMEM;
}
- op[0]=1; /* Operation count */
- op[1]=0; /* Reserved */
- op[2]=I2O_PARAMS_LIST_GET; /* Operation */
- op[3]=table; /* Group */
- /* Specific fields or the whole group? */
- if(*field != -1)
- { /* FIXME: Fields can be variable size */
- op[4]=fieldlen;
- for (i=0; i < fieldlen; i++)
- op[4+i]=field[i];
- }
- else
- {
- op[4]=-1;
- op[5]=0;
- }
-
- memcpy(bl, op, 12);
-
- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
- msg[1]=I2O_CMD_UTIL_PARAMS_GET<<24|HOST_TID<<12|tid;
- msg[2]=context|0x80000000; /* So we can pick it out */
- msg[3]=(u32)flag;
- msg[4]=0;
- msg[5]=0x54000000|12;
- msg[6]=virt_to_bus(bl);
+ 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 */
- msg[7]=0xD0000000|(buflen+48);
- msg[8]=virt_to_bus(bl+4);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, context,
+ opblk, 10+ibuflen, resblk, reslen, flag);
- /*
- * Post the message and await a reply
- */
+ kfree(opblk);
+ return size;
+}
- if(i2o_post_wait(c, tid, msg, sizeof(msg), flag,2)<0)
- return -1;
-
- if(bl[5]&0x00FF00000) /* BlockStatus != SUCCESS */
- {
- printk(KERN_WARNING "i2o_query_table - Error\n"
- "ErrorInfoSize = 0x%02x, BlockStatus = 0x%02x, "
- "BlockSize = 0x%04x\n",
- bl[5]>>24, (bl[5]>>16)&0xFF, bl[5]&0xFFFF);
- kfree(bl);
- return -1;
- }
+/*
+ * Clear table group, i.e. delete all rows.
+ */
- if((bl[4]&0xFFFF)!=1)
- printk(KERN_ERR "i2o: query ResultCount = %0#4x\n",
- bl[4]&0xFFFF);
+int i2o_clear_table(struct i2o_controller *iop, int tid, int context,
+ int group, int *flag)
+{
+ u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group };
+ u8 resblk[32]; /* min 8 bytes for result header */
- memcpy(buf, bl+6, buflen);
- kfree(bl);
- return 0;
+ return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
+ opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
}
-#endif
/*
- * Set (for now) scalar value
+ * Add a new row into a table group.
*
- * TODO: Add support for table groups
- */
+ * 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_params_set(struct i2o_controller *c, int tid, int context, int table,
- int field, void *buf, int buflen, int *flag)
+int i2o_row_add_table(struct i2o_controller *iop, int tid, int context,
+ int group, int fieldcount, void *buf, int buflen,
+ int *flag)
{
- static u16 opdata[]={1,0,6,0,1,4,0};
- u32 *bl;
- u32 msg[9];
+ u16 *opblk;
+ u8 resblk[32]; /* min 8 bytes for header */
+ int size;
- bl=kmalloc(buflen+64, GFP_KERNEL);
- if(bl==NULL)
+ opblk = kmalloc(buflen+64, GFP_KERNEL);
+ if (opblk == NULL)
{
- printk(KERN_ERR "i2o: no memory for set buffer.\n");
+ printk(KERN_ERR "i2o: no memory for operation buffer.\n");
return -ENOMEM;
}
- opdata[3]=table;
- /* Single value or the whole group? */
- if(field != -1) {
- opdata[4]=1;
- opdata[5]=field;
- opdata[6]=*(u16 *)buf;
- }
- else {
- opdata[4]=-1;
- opdata[5]=0;
- }
+ 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);
- memcpy(bl, opdata, 14);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
+ opblk, 10+buflen, resblk, sizeof(resblk), flag);
- msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
- msg[1]=I2O_CMD_UTIL_PARAMS_SET<<24|HOST_TID<<12|tid;
- msg[2]=context|0x80000000; /* So we can pick it out */
- msg[3]=(u32)flag;
- msg[4]=0;
- msg[5]=0x54000000|14;
- msg[6]=virt_to_bus(bl);
- msg[7]=0xD0000000|(buflen+48);
- msg[8]=virt_to_bus(bl+4);
-
- /* Post the message and wait for a reply */
- if(i2o_post_wait(c, tid, msg, 36, flag, 5)<0)
- {
- kfree(bl);
- return -1;
- }
+ kfree(opblk);
+ return size;
+}
- /* Perhaps we should check errors, eh? */
- if(bl[5]&0x00FF00000) /* BlockStatus != SUCCESS */
- {
- printk(KERN_WARNING "i2o_params_set - Error\n"
- "ErrorInfoSize = %0#2x, BlockStatus = %0#2x, "
- "BlockSize = %0#4x\n",
- bl[5]>>24, (bl[5]>>16)&0xFF, bl[5]&0xFFFF);
- kfree(bl);
- return -1;
- }
+/*
+ * Delete rows from a table group.
+ */
+
+int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context,
+ int group, int keycount, void *keys, int keyslen,
+ int *flag)
+{
+ u16 *opblk;
+ u8 resblk[32]; /* min 8 bytes for header */
+ int size;
- if((bl[4] & 0xFFFF) != 1)
+ opblk = kmalloc(keyslen+64, GFP_KERNEL);
+ if (opblk == NULL)
{
- printk(KERN_ERR "i2o: params set ResultCount = %0#4x\n",
- bl[4]&0xFFFF);
+ printk(KERN_ERR "i2o: no memory for operation buffer.\n");
+ return -ENOMEM;
}
- kfree(bl);
- return 0;
-}
+ opblk[0] = 1; /* operation count */
+ opblk[1] = 0; /* pad */
+ opblk[2] = I2O_PARAMS_ROW_DELETE;
+ opblk[3] = group;
+ opblk[4] = keycount;
+ memcpy(opblk+5, keys, keyslen);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
+ opblk, 10+keyslen, resblk, sizeof(resblk), flag);
+
+ kfree(opblk);
+ return size;
+}
-void report_common_status(u8 req_status)
+void i2o_report_common_status(u8 req_status)
{
/* the following reply status strings are common to all classes */
@@ -1719,7 +1699,7 @@
return;
}
-static void report_common_dsc(u16 detailed_status)
+static void i2o_report_common_dsc(u16 detailed_status)
{
/* The following detailed statuscodes are valid
- for executive class, utility class, DDM class and
@@ -1766,7 +1746,7 @@
return;
}
-void report_lan_dsc(u16 detailed_status)
+static void i2o_report_lan_dsc(u16 detailed_status)
{
static char *LAN_DSC[] = { // Lan detailed status code strings
"SUCCESS",
@@ -1786,10 +1766,11 @@
"DEST_ADDRESS_DETECTED",
"DEST_ADDRESS_OMITTED",
"PARTIAL_PACKET_RETURNED",
- "TEMP_SUSPENDED_STATE"
+ "TEMP_SUSPENDED_STATE", // last Lan detailed status code
+ "INVALID_REQUEST" // general detailed status code
};
- if (detailed_status > I2O_LAN_DSC_TEMP_SUSPENDED_STATE)
+ if (detailed_status > I2O_DSC_INVALID_REQUEST)
printk("%0#4x.\n", detailed_status);
else
printk("%s.\n", LAN_DSC[detailed_status]);
@@ -1797,7 +1778,7 @@
return;
}
-static void report_util_cmd(u8 cmd)
+static void i2o_report_util_cmd(u8 cmd)
{
switch (cmd) {
case I2O_CMD_UTIL_NOP:
@@ -1850,7 +1831,7 @@
}
-static void report_exec_cmd(u8 cmd)
+static void i2o_report_exec_cmd(u8 cmd)
{
switch (cmd) {
case I2O_CMD_ADAPTER_ASSIGN:
@@ -1959,7 +1940,7 @@
return;
}
-static void report_lan_cmd(u8 cmd)
+static void i2o_report_lan_cmd(u8 cmd)
{
switch (cmd) {
case LAN_PACKET_SEND:
@@ -1985,30 +1966,32 @@
}
/* TODO: Add support for other classes */
-void i2o_report_status(const char *severity, const char *module, u8 cmd,
- u8 req_status, u16 detailed_status)
+void i2o_report_status(const char *severity, const char *module, u32 *msg)
{
- printk("%s", severity);
- printk("%s: ", module);
+ u8 cmd = (msg[1]>>24)&0xFF;
+ u8 req_status = (msg[4]>>24)&0xFF;
+ u16 detailed_status = msg[4]&0xFFFF;
+
+ printk("%s%s: ", severity, module);
if (cmd < 0x1F) { // Utility Class
- report_util_cmd(cmd);
- report_common_status(req_status);
- report_common_dsc(detailed_status);
+ i2o_report_util_cmd(cmd);
+ i2o_report_common_status(req_status);
+ i2o_report_common_dsc(detailed_status);
return;
}
if (cmd >= 0x30 && cmd <= 0x3F) { // LAN class
- report_lan_cmd(cmd);
- report_common_status(req_status);
- report_lan_dsc(detailed_status);
+ i2o_report_lan_cmd(cmd);
+ i2o_report_common_status(req_status);
+ i2o_report_lan_dsc(detailed_status);
return;
}
if (cmd >= 0xA0 && cmd <= 0xEF) { // Executive class
- report_exec_cmd(cmd);
- report_common_status(req_status);
- report_common_dsc(detailed_status);
+ i2o_report_exec_cmd(cmd);
+ i2o_report_common_status(req_status);
+ i2o_report_common_dsc(detailed_status);
return;
}
@@ -2017,6 +2000,8 @@
}
+#ifdef CONFIG_MODULE
+
EXPORT_SYMBOL(i2o_install_handler);
EXPORT_SYMBOL(i2o_remove_handler);
EXPORT_SYMBOL(i2o_install_device);
@@ -2037,16 +2022,75 @@
EXPORT_SYMBOL(i2o_get_class_name);
EXPORT_SYMBOL(i2o_query_scalar);
-EXPORT_SYMBOL(i2o_params_set);
+EXPORT_SYMBOL(i2o_set_scalar);
+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);
EXPORT_SYMBOL(i2o_issue_claim);
EXPORT_SYMBOL(i2o_report_status);
-EXPORT_SYMBOL(report_common_status);
-EXPORT_SYMBOL(report_lan_dsc);
-
-EXPORT_SYMBOL(i2o_wait_message);
MODULE_AUTHOR("Red Hat Software");
MODULE_DESCRIPTION("I2O Core");
+
+
+int init_module(void)
+{
+ if (i2o_install_handler(&i2o_core_handler) < 0)
+ {
+ printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
+ return 0;
+ }
+
+ core_context = i2o_core_handler.context;
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ i2o_remove_handler(&i2o_core_handler);
+}
+
+#else
+
+extern int i2o_block_init(void);
+extern int i2o_config_init(void);
+extern int i2o_lan_init(void);
+extern int i2o_pci_init(void);
+extern int i2o_proc_init(void);
+extern int i2o_scsi_init(void);
+
+__init int i2o_init(void)
+{
+ if (i2o_install_handler(&i2o_core_handler) < 0)
+ {
+ printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
+ return 0;
+ }
+
+ core_context = i2o_core_handler.context;
+#ifdef CONFIG_I2O_PCI
+ i2o_pci_init();
+#endif
+ i2o_config_init();
+#ifdef CONFIG_I2O_BLOCK
+ i2o_block_init();
+#endif
+#ifdef CONFIG_I2O_SCSI
+ i2o_scsi_init();
+#endif
+#ifdef CONFIG_I2O_LAN
+ i2o_lan_init();
+#endif
+#ifdef CONFIG_I2O_PROC
+ i2o_proc_init();
+#endif
+ return 0;
+}
+
+#endif
\ No newline at end of file
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)