diff options
author | ach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk> | 2003-02-26 19:17:32 +0000 |
---|---|---|
committer | ach61@labyrinth.cl.cam.ac.uk <ach61@labyrinth.cl.cam.ac.uk> | 2003-02-26 19:17:32 +0000 |
commit | a474d07ad6848eb61c591d57ff64400d66cd9007 (patch) | |
tree | 8ea698bf53a6faa850ef9c63dc0659c0feb5db01 /xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers | |
parent | 5f8cbb69be187519af9ecee587d5152be1c00cc2 (diff) | |
parent | 47b95f44ede3bb13fd5d22e29921255274f87926 (diff) | |
download | xen-a474d07ad6848eb61c591d57ff64400d66cd9007.tar.gz xen-a474d07ad6848eb61c591d57ff64400d66cd9007.tar.bz2 xen-a474d07ad6848eb61c591d57ff64400d66cd9007.zip |
bitkeeper revision 1.106 (3e5d12ccK5E6c5JC__10GKs1f6x0fw)
Merge labyrinth.cl.cam.ac.uk:/usr/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/anfs/scratch/boulderdash/ach61/xeno/xeno.bk
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers')
4 files changed, 335 insertions, 10 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..c6d1c7dc63 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_segment.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..6e7e713c86 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 @@ -22,6 +22,7 @@ #include <asm/hypervisor-ifs/block.h> #include <asm/hypervisor-ifs/hypervisor-if.h> #include <asm/io.h> +#include <asm/atomic.h> #include <asm/uaccess.h> #define MAJOR_NR XLBLK_MAJOR /* force defns in blk.h, must precede include */ @@ -58,6 +59,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 xen_disk_info; +atomic_t xlblk_control_count; int hypervisor_request(void * id, int operation, @@ -166,7 +168,7 @@ static int xenolinux_block_revalidate(kdev_t dev) * virtual address in the guest os. * block_number: block to read * block_size: size of each block - * device: ide/hda is 768 or 0x300 + * device: ide/hda is 768 or 0x300 should be disk#!!! */ int hypervisor_request(void * id, int operation, @@ -193,6 +195,8 @@ int hypervisor_request(void * id, switch ( operation ) { + case XEN_BLOCK_SEG_CREATE: + case XEN_BLOCK_SEG_DELETE: case XEN_BLOCK_PROBE: phys_device = (kdev_t) 0; sector_number = 0; @@ -321,7 +325,21 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs) i = BLK_RING_INC(i) ) { blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp; - if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1); + switch (bret->operation) + { + case XEN_BLOCK_READ : + case XEN_BLOCK_WRITE : + if ( (bh = bret->id) != NULL ) bh->b_end_io(bh, 1); + break; + + case XEN_BLOCK_SEG_CREATE : + case XEN_BLOCK_SEG_DELETE : + atomic_dec(&xlblk_control_count); + break; + + default: + break; + } } resp_cons = i; @@ -337,6 +355,8 @@ int __init xlblk_init(void) { int i, error, result; + atomic_set(&xlblk_control_count, 0); + /* This mapping was created early at boot time. */ blk_ring = (blk_ring_t *)fix_to_virt(FIX_BLKRING_BASE); blk_ring->req_prod = blk_ring->resp_prod = resp_cons = 0; @@ -356,6 +376,7 @@ int __init xlblk_init(void) BUG(); HYPERVISOR_block_io_op(); while ( blk_ring->resp_prod != 1 ) barrier(); + printk (KERN_ALERT "block device probe:\n"); for ( i = 0; i < xen_disk_info.count; i++ ) { printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n", diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c index 2ddef271e5..8d695689ba 100644 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c @@ -138,6 +138,11 @@ int proc_write_bdt(struct file *file, const char *buffer, sscanf(local, "%c %i %i %i", &opcode, &block_number, &block_size, &device); + if (data) + { + kfree(data); + } + if (opcode == 'r' || opcode == 'R') { meta.operation = XEN_BLOCK_READ; @@ -151,6 +156,31 @@ int proc_write_bdt(struct file *file, const char *buffer, meta.operation = XEN_BLOCK_DEBUG; block_size = 10000; } + else if (opcode == 'c' || opcode == 'C') + { + xv_disk_t *xvd; + int loop; + + meta.operation = XEN_BLOCK_SEG_CREATE; + data = kmalloc (sizeof(xv_disk_t), GFP_KERNEL); + if (data == NULL) + { + kfree(local); + return -ENOMEM; + } + + xvd = (xv_disk_t *)data; + xvd->mode = XEN_DISK_READ_WRITE; + xvd->domain = block_number; + xvd->segment = block_size; + xvd->ext_count = device; + for (loop = 0; loop < xvd->ext_count; loop++) + { + xvd->extents[loop].disk = block_number + 1; /* random */ + xvd->extents[loop].offset = block_size + 1; + xvd->extents[loop].size = device + 1; + } + } else { printk(KERN_ALERT @@ -158,15 +188,14 @@ int proc_write_bdt(struct file *file, const char *buffer, return -EINVAL; } - if (data) - { - kfree(data); - } - data = kmalloc(block_size * sizeof(char), GFP_KERNEL); if (data == NULL) { - kfree(local); - return -ENOMEM; + data = kmalloc(block_size * sizeof(char), GFP_KERNEL); + if (data == NULL) + { + kfree(local); + return -ENOMEM; + } } meta.block_number = block_number; diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c new file mode 100644 index 0000000000..da14be14df --- /dev/null +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c @@ -0,0 +1,275 @@ +/* + * xl_segment.c + * + * XenoLinux virtual disk driver. + */ + + +#include <linux/config.h> +#include <linux/module.h> + +#include <linux/proc_fs.h> +#include <linux/delay.h> +#include <asm/uaccess.h> +#include <asm/atomic.h> + +#include <asm/hypervisor-ifs/block.h> +#include <asm/hypervisor-ifs/hypervisor-if.h> + +static struct proc_dir_entry *vhd; +xv_disk_t xvd; + +extern atomic_t xlblk_control_count; /* xl_block.c */ + +/******************************************************************/ + +static int proc_read_vhd(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + return 0; +} + +#define isdelim(c) \ + (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0) + +char *get_string(char *string) /* a bit like strtok */ +{ + static char *temp; + int loop = 0; + + if (string != NULL) + temp = string; + else + string = temp; + + try_again: + + while (!isdelim(string[loop])) + { + if (string[loop] == '\0') + return NULL; + loop++; + } + + string[loop] = '\0'; + temp = (string + loop + 1); + + if (loop == 0) + { + string = temp; + goto try_again; + } + + return string; +} + + +#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0) +unsigned long to_number(char *string) /* atoi */ +{ + unsigned long value = 0; + + if (string == NULL) return 0; + + while (!isdigit(*string) && *string != '\0') string++; + + while (isdigit(*string)) + { + value = value * 10 + (*string - '0'); + string++; + } + + return value; +} + +static int proc_write_vhd(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL); + char *string; + int loop; + int counter; + xv_disk_t xvd; + + memset (&xvd, 0, sizeof(xvd)); + + if (copy_from_user(local, buffer, count)) + { + return -EFAULT; + } + local[count] = '\0'; + + string = get_string(local); /* look for Domain */ + if (string == NULL) /* empty string */ + { + return count; + } + if (*string != 'd' && *string != 'D') + { + printk (KERN_ALERT + "error: domain specifier missing [%s]. should be \"domain\".\n", + string); + return count; + } + + string = get_string(NULL); /* domain number */ + if (string == NULL) + { + printk (KERN_ALERT "error: domain number missing\n"); + return count; + } + xvd.domain = (int) to_number(string); + + string = get_string(NULL); + if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0)) + { + xvd.mode = XEN_DISK_READ_ONLY; + } + else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0)) + { + xvd.mode = XEN_DISK_READ_ONLY; + } + else + { + printk (KERN_ALERT + "error: bad mode [%s]. should be \"rw\" or \"ro\".\n", + string); + return count; + } + + string = get_string(NULL); /* look for Segment */ + if (string == NULL || (*string != 's' && *string != 'S')) + { + printk (KERN_ALERT + "error: segment specifier missing [%s]. should be \"segment\".\n", + string); + return count; + } + + string = get_string(NULL); /* segment number */ + if (string == NULL) + { + printk (KERN_ALERT "error: segment number missing\n"); + return count; + } + xvd.segment = (int) to_number(string); + + string = get_string(NULL); /* look for Extents */ + if (string == NULL || (*string != 'e' && *string != 'E')) + { + printk (KERN_ALERT + "error: extents specifier missing [%s]. should be \"extents\".\n", + string); + return count; + } + + string = get_string(NULL); /* number of extents */ + if (string == NULL) + { + printk (KERN_ALERT "error: number of extents missing\n"); + return count; + } + xvd.ext_count = (int) to_number(string); + + /* ignore parenthesis */ + + for (loop = 0; loop < xvd.ext_count; loop++) + { + string = get_string(NULL); /* look for Disk */ + if (string == NULL || (*string != 'd' && *string != 'D')) + { + printk (KERN_ALERT + "hmm, extent disk specifier missing [%s]. should be \"disk\".\n", + string); + return count; + } + string = get_string(NULL); /* disk number */ + if (string == NULL) + { + printk (KERN_ALERT "error: disk number missing\n"); + return count; + } + xvd.extents[loop].disk = (int) to_number(string); + + string = get_string(NULL); /* look for Offset */ + if (string == NULL || (*string != 'o' && *string != 'O')) + { + printk (KERN_ALERT + "error: disk offset missing [%s]. should be \"offset\".\n", + string); + return count; + } + string = get_string(NULL); /* offset */ + if (string == NULL) + { + printk (KERN_ALERT "error: offset missing\n"); + return count; + } + xvd.extents[loop].offset = to_number(string); + + string = get_string(NULL); /* look for Size */ + if (string == NULL || (*string != 's' && *string != 'S')) + { + printk (KERN_ALERT + "error: extent size missing [%s]. should be \"size\".\n", + string); + return count; + } + string = get_string(NULL); /* size */ + if (string == NULL) + { + printk (KERN_ALERT "error: extent size missing\n"); + return count; + } + xvd.extents[loop].size = to_number(string); + } + + { + /* get lock xlblk_control_lock */ + counter = atomic_read(&xlblk_control_count); + atomic_inc(&xlblk_control_count); + /* release lock xlblk_control_lock */ + } + + hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd, + 0, 0, (kdev_t) 0); + HYPERVISOR_block_io_op(); + + while (atomic_read(&xlblk_control_count) != counter) barrier(); + + /* while ( blk_ring->resp_prod != 1 ) barrier(); */ + + /* mdelay(1000); */ + + return count; +} + +/******************************************************************/ + +int __init xlseg_init(void) +{ + vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL); + if (vhd == NULL) + { + panic ("xlseg_init: unable to create vhd proc entry\n"); + } + vhd->data = NULL; + vhd->read_proc = proc_read_vhd; + vhd->write_proc = proc_write_vhd; + vhd->owner = THIS_MODULE; + + memset(&xvd, 0, sizeof(xvd)); + + printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver installed\n"); + return 0; +} + +static void __exit xlseg_cleanup(void) +{ + printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n"); +} + +#ifdef MODULE +module_init(xlseg_init); +module_exit(xlseg_cleanup); +#endif |