diff options
author | kaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk> | 2003-03-06 16:04:47 +0000 |
---|---|---|
committer | kaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk> | 2003-03-06 16:04:47 +0000 |
commit | 8e06473cff7350a2ea62c5406cf2a733ebe82478 (patch) | |
tree | 029a9c0d9c0e8634889fe34738b4d084f46ac5c1 /xenolinux-2.4.21-pre4-sparse/arch | |
parent | dfca2c82d597482bab554fd1256cdb13154efba7 (diff) | |
download | xen-8e06473cff7350a2ea62c5406cf2a733ebe82478.tar.gz xen-8e06473cff7350a2ea62c5406cf2a733ebe82478.tar.bz2 xen-8e06473cff7350a2ea62c5406cf2a733ebe82478.zip |
bitkeeper revision 1.105.1.9 (3e67719fUVPJZo6pYtLZ12frkd1BqQ)
xl_scsi.c, xl_ide.c, grok.c:
new file
Many files:
Steve's new SCSI world.
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse/arch')
4 files changed, 579 insertions, 147 deletions
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile index 74a0c6c565..56413ed106 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile @@ -1,3 +1,3 @@ O_TARGET := blk.o -obj-y := xl_block.o xl_block_test.o +obj-y := xl_block.o xl_ide.o xl_scsi.o xl_block_test.o include $(TOPDIR)/Rules.make diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c index 0b77e5536e..3130280c57 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c @@ -24,27 +24,26 @@ #include <asm/io.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; -void xlblk_ide_register_disk(int, unsigned long); -#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_RESPONSE_IRQ _EVENT_BLK_RESP +#define XLBLK_MAX 32 /* XXX SMH: this the max of XLIDE_MAX and XLSCSI_MAX */ + +#define XLBLK_RESPONSE_IRQ _EVENT_BLK_RESP #define DEBUG_IRQ _EVENT_DEBUG #if 0 @@ -57,7 +56,8 @@ 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 xen_disk_info; + +xen_disk_info_t xen_disk_info; int hypervisor_request(void * id, int operation, @@ -70,52 +70,136 @@ int hypervisor_request(void * id, /* ------------------------------------------------------------------------ */ -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: - DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, - (long) xen_disk_info.disks[0].capacity); - return put_user(xen_disk_info.disks[0].capacity, - (unsigned long *) argument); + DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); + return put_user(part->nr_sects, (unsigned long *) argument); case BLKRRPART: DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); break; case BLKSSZGET: - DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET, - xlblk_hardsect_size[minor_dev]); - return xlblk_hardsect_size[minor_dev]; - + 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 HDIO_GETGEO: DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); if (!argument) return -EINVAL; @@ -143,13 +227,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; @@ -200,14 +284,13 @@ int hypervisor_request(void * id, case XEN_BLOCK_READ: case XEN_BLOCK_WRITE: - if ( MAJOR(device) != XLBLK_MAJOR ) - panic("error: xl_block::hypervisor_request: " - "unknown device [0x%x]\n", device); - phys_device = MKDEV(IDE0_MAJOR, 0); + + phys_device = xldev_to_physdev(device); + /* Compute real buffer location on disk */ sector_number = block_number; - if ( (gd = (struct gendisk *)xen_disk_info.disks[0].gendisk) != NULL ) - sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect; + gd = xldev_to_gendisk(device, NULL); + sector_number += gd->part[MINOR(device)].start_sect; break; default: @@ -234,7 +317,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; @@ -242,9 +325,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, @@ -310,7 +394,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; @@ -327,15 +411,24 @@ 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. */ - do_xlblk_request(BLK_DEFAULT_QUEUE(MAJOR_NR)); - + 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)); + } + spin_unlock_irqrestore(&io_request_lock, flags); } int __init xlblk_init(void) { - int i, error, result; + int i, error; /* This mapping was created early at boot time. */ blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE); @@ -356,129 +449,57 @@ int __init xlblk_init(void) BUG(); HYPERVISOR_block_io_op(); while ( blk_ring->resp_prod != 1 ) barrier(); + for ( i = 0; i < xen_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, xen_disk_info.disks[i].type, xen_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] = xen_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, xen_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); - - xen_disk_info.disks[idx].gendisk = gd; - - /* default disk size is just a big number. in the future, we - need a message to probe the devices to determine the actual size */ - register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS, - &xenolinux_block_fops, capacity); - - return; -} - - static void __exit xlblk_cleanup(void) { - /* CHANGE FOR MULTIQUEUE */ - blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major)); - - /* clean up global arrays */ - read_ahead[xlblk_major] = 0; + int i; - 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; + 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 (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; } diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c new file mode 100644 index 0000000000..50f80038ee --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c @@ -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; +} + diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c new file mode 100644 index 0000000000..3ee86509f1 --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c @@ -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; +} + |