#include <asm/atomic.h>
#include <linux/blkdev.h>
#include <linux/i2o.h>
-#include "../../scsi/scsi.h"
-#include "../../scsi/hosts.h"
-#if BITS_PER_LONG == 64
-#error FIXME: driver does not support 64-bit platforms
-#endif
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
#define VERSION_STRING "Version 0.1.2"
static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
{
- Scsi_Cmnd *current_command;
+ struct scsi_cmnd *current_command;
spinlock_t *lock;
u32 *m = (u32 *)msg;
u8 as,ds,st;
{
spin_unlock_irqrestore(&retry_lock, flags);
/* Create a scsi error for this */
- current_command = (Scsi_Cmnd *)m[3];
+ current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
+ if(!current_command)
+ return;
+
lock = current_command->device->host->host_lock;
printk("Aborted %ld\n", current_command->serial_number);
printk(KERN_INFO "i2o_scsi: bus reset completed.\n");
return;
}
- /*
- * FIXME: 64bit breakage
- */
- current_command = (Scsi_Cmnd *)m[3];
+ current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
/*
* Is this a control request coming back - eg an abort ?
*/
+ atomic_dec(&queue_depth);
+
if(current_command==NULL)
{
if(st)
dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number);
- atomic_dec(&queue_depth);
-
if(st == 0x06)
{
if(le32_to_cpu(m[5]) < current_command->underflow)
*/
current_command->result = DID_OK << 16 | ds;
- if (current_command->use_sg)
- pci_unmap_sg(c->pdev, (struct scatterlist *)current_command->buffer, current_command->use_sg, scsi_to_pci_dma_dir(current_command->sc_data_direction));
- else if (current_command->request_bufflen)
- pci_unmap_single(c->pdev, (dma_addr_t)((long)current_command->SCp.ptr), current_command->request_bufflen, scsi_to_pci_dma_dir(current_command->sc_data_direction));
+ if (current_command->use_sg) {
+ pci_unmap_sg(c->pdev,
+ (struct scatterlist *)current_command->buffer,
+ current_command->use_sg,
+ current_command->sc_data_direction);
+ } else if (current_command->request_bufflen) {
+ pci_unmap_single(c->pdev,
+ (dma_addr_t)((long)current_command->SCp.ptr),
+ current_command->request_bufflen,
+ current_command->sc_data_direction);
+ }
lock = current_command->device->host->host_lock;
spin_lock_irqsave(lock, flags);
* scsi controller and then let the enumeration fake up the rest
*/
-static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
+static int i2o_scsi_detect(struct scsi_host_template * tpnt)
{
struct Scsi_Host *shpnt = NULL;
int i;
* Locks: takes the controller lock on error path only
*/
-static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
+ void (*done) (struct scsi_cmnd *))
{
int i;
int tid;
struct i2o_controller *c;
- Scsi_Cmnd *current_command;
+ struct scsi_cmnd *current_command;
struct Scsi_Host *host;
struct i2o_scsi_host *hostdata;
u32 *msg, *mptr;
if(tid == -1)
{
SCpnt->result = DID_NO_CONNECT << 16;
- spin_lock_irqsave(host->host_lock, flags);
done(SCpnt);
- spin_unlock_irqrestore(host->host_lock, flags);
return 0;
}
if(m==0xFFFFFFFF)
return 1;
- msg = (u32 *)(c->mem_offset + m);
+ msg = (u32 *)(c->msg_virt + m);
/*
* Put together a scsi execscb message
len = SCpnt->request_bufflen;
direction = 0x00000000; // SGL IN (osm<--iop)
- if(SCpnt->sc_data_direction == SCSI_DATA_NONE)
+ if (SCpnt->sc_data_direction == DMA_NONE) {
scsidir = 0x00000000; // DATA NO XFER
- else if(SCpnt->sc_data_direction == SCSI_DATA_WRITE)
- {
- direction=0x04000000; // SGL OUT (osm-->iop)
- scsidir =0x80000000; // DATA OUT (iop-->dev)
- }
- else if(SCpnt->sc_data_direction == SCSI_DATA_READ)
- {
- scsidir =0x40000000; // DATA IN (iop<--dev)
- }
- else
- {
+ } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
+ direction = 0x04000000; // SGL OUT (osm-->iop)
+ scsidir = 0x80000000; // DATA OUT (iop-->dev)
+ } else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
+ scsidir = 0x40000000; // DATA IN (iop<--dev)
+ } else {
/* Unknown - kill the command */
SCpnt->result = DID_NO_CONNECT << 16;
i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
i2o_raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */
- /* Sorry 64bit folks. FIXME */
- i2o_raw_writel((u32)SCpnt, &msg[3]); /* We want the SCSI control block back */
+ i2o_raw_writel(i2o_context_list_add(SCpnt, c), &msg[3]); /* We want the SCSI control block back */
/* LSI_920_PCI_QUIRK
*
len = 0;
sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ SCpnt->sc_data_direction);
/* FIXME: handle fail */
if(!sg_count)
dma_addr = pci_map_single(c->pdev,
SCpnt->request_buffer,
SCpnt->request_bufflen,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ SCpnt->sc_data_direction);
if(dma_addr == 0)
BUG(); /* How to handle ?? */
SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
* @SCpnt: command to abort
*
* Ask the I2O controller to abort a command. This is an asynchrnous
- * process and oru callback handler will see the command complete
+ * process and our callback handler will see the command complete
* with an aborted message if it succeeds.
*
* Locks: no locks are held or needed
*/
-int i2o_scsi_abort(Scsi_Cmnd * SCpnt)
+static int i2o_scsi_abort(struct scsi_cmnd * SCpnt)
{
struct i2o_controller *c;
struct Scsi_Host *host;
struct i2o_scsi_host *hostdata;
- unsigned long msg;
- u32 m;
+ u32 msg[5];
int tid;
- unsigned long timeout;
+ int status = FAILED;
printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
if(tid==-1)
{
printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n");
- return FAILED;
+ return status;
}
c = hostdata->controller;
spin_unlock_irq(host->host_lock);
- timeout = jiffies+2*HZ;
- do
- {
- m = le32_to_cpu(I2O_POST_READ32(c));
- if(m != 0xFFFFFFFF)
- break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- mb();
- }
- while(time_before(jiffies, timeout));
-
- msg = c->mem_offset + m;
-
- i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg);
- i2o_raw_writel(I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid, msg+4);
- i2o_raw_writel(scsi_context, msg+8);
- i2o_raw_writel(0, msg+12); /* Not needed for an abort */
- i2o_raw_writel((u32)SCpnt, msg+16);
- wmb();
- i2o_post_message(c,m);
- wmb();
-
+ msg[0] = FIVE_WORD_MSG_SIZE;
+ msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid;
+ msg[2] = scsi_context;
+ msg[3] = 0;
+ msg[4] = i2o_context_list_remove(SCpnt, c);
+ if(i2o_post_wait(c, msg, sizeof(msg), 240))
+ status = SUCCESS;
+
spin_lock_irq(host->host_lock);
- return SUCCESS;
+ return status;
}
/**
* Locks: called with no lock held, requires no locks.
*/
-static int i2o_scsi_bus_reset(Scsi_Cmnd * SCpnt)
+static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt)
{
int tid;
struct i2o_controller *c;
struct Scsi_Host *host;
struct i2o_scsi_host *hostdata;
u32 m;
- unsigned long msg;
+ void *msg;
unsigned long timeout;
while(time_before(jiffies, timeout));
- msg = c->mem_offset + m;
+ msg = c->msg_virt + m;
i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4);
i2o_raw_writel(scsi_context|0x80000000, msg+8);
return SUCCESS;
}
-/**
- * i2o_scsi_host_reset - host reset callback
- * @SCpnt: command causing the reset
- *
- * An I2O controller can be many things at once. While we can
- * reset a controller the potential mess from doing so is vast, and
- * it's better to simply hold on and pray
- */
-
-static int i2o_scsi_host_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
-}
-
-/**
- * i2o_scsi_device_reset - device reset callback
- * @SCpnt: command causing the reset
- *
- * I2O does not (AFAIK) support doing a device reset
- */
-
-static int i2o_scsi_device_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
-}
-
/**
* i2o_scsi_bios_param - Invent disk geometry
* @sdev: scsi device
MODULE_LICENSE("GPL");
-static Scsi_Host_Template driver_template = {
+static struct scsi_host_template driver_template = {
.proc_name = "i2o_scsi",
.name = "I2O SCSI Layer",
.detect = i2o_scsi_detect,
.queuecommand = i2o_scsi_queuecommand,
.eh_abort_handler = i2o_scsi_abort,
.eh_bus_reset_handler = i2o_scsi_bus_reset,
- .eh_device_reset_handler= i2o_scsi_device_reset,
- .eh_host_reset_handler = i2o_scsi_host_reset,
.bios_param = i2o_scsi_bios_param,
.can_queue = I2O_SCSI_CAN_QUEUE,
.this_id = 15,