Commit 0bd4095a authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] bring i2o_block/i2o_scsi back to life

parent 4acc3931
...@@ -55,8 +55,6 @@ ...@@ -55,8 +55,6 @@
* Serial number scanning to find duplicates for FC multipathing * Serial number scanning to find duplicates for FC multipathing
*/ */
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/major.h> #include <linux/major.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -132,15 +130,12 @@ ...@@ -132,15 +130,12 @@
#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D #define I2O_BSA_DSC_VOLUME_CHANGED 0x000D
#define I2O_BSA_DSC_TIMEOUT 0x000E #define I2O_BSA_DSC_TIMEOUT 0x000E
#define I2O_UNIT(dev) (i2ob_dev[minor((dev)) & 0xf0])
#define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock) #define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock)
/* /*
* Some of these can be made smaller later * Some of these can be made smaller later
*/ */
static int i2ob_blksizes[MAX_I2OB<<4];
static int i2ob_sizes[MAX_I2OB<<4];
static int i2ob_media_change_flag[MAX_I2OB]; static int i2ob_media_change_flag[MAX_I2OB];
static u32 i2ob_max_sectors[MAX_I2OB<<4]; static u32 i2ob_max_sectors[MAX_I2OB<<4];
...@@ -166,6 +161,7 @@ struct i2ob_device ...@@ -166,6 +161,7 @@ struct i2ob_device
int rcache; int rcache;
int wcache; int wcache;
int power; int power;
int index;
}; };
/* /*
...@@ -179,6 +175,9 @@ struct i2ob_request ...@@ -179,6 +175,9 @@ struct i2ob_request
struct i2ob_request *next; struct i2ob_request *next;
struct request *req; struct request *req;
int num; int num;
int sg_dma_direction;
int sg_nents;
struct scatterlist sg_table[16];
}; };
/* /*
...@@ -259,6 +258,30 @@ static u32 i2ob_get(struct i2ob_device *dev) ...@@ -259,6 +258,30 @@ static u32 i2ob_get(struct i2ob_device *dev)
struct i2o_controller *c=dev->controller; struct i2o_controller *c=dev->controller;
return I2O_POST_READ32(c); return I2O_POST_READ32(c);
} }
static int i2ob_build_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
{
struct scatterlist *sg = ireq->sg_table;
int nents;
nents = blk_rq_map_sg(dev->req_queue, ireq->req, ireq->sg_table);
if (rq_data_dir(ireq->req) == READ)
ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
else
ireq->sg_dma_direction = PCI_DMA_TODEVICE;
ireq->sg_nents = pci_map_sg(dev->controller->pdev, sg, nents, ireq->sg_dma_direction);
return ireq->sg_nents;
}
void i2ob_free_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
{
struct pci_dev *pdev = dev->controller->pdev;
struct scatterlist *sg = ireq->sg_table;
int nents = ireq->sg_nents;
pci_unmap_sg(pdev, sg, nents, ireq->sg_dma_direction);
}
/** /**
* i2ob_send - Turn a request into a message and send it * i2ob_send - Turn a request into a message and send it
...@@ -273,8 +296,6 @@ static u32 i2ob_get(struct i2ob_device *dev) ...@@ -273,8 +296,6 @@ static u32 i2ob_get(struct i2ob_device *dev)
* *
* No cleanup is done by this interface. It is done on the interrupt side when the * No cleanup is done by this interface. It is done on the interrupt side when the
* reply arrives * reply arrives
*
* To Fix: Generate PCI maps of the buffers
*/ */
static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit) static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit)
...@@ -285,15 +306,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, ...@@ -285,15 +306,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
unsigned long mptr; unsigned long mptr;
u64 offset; u64 offset;
struct request *req = ireq->req; struct request *req = ireq->req;
struct bio *bio = req->bio;
int count = req->nr_sectors<<9; int count = req->nr_sectors<<9;
unsigned long last = 0; struct scatterlist *sg;
unsigned short size = 0; int sgnum;
int i;
// printk(KERN_INFO "i2ob_send called\n"); // printk(KERN_INFO "i2ob_send called\n");
/* Map the message to a virtual address */ /* Map the message to a virtual address */
msg = c->mem_offset + m; msg = c->mem_offset + m;
sgnum = i2ob_build_sglist(dev, ireq);
/* FIXME: if we have no resources how should we get out of this */
if(sgnum == 0)
BUG();
/* /*
* Build the message based on the request. * Build the message based on the request.
*/ */
...@@ -313,34 +340,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, ...@@ -313,34 +340,21 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
i2o_raw_writel(offset>>32, msg+28); i2o_raw_writel(offset>>32, msg+28);
mptr=msg+32; mptr=msg+32;
if(req->cmd == READ) sg = ireq->sg_table;
if(rq_data_dir(req) == READ)
{ {
DEBUG("READ\n"); DEBUG("READ\n");
i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4); i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
while(bio!=NULL) for(i = sgnum; i > 0; i--)
{ {
if(bio_to_phys(bio) == last) { if(i != 1)
size += bio->bi_size; i2o_raw_writel(0x10000000|sg_dma_len(sg), mptr);
last += bio->bi_size;
if(bio->bi_next)
i2o_raw_writel(0x10000000|(size), mptr-8);
else
__raw_writel(0xD0000000|(size), mptr-8);
}
else else
{ i2o_raw_writel(0xD0000000|sg_dma_len(sg), mptr);
if(bio->bi_next) i2o_raw_writel(sg_dma_address(sg), mptr+4);
i2o_raw_writel(0x10000000|bio->bi_size, mptr); mptr += 8;
else count -= sg_dma_len(sg);
i2o_raw_writel(0xD0000000|bio->bi_size, mptr); sg++;
i2o_raw_writel(bio_to_phys(bio), mptr+4);
mptr += 8;
size = bio->bi_size;
last = bio_to_phys(bio) + size;
}
count -= bio->bi_size;
bio = bio->bi_next;
} }
switch(dev->rcache) switch(dev->rcache)
{ {
...@@ -359,34 +373,20 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, ...@@ -359,34 +373,20 @@ static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq,
// printk("Reading %d entries %d bytes.\n", // printk("Reading %d entries %d bytes.\n",
// mptr-msg-8, req->nr_sectors<<9); // mptr-msg-8, req->nr_sectors<<9);
} }
else if(req->cmd == WRITE) else if(rq_data_dir(req) == WRITE)
{ {
DEBUG("WRITE\n"); DEBUG("WRITE\n");
i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4); i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
while(bio!=NULL) for(i = sgnum; i > 0; i--)
{ {
if(bio_to_phys(bio) == last) { if(i != 1)
size += bio->bi_size; i2o_raw_writel(0x14000000|sg_dma_len(sg), mptr);
last += bio->bi_size;
if(bio->bi_next)
i2o_raw_writel(0x14000000|(size), mptr-8);
else
i2o_raw_writel(0xD4000000|(size), mptr-8);
}
else else
{ i2o_raw_writel(0xD4000000|sg_dma_len(sg), mptr);
if(bio->bi_next) i2o_raw_writel(sg_dma_address(sg), mptr+4);
i2o_raw_writel(0x14000000|(bio->bi_size), mptr); mptr += 8;
else count -= sg_dma_len(sg);
i2o_raw_writel(0xD4000000|(bio->bi_size), mptr); sg++;
i2o_raw_writel(bio_to_phys(bio), mptr+4);
mptr += 8;
size = bio->bi_size;
last = bio_to_phys(bio) + bio->bi_size;
}
count -= bio->bi_size;
bio = bio->bi_next;
} }
switch(dev->wcache) switch(dev->wcache)
...@@ -502,7 +502,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -502,7 +502,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
/* Now flush the message by making it a NOP */ /* Now flush the message by making it a NOP */
m[0]&=0x00FFFFFF; m[0]&=0x00FFFFFF;
m[0]|=(I2O_CMD_UTIL_NOP)<<24; m[0]|=(I2O_CMD_UTIL_NOP)<<24;
i2o_post_message(c,virt_to_bus(m)); i2o_post_message(c, ((unsigned long)m) - c->mem_offset);
return; return;
} }
...@@ -594,6 +594,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str ...@@ -594,6 +594,7 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
* may be running polled controllers from a BH... * may be running polled controllers from a BH...
*/ */
i2ob_free_sglist(dev, ireq);
spin_lock_irqsave(I2O_LOCK(c->unit), flags); spin_lock_irqsave(I2O_LOCK(c->unit), flags);
i2ob_unhook_request(ireq, c->unit); i2ob_unhook_request(ireq, c->unit);
i2ob_end_request(ireq->req); i2ob_end_request(ireq->req);
...@@ -715,7 +716,6 @@ static int i2ob_evt(void *dummy) ...@@ -715,7 +716,6 @@ static int i2ob_evt(void *dummy)
i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8); i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
spin_lock_irqsave(I2O_LOCK(unit), flags); spin_lock_irqsave(I2O_LOCK(unit), flags);
i2ob_sizes[unit] = (int)(size>>10);
set_capacity(i2ob_disk[unit>>4], size>>9); set_capacity(i2ob_disk[unit>>4], size>>9);
spin_unlock_irqrestore(I2O_LOCK(unit), flags); spin_unlock_irqrestore(I2O_LOCK(unit), flags);
break; break;
...@@ -782,7 +782,6 @@ static void i2ob_request(request_queue_t *q) ...@@ -782,7 +782,6 @@ static void i2ob_request(request_queue_t *q)
{ {
struct request *req; struct request *req;
struct i2ob_request *ireq; struct i2ob_request *ireq;
int unit;
struct i2ob_device *dev; struct i2ob_device *dev;
u32 m; u32 m;
...@@ -796,9 +795,8 @@ static void i2ob_request(request_queue_t *q) ...@@ -796,9 +795,8 @@ static void i2ob_request(request_queue_t *q)
if(req->rq_status == RQ_INACTIVE) if(req->rq_status == RQ_INACTIVE)
return; return;
unit = minor(req->rq_dev); dev = req->rq_disk->private_data;
dev = &i2ob_dev[(unit&0xF0)];
/* /*
* Queue depths probably belong with some kind of * Queue depths probably belong with some kind of
...@@ -828,7 +826,7 @@ static void i2ob_request(request_queue_t *q) ...@@ -828,7 +826,7 @@ static void i2ob_request(request_queue_t *q)
i2ob_queues[dev->unit]->i2ob_qhead = ireq->next; i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
ireq->req = req; ireq->req = req;
i2ob_send(m, dev, ireq, (unit&0xF0)); i2ob_send(m, dev, ireq, (dev->unit&0xF0));
} }
} }
...@@ -896,27 +894,19 @@ static void i2o_block_biosparam( ...@@ -896,27 +894,19 @@ static void i2o_block_biosparam(
static int i2ob_ioctl(struct inode *inode, struct file *file, static int i2ob_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct i2ob_device *dev; struct gendisk *disk = inode->i_bdev->bd_disk;
int minor; struct i2ob_device *dev = disk->private_data;
/* Anyone capable of this syscall can do *real bad* things */ /* Anyone capable of this syscall can do *real bad* things */
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (!inode)
return -EINVAL;
minor = minor(inode->i_rdev);
if (minor >= (MAX_I2OB<<4))
return -ENODEV;
dev = &i2ob_dev[minor];
switch (cmd) { switch (cmd) {
case HDIO_GETGEO: case HDIO_GETGEO:
{ {
struct hd_geometry g; struct hd_geometry g;
int u=minor >> 4; i2o_block_biosparam(get_capacity(disk),
i2o_block_biosparam(get_capacity(i2ob_disk[u]), &g.cylinders, &g.heads, &g.sectors);
&g.cylinders, &g.heads, &g.sectors);
g.start = get_start_sect(inode->i_bdev); g.start = get_start_sect(inode->i_bdev);
return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0; return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0;
} }
...@@ -945,13 +935,8 @@ static int i2ob_ioctl(struct inode *inode, struct file *file, ...@@ -945,13 +935,8 @@ static int i2ob_ioctl(struct inode *inode, struct file *file,
static int i2ob_release(struct inode *inode, struct file *file) static int i2ob_release(struct inode *inode, struct file *file)
{ {
struct i2ob_device *dev; struct gendisk *disk = inode->i_bdev->bd_disk;
int minor; struct i2ob_device *dev = disk->private_data;
minor = minor(inode->i_rdev);
if (minor >= (MAX_I2OB<<4))
return -ENODEV;
dev = &i2ob_dev[(minor&0xF0)];
/* /*
* This is to deail with the case of an application * This is to deail with the case of an application
...@@ -1022,15 +1007,8 @@ static int i2ob_release(struct inode *inode, struct file *file) ...@@ -1022,15 +1007,8 @@ static int i2ob_release(struct inode *inode, struct file *file)
static int i2ob_open(struct inode *inode, struct file *file) static int i2ob_open(struct inode *inode, struct file *file)
{ {
int minor; struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2ob_device *dev; struct i2ob_device *dev = disk->private_data;
if (!inode)
return -EINVAL;
minor = minor(inode->i_rdev);
if (minor >= MAX_I2OB<<4)
return -ENODEV;
dev=&i2ob_dev[(minor&0xF0)];
if(!dev->i2odev) if(!dev->i2odev)
return -ENODEV; return -ENODEV;
...@@ -1133,7 +1111,6 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1133,7 +1111,6 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
power = 0; power = 0;
i2ob_query_device(dev, 0x0000, 5, &flags, 4); i2ob_query_device(dev, 0x0000, 5, &flags, 4);
i2ob_query_device(dev, 0x0000, 6, &status, 4); i2ob_query_device(dev, 0x0000, 6, &status, 4);
i2ob_sizes[unit] = (int)(size>>10);
set_capacity(i2ob_disk[unit>>4], size>>9); set_capacity(i2ob_disk[unit>>4], size>>9);
/* /*
...@@ -1146,14 +1123,18 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i ...@@ -1146,14 +1123,18 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
for(i=unit;i<=unit+15;i++) for(i=unit;i<=unit+15;i++)
{ {
request_queue_t *q = i2ob_dev[unit].req_queue; request_queue_t *q = i2ob_dev[unit].req_queue;
int segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
if(segments > 16)
segments = 16;
i2ob_dev[i].power = power; /* Save power state */ i2ob_dev[i].power = power; /* Save power state */
i2ob_dev[unit].flags = flags; /* Keep the type info */ i2ob_dev[unit].flags = flags; /* Keep the type info */
blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers blk_queue_max_sectors(q, 96); /* 256 might be nicer but many controllers
explode on 65536 or higher */ explode on 65536 or higher */
blk_queue_max_phys_segments(q, (d->controller->status_block->inbound_frame_size - 7) / 2); blk_queue_max_phys_segments(q, segments);
blk_queue_max_hw_segments(q, (d->controller->status_block->inbound_frame_size - 7) / 2); blk_queue_max_hw_segments(q, segments);
i2ob_dev[i].rcache = CACHE_SMARTFETCH; i2ob_dev[i].rcache = CACHE_SMARTFETCH;
i2ob_dev[i].wcache = CACHE_WRITETHROUGH; i2ob_dev[i].wcache = CACHE_WRITETHROUGH;
...@@ -1372,7 +1353,7 @@ static void i2ob_scan(int bios) ...@@ -1372,7 +1353,7 @@ static void i2ob_scan(int bios)
printk(KERN_WARNING "Could not install I2O block device\n"); printk(KERN_WARNING "Could not install I2O block device\n");
else else
{ {
add_disk(i2o_disk[scan_unit>>4]); add_disk(i2ob_disk[scan_unit>>4]);
scan_unit+=16; scan_unit+=16;
i2ob_dev_count++; i2ob_dev_count++;
...@@ -1459,7 +1440,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1459,7 +1440,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
printk(KERN_ERR "i2o_block: Could not install new device\n"); printk(KERN_ERR "i2o_block: Could not install new device\n");
else else
{ {
add_disk(i2o_disk[unit>>4]); add_disk(i2ob_disk[unit>>4]);
i2ob_dev_count++; i2ob_dev_count++;
i2o_device_notify_on(d, &i2o_block_handler); i2o_device_notify_on(d, &i2o_block_handler);
} }
...@@ -1544,7 +1525,8 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d) ...@@ -1544,7 +1525,8 @@ void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
*/ */
static int i2ob_media_change(struct gendisk *disk) static int i2ob_media_change(struct gendisk *disk)
{ {
int i = (int)disk->private_data; struct i2ob_device *p = disk->private_data;
int i = p->index;
if(i2ob_media_change_flag[i]) if(i2ob_media_change_flag[i])
{ {
i2ob_media_change_flag[i]=0; i2ob_media_change_flag[i]=0;
...@@ -1555,9 +1537,8 @@ static int i2ob_media_change(struct gendisk *disk) ...@@ -1555,9 +1537,8 @@ static int i2ob_media_change(struct gendisk *disk)
static int i2ob_revalidate(struct gendisk *disk) static int i2ob_revalidate(struct gendisk *disk)
{ {
int i = (int)disk->private_data; struct i2ob_device *p = disk->private_data;
return i2ob_install_device(i2ob_dev[i<<4].controller, return i2ob_install_device(p->controller, p->i2odev, p->index<<4);
i2ob_dev[i<<4].i2odev, i<<4);
} }
/* /*
...@@ -1640,10 +1621,9 @@ static int i2o_block_init(void) ...@@ -1640,10 +1621,9 @@ static int i2o_block_init(void)
struct gendisk *disk = alloc_disk(16); struct gendisk *disk = alloc_disk(16);
if (!disk) if (!disk)
goto oom; goto oom;
/* to be cleaned up */ i2ob_dev[i<<4].index = i;
disk->private_data = (void*)i;
disk->queue = i2ob_dev[i<<4].req_queue; disk->queue = i2ob_dev[i<<4].req_queue;
i2o_disk[i] = disk; i2ob_disk[i] = disk;
} }
#ifdef MODULE #ifdef MODULE
printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR); printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
...@@ -1662,12 +1642,11 @@ static int i2o_block_init(void) ...@@ -1662,12 +1642,11 @@ static int i2o_block_init(void)
i2ob_dev[i].head = NULL; i2ob_dev[i].head = NULL;
i2ob_dev[i].tail = NULL; i2ob_dev[i].tail = NULL;
i2ob_dev[i].depth = MAX_I2OB_DEPTH; i2ob_dev[i].depth = MAX_I2OB_DEPTH;
i2ob_blksizes[i] = 1024;
i2ob_max_sectors[i] = 2; i2ob_max_sectors[i] = 2;
} }
for (i = 0; i < MAX_I2OB; i++) { for (i = 0; i < MAX_I2OB; i++) {
struct gendisk *disk = i2ob_disk + i; struct gendisk *disk = i2ob_disk[i];
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = i<<4; disk->first_minor = i<<4;
disk->fops = &i2ob_fops; disk->fops = &i2ob_fops;
...@@ -1715,7 +1694,7 @@ static int i2o_block_init(void) ...@@ -1715,7 +1694,7 @@ static int i2o_block_init(void)
oom: oom:
while (i--) while (i--)
put_disk(i2o_disk[i]); put_disk(i2ob_disk[i]);
unregister_blkdev(MAJOR_NR, "i2o_block"); unregister_blkdev(MAJOR_NR, "i2o_block");
return -ENOMEM; return -ENOMEM;
} }
...@@ -1769,7 +1748,7 @@ static void i2o_block_exit(void) ...@@ -1769,7 +1748,7 @@ static void i2o_block_exit(void)
i2o_remove_handler(&i2o_block_handler); i2o_remove_handler(&i2o_block_handler);
for (i = 0; i < MAX_I2OB; i++) for (i = 0; i < MAX_I2OB; i++)
put_disk(i2o_disk[i]); put_disk(i2ob_disk[i]);
/* /*
* Return the block device * Return the block device
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
* Fix the resource management problems. * Fix the resource management problems.
*/ */
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -55,18 +54,22 @@ ...@@ -55,18 +54,22 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/version.h>
#include <linux/i2o.h> #include <linux/i2o.h>
#include "../../scsi/scsi.h" #include "../../scsi/scsi.h"
#include "../../scsi/hosts.h" #include "../../scsi/hosts.h"
#include "../../scsi/sd.h" #include "../../scsi/sd.h"
#include "i2o_scsi.h"
#define VERSION_STRING "Version 0.1.1" #if BITS_PER_LONG == 64
#error FIXME: driver does not support 64-bit platforms
#endif
#define VERSION_STRING "Version 0.1.2"
#define dprintk(x) #define dprintk(x)
#define MAXHOSTS 32 #define I2O_SCSI_CAN_QUEUE 4
#define MAXHOSTS 32
struct i2o_scsi_host struct i2o_scsi_host
{ {
...@@ -320,6 +323,12 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru ...@@ -320,6 +323,12 @@ static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, stru
* It worked maybe ? * It worked maybe ?
*/ */
current_command->result = DID_OK << 16 | ds; 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));
lock = current_command->host->host_lock; lock = current_command->host->host_lock;
spin_lock_irqsave(lock, flags); spin_lock_irqsave(lock, flags);
current_command->scsi_done(current_command); current_command->scsi_done(current_command);
...@@ -453,7 +462,6 @@ static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct ...@@ -453,7 +462,6 @@ static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct
static int i2o_scsi_detect(Scsi_Host_Template * tpnt) static int i2o_scsi_detect(Scsi_Host_Template * tpnt)
{ {
unsigned long flags;
struct Scsi_Host *shpnt = NULL; struct Scsi_Host *shpnt = NULL;
int i; int i;
int count; int count;
...@@ -680,6 +688,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -680,6 +688,7 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
spin_unlock_irqrestore(host->host_lock, flags); spin_unlock_irqrestore(host->host_lock, flags);
return 0; return 0;
} }
i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]); 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 */ i2o_raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */
...@@ -752,10 +761,18 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -752,10 +761,18 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
if(SCpnt->use_sg) if(SCpnt->use_sg)
{ {
struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer; struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
int sg_count;
int chain = 0; int chain = 0;
len = 0; len = 0;
sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
/* FIXME: handle fail */
if(!sg_count)
BUG();
if((sg_max_frags > 11) && (SCpnt->use_sg > 11)) if((sg_max_frags > 11) && (SCpnt->use_sg > 11))
{ {
chain = 1; chain = 1;
...@@ -775,27 +792,27 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -775,27 +792,27 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
sg_chain_tag = 0; sg_chain_tag = 0;
for(i = 0 ; i < SCpnt->use_sg; i++) for(i = 0 ; i < SCpnt->use_sg; i++)
{ {
*mptr++=direction|0x10000000|sg->length; *mptr++=cpu_to_le32(direction|0x10000000|sg_dma_len(sg));
len+=sg->length; len+=sg_dma_len(sg);
*mptr++=virt_to_bus(page_address(sg->page)+sg->offset); *mptr++=cpu_to_le32(sg_dma_address(sg));
sg++; sg++;
} }
mptr[-2]=direction|0xD0000000|(sg-1)->length; mptr[-2]=cpu_to_le32(direction|0xD0000000|sg_dma_len(sg-1));
} }
else else
{ {
for(i = 0 ; i < SCpnt->use_sg; i++) for(i = 0 ; i < SCpnt->use_sg; i++)
{ {
i2o_raw_writel(direction|0x10000000|sg->length, mptr++); i2o_raw_writel(direction|0x10000000|sg_dma_len(sg), mptr++);
len+=sg->length; len+=sg->length;
i2o_raw_writel(virt_to_bus(page_address(sg->page) + sg->offset), mptr++); i2o_raw_writel(sg_dma_address(sg), mptr++);
sg++; sg++;
} }
/* Make this an end of list. Again evade the 920 bug and /* Make this an end of list. Again evade the 920 bug and
unwanted PCI read traffic */ unwanted PCI read traffic */
i2o_raw_writel(direction|0xD0000000|(sg-1)->length, &mptr[-2]); i2o_raw_writel(direction|0xD0000000|sg_dma_len(sg-1), &mptr[-2]);
} }
if(!chain) if(!chain)
...@@ -818,8 +835,16 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) ...@@ -818,8 +835,16 @@ static int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
} }
else else
{ {
dma_addr_t dma_addr;
dma_addr = pci_map_single(c->pdev,
SCpnt->request_buffer,
SCpnt->request_bufflen,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
if(dma_addr == 0)
BUG(); /* How to handle ?? */
SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++); i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
i2o_raw_writel(virt_to_bus(SCpnt->request_buffer), mptr++); i2o_raw_writel(dma_addr, mptr++);
} }
} }
...@@ -1046,6 +1071,24 @@ MODULE_AUTHOR("Red Hat Software"); ...@@ -1046,6 +1071,24 @@ MODULE_AUTHOR("Red Hat Software");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static Scsi_Host_Template driver_template = I2OSCSI; static Scsi_Host_Template driver_template = {
.proc_name = "i2o_scsi",
.name = "I2O SCSI Layer",
.detect = i2o_scsi_detect,
.release = i2o_scsi_release,
.info = i2o_scsi_info,
.command = i2o_scsi_command,
.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,
.sg_tablesize = 8,
.cmd_per_lun = 6,
.use_clustering = ENABLE_CLUSTERING,
};
#include "../../scsi/scsi_module.c" #include "../../scsi/scsi_module.c"
#ifndef _I2O_SCSI_H
#define _I2O_SCSI_H
#include <linux/types.h>
#include <linux/kdev_t.h>
#define I2O_SCSI_ID 15
#define I2O_SCSI_CAN_QUEUE 4
#define I2O_SCSI_CMD_PER_LUN 6
static int i2o_scsi_detect(Scsi_Host_Template *);
static const char *i2o_scsi_info(struct Scsi_Host *);
static int i2o_scsi_command(Scsi_Cmnd *);
static int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int i2o_scsi_abort(Scsi_Cmnd *);
static int i2o_scsi_bus_reset(Scsi_Cmnd *);
static int i2o_scsi_host_reset(Scsi_Cmnd *);
static int i2o_scsi_device_reset(Scsi_Cmnd *);
static int i2o_scsi_bios_param(Disk *, struct block_device *, int *);
static int i2o_scsi_release(struct Scsi_Host *host);
#define I2OSCSI { \
next: NULL, \
proc_name: "i2o_scsi", \
name: "I2O SCSI Layer", \
detect: i2o_scsi_detect, \
release: i2o_scsi_release, \
info: i2o_scsi_info, \
command: i2o_scsi_command, \
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: I2O_SCSI_ID, \
sg_tablesize: 8, \
cmd_per_lun: I2O_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING \
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment