#include <linux/module.h>
#include <linux/i2o.h>
+#include <linux/delay.h>
/* global I2O controller list */
LIST_HEAD(i2o_controllers);
if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT;
- memset(status, 0, 4);
+ memset(status, 0, 8);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
rc = -ETIMEDOUT;
goto exit;
}
+
+ /* Promise bug */
+ if (status[1] || status[4]) {
+ *status = 0;
+ break;
+ }
+
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
/* 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
*/
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 */
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;
};
/**
}
#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;
}
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
* 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