mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.109 (3e677d37B9PCxHLX7a1Iufrz4eSUqA)
Manual merge of SMH + ACH worlds.
This commit is contained in:
commit
796305db16
25 files changed
+1535
-977
No files matched your search
@@ -251,6 +251,7 @@
|
||||
3ddb79be04dyXzyXqDbMRS_1funwXQ xen/drivers/block/blkpg.c
|
||||
3ddb79beME_0abStePF6fU8XLuQnWw xen/drivers/block/elevator.c
|
||||
3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
|
||||
3e677183FxihZVsJDCnvV2S0-FEZyA xen/drivers/block/grok.c
|
||||
3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
|
||||
3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
|
||||
3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
|
||||
@@ -477,6 +478,8 @@
|
||||
3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
|
||||
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
|
||||
3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
|
||||
3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c
|
||||
3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c
|
||||
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
|
||||
3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
|
||||
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/net/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/block/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
|
||||
#ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
|
||||
ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
|
||||
|
||||
HOSTCC = gcc
|
||||
|
||||
@@ -193,6 +193,67 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX SMH: stuff from fs/partitions dumped here temporarily */
|
||||
|
||||
|
||||
/*
|
||||
* This function will re-read the partition tables for a given device,
|
||||
* and set things back up again. There are some important caveats,
|
||||
* however. You must ensure that no one is using the device, and no one
|
||||
* can start using the device while this function is being executed.
|
||||
*
|
||||
* Much of the cleanup from the old partition tables should have already been
|
||||
* done
|
||||
*/
|
||||
void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
|
||||
struct block_device_operations *ops, long size)
|
||||
{
|
||||
if (!gdev)
|
||||
return;
|
||||
grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
|
||||
}
|
||||
|
||||
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
|
||||
{
|
||||
int i;
|
||||
int first_minor = drive << dev->minor_shift;
|
||||
int end_minor = first_minor + dev->max_p;
|
||||
|
||||
if(!dev->sizes)
|
||||
blk_size[dev->major] = NULL;
|
||||
|
||||
dev->part[first_minor].nr_sects = size;
|
||||
#ifdef DEVFS_MUST_DIE
|
||||
/* No such device or no minors to use for partitions */
|
||||
if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
|
||||
devfs_register_partitions (dev, first_minor, 0);
|
||||
#endif
|
||||
|
||||
if (!size || minors == 1)
|
||||
return;
|
||||
|
||||
if (dev->sizes) {
|
||||
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
|
||||
for (i = first_minor + 1; i < end_minor; i++)
|
||||
dev->sizes[i] = 0;
|
||||
}
|
||||
blk_size[dev->major] = dev->sizes;
|
||||
#if 0
|
||||
/* XXX SMH: don't actually check partition details yet */
|
||||
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to set the sizes array before we will be able to access
|
||||
* any of the partitions on this device.
|
||||
*/
|
||||
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
|
||||
for (i = first_minor; i < end_minor; i++)
|
||||
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern int blk_dev_init(void);
|
||||
extern int net_dev_init(void);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
|
||||
{
|
||||
int i;
|
||||
int first_minor = drive << dev->minor_shift;
|
||||
int end_minor = first_minor + dev->max_p;
|
||||
|
||||
if(!dev->sizes)
|
||||
blk_size[dev->major] = NULL;
|
||||
|
||||
dev->part[first_minor].nr_sects = size;
|
||||
#ifdef DEVFS_MUST_DIE
|
||||
/* No such device or no minors to use for partitions */
|
||||
if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
|
||||
devfs_register_partitions (dev, first_minor, 0);
|
||||
#endif
|
||||
|
||||
if (!size || minors == 1)
|
||||
return;
|
||||
|
||||
if (dev->sizes) {
|
||||
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
|
||||
for (i = first_minor + 1; i < end_minor; i++)
|
||||
dev->sizes[i] = 0;
|
||||
}
|
||||
blk_size[dev->major] = dev->sizes;
|
||||
#if 0
|
||||
/* XXX SMH: don't actually check partition details yet */
|
||||
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to set the sizes array before we will be able to access
|
||||
* any of the partitions on this device.
|
||||
*/
|
||||
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
|
||||
for (i = first_minor; i < end_minor; i++)
|
||||
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
|
||||
}
|
||||
}
|
||||
@@ -240,23 +240,23 @@ static void dispatch_debug_block_io(struct task_struct *p, int index)
|
||||
|
||||
static void dispatch_create_segment(struct task_struct *p, int index)
|
||||
{
|
||||
blk_ring_t *blk_ring = p->blk_ring_base;
|
||||
xv_disk_t *xvd;
|
||||
int result;
|
||||
blk_ring_t *blk_ring = p->blk_ring_base;
|
||||
xv_disk_t *xvd;
|
||||
int result;
|
||||
|
||||
if (p->domain != 0)
|
||||
{
|
||||
printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
|
||||
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
|
||||
if (p->domain != 0)
|
||||
{
|
||||
DPRINTK("dispatch_create_segment called by dom%d\n", p->domain);
|
||||
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
|
||||
result = xen_segment_create(xvd);
|
||||
|
||||
make_response(p, blk_ring->ring[index].req.id,
|
||||
XEN_BLOCK_SEG_CREATE, result);
|
||||
return;
|
||||
}
|
||||
|
||||
xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
|
||||
result = xen_segment_create(xvd);
|
||||
|
||||
make_response(p, blk_ring->ring[index].req.id,
|
||||
XEN_BLOCK_SEG_CREATE, result);
|
||||
return;
|
||||
}
|
||||
|
||||
static void dispatch_delete_segment(struct task_struct *p, int index)
|
||||
@@ -268,12 +268,16 @@ static void dispatch_probe_blk(struct task_struct *p, int index)
|
||||
{
|
||||
extern void ide_probe_devices(xen_disk_info_t *xdi, int *count,
|
||||
drive_t xdrives[]);
|
||||
extern void scsi_probe_devices(xen_disk_info_t *xdi, int *count,
|
||||
drive_t xdrives[]);
|
||||
|
||||
blk_ring_t *blk_ring = p->blk_ring_base;
|
||||
xen_disk_info_t *xdi;
|
||||
|
||||
xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
|
||||
|
||||
ide_probe_devices(xdi, &num_xdrives, xdrives);
|
||||
/* scsi_probe_devices(xdi, &num_xdrives, xdrives); */ /* future */
|
||||
scsi_probe_devices(xdi, &num_xdrives, xdrives);
|
||||
|
||||
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, 0);
|
||||
}
|
||||
@@ -371,39 +375,38 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
xen_device = blk_ring->ring[index].req.device;
|
||||
if (IS_XHD_MAJOR(xen_device))
|
||||
{
|
||||
if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
|
||||
else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
|
||||
else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
|
||||
else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
|
||||
else
|
||||
{
|
||||
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
|
||||
xen_device);
|
||||
BUG();
|
||||
}
|
||||
if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
|
||||
else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
|
||||
else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
|
||||
else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
|
||||
else
|
||||
{
|
||||
printk(KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
|
||||
xen_device);
|
||||
BUG();
|
||||
}
|
||||
|
||||
block_number = blk_ring->ring[index].req.block_number;
|
||||
sector_number = blk_ring->ring[index].req.sector_number;
|
||||
block_number = blk_ring->ring[index].req.block_number;
|
||||
sector_number = blk_ring->ring[index].req.sector_number;
|
||||
}
|
||||
else if (IS_VHD_MAJOR(xen_device))
|
||||
{
|
||||
int s;
|
||||
if (s = xen_segment_map_request(&phys_device, &block_number,
|
||||
§or_number,
|
||||
p, operation, xen_device,
|
||||
blk_ring->ring[index].req.block_number,
|
||||
blk_ring->ring[index].req.sector_number))
|
||||
{
|
||||
printk ("dispatch_rw_block_io: xen_segment_map_request status: %d\n",
|
||||
s);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
int s;
|
||||
if (s = xen_segment_map_request(&phys_device, &block_number,
|
||||
§or_number,
|
||||
p, operation, xen_device,
|
||||
blk_ring->ring[index].req.block_number,
|
||||
blk_ring->ring[index].req.sector_number))
|
||||
{
|
||||
DPRINTK("dispatch_rw_block_io: xen_seg_map_request status: %d\n", s);
|
||||
goto bad_descriptor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
|
||||
xen_device);
|
||||
BUG();
|
||||
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
|
||||
xen_device);
|
||||
BUG();
|
||||
}
|
||||
|
||||
bh->b_blocknr = block_number;
|
||||
@@ -433,9 +436,8 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
|
||||
return;
|
||||
|
||||
bad_descriptor:
|
||||
printk (KERN_ALERT "dispatch rw blockio bad descriptor\n");
|
||||
DPRINTK("dispatch rw blockio bad descriptor\n");
|
||||
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -468,23 +470,23 @@ static void make_response(struct task_struct *p, void *id,
|
||||
|
||||
static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct task_struct *p;
|
||||
blk_ring_t *blk_ring ;
|
||||
struct task_struct *p;
|
||||
blk_ring_t *blk_ring ;
|
||||
|
||||
printk("Dumping block queue stats: nr_pending = %d\n",
|
||||
atomic_read(&nr_pending));
|
||||
printk("Dumping block queue stats: nr_pending = %d\n",
|
||||
atomic_read(&nr_pending));
|
||||
|
||||
p = current->next_task;
|
||||
do
|
||||
{
|
||||
printk (KERN_ALERT "Domain: %d\n", p->domain);
|
||||
blk_ring = p->blk_ring_base;
|
||||
p = current->next_task;
|
||||
do
|
||||
{
|
||||
printk (KERN_ALERT "Domain: %d\n", p->domain);
|
||||
blk_ring = p->blk_ring_base;
|
||||
|
||||
printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
|
||||
blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
|
||||
printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
|
||||
blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
|
||||
|
||||
p = p->next_task;
|
||||
} while (p != current);
|
||||
p = p->next_task;
|
||||
} while (p != current);
|
||||
}
|
||||
|
||||
/* Start-of-day initialisation for a new domain. */
|
||||
|
||||
@@ -183,12 +183,6 @@ int unregister_blkdev(unsigned int major, const char * name) { return 0; }
|
||||
int invalidate_device(kdev_t dev, int do_sync) { return 0; }
|
||||
/* fs/buffer.c... */
|
||||
void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { }
|
||||
/* fs/partitions/check.c... */
|
||||
void grok_partitions(struct gendisk *dev, int drive,
|
||||
unsigned minors, long size) { }
|
||||
void register_disk(struct gendisk *dev, kdev_t first,
|
||||
unsigned minors, struct block_device_operations *ops,
|
||||
long size) { }
|
||||
/* fs/devices.c... */
|
||||
const char * kdevname(kdev_t dev) { return NULL; }
|
||||
/* End of XXXXXX region */
|
||||
|
||||
@@ -253,7 +253,6 @@ int aac_get_containers(struct aac_dev *dev)
|
||||
dinfo->count = cpu_to_le32(index);
|
||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||
|
||||
printk("aac_get_container: getting info for container %d\n", index);
|
||||
status = fib_send(ContainerCommand,
|
||||
fibptr,
|
||||
sizeof (struct aac_query_mount),
|
||||
|
||||
@@ -1410,7 +1410,7 @@ unsigned int aac_response_normal(struct aac_queue * q);
|
||||
unsigned int aac_command_normal(struct aac_queue * q);
|
||||
#ifdef TRY_TASKLET
|
||||
extern struct tasklet_struct aac_command_tasklet;
|
||||
int aac_command_thread(unsigned long data);
|
||||
void aac_command_thread(unsigned long data);
|
||||
#else
|
||||
int aac_command_thread(struct aac_dev * dev);
|
||||
#endif
|
||||
|
||||
@@ -325,10 +325,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
||||
}
|
||||
memset(dev->queues, 0, sizeof(struct aac_queue_block));
|
||||
|
||||
printk("aac_init_adapater, dev is %p\n", dev);
|
||||
if (aac_comm_init(dev)<0)
|
||||
return NULL;
|
||||
printk("aac_init_adapater, dev->init is %p\n", dev->init);
|
||||
|
||||
/*
|
||||
* Initialize the list of fibs
|
||||
*/
|
||||
|
||||
@@ -535,12 +535,13 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
||||
* do_softirq() after scheduling the tasklet, as long as we
|
||||
* are _sure_ we hold no locks here...
|
||||
*/
|
||||
printk("about to softirq aac_command_thread...\n");
|
||||
// printk("about to softirq aac_command_thread...\n");
|
||||
while (!fibptr->done) {
|
||||
tasklet_schedule(&aac_command_tasklet);
|
||||
mdelay(100);
|
||||
do_softirq(); /* force execution */
|
||||
// mdelay(100);
|
||||
}
|
||||
printk("back from softirq cmd thread and fibptr->done!\n");
|
||||
// printk("back from softirq cmd thread and fibptr->done!\n");
|
||||
#else
|
||||
printk("about to bail at aac_command_thread...\n");
|
||||
while (!fibptr->done) {
|
||||
@@ -843,11 +844,12 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
|
||||
*/
|
||||
|
||||
#ifndef TRY_TASKLET
|
||||
DECLARE_TASKLET_DISABLED(aac_command_tasklet, aac_command_thread, 0);
|
||||
int aac_command_thread(struct aac_dev * dev)
|
||||
{
|
||||
#else
|
||||
int aac_command_thread(unsigned long data)
|
||||
DECLARE_TASKLET_DISABLED(aac_command_tasklet, aac_command_thread, 0);
|
||||
void aac_command_thread(unsigned long data)
|
||||
#define return(_x) return
|
||||
{
|
||||
struct aac_dev *dev = (struct aac_dev *)data;
|
||||
#endif
|
||||
@@ -863,9 +865,8 @@ int aac_command_thread(unsigned long data)
|
||||
/*
|
||||
* We can only have one thread per adapter for AIF's.
|
||||
*/
|
||||
printk("aac_command_'thread': entered.\n");
|
||||
if (dev->aif_thread)
|
||||
return -EINVAL;
|
||||
return(-EINVAL);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
@@ -888,9 +889,7 @@ int aac_command_thread(unsigned long data)
|
||||
// while(1)
|
||||
{
|
||||
|
||||
printk("aac_command_thread: in 'loop'\n");
|
||||
spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
|
||||
printk("flags = %x\n", flags);
|
||||
while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {
|
||||
struct list_head *entry;
|
||||
struct aac_aifcmd * aifcmd;
|
||||
@@ -905,7 +904,6 @@ int aac_command_thread(unsigned long data)
|
||||
|
||||
spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock,flags);
|
||||
fib = list_entry(entry, struct hw_fib, header.FibLinks);
|
||||
printk("aac_command_thread: got fib \n");
|
||||
/*
|
||||
* We will process the FIB here or pass it to a
|
||||
* worker thread that is TBD. We Really can't
|
||||
@@ -923,7 +921,6 @@ int aac_command_thread(unsigned long data)
|
||||
*/
|
||||
aifcmd = (struct aac_aifcmd *) fib->data;
|
||||
if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) {
|
||||
printk("aac_command_thread: handling aif... :-( \n");
|
||||
aac_handle_aif(dev, &fibptr);
|
||||
} else {
|
||||
/* The u32 here is important and intended. We are using
|
||||
@@ -1024,5 +1021,5 @@ int aac_command_thread(unsigned long data)
|
||||
dev->aif_thread = 0;
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
return(0);
|
||||
}
|
||||
@@ -338,7 +338,6 @@ static int aac_detect(Scsi_Host_Template *template)
|
||||
#endif
|
||||
|
||||
template->present = aac_count; /* # of cards of this type found */
|
||||
printk(KERN_DEBUG "aac_detect: returning %d\n", aac_count);
|
||||
return aac_count;
|
||||
}
|
||||
|
||||
@@ -461,7 +460,7 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
|
||||
struct buffer_head * buf;
|
||||
|
||||
dprintk((KERN_DEBUG "aac_biosparm.\n"));
|
||||
|
||||
|
||||
/*
|
||||
* Assuming extended translation is enabled - #REVISIT#
|
||||
*/
|
||||
@@ -499,7 +498,6 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
|
||||
* table entry whose end_head matches one of the standard geometry
|
||||
* translations ( 64/32, 128/32, 255/63 ).
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55))
|
||||
@@ -560,7 +558,6 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
|
||||
param->heads, param->sectors));
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
brelse(buf);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -311,7 +311,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
|
||||
struct aac_init *init;
|
||||
|
||||
init = dev->init;
|
||||
printk("aac_rx_start: dev is %p, init is %p\n", dev, init);
|
||||
|
||||
init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
|
||||
/*
|
||||
* Tell the adapter we are back and up and running so it will scan
|
||||
|
||||
+468
-480
File diff suppressed because it is too large.
Load diff
+141
-138
@@ -633,18 +633,18 @@ struct scsi_device {
|
||||
* with low level drivers that support multiple outstanding commands.
|
||||
*/
|
||||
typedef struct scsi_pointer {
|
||||
char *ptr; /* data pointer */
|
||||
int this_residual; /* left in this buffer */
|
||||
struct scatterlist *buffer; /* which buffer */
|
||||
int buffers_residual; /* how many buffers left */
|
||||
|
||||
dma_addr_t dma_handle;
|
||||
|
||||
volatile int Status;
|
||||
volatile int Message;
|
||||
volatile int have_data_in;
|
||||
volatile int sent_command;
|
||||
volatile int phase;
|
||||
char *ptr; /* data pointer */
|
||||
int this_residual; /* left in this buffer */
|
||||
struct scatterlist *buffer; /* which buffer */
|
||||
int buffers_residual; /* how many buffers left */
|
||||
|
||||
dma_addr_t dma_handle;
|
||||
|
||||
volatile int Status;
|
||||
volatile int Message;
|
||||
volatile int have_data_in;
|
||||
volatile int sent_command;
|
||||
volatile int phase;
|
||||
} Scsi_Pointer;
|
||||
|
||||
/*
|
||||
@@ -685,146 +685,149 @@ struct scsi_request {
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME(eric) - one of the great regrets that I have is that I failed to define
|
||||
* these structure elements as something like sc_foo instead of foo. This would
|
||||
* make it so much easier to grep through sources and so forth. I propose that
|
||||
* all new elements that get added to these structures follow this convention.
|
||||
* As time goes on and as people have the stomach for it, it should be possible to
|
||||
* go back and retrofit at least some of the elements here with with the prefix.
|
||||
*/
|
||||
* FIXME(eric) - one of the great regrets that I have is that I failed
|
||||
* to define these structure elements as something like sc_foo instead
|
||||
* of foo. This would make it so much easier to grep through sources
|
||||
* and so forth. I propose that all new elements that get added to
|
||||
* these structures follow this convention. As time goes on and as
|
||||
* people have the stomach for it, it should be possible to go back
|
||||
* and retrofit at least some of the elements here with with the
|
||||
* prefix.
|
||||
*/
|
||||
|
||||
struct scsi_cmnd {
|
||||
int sc_magic;
|
||||
int sc_magic;
|
||||
/* private: */
|
||||
/*
|
||||
* This information is private to the scsi mid-layer. Wrapping it in a
|
||||
* struct private is a way of marking it in a sort of C++ type of way.
|
||||
*/
|
||||
struct Scsi_Host *host;
|
||||
unsigned short state;
|
||||
unsigned short owner;
|
||||
Scsi_Device *device;
|
||||
Scsi_Request *sc_request;
|
||||
struct scsi_cmnd *next;
|
||||
struct scsi_cmnd *reset_chain;
|
||||
|
||||
int eh_state; /* Used for state tracking in error handlr */
|
||||
void (*done) (struct scsi_cmnd *); /* Mid-level done function */
|
||||
/*
|
||||
A SCSI Command is assigned a nonzero serial_number when internal_cmnd
|
||||
passes it to the driver's queue command function. The serial_number
|
||||
is cleared when scsi_done is entered indicating that the command has
|
||||
been completed. If a timeout occurs, the serial number at the moment
|
||||
of timeout is copied into serial_number_at_timeout. By subsequently
|
||||
comparing the serial_number and serial_number_at_timeout fields
|
||||
during abort or reset processing, we can detect whether the command
|
||||
has already completed. This also detects cases where the command has
|
||||
completed and the SCSI Command structure has already being reused
|
||||
for another command, so that we can avoid incorrectly aborting or
|
||||
resetting the new command.
|
||||
*/
|
||||
|
||||
unsigned long serial_number;
|
||||
unsigned long serial_number_at_timeout;
|
||||
|
||||
int retries;
|
||||
int allowed;
|
||||
int timeout_per_command;
|
||||
int timeout_total;
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* We handle the timeout differently if it happens when a reset,
|
||||
* abort, etc are in process.
|
||||
*/
|
||||
unsigned volatile char internal_timeout;
|
||||
struct scsi_cmnd *bh_next; /* To enumerate the commands waiting
|
||||
to be processed. */
|
||||
/*
|
||||
* This information is private to the scsi mid-layer. Wrapping it in a
|
||||
* struct private is a way of marking it in a sort of C++ type of way.
|
||||
*/
|
||||
struct Scsi_Host *host;
|
||||
unsigned short state;
|
||||
unsigned short owner;
|
||||
Scsi_Device *device;
|
||||
Scsi_Request *sc_request;
|
||||
struct scsi_cmnd *next;
|
||||
struct scsi_cmnd *reset_chain;
|
||||
|
||||
int eh_state; /* Used for state tracking in error handlr */
|
||||
void (*done) (struct scsi_cmnd *); /* Mid-level done function */
|
||||
/*
|
||||
A SCSI Command is assigned a nonzero serial_number when internal_cmnd
|
||||
passes it to the driver's queue command function. The serial_number
|
||||
is cleared when scsi_done is entered indicating that the command has
|
||||
been completed. If a timeout occurs, the serial number at the moment
|
||||
of timeout is copied into serial_number_at_timeout. By subsequently
|
||||
comparing the serial_number and serial_number_at_timeout fields
|
||||
during abort or reset processing, we can detect whether the command
|
||||
has already completed. This also detects cases where the command has
|
||||
completed and the SCSI Command structure has already being reused
|
||||
for another command, so that we can avoid incorrectly aborting or
|
||||
resetting the new command.
|
||||
*/
|
||||
|
||||
unsigned long serial_number;
|
||||
unsigned long serial_number_at_timeout;
|
||||
|
||||
int retries;
|
||||
int allowed;
|
||||
int timeout_per_command;
|
||||
int timeout_total;
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* We handle the timeout differently if it happens when a reset,
|
||||
* abort, etc are in process.
|
||||
*/
|
||||
unsigned volatile char internal_timeout;
|
||||
struct scsi_cmnd *bh_next; /* To enumerate the commands waiting
|
||||
to be processed. */
|
||||
|
||||
/* public: */
|
||||
|
||||
unsigned int target;
|
||||
unsigned int lun;
|
||||
unsigned int channel;
|
||||
unsigned char cmd_len;
|
||||
unsigned char old_cmd_len;
|
||||
unsigned char sc_data_direction;
|
||||
unsigned char sc_old_data_direction;
|
||||
|
||||
/* These elements define the operation we are about to perform */
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned request_bufflen; /* Actual request size */
|
||||
|
||||
struct timer_list eh_timeout; /* Used to time out the command. */
|
||||
void *request_buffer; /* Actual requested buffer */
|
||||
void **bounce_buffers; /* Array of bounce buffers when using scatter-gather */
|
||||
|
||||
/* These elements define the operation we ultimately want to perform */
|
||||
unsigned char data_cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned short old_use_sg; /* We save use_sg here when requesting
|
||||
* sense info */
|
||||
unsigned short use_sg; /* Number of pieces of scatter-gather */
|
||||
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
|
||||
unsigned short abort_reason; /* If the mid-level code requests an
|
||||
|
||||
unsigned int target;
|
||||
unsigned int lun;
|
||||
unsigned int channel;
|
||||
unsigned char cmd_len;
|
||||
unsigned char old_cmd_len;
|
||||
unsigned char sc_data_direction;
|
||||
unsigned char sc_old_data_direction;
|
||||
|
||||
/* These elements define the operation we are about to perform */
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned request_bufflen; /* Actual request size */
|
||||
|
||||
struct timer_list eh_timeout; /* Used to time out the command. */
|
||||
void *request_buffer; /* Actual requested buffer */
|
||||
void **bounce_buffers; /* Array of bounce buffers when
|
||||
using scatter-gather */
|
||||
|
||||
/* These elements define the operation we ultimately want to perform */
|
||||
unsigned char data_cmnd[MAX_COMMAND_SIZE];
|
||||
unsigned short old_use_sg; /* We save use_sg here when requesting
|
||||
* sense info */
|
||||
unsigned short use_sg; /* Number of pieces of scatter-gather */
|
||||
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
|
||||
unsigned short abort_reason; /* If the mid-level code requests an
|
||||
* abort, this is the reason. */
|
||||
unsigned bufflen; /* Size of data buffer */
|
||||
void *buffer; /* Data buffer */
|
||||
|
||||
unsigned underflow; /* Return error if less than
|
||||
this amount is transferred */
|
||||
unsigned old_underflow; /* save underflow here when reusing the
|
||||
unsigned bufflen; /* Size of data buffer */
|
||||
void *buffer; /* Data buffer */
|
||||
|
||||
unsigned underflow; /* Return error if less than
|
||||
this amount is transferred */
|
||||
unsigned old_underflow; /* save underflow here when reusing the
|
||||
* command for error handling */
|
||||
|
||||
unsigned transfersize; /* How much we are guaranteed to
|
||||
|
||||
unsigned transfersize; /* How much we are guaranteed to
|
||||
transfer with each SCSI transfer
|
||||
(ie, between disconnect /
|
||||
reconnects. Probably == sector
|
||||
size */
|
||||
|
||||
int resid; /* Number of bytes requested to be
|
||||
transferred less actual number
|
||||
transferred (0 if not supported) */
|
||||
|
||||
struct request request; /* A copy of the command we are
|
||||
|
||||
int resid; /* Number of bytes requested to be
|
||||
transferred less actual number
|
||||
transferred (0 if not supported) */
|
||||
|
||||
struct request request; /* A copy of the command we are
|
||||
working on */
|
||||
|
||||
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
|
||||
/* obtained by REQUEST SENSE when CHECK CONDITION is
|
||||
* received on original command (auto-sense) */
|
||||
|
||||
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE
|
||||
* when CHECK CONDITION is
|
||||
* received on original command
|
||||
* (auto-sense) */
|
||||
unsigned flags;
|
||||
|
||||
/*
|
||||
* Used to indicate that a command which has timed out also
|
||||
* completed normally. Typically the completion function will
|
||||
* do nothing but set this flag in this instance because the
|
||||
* timeout handler is already running.
|
||||
*/
|
||||
unsigned done_late:1;
|
||||
|
||||
/* Low-level done function - can be used by low-level driver to point
|
||||
* to completion function. Not used by mid/upper level code. */
|
||||
void (*scsi_done) (struct scsi_cmnd *);
|
||||
|
||||
/*
|
||||
* The following fields can be written to by the host specific code.
|
||||
* Everything else should be left alone.
|
||||
*/
|
||||
|
||||
Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
|
||||
|
||||
unsigned char *host_scribble;
|
||||
|
||||
unsigned flags;
|
||||
/* The host adapter is allowed to call scsi_malloc and get some
|
||||
* memory and hang it here. The host adapter is also expected to
|
||||
* call scsi_free to release this memory. (The memory obtained
|
||||
* by scsi_malloc is guaranteed to be at an address < 16Mb). */
|
||||
|
||||
/*
|
||||
* Used to indicate that a command which has timed out also
|
||||
* completed normally. Typically the completion function will
|
||||
* do nothing but set this flag in this instance because the
|
||||
* timeout handler is already running.
|
||||
*/
|
||||
unsigned done_late:1;
|
||||
|
||||
/* Low-level done function - can be used by low-level driver to point
|
||||
* to completion function. Not used by mid/upper level code. */
|
||||
void (*scsi_done) (struct scsi_cmnd *);
|
||||
|
||||
/*
|
||||
* The following fields can be written to by the host specific code.
|
||||
* Everything else should be left alone.
|
||||
*/
|
||||
|
||||
Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
|
||||
|
||||
unsigned char *host_scribble; /* The host adapter is allowed to
|
||||
* call scsi_malloc and get some memory
|
||||
* and hang it here. The host adapter
|
||||
* is also expected to call scsi_free
|
||||
* to release this memory. (The memory
|
||||
* obtained by scsi_malloc is guaranteed
|
||||
* to be at an address < 16Mb). */
|
||||
|
||||
int result; /* Status code from lower level driver */
|
||||
|
||||
unsigned char tag; /* SCSI-II queued command tag */
|
||||
unsigned long pid; /* Process ID, starts at 0 */
|
||||
|
||||
int result; /* Status code from lower level driver */
|
||||
|
||||
unsigned char tag; /* SCSI-II queued command tag */
|
||||
unsigned long pid; /* Process ID, starts at 0 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1914,9 +1914,9 @@ void scsi_error_handler(void *data)
|
||||
/*
|
||||
* Wake up the thread that created us.
|
||||
*/
|
||||
#if 0
|
||||
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent %d\n", host->eh_notify->count.counter));
|
||||
|
||||
#if 0
|
||||
up(host->eh_notify);
|
||||
#endif
|
||||
|
||||
|
||||
+91
-82
@@ -73,7 +73,7 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
|
||||
unsigned long flags;
|
||||
|
||||
ASSERT_LOCK(&io_request_lock, 0);
|
||||
|
||||
|
||||
rq->cmd = SPECIAL;
|
||||
rq->special = data;
|
||||
rq->q = NULL;
|
||||
@@ -362,92 +362,98 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
|
||||
int requeue,
|
||||
int frequeue)
|
||||
{
|
||||
struct request *req;
|
||||
struct buffer_head *bh;
|
||||
Scsi_Device * SDpnt;
|
||||
int nsect;
|
||||
|
||||
ASSERT_LOCK(&io_request_lock, 0);
|
||||
|
||||
req = &SCpnt->request;
|
||||
req->errors = 0;
|
||||
if (!uptodate) {
|
||||
printk(" I/O error: dev %s, sector %lu\n",
|
||||
kdevname(req->rq_dev), req->sector);
|
||||
}
|
||||
do {
|
||||
if ((bh = req->bh) != NULL) {
|
||||
nsect = bh->b_size >> 9;
|
||||
blk_finished_io(nsect);
|
||||
req->bh = bh->b_reqnext;
|
||||
bh->b_reqnext = NULL;
|
||||
sectors -= nsect;
|
||||
bh->b_end_io(bh, uptodate);
|
||||
if ((bh = req->bh) != NULL) {
|
||||
req->hard_sector += nsect;
|
||||
req->hard_nr_sectors -= nsect;
|
||||
req->sector += nsect;
|
||||
req->nr_sectors -= nsect;
|
||||
|
||||
req->current_nr_sectors = bh->b_size >> 9;
|
||||
if (req->nr_sectors < req->current_nr_sectors) {
|
||||
req->nr_sectors = req->current_nr_sectors;
|
||||
printk("scsi_end_request: buffer-list destroyed\n");
|
||||
}
|
||||
}
|
||||
struct request *req;
|
||||
struct buffer_head *bh;
|
||||
Scsi_Device * SDpnt;
|
||||
int nsect;
|
||||
|
||||
ASSERT_LOCK(&io_request_lock, 0);
|
||||
|
||||
req = &SCpnt->request;
|
||||
req->errors = 0;
|
||||
if (!uptodate) {
|
||||
printk(" I/O error: dev %s, sector %lu\n",
|
||||
kdevname(req->rq_dev), req->sector);
|
||||
}
|
||||
do {
|
||||
if ((bh = req->bh) != NULL) {
|
||||
nsect = bh->b_size >> 9;
|
||||
blk_finished_io(nsect);
|
||||
req->bh = bh->b_reqnext;
|
||||
bh->b_reqnext = NULL;
|
||||
sectors -= nsect;
|
||||
bh->b_end_io(bh, uptodate);
|
||||
if ((bh = req->bh) != NULL) {
|
||||
req->hard_sector += nsect;
|
||||
req->hard_nr_sectors -= nsect;
|
||||
req->sector += nsect;
|
||||
req->nr_sectors -= nsect;
|
||||
|
||||
req->current_nr_sectors = bh->b_size >> 9;
|
||||
if (req->nr_sectors < req->current_nr_sectors) {
|
||||
req->nr_sectors = req->current_nr_sectors;
|
||||
printk("scsi_end_request: buffer-list destroyed\n");
|
||||
}
|
||||
} while (sectors && bh);
|
||||
|
||||
}
|
||||
}
|
||||
} while (sectors && bh);
|
||||
|
||||
/*
|
||||
* If there are blocks left over at the end, set up the command
|
||||
* to queue the remainder of them.
|
||||
*/
|
||||
if (req->bh) {
|
||||
request_queue_t *q;
|
||||
|
||||
if( !requeue )
|
||||
{
|
||||
return SCpnt;
|
||||
}
|
||||
|
||||
q = &SCpnt->device->request_queue;
|
||||
|
||||
req->buffer = bh->b_data;
|
||||
/*
|
||||
* If there are blocks left over at the end, set up the command
|
||||
* to queue the remainder of them.
|
||||
* Bleah. Leftovers again. Stick the leftovers in
|
||||
* the front of the queue, and goose the queue again.
|
||||
*/
|
||||
if (req->bh) {
|
||||
request_queue_t *q;
|
||||
|
||||
if( !requeue )
|
||||
{
|
||||
return SCpnt;
|
||||
}
|
||||
|
||||
q = &SCpnt->device->request_queue;
|
||||
|
||||
req->buffer = bh->b_data;
|
||||
/*
|
||||
* Bleah. Leftovers again. Stick the leftovers in
|
||||
* the front of the queue, and goose the queue again.
|
||||
*/
|
||||
scsi_queue_next_request(q, SCpnt);
|
||||
return SCpnt;
|
||||
}
|
||||
scsi_queue_next_request(q, SCpnt);
|
||||
return SCpnt;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* This request is done. If there is someone blocked waiting for this
|
||||
* request, wake them up. Typically used to wake up processes trying
|
||||
* to swap a page into memory.
|
||||
*/
|
||||
if (req->waiting != NULL) {
|
||||
complete(req->waiting);
|
||||
}
|
||||
/*
|
||||
* This request is done. If there is someone blocked waiting for this
|
||||
* request, wake them up. Typically used to wake up processes trying
|
||||
* to swap a page into memory.
|
||||
*/
|
||||
if (req->waiting != NULL) {
|
||||
complete(req->waiting);
|
||||
}
|
||||
#else
|
||||
/* XXX SMH: we're done -- flip the flag for the spinner :-| */
|
||||
if(req->waiting && (*(int *)(req->waiting) != NULL)) {
|
||||
printk("__scsi_end_request: flipping wait status on req %p\n", req);
|
||||
*(int *)(req->waiting) = NULL;
|
||||
} // else printk("__scsi_end_request: no-one to notify!!\n");
|
||||
#endif
|
||||
req_finished_io(req);
|
||||
add_blkdev_randomness(MAJOR(req->rq_dev));
|
||||
|
||||
SDpnt = SCpnt->device;
|
||||
|
||||
/*
|
||||
* This will goose the queue request function at the end, so we don't
|
||||
* need to worry about launching another command.
|
||||
*/
|
||||
__scsi_release_command(SCpnt);
|
||||
|
||||
if( frequeue ) {
|
||||
request_queue_t *q;
|
||||
|
||||
q = &SDpnt->request_queue;
|
||||
scsi_queue_next_request(q, NULL);
|
||||
}
|
||||
return NULL;
|
||||
req_finished_io(req);
|
||||
add_blkdev_randomness(MAJOR(req->rq_dev));
|
||||
|
||||
SDpnt = SCpnt->device;
|
||||
|
||||
/*
|
||||
* This will goose the queue request function at the end, so we don't
|
||||
* need to worry about launching another command.
|
||||
*/
|
||||
__scsi_release_command(SCpnt);
|
||||
|
||||
if( frequeue ) {
|
||||
request_queue_t *q;
|
||||
|
||||
q = &SDpnt->request_queue;
|
||||
scsi_queue_next_request(q, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -554,6 +560,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
|
||||
int this_count = SCpnt->bufflen >> 9;
|
||||
request_queue_t *q = &SCpnt->device->request_queue;
|
||||
|
||||
// printk("scsi_io_completion entered.\n");
|
||||
/*
|
||||
* We must do one of several things here:
|
||||
*
|
||||
@@ -1053,6 +1060,7 @@ void scsi_request_fn(request_queue_t * q)
|
||||
* get those allocated here.
|
||||
*/
|
||||
if (!SDpnt->scsi_init_io_fn(SCpnt)) {
|
||||
printk("scsi_request_fn: scsi_init_io_fn failed :-(\n");
|
||||
SCpnt = __scsi_end_request(SCpnt, 0,
|
||||
SCpnt->request.nr_sectors, 0, 0);
|
||||
if( SCpnt != NULL )
|
||||
@@ -1068,6 +1076,7 @@ void scsi_request_fn(request_queue_t * q)
|
||||
* Initialize the actual SCSI command for this request.
|
||||
*/
|
||||
if (!STpnt->init_command(SCpnt)) {
|
||||
printk("scsi_request_fn: init_command failed :-(\n");
|
||||
scsi_release_buffers(SCpnt);
|
||||
SCpnt = __scsi_end_request(SCpnt, 0,
|
||||
SCpnt->request.nr_sectors, 0, 0);
|
||||
|
||||
@@ -802,6 +802,7 @@ __inline static int __init_io(Scsi_Cmnd * SCpnt,
|
||||
int this_count;
|
||||
void ** bbpnt;
|
||||
|
||||
// printk("scsi_merge.c: __init_io entered\n");
|
||||
/*
|
||||
* FIXME(eric) - don't inline this - it doesn't depend on the
|
||||
* integer flags. Come to think of it, I don't think this is even
|
||||
|
||||
+71
-2
@@ -61,6 +61,8 @@
|
||||
|
||||
#include <xeno/genhd.h>
|
||||
|
||||
#include <asm/domain_page.h> /* SMH: for [un_]map_domain_mem() */
|
||||
|
||||
/*
|
||||
* static const char RCSid[] = "$Header:";
|
||||
*/
|
||||
@@ -324,6 +326,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
|
||||
!dpnt->device ||
|
||||
!dpnt->device->online ||
|
||||
block + SCpnt->request.nr_sectors > ppnt->nr_sects) {
|
||||
|
||||
SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
|
||||
SCpnt->request.nr_sectors));
|
||||
SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
|
||||
@@ -1132,8 +1135,8 @@ static int sd_init()
|
||||
sd_registered++;
|
||||
}
|
||||
/* We do not support attaching loadable devices yet. */
|
||||
if (rscsi_disks)
|
||||
return 0;
|
||||
if (rscsi_disks)
|
||||
return 0;
|
||||
|
||||
rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
|
||||
if (!rscsi_disks)
|
||||
@@ -1296,9 +1299,73 @@ static void sd_finish()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* XXX SMH: turn on some logging */
|
||||
scsi_logging_level = ~0;
|
||||
SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, 1);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XXX SMH: gross 'probe' function to allow xeno world to grope us;
|
||||
** this should really not be in the disk-specific code as it should
|
||||
** report tapes, CDs, etc. But for now this looks like the easiest
|
||||
** place to hook it in :-(
|
||||
*/
|
||||
void scsi_probe_devices(xen_disk_info_t *xdi)
|
||||
{
|
||||
Scsi_Disk *sd;
|
||||
int i, base, diskinfo[4];
|
||||
xen_disk_info_t *xen_xdi =
|
||||
(xen_disk_info_t *)map_domain_mem(virt_to_phys(xdi));
|
||||
|
||||
/* We've already had IDE probe => we need to append our info */
|
||||
base = xen_xdi->count;
|
||||
|
||||
for (sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++) {
|
||||
|
||||
if (sd->device !=NULL) {
|
||||
|
||||
xen_xdi->disks[xen_xdi->count].type = XEN_DISK_SCSI;
|
||||
xen_xdi->disks[xen_xdi->count].capacity = sd->capacity;
|
||||
xen_xdi->count++;
|
||||
|
||||
/* default bios params to most commonly used values */
|
||||
diskinfo[0] = 0x40;
|
||||
diskinfo[1] = 0x20;
|
||||
diskinfo[2] = (sd->capacity) >> 11;
|
||||
|
||||
/* override with calculated, extended default,
|
||||
or driver values */
|
||||
/* XXX SMH: gross in-line literal major number. XXX FIXME. */
|
||||
if(sd->device->host->hostt->bios_param != NULL)
|
||||
sd->device->host->hostt->bios_param(
|
||||
sd, MKDEV(SCSI_DISK0_MAJOR, 0), &diskinfo[0]);
|
||||
else scsicam_bios_param(sd, MKDEV(SCSI_DISK0_MAJOR, 0),
|
||||
&diskinfo[0]);
|
||||
|
||||
|
||||
printk (KERN_ALERT "SCSI-XENO %d\n", xen_xdi->count - base);
|
||||
printk (KERN_ALERT " capacity 0x%x\n", sd->capacity);
|
||||
printk (KERN_ALERT " head 0x%x\n", diskinfo[0]);
|
||||
printk (KERN_ALERT " sector 0x%x\n", diskinfo[1]);
|
||||
printk (KERN_ALERT " cylinder 0x%x\n", diskinfo[2]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
unmap_domain_mem(xen_xdi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int sd_detect(Scsi_Device * SDp)
|
||||
{
|
||||
if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD)
|
||||
@@ -1463,6 +1530,8 @@ static void sd_detach(Scsi_Device * SDp)
|
||||
|
||||
static int __init init_sd(void)
|
||||
{
|
||||
extern int scsi_register_module(int, void *);
|
||||
|
||||
sd_template.module = THIS_MODULE;
|
||||
return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define CONFIG_BLK_DEV_PIIX 1
|
||||
|
||||
#define CONFIG_SCSI 1
|
||||
#define CONFIG_SCSI_LOGGING 1
|
||||
#define CONFIG_BLK_DEV_SD 1
|
||||
#define CONFIG_SD_EXTRA_DEVS 40
|
||||
#define CONFIG_SCSI_MULTI_LUN 1
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
O_TARGET := blk.o
|
||||
obj-y := xl_block.o xl_segment.o xl_segment_proc.o xl_block_test.o
|
||||
obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o
|
||||
obj-y += xl_segment_proc.o xl_block_test.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -1,7 +1,7 @@
|
||||
/******************************************************************************
|
||||
* xl_block.c
|
||||
*
|
||||
* Xenolinux virtual block-device driver (xhd).
|
||||
* Xenolinux virtual block-device driver.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -25,22 +25,23 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define MAJOR_NR XLBLK_MAJOR /* force defns in blk.h, must precede include */
|
||||
static int xlblk_major = XLBLK_MAJOR;
|
||||
#include <linux/blk.h>
|
||||
|
||||
/* Copied from linux/ide.h */
|
||||
typedef unsigned char byte;
|
||||
|
||||
#define XLBLK_MAX 32 /* Maximum minor devices we support */
|
||||
#define XLBLK_MAJOR_NAME "xhd"
|
||||
#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
|
||||
#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1) /* from ide.h::PARTN_MASK */
|
||||
static int xlblk_blk_size[XLBLK_MAX];
|
||||
static int xlblk_blksize_size[XLBLK_MAX];
|
||||
static int xlblk_read_ahead;
|
||||
static int xlblk_hardsect_size[XLBLK_MAX];
|
||||
static int xlblk_max_sectors[XLBLK_MAX];
|
||||
extern int xlide_init(int xidx, int idx);
|
||||
extern int xlide_hwsect(int minor);
|
||||
extern void xlide_cleanup(void);
|
||||
extern int xlscsi_init(int xidx, int idx);
|
||||
extern int xlscsi_hwsect(int minor);
|
||||
extern void xlscsi_cleanup(void);
|
||||
|
||||
static int nide = 0; // number of IDE devices we have
|
||||
static int nscsi = 0; // number of SCSI devices we have
|
||||
|
||||
|
||||
#define XLBLK_MAX 32 /* XXX SMH: this the max of XLIDE_MAX and XLSCSI_MAX */
|
||||
|
||||
#define XLBLK_RESPONSE_IRQ _EVENT_BLK_RESP
|
||||
|
||||
@@ -56,6 +57,7 @@ static int xlblk_max_sectors[XLBLK_MAX];
|
||||
|
||||
static blk_ring_t *blk_ring;
|
||||
static unsigned int resp_cons; /* Response consumer for comms ring. */
|
||||
|
||||
static xen_disk_info_t xlblk_disk_info;
|
||||
atomic_t xlblk_control_count;
|
||||
|
||||
@@ -69,54 +71,139 @@ int hypervisor_request(void * id,
|
||||
kdev_t device,
|
||||
struct gendisk *gd);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int xenolinux_block_open(struct inode *inode, struct file *filep)
|
||||
/* Convert from a XenoLinux (major,minor) to the Xen-level 'physical' device */
|
||||
static kdev_t xldev_to_physdev(kdev_t xldev)
|
||||
{
|
||||
int xlmajor = MAJOR(xldev);
|
||||
int major, minor;
|
||||
|
||||
switch(xlmajor) {
|
||||
case XLIDE_MAJOR:
|
||||
major = IDE0_MAJOR;
|
||||
minor = 0; /* we do minor offsetting manually by addition */
|
||||
break;
|
||||
|
||||
case XLSCSI_MAJOR:
|
||||
major = SCSI_DISK0_MAJOR;
|
||||
minor = 0; /* we do minor offsetting manually by addition */
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("xldev_to_physdev: unhandled major %d\n", xlmajor);
|
||||
break;
|
||||
}
|
||||
|
||||
return MKDEV(major, minor);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Locate the gendisk structure associated with a particular xenolinux disk;
|
||||
** this requires a scan of the xen_disk_info[] array currently which kind of
|
||||
** sucks. However we can clean this whole area up later (i.e. post SOSP).
|
||||
*/
|
||||
struct gendisk *xldev_to_gendisk(kdev_t xldev, int *t)
|
||||
{
|
||||
int i, j, posn, type;
|
||||
|
||||
switch(MAJOR(xldev)) {
|
||||
|
||||
case XLIDE_MAJOR:
|
||||
type = 1;
|
||||
posn = 1;
|
||||
break;
|
||||
|
||||
case XLSCSI_MAJOR:
|
||||
type = 2;
|
||||
posn = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("xldev_to_gendisk: unhandled major %d\n", MAJOR(xldev));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for ( i = j = 0; i < xen_disk_info.count; i++ ) {
|
||||
if(xen_disk_info.disks[i].type == type)
|
||||
if(++j == posn)
|
||||
break;
|
||||
}
|
||||
|
||||
if(t)
|
||||
*t = type;
|
||||
|
||||
return (xen_disk_info.disks[i].gendisk);
|
||||
}
|
||||
|
||||
int xenolinux_block_open(struct inode *inode, struct file *filep)
|
||||
{
|
||||
DPRINTK("xenolinux_block_open\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenolinux_block_release(struct inode *inode, struct file *filep)
|
||||
int xenolinux_block_release(struct inode *inode, struct file *filep)
|
||||
{
|
||||
DPRINTK("xenolinux_block_release\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
|
||||
|
||||
int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
unsigned command, unsigned long argument)
|
||||
{
|
||||
int minor_dev;
|
||||
int minor_dev, type;
|
||||
struct hd_geometry *geo = (struct hd_geometry *)argument;
|
||||
|
||||
struct gendisk *gd;
|
||||
struct hd_struct *part;
|
||||
|
||||
DPRINTK("xenolinux_block_ioctl\n");
|
||||
|
||||
/* check permissions */
|
||||
if (!capable(CAP_SYS_ADMIN)) return -EPERM;
|
||||
if (!inode) return -EINVAL;
|
||||
|
||||
minor_dev = MINOR(inode->i_rdev);
|
||||
if (minor_dev >= XLBLK_MAX) return -ENODEV;
|
||||
|
||||
DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
|
||||
command, (long) argument, minor_dev);
|
||||
|
||||
gd = xldev_to_gendisk(inode->i_rdev, &type);
|
||||
part = &gd->part[minor_dev];
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case BLKGETSIZE: /* get size */
|
||||
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE,
|
||||
(long) xlblk_disk_info.disks[0].capacity);
|
||||
return put_user(xlblk_disk_info.disks[0].capacity,
|
||||
(unsigned long *) argument);
|
||||
case BLKGETSIZE:
|
||||
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
|
||||
return put_user(part->nr_sects, (unsigned long *) argument);
|
||||
|
||||
case BLKRRPART: /* re-read partition table */
|
||||
DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
|
||||
break;
|
||||
|
||||
case BLKBSZGET: /* get block size */
|
||||
DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET);
|
||||
break;
|
||||
case BLKSSZGET:
|
||||
switch(type) {
|
||||
case 1:
|
||||
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
|
||||
xlide_hwsect(minor_dev));
|
||||
return xlide_hwsect(minor_dev);
|
||||
break;
|
||||
case 2:
|
||||
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
|
||||
xlscsi_hwsect(minor_dev));
|
||||
return xlscsi_hwsect(minor_dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("BLKSSZGET ioctl() on bogus type %d disk!\n", type);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
case BLKBSZSET: /* set block size */
|
||||
DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
|
||||
@@ -163,13 +250,13 @@ static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenolinux_block_check(kdev_t dev)
|
||||
int xenolinux_block_check(kdev_t dev)
|
||||
{
|
||||
DPRINTK("xenolinux_block_check\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xenolinux_block_revalidate(kdev_t dev)
|
||||
int xenolinux_block_revalidate(kdev_t dev)
|
||||
{
|
||||
DPRINTK("xenolinux_block_revalidate\n");
|
||||
return 0;
|
||||
@@ -224,30 +311,13 @@ int hypervisor_request(void * id,
|
||||
|
||||
case XEN_BLOCK_READ:
|
||||
case XEN_BLOCK_WRITE:
|
||||
/* only accept requests for xhd and vhd devices */
|
||||
if (!IS_XHD_MAJOR(MAJOR(device)) && !IS_VHD_MAJOR(MAJOR(device)))
|
||||
panic("error: xl_block::hypervisor_request: "
|
||||
"unknown device [0x%x]\n", device);
|
||||
phys_device = MAJOR(device);
|
||||
|
||||
/* Compute real buffer location on disk.
|
||||
* note: gd will be null when we read the partition table.
|
||||
*/
|
||||
phys_device = xldev_to_physdev(device);
|
||||
if (!IS_XHD_MAJOR(MAJOR(device)))
|
||||
phys_device = MAJOR(device);
|
||||
/* Compute real buffer location on disk */
|
||||
sector_number = block_number;
|
||||
if ( gd != NULL )
|
||||
{
|
||||
sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
|
||||
}
|
||||
|
||||
/*
|
||||
if (IS_VHD_MAJOR(MAJOR(device)))
|
||||
{
|
||||
printk (KERN_ALERT "%lx + %lx = %lx (%x)\n",
|
||||
block_number,
|
||||
gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect,
|
||||
sector_number, device);
|
||||
}
|
||||
*/
|
||||
gd = xldev_to_gendisk(device, NULL);
|
||||
sector_number += gd->part[MINOR(device)].start_sect;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -274,7 +344,7 @@ int hypervisor_request(void * id,
|
||||
* do_xlblk_request
|
||||
* read a block; request is in a request queue
|
||||
*/
|
||||
static void do_xlblk_request (request_queue_t *rq)
|
||||
void do_xlblk_request (request_queue_t *rq)
|
||||
{
|
||||
struct request *req;
|
||||
struct buffer_head *bh;
|
||||
@@ -282,9 +352,10 @@ static void do_xlblk_request (request_queue_t *rq)
|
||||
|
||||
DPRINTK("xlblk.c::do_xlblk_request for '%s'\n", DEVICE_NAME);
|
||||
|
||||
while ( !rq->plugged && !QUEUE_EMPTY )
|
||||
while ( !rq->plugged && !list_empty(&rq->queue_head))
|
||||
{
|
||||
if ( (req = CURRENT) == NULL ) goto out;
|
||||
if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL )
|
||||
goto out;
|
||||
|
||||
DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
|
||||
req, req->cmd, req->sector,
|
||||
@@ -351,7 +422,7 @@ static struct block_device_operations xenolinux_block_fops =
|
||||
|
||||
static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct buffer_head *bh;
|
||||
|
||||
@@ -383,10 +454,18 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
resp_cons = i;
|
||||
|
||||
/* KAF: We can push work down at this point. We have the lock. */
|
||||
/* aho: okay, so this is a bit of a hack. we'll kick every queue... */
|
||||
do_xlblk_request(BLK_DEFAULT_QUEUE(XLBLK_MAJOR));
|
||||
do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
|
||||
|
||||
for (i = 0; i < xen_disk_info.count; i++) {
|
||||
/*
|
||||
** XXX SMH: this is pretty broken ...
|
||||
** a) should really only kick devs w/ outstanding work
|
||||
** b) should cover /all/ devs, not just first IDE & SCSI
|
||||
** KAF will fix this I'm sure.
|
||||
*/
|
||||
do_xlblk_request(BLK_DEFAULT_QUEUE(IDE0_MAJOR));
|
||||
do_xlblk_request(BLK_DEFAULT_QUEUE(SCSI_DISK0_MAJOR));
|
||||
do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&io_request_lock, flags);
|
||||
}
|
||||
|
||||
@@ -419,143 +498,54 @@ int __init xlblk_init(void)
|
||||
BUG();
|
||||
HYPERVISOR_block_io_op();
|
||||
while ( blk_ring->resp_prod != 1 ) barrier();
|
||||
printk (KERN_ALERT "xhd block device probe:\n");
|
||||
for ( i = 0; i < xlblk_disk_info.count; i++ )
|
||||
{
|
||||
/*
|
||||
** SMH: initialize all the disks we found; this is complicated a
|
||||
** bit by the fact that we have both IDE and SCSI disks underneath
|
||||
*/
|
||||
printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
|
||||
i, xlblk_disk_info.disks[i].type,
|
||||
xlblk_disk_info.disks[i].capacity);
|
||||
}
|
||||
|
||||
SET_MODULE_OWNER(&xenolinux_block_fops);
|
||||
result = register_blkdev(xlblk_major, "block", &xenolinux_block_fops);
|
||||
if (result < 0) {
|
||||
printk (KERN_ALERT "xenolinux block: can't get major %d\n",
|
||||
xlblk_major);
|
||||
return result;
|
||||
|
||||
switch(xen_disk_info.disks[i].type) {
|
||||
case 1:
|
||||
xlide_init(i, nide++);
|
||||
break;
|
||||
case 2:
|
||||
xlscsi_init(i, nscsi++);
|
||||
break;
|
||||
default:
|
||||
printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize global arrays in drivers/block/ll_rw_block.c */
|
||||
for (i = 0; i < XLBLK_MAX; i++) {
|
||||
xlblk_blk_size[i] = xlblk_disk_info.disks[0].capacity;
|
||||
xlblk_blksize_size[i] = 512;
|
||||
xlblk_hardsect_size[i] = 512;
|
||||
xlblk_max_sectors[i] = 128;
|
||||
}
|
||||
xlblk_read_ahead = 8;
|
||||
|
||||
blk_size[xlblk_major] = xlblk_blk_size;
|
||||
blksize_size[xlblk_major] = xlblk_blksize_size;
|
||||
hardsect_size[xlblk_major] = xlblk_hardsect_size;
|
||||
read_ahead[xlblk_major] = xlblk_read_ahead;
|
||||
max_sectors[xlblk_major] = xlblk_max_sectors;
|
||||
|
||||
blk_init_queue(BLK_DEFAULT_QUEUE(xlblk_major), do_xlblk_request);
|
||||
|
||||
/*
|
||||
* Turn off barking 'headactive' mode. We dequeue buffer heads as
|
||||
* soon as we pass them down to Xen.
|
||||
*/
|
||||
blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
|
||||
|
||||
xlblk_ide_register_disk(0, xlblk_disk_info.disks[0].capacity);
|
||||
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual Block Device Driver installed [device: %d]\n",
|
||||
xlblk_major);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
void xlblk_ide_register_disk(int idx, unsigned long capacity)
|
||||
{
|
||||
int units;
|
||||
int minors;
|
||||
struct gendisk *gd;
|
||||
|
||||
/* plagarized from ide-probe.c::init_gendisk */
|
||||
|
||||
units = 2; /* from ide.h::MAX_DRIVES */
|
||||
|
||||
minors = units * (1<<IDE_PARTN_BITS);
|
||||
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
|
||||
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
|
||||
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
|
||||
memset(gd->part, 0, minors * sizeof(struct hd_struct));
|
||||
|
||||
gd->major = xlblk_major;
|
||||
gd->major_name = XLBLK_MAJOR_NAME;
|
||||
gd->minor_shift = IDE_PARTN_BITS;
|
||||
gd->max_p = 1<<IDE_PARTN_BITS;
|
||||
gd->nr_real = units;
|
||||
gd->real_devices = NULL;
|
||||
gd->next = NULL;
|
||||
gd->fops = &xenolinux_block_fops;
|
||||
gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
|
||||
gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
|
||||
|
||||
if (gd->de_arr)
|
||||
memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
|
||||
|
||||
if (gd->flags)
|
||||
memset (gd->flags, 0, sizeof *gd->flags * units);
|
||||
|
||||
add_gendisk(gd);
|
||||
|
||||
xlblk_disk_info.disks[idx].gendisk = gd;
|
||||
|
||||
register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
|
||||
&xenolinux_block_fops, capacity);
|
||||
|
||||
{
|
||||
int loop = 0;
|
||||
printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
|
||||
for (loop = 0; loop < minors; loop++)
|
||||
{
|
||||
if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
|
||||
{
|
||||
printk (KERN_ALERT
|
||||
" %2d: 0x%6lx %8ld 0x%6lx %7ld\n", loop,
|
||||
gd->part[loop].start_sect, gd->part[loop].start_sect,
|
||||
gd->part[loop].nr_sects, gd->part[loop].nr_sects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __exit xlblk_cleanup(void)
|
||||
{
|
||||
/* CHANGE FOR MULTIQUEUE */
|
||||
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major));
|
||||
int i;
|
||||
|
||||
/* clean up global arrays */
|
||||
read_ahead[xlblk_major] = 0;
|
||||
for ( i = 0; i < xen_disk_info.count; i++ )
|
||||
{
|
||||
switch(xen_disk_info.disks[i].type) {
|
||||
case 1:
|
||||
xlide_cleanup();
|
||||
break;
|
||||
case 2:
|
||||
xlscsi_cleanup();
|
||||
break;
|
||||
default:
|
||||
printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (blk_size[xlblk_major])
|
||||
kfree(blk_size[xlblk_major]);
|
||||
blk_size[xlblk_major] = NULL;
|
||||
|
||||
if (blksize_size[xlblk_major])
|
||||
kfree(blksize_size[xlblk_major]);
|
||||
blksize_size[xlblk_major] = NULL;
|
||||
|
||||
if (hardsect_size[xlblk_major])
|
||||
kfree(hardsect_size[xlblk_major]);
|
||||
hardsect_size[xlblk_major] = NULL;
|
||||
|
||||
/* XXX: free each gendisk */
|
||||
if (unregister_blkdev(xlblk_major, "block"))
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual Block Device Driver uninstalled w/ errs\n");
|
||||
else
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual Block Device Driver uninstalled\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/******************************************************************************
|
||||
* xl_ide.c
|
||||
*
|
||||
* Xenolinux virtual IDE block-device driver.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#define MAJOR_NR XLIDE_MAJOR /* force defns in blk.h, must precede include */
|
||||
static int xlide_major = XLIDE_MAJOR;
|
||||
#include <linux/blk.h>
|
||||
|
||||
void xlide_ide_register_disk(int, unsigned long);
|
||||
|
||||
#define XLIDE_MAX 32 /* Maximum minor devices we support */
|
||||
#define XLIDE_MAJOR_NAME "xhd"
|
||||
#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
|
||||
#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1) /* from ide.h::PARTN_MASK */
|
||||
static int xlide_blk_size[XLIDE_MAX];
|
||||
static int xlide_blksize_size[XLIDE_MAX];
|
||||
static int xlide_read_ahead;
|
||||
static int xlide_hardsect_size[XLIDE_MAX];
|
||||
static int xlide_max_sectors[XLIDE_MAX];
|
||||
|
||||
extern xen_disk_info_t xen_disk_info;
|
||||
|
||||
|
||||
extern int xenolinux_block_open(struct inode *inode, struct file *filep);
|
||||
extern int xenolinux_block_release(struct inode *inode, struct file *filep);
|
||||
extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
unsigned command, unsigned long argument);
|
||||
extern int xenolinux_block_check(kdev_t dev);
|
||||
extern int xenolinux_block_revalidate(kdev_t dev);
|
||||
|
||||
|
||||
extern void do_xlblk_request (request_queue_t *rq);
|
||||
|
||||
|
||||
static struct block_device_operations xlide_block_fops =
|
||||
{
|
||||
open: xenolinux_block_open,
|
||||
release: xenolinux_block_release,
|
||||
ioctl: xenolinux_block_ioctl,
|
||||
check_media_change: xenolinux_block_check,
|
||||
revalidate: xenolinux_block_revalidate,
|
||||
};
|
||||
|
||||
|
||||
/* tiny inteface fn */
|
||||
int xlide_hwsect(int minor)
|
||||
{
|
||||
return xlide_hardsect_size[minor];
|
||||
}
|
||||
|
||||
|
||||
void xlide_register_disk(int xidx, int idx)
|
||||
{
|
||||
int units;
|
||||
int minors;
|
||||
struct gendisk *gd;
|
||||
|
||||
/* plagarized from ide-probe.c::init_gendisk */
|
||||
units = 2; /* from ide.h::MAX_DRIVES */
|
||||
|
||||
minors = units * (1<<IDE_PARTN_BITS);
|
||||
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
|
||||
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
|
||||
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
|
||||
memset(gd->part, 0, minors * sizeof(struct hd_struct));
|
||||
|
||||
gd->major = xlide_major; /* XXX should be idx-specific */
|
||||
gd->major_name = XLIDE_MAJOR_NAME; /* XXX should be idx-specific */
|
||||
gd->minor_shift = IDE_PARTN_BITS;
|
||||
gd->max_p = 1<<IDE_PARTN_BITS;
|
||||
gd->nr_real = units;
|
||||
gd->real_devices = NULL;
|
||||
gd->next = NULL;
|
||||
gd->fops = &xlide_block_fops;
|
||||
gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
|
||||
gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
|
||||
|
||||
if (gd->de_arr)
|
||||
memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
|
||||
|
||||
if (gd->flags)
|
||||
memset (gd->flags, 0, sizeof *gd->flags * units);
|
||||
|
||||
add_gendisk(gd);
|
||||
|
||||
xen_disk_info.disks[xidx].gendisk = gd;
|
||||
|
||||
/* XXX major should be idx-specific */
|
||||
register_disk(gd, MKDEV(xlide_major, 0), 1<<IDE_PARTN_BITS,
|
||||
&xlide_block_fops, xen_disk_info.disks[xidx].capacity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Initialize a XenoLinux IDE disk; the 'xidx' is the index into the
|
||||
** xen_disk_info array so we can grab interesting values; the 'idx' is
|
||||
** a count of the number of XLSCSI disks we've seen so far, starting at 0
|
||||
** XXX SMH: this is all so ugly because the xen_disk_info() structure and
|
||||
** array doesn't really give us what we want. Ho hum. To be tidied someday.
|
||||
*/
|
||||
int xlide_init(int xidx, int idx)
|
||||
{
|
||||
int i, major, result;
|
||||
|
||||
SET_MODULE_OWNER(&xlide_block_fops);
|
||||
|
||||
major = xlide_major + idx; /* XXX assume we have a linear major space */
|
||||
|
||||
/* XXX SMH: name below should vary with major */
|
||||
result = register_blkdev(major, XLIDE_MAJOR_NAME, &xlide_block_fops);
|
||||
if (result < 0) {
|
||||
printk (KERN_ALERT "XL IDE: can't get major %d\n",
|
||||
major);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize global arrays in drivers/block/ll_rw_block.c */
|
||||
for (i = 0; i < XLIDE_MAX; i++) {
|
||||
xlide_blk_size[i] = xen_disk_info.disks[0].capacity;
|
||||
xlide_blksize_size[i] = 512;
|
||||
xlide_hardsect_size[i] = 512;
|
||||
xlide_max_sectors[i] = 128;
|
||||
}
|
||||
xlide_read_ahead = 8;
|
||||
|
||||
blk_size[major] = xlide_blk_size;
|
||||
blksize_size[major] = xlide_blksize_size;
|
||||
hardsect_size[major] = xlide_hardsect_size;
|
||||
read_ahead[major] = xlide_read_ahead;
|
||||
max_sectors[major] = xlide_max_sectors;
|
||||
|
||||
blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
|
||||
|
||||
/*
|
||||
* Turn off barking 'headactive' mode. We dequeue buffer heads as
|
||||
* soon as we pass them down to Xen.
|
||||
*/
|
||||
blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
|
||||
|
||||
xlide_register_disk(xidx, idx);
|
||||
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual IDE Device Driver installed [device: %d]\n",
|
||||
major);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void xlide_cleanup(void)
|
||||
{
|
||||
/* CHANGE FOR MULTIQUEUE */
|
||||
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlide_major));
|
||||
|
||||
/* clean up global arrays */
|
||||
read_ahead[xlide_major] = 0;
|
||||
|
||||
if (blk_size[xlide_major])
|
||||
kfree(blk_size[xlide_major]);
|
||||
blk_size[xlide_major] = NULL;
|
||||
|
||||
if (blksize_size[xlide_major])
|
||||
kfree(blksize_size[xlide_major]);
|
||||
blksize_size[xlide_major] = NULL;
|
||||
|
||||
if (hardsect_size[xlide_major])
|
||||
kfree(hardsect_size[xlide_major]);
|
||||
hardsect_size[xlide_major] = NULL;
|
||||
|
||||
/* XXX: free each gendisk */
|
||||
if (unregister_blkdev(xlide_major, XLIDE_MAJOR_NAME))
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual IDE Device Driver uninstalled w/ errs\n");
|
||||
else
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual IDE Device Driver uninstalled\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/******************************************************************************
|
||||
* xl_scsi.c
|
||||
*
|
||||
* Xenolinux virtual SCSI block-device driver.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#define MAJOR_NR XLSCSI_MAJOR /* force defns in blk.h, must precede include */
|
||||
static int xlscsi_major = XLSCSI_MAJOR;
|
||||
#include <linux/blk.h>
|
||||
|
||||
/* Copied from linux/ide.h */
|
||||
typedef unsigned char byte;
|
||||
|
||||
void xlscsi_ide_register_disk(int, unsigned long);
|
||||
|
||||
#define SCSI_DISKS_PER_MAJOR 16 /* max number of devices per scsi major */
|
||||
#define XLSCSI_MAX 32 /* maximum minor devices we support */
|
||||
#define XLSCSI_MAJOR_NAME "xsd"
|
||||
|
||||
static int xlscsi_blk_size[XLSCSI_MAX];
|
||||
static int xlscsi_blksize_size[XLSCSI_MAX];
|
||||
static int xlscsi_read_ahead;
|
||||
static int xlscsi_hardsect_size[XLSCSI_MAX];
|
||||
static int xlscsi_max_sectors[XLSCSI_MAX];
|
||||
|
||||
#if 0
|
||||
#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
|
||||
#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
|
||||
#else
|
||||
#define DPRINTK(_f, _a...) ((void)0)
|
||||
#define DPRINTK_IOCTL(_f, _a...) ((void)0)
|
||||
#endif
|
||||
|
||||
extern xen_disk_info_t xen_disk_info;
|
||||
|
||||
extern int xenolinux_block_open(struct inode *inode, struct file *filep);
|
||||
extern int xenolinux_block_release(struct inode *inode, struct file *filep);
|
||||
extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
|
||||
unsigned command, unsigned long argument);
|
||||
extern int xenolinux_block_check(kdev_t dev);
|
||||
extern int xenolinux_block_revalidate(kdev_t dev);
|
||||
|
||||
|
||||
extern void do_xlblk_request (request_queue_t *rq);
|
||||
|
||||
static struct block_device_operations xlscsi_block_fops =
|
||||
{
|
||||
open: xenolinux_block_open,
|
||||
release: xenolinux_block_release,
|
||||
ioctl: xenolinux_block_ioctl,
|
||||
check_media_change: xenolinux_block_check,
|
||||
revalidate: xenolinux_block_revalidate,
|
||||
};
|
||||
|
||||
|
||||
/* tiny inteface fn */
|
||||
int xlscsi_hwsect(int minor)
|
||||
{
|
||||
return xlscsi_hardsect_size[minor];
|
||||
}
|
||||
|
||||
|
||||
void xlscsi_register_disk(int xidx, int idx)
|
||||
{
|
||||
int minors;
|
||||
struct gendisk *gd;
|
||||
unsigned long capacity;
|
||||
|
||||
minors = XLSCSI_MAX;
|
||||
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
|
||||
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
|
||||
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
|
||||
memset(gd->part, 0, minors * sizeof(struct hd_struct));
|
||||
|
||||
if(idx > 0)
|
||||
printk("xlscsi_register_disk: need fix to handle "
|
||||
"multiple SCSI majors!\n");
|
||||
|
||||
gd->major = xlscsi_major; /* XXX should be idx-specific */
|
||||
gd->major_name = XLSCSI_MAJOR_NAME; /* XXX should be idx-specific */
|
||||
gd->minor_shift = 4;
|
||||
gd->max_p = 1<<4;
|
||||
gd->nr_real = SCSI_DISKS_PER_MAJOR;
|
||||
gd->real_devices = NULL;
|
||||
gd->next = NULL;
|
||||
gd->fops = &xlscsi_block_fops;
|
||||
gd->de_arr = kmalloc (sizeof *gd->de_arr * SCSI_DISKS_PER_MAJOR,
|
||||
GFP_KERNEL);
|
||||
gd->flags = kmalloc (sizeof *gd->flags * SCSI_DISKS_PER_MAJOR,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (gd->de_arr)
|
||||
memset (gd->de_arr, 0, sizeof *gd->de_arr * SCSI_DISKS_PER_MAJOR);
|
||||
|
||||
if (gd->flags)
|
||||
memset (gd->flags, 0, sizeof *gd->flags * SCSI_DISKS_PER_MAJOR);
|
||||
|
||||
add_gendisk(gd);
|
||||
|
||||
xen_disk_info.disks[xidx].gendisk = gd;
|
||||
|
||||
/* XXX major below should be idx-specific */
|
||||
register_disk(gd, MKDEV(xlscsi_major, 0), 1<<4, &xlscsi_block_fops,
|
||||
xen_disk_info.disks[xidx].capacity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Initialize a XenoLinux SCSI disk; the 'xidx' is the index into the
|
||||
** xen_disk_info array so we can grab interesting values; the 'idx' is
|
||||
** a count of the number of XLSCSI disks we've seen so far, starting at 0
|
||||
** XXX SMH: this is all so ugly because the xen_disk_info() structure and
|
||||
** array doesn't really give us what we want. Ho hum. To be tidied someday.
|
||||
*/
|
||||
int xlscsi_init(int xidx, int idx)
|
||||
{
|
||||
int i, major, result;
|
||||
|
||||
SET_MODULE_OWNER(&xlscsi_block_fops);
|
||||
|
||||
major = xlscsi_major + idx; /* XXX asume we have linear major space */
|
||||
|
||||
/* XXX SMH: 'name' below should vary for different major values */
|
||||
result = register_blkdev(major, XLSCSI_MAJOR_NAME, &xlscsi_block_fops);
|
||||
|
||||
if (result < 0) {
|
||||
printk (KERN_ALERT "XL SCSI: can't get major %d\n", major);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* initialize global arrays in drivers/block/ll_rw_block.c */
|
||||
for (i = 0; i < XLSCSI_MAX; i++) {
|
||||
xlscsi_blk_size[i] = xen_disk_info.disks[xidx].capacity;
|
||||
xlscsi_blksize_size[i] = 512;
|
||||
xlscsi_hardsect_size[i] = 512;
|
||||
xlscsi_max_sectors[i] = 128;
|
||||
}
|
||||
xlscsi_read_ahead = 8;
|
||||
|
||||
blk_size[major] = xlscsi_blk_size;
|
||||
blksize_size[major] = xlscsi_blksize_size;
|
||||
hardsect_size[major] = xlscsi_hardsect_size;
|
||||
read_ahead[major] = xlscsi_read_ahead;
|
||||
max_sectors[major] = xlscsi_max_sectors;
|
||||
|
||||
blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
|
||||
|
||||
/*
|
||||
* Turn off barking 'headactive' mode. We dequeue buffer heads as
|
||||
* soon as we pass them down to Xen.
|
||||
*/
|
||||
blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
|
||||
|
||||
xlscsi_register_disk(xidx, idx);
|
||||
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual SCSI Device Driver installed [device: %d]\n",
|
||||
major);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void xlscsi_cleanup(void)
|
||||
{
|
||||
/* CHANGE FOR MULTIQUEUE */
|
||||
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlscsi_major));
|
||||
|
||||
/* clean up global arrays */
|
||||
read_ahead[xlscsi_major] = 0;
|
||||
|
||||
if (blk_size[xlscsi_major])
|
||||
kfree(blk_size[xlscsi_major]);
|
||||
blk_size[xlscsi_major] = NULL;
|
||||
|
||||
if (blksize_size[xlscsi_major])
|
||||
kfree(blksize_size[xlscsi_major]);
|
||||
blksize_size[xlscsi_major] = NULL;
|
||||
|
||||
if (hardsect_size[xlscsi_major])
|
||||
kfree(hardsect_size[xlscsi_major]);
|
||||
hardsect_size[xlscsi_major] = NULL;
|
||||
|
||||
/* XXX: free each gendisk */
|
||||
if (unregister_blkdev(xlscsi_major, XLSCSI_MAJOR_NAME))
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual SCSI Device Driver uninstalled w/ errs\n");
|
||||
else
|
||||
printk(KERN_ALERT
|
||||
"XenoLinux Virtual SCSI Device Driver uninstalled\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
|
||||
#define UMEM_MAJOR 116 /* http://www.umem.com/ Battery Backed RAM */
|
||||
|
||||
/* note: 123, 124, 125, 126 and 234, 235, 236, 237 are defined in xeno_major */
|
||||
#include <asm/hypervisor-ifs/xeno-major.h>
|
||||
#define XLIDE_MAJOR 123 /* XenoLinux IDE Device */
|
||||
#define XLSCSI_MAJOR 133 /* XenoLinux SCSI Device */
|
||||
|
||||
#define RTF_MAJOR 150
|
||||
#define RAW_MAJOR 162
|
||||
|
||||
@@ -232,13 +232,7 @@ static struct dev_name_struct {
|
||||
{ "ataraid/d15p",0x72F0 },
|
||||
#if defined(CONFIG_XENOLINUX_BLOCK)
|
||||
{ "xhda", 0x7B00 },
|
||||
{ "xhdb", 0x7C00 },
|
||||
{ "xhdc", 0x7D00 },
|
||||
{ "xhdd", 0x7E00 },
|
||||
{ "vhda", 0xEA00 },
|
||||
{ "vhdb", 0xEB00 },
|
||||
{ "vhdc", 0xEC00 },
|
||||
{ "vhdd", 0xED00 },
|
||||
{ "xsda", 0x8500 },
|
||||
#endif
|
||||
{ "nftla", 0x5d00 },
|
||||
{ "nftlb", 0x5d10 },
|
||||
|
||||