diff options
author | kaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk> | 2003-03-06 16:54:15 +0000 |
---|---|---|
committer | kaf24@labyrinth.cl.cam.ac.uk <kaf24@labyrinth.cl.cam.ac.uk> | 2003-03-06 16:54:15 +0000 |
commit | 796305db16ed924df9d4061b70ba110e5978b226 (patch) | |
tree | 99fa4a1fe2f7b38485172dfe7720924f0178c9dc /xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers | |
parent | 454a736db481ae4527360d5630ca9cd4148567c9 (diff) | |
parent | 8e06473cff7350a2ea62c5406cf2a733ebe82478 (diff) | |
download | xen-796305db16ed924df9d4061b70ba110e5978b226.tar.gz xen-796305db16ed924df9d4061b70ba110e5978b226.tar.bz2 xen-796305db16ed924df9d4061b70ba110e5978b226.zip |
bitkeeper revision 1.109 (3e677d37B9PCxHLX7a1Iufrz4eSUqA)
Manual merge of SMH + ACH worlds.
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers')
4 files changed, 582 insertions, 180 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 594aab25b8..fd6b63f51e 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,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 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 bc87e7eb7b..af270f1aa1 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 @@ -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); + + 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; + } } - - 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; - } - - /* 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)); - - /* clean up global arrays */ - read_ahead[xlblk_major] = 0; - - if (blk_size[xlblk_major]) - kfree(blk_size[xlblk_major]); - blk_size[xlblk_major] = NULL; + int i; - 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; +} + |