]> git.hungrycats.org Git - linux/commitdiff
[PATCH] i2o: added support for Promise controllers
authorMarkus Lidel <markus.lidel@shadowconnect.com>
Tue, 19 Oct 2004 01:18:07 +0000 (18:18 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 19 Oct 2004 01:18:07 +0000 (18:18 -0700)
- added support for Promise I2O controllers, which need a different
  initialization sequence (original from Alan Cox)

Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/message/i2o/iop.c
drivers/message/i2o/pci.c

index 5b5a5bfa9b49bd47a67f58265744bd32f27e0a94..46fa7dfd6eb127fb480b7a505c25ff686bbf8dfb 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/module.h>
 #include <linux/i2o.h>
+#include <linux/delay.h>
 
 /* global I2O controller list */
 LIST_HEAD(i2o_controllers);
@@ -470,7 +471,7 @@ static int i2o_iop_reset(struct i2o_controller *c)
        if (m == I2O_QUEUE_EMPTY)
                return -ETIMEDOUT;
 
-       memset(status, 0, 4);
+       memset(status, 0, 8);
 
        /* Quiesce all IOPs first */
        i2o_iop_quiesce_all();
@@ -495,6 +496,13 @@ static int i2o_iop_reset(struct i2o_controller *c)
                        rc = -ETIMEDOUT;
                        goto exit;
                }
+
+               /* Promise bug */
+               if (status[1] || status[4]) {
+                       *status = 0;
+                       break;
+               }
+
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
 
@@ -605,12 +613,30 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c)
        /* Post frames */
        for (i = 0; i < NMBR_MSG_FRAMES; i++) {
                i2o_flush_reply(c, m);
+               udelay(1);      /* Promise */
                m += MSG_FRAME_SIZE * 4;
        }
 
        return 0;
 }
 
+/**
+ *     i2o_iop_send_nop - send a core NOP message
+ *     @c: controller
+ *
+ *     Send a no-operation message with a reply set to cause no
+ *     action either. Needed for bringing up promise controllers.
+ */
+static int i2o_iop_send_nop(struct i2o_controller *c)
+{
+       struct i2o_message *msg;
+       u32 m = i2o_msg_get_wait(c, &msg, HZ);
+       if (m == I2O_QUEUE_EMPTY)
+               return -ETIMEDOUT;
+       i2o_msg_nop(c, m);
+       return 0;
+}
+
 /**
  *     i2o_iop_activate - Bring controller up to HOLD
  *     @c: controller
@@ -622,8 +648,27 @@ int i2o_iop_init_outbound_queue(struct i2o_controller *c)
  */
 static int i2o_iop_activate(struct i2o_controller *c)
 {
+       struct pci_dev *i960 = NULL;
        i2o_status_block *sb = c->status_block.virt;
        int rc;
+
+       if (c->promise) {
+               /* Beat up the hardware first of all */
+               i960 =
+                   pci_find_slot(c->pdev->bus->number,
+                                 PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
+               if (i960)
+                       pci_write_config_word(i960, 0x42, 0);
+
+               /* Follow this sequence precisely or the controller
+                  ceases to perform useful functions until reboot */
+               if ((rc = i2o_iop_send_nop(c)))
+                       return rc;
+
+               if ((rc = i2o_iop_reset(c)))
+                       return rc;
+       }
+
        /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
        /* In READY state, Get status */
 
@@ -659,13 +704,22 @@ static int i2o_iop_activate(struct i2o_controller *c)
        if (rc)
                return rc;
 
+       if (c->promise) {
+               if ((rc = i2o_iop_send_nop(c)))
+                       return rc;
+
+               if ((rc = i2o_status_get(c)))
+                       return rc;
+
+               if (i960)
+                       pci_write_config_word(i960, 0x42, 0x3FF);
+       }
+
        /* In HOLD state */
 
        rc = i2o_hrt_get(c);
-       if (rc)
-               return rc;
 
-       return 0;
+       return rc;
 };
 
 /**
index 2d85609b84d3f5801f3d536786e28f7e0b249544..f98849abbe2a13b9a9ee9f37f78f7b85b926a95a 100644 (file)
@@ -231,7 +231,7 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
        }
 #endif
 
-       if (i2o_dma_alloc(dev, &c->status, 4, GFP_KERNEL)) {
+       if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
                i2o_pci_free(c);
                return -ENOMEM;
        }
@@ -277,7 +277,6 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
        struct device *dev = &c->pdev->dev;
        struct i2o_message *m;
        u32 mv;
-       u32 *msg;
 
        /*
         * Old 960 steppings had a bug in the I2O unit that caused
@@ -298,11 +297,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
                 * Because bus_to_virt is deprecated, we have calculate the
                 * location by ourself!
                 */
-               m = (struct i2o_message *)(mv -
-                                          (unsigned long)c->out_queue.phys +
-                                          (unsigned long)c->out_queue.virt);
-
-               msg = (u32 *) m;
+               m = i2o_msg_out_to_virt(c, mv);
 
                /*
                 *      Ensure this message is seen coherently but cachably by