aboutsummaryrefslogtreecommitdiffstats
path: root/xenolinux-2.4.21-pre4-sparse
diff options
context:
space:
mode:
Diffstat (limited to 'xenolinux-2.4.21-pre4-sparse')
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile3
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c122
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c46
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c433
-rw-r--r--xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c280
-rw-r--r--xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c2
-rw-r--r--xenolinux-2.4.21-pre4-sparse/include/linux/blk.h7
7 files changed, 846 insertions, 47 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 56413ed106..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_ide.o xl_scsi.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 3130280c57..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
@@ -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>
#include <linux/blk.h>
@@ -29,7 +30,6 @@
/* Copied from linux/ide.h */
typedef unsigned char byte;
-
extern int xlide_init(int xidx, int idx);
extern int xlide_hwsect(int minor);
extern void xlide_cleanup(void);
@@ -44,6 +44,7 @@ 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
+
#define DEBUG_IRQ _EVENT_DEBUG
#if 0
@@ -57,15 +58,18 @@ static int nscsi = 0; // number of SCSI devices we have
static blk_ring_t *blk_ring;
static unsigned int resp_cons; /* Response consumer for comms ring. */
-xen_disk_info_t xen_disk_info;
-
-int hypervisor_request(void * id,
- int operation,
- char * buffer,
- unsigned long block_number,
- unsigned short block_size,
- kdev_t device);
+static xen_disk_info_t xlblk_disk_info;
+atomic_t xlblk_control_count;
+void xlblk_ide_register_disk(int, unsigned long);
+void do_xlseg_requestX (request_queue_t *rq);
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
/* ------------------------------------------------------------------------
*/
@@ -178,7 +182,7 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
return put_user(part->nr_sects, (unsigned long *) argument);
- case BLKRRPART:
+ case BLKRRPART: /* re-read partition table */
DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
break;
@@ -200,7 +204,26 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
return 0;
}
+
+ case BLKBSZSET: /* set block size */
+ DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
+ break;
+
+ case BLKRASET: /* set read-ahead */
+ DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET);
+ break;
+
+ case BLKRAGET: /* get read-ahead */
+ DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET);
+ break;
+
+ case BLKSSZGET: /* get sector size */
+ DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
+ xlblk_hardsect_size[minor_dev]);
+ return xlblk_hardsect_size[minor_dev];
+
case HDIO_GETGEO:
+ /* note: these values are complete garbage */
DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO);
if (!argument) return -EINVAL;
if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
@@ -210,13 +233,13 @@ int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
return 0;
case HDIO_GETGEO_BIG:
+ /* note: these values are complete garbage */
DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
if (!argument) return -EINVAL;
if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
-
return 0;
default:
@@ -245,26 +268,27 @@ int xenolinux_block_revalidate(kdev_t dev)
* request block io
*
* id: for guest use only.
- * operation: XEN_BLOCK_READ, XEN_BLOCK_WRITE or XEN_BLOCK_PROBE
+ * operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*}
* buffer: buffer to read/write into. this should be a
* 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: xhd or vhd
+ * gd: partition information if XEN_BLOCK_{READ,WRITE}
*/
-int hypervisor_request(void * id,
- int operation,
- char * buffer,
- unsigned long block_number,
- unsigned short block_size,
- kdev_t device)
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd)
{
int position;
void *buffer_ma;
kdev_t phys_device = (kdev_t) 0;
unsigned long sector_number = 0;
- struct gendisk *gd;
-
+
/*
* Bail if there's no room in the request communication ring. This may be
* because we have a whole bunch of outstanding responses to process. No
@@ -277,16 +301,19 @@ int hypervisor_request(void * id,
switch ( operation )
{
- case XEN_BLOCK_PROBE:
+ case XEN_BLOCK_SEG_CREATE:
+ case XEN_BLOCK_SEG_DELETE:
+ case XEN_BLOCK_PROBE_BLK:
+ case XEN_BLOCK_PROBE_SEG:
phys_device = (kdev_t) 0;
sector_number = 0;
break;
case XEN_BLOCK_READ:
case XEN_BLOCK_WRITE:
-
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;
gd = xldev_to_gendisk(device, NULL);
@@ -346,8 +373,9 @@ void do_xlblk_request (request_queue_t *rq)
{
full = hypervisor_request(
bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE,
- bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev);
-
+ bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
+ (struct gendisk *)xlblk_disk_info.disks[0].gendisk);
+
if ( full ) goto out;
queued++;
@@ -405,7 +433,22 @@ 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 :
+ case XEN_BLOCK_PROBE_SEG :
+ atomic_dec(&xlblk_control_count);
+ break;
+
+ default:
+ break;
+ }
}
resp_cons = i;
@@ -420,6 +463,7 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
*/
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);
@@ -428,7 +472,9 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
int __init xlblk_init(void)
{
- int i, error;
+ 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);
@@ -441,24 +487,26 @@ int __init xlblk_init(void)
goto fail;
}
- memset (&xen_disk_info, 0, sizeof(xen_disk_info));
- xen_disk_info.count = 0;
+ /* probe for disk information */
+ memset (&xlblk_disk_info, 0, sizeof(xlblk_disk_info));
+ xlblk_disk_info.count = 0;
- if ( hypervisor_request(NULL, XEN_BLOCK_PROBE, (char *) &xen_disk_info,
- 0, 0, (kdev_t) 0) )
+ if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_BLK,
+ (char *) &xlblk_disk_info,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *) NULL))
BUG();
HYPERVISOR_block_io_op();
while ( blk_ring->resp_prod != 1 ) barrier();
-
- for ( i = 0; i < xen_disk_info.count; i++ )
+ 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, xen_disk_info.disks[i].type,
- xen_disk_info.disks[i].capacity);
+ i, xlblk_disk_info.disks[i].type,
+ xlblk_disk_info.disks[i].capacity);
switch(xen_disk_info.disks[i].type) {
case 1:
@@ -471,7 +519,6 @@ int __init xlblk_init(void)
printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
break;
}
-
}
return 0;
@@ -480,7 +527,6 @@ int __init xlblk_init(void)
return error;
}
-
static void __exit xlblk_cleanup(void)
{
int i;
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..b239655794 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;
@@ -177,7 +206,8 @@ int proc_write_bdt(struct file *file, const char *buffer,
/* submit request */
hypervisor_request(0, meta.operation, meta.buffer,
meta.block_number, meta.block_size,
- meta.device);
+ meta.device,
+ (struct gendisk *) NULL);
HYPERVISOR_block_io_op();
mdelay(1000); /* should wait for a proper acknowledgement/response. */
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..0754daa9a3
--- /dev/null
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
@@ -0,0 +1,433 @@
+/******************************************************************************
+ * xl_segment.c
+ *
+ * Xenolinux virtual block-device driver (vhd).
+ *
+ */
+
+#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>
+
+#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 XLSEG_MAJOR /* force defns in blk.h, must precede include */
+static int xlseg_major = XLSEG_MAJOR;
+#include <linux/blk.h>
+
+/* Copied from linux/ide.h */
+typedef unsigned char byte;
+
+#define XLSEG_MAX 32 /* Maximum minor devices we support */
+#define XLSEG_MAJOR_NAME "xhd"
+
+static int xlseg_blk_size[XLSEG_MAX];
+static int xlseg_blksize_size[XLSEG_MAX];
+static int xlseg_read_ahead;
+static int xlseg_hardsect_size[XLSEG_MAX];
+static int xlseg_max_sectors[XLSEG_MAX];
+
+extern atomic_t xlblk_control_count; /* xl_block.c */
+
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
+void xlseg_register_disk(int idx, unsigned long capacity);
+
+#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
+
+static xen_disk_info_t xlseg_disk_info;
+
+/* ------------------------------------------------------------------------
+ */
+
+static int xenolinux_segment_open(struct inode *inode, struct file *filep)
+{
+ DPRINTK("xenolinux_segment_release\n");
+ return 0;
+}
+
+static int xenolinux_segment_release(struct inode *inode, struct file *filep)
+{
+ DPRINTK("xenolinux_segment_release\n");
+ return 0;
+}
+
+static int xenolinux_segment_ioctl(struct inode *inode, struct file *filep,
+ unsigned command, unsigned long argument)
+{
+ int minor_dev;
+ struct hd_geometry *geo = (struct hd_geometry *)argument;
+ struct gendisk *gd = (struct gendisk *)xlseg_disk_info.disks[0].gendisk;
+
+ DPRINTK("xenolinux_segment_ioctl\n");
+
+ /* check permissions */
+ if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+ if (!inode) return -EINVAL;
+ minor_dev = MINOR(inode->i_rdev);
+ if (minor_dev >= XLSEG_MAX) return -ENODEV;
+
+ DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
+ command, (long) argument, minor_dev);
+
+ switch (command)
+ {
+ case BLKGETSIZE:
+ if (gd != NULL)
+ {
+ printk(KERN_ALERT "minordev: %d\n", minor_dev);
+ printk(KERN_ALERT "[0] start: %lx\n", gd->part[0].start_sect);
+ printk(KERN_ALERT "[0] count: %lx\n", gd->part[0].nr_sects);
+ printk(KERN_ALERT "[1] start: %lx\n", gd->part[1].start_sect);
+ printk(KERN_ALERT "[1] count: %lx\n", gd->part[1].nr_sects);
+ printk(KERN_ALERT "[2] start: %lx\n", gd->part[2].start_sect);
+ printk(KERN_ALERT "[2] count: %lx\n", gd->part[2].nr_sects);
+
+ DPRINTK_IOCTL(" BLKGETSIZE gd: %x %lx\n", BLKGETSIZE,
+ gd->part[minor_dev].nr_sects);
+ return put_user(gd->part[minor_dev].nr_sects,
+ (unsigned long *)argument);
+ }
+ else
+ {
+ DPRINTK_IOCTL(" BLKGETSIZE disk: %x %lx\n", BLKGETSIZE,
+ xlseg_disk_info.disks[0].capacity);
+ return put_user(xlseg_disk_info.disks[0].capacity,
+ (unsigned long *) argument);
+ }
+
+ case BLKRRPART:
+ DPRINTK_IOCTL(" BLKRRPART: \n");
+ /* we don't have re-validate drive yet... so you need to reboot! */
+ break;
+
+ case BLKSSZGET:
+ DPRINTK_IOCTL(" BLKSSZGET: %d\n",
+ xlseg_hardsect_size[minor_dev]);
+ return xlseg_hardsect_size[minor_dev];
+
+ case HDIO_GETGEO:
+ /* note: these values are complete garbage */
+ DPRINTK_IOCTL(" HDIO_GETGEO: \n");
+ if (!argument) return -EINVAL;
+ if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
+ if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
+ if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
+ if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT;
+ return 0;
+
+ case HDIO_GETGEO_BIG:
+ /* note: these values are complete garbage */
+ DPRINTK_IOCTL(" HDIO_GETGEO_BIG\n");
+ if (!argument) return -EINVAL;
+ if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
+ if (put_user(0xff, (byte *)&geo->heads)) return -EFAULT;
+ if (put_user(0x3f, (byte *)&geo->sectors)) return -EFAULT;
+ if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
+ return 0;
+
+ default:
+ DPRINTK_IOCTL(" eh? unknown ioctl\n");
+ break;
+ }
+
+ return 0;
+}
+
+static int xenolinux_segment_check(kdev_t dev)
+{
+ DPRINTK("xenolinux_segment_check\n");
+ return 0;
+}
+
+static int xenolinux_segment_revalidate(kdev_t dev)
+{
+ DPRINTK("xenolinux_segment_revalidate\n");
+ return 0;
+}
+
+void do_xlseg_requestX (request_queue_t *rq)
+{
+ /* this is a bit dumb. do_xlseg_request is defined in blk.h
+ and this is thus static. but we have cooperative
+ device drivers... */
+ do_xlseg_request(rq);
+}
+
+/*
+ * do_xlseg_request
+ * read a block; request is in a request queue
+ */
+static void do_xlseg_request (request_queue_t *rq)
+{
+ struct request *req;
+ struct buffer_head *bh;
+ int rw, nsect, full, queued = 0;
+
+ /* DPRINTK("do_xlseg_request for '%s'\n", DEVICE_NAME); */
+
+ while ( !rq->plugged && !QUEUE_EMPTY )
+ {
+ if ( (req = CURRENT) == NULL ) goto out;
+
+ DPRINTK("do_xlseg_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
+ req, req->cmd, req->sector,
+ req->current_nr_sectors, req->nr_sectors, req->bh);
+
+ rw = req->cmd;
+ if ( rw == READA ) rw = READ;
+ if ((rw != READ) && (rw != WRITE))
+ panic("XenoLinux Virtual Segment Device: bad cmd: %d\n", rw);
+
+ req->errors = 0;
+
+ bh = req->bh;
+ while ( bh != NULL )
+ {
+ full = hypervisor_request(
+ bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE,
+ bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
+ (struct gendisk *)xlseg_disk_info.disks[0].gendisk);
+
+ if ( full )
+ {
+ goto out;
+ }
+
+ queued++;
+
+ /* Dequeue the buffer head from the request. */
+ nsect = bh->b_size >> 9;
+ req->bh = bh->b_reqnext;
+ bh->b_reqnext = NULL;
+ bh = req->bh;
+
+ if ( bh != NULL )
+ {
+ /* There's another buffer head to do. Update the request. */
+ req->hard_sector += nsect;
+ req->hard_nr_sectors -= nsect;
+ req->sector = req->hard_sector;
+ req->nr_sectors = req->hard_nr_sectors;
+ req->current_nr_sectors = bh->b_size >> 9;
+ req->buffer = bh->b_data;
+ }
+ else
+ {
+ /* That was the last buffer head. Finalise the request. */
+ if ( end_that_request_first(req, 1, "XenSeg") ) BUG();
+ blkdev_dequeue_request(req);
+ end_that_request_last(req);
+ }
+ }
+ }
+
+ out:
+ if ( queued != 0 ) HYPERVISOR_block_io_op();
+}
+
+
+static struct block_device_operations xenolinux_segment_fops =
+{
+ open: xenolinux_segment_open,
+ release: xenolinux_segment_release,
+ ioctl: xenolinux_segment_ioctl,
+ check_media_change: xenolinux_segment_check,
+ revalidate: xenolinux_segment_revalidate,
+};
+
+
+int __init xlseg_init(void)
+{
+ int i, result;
+ int counter;
+
+ /* probe for disk information */
+ memset (&xlseg_disk_info, 0, sizeof(xlseg_disk_info));
+ xlseg_disk_info.count = 0;
+
+
+ {
+ /* get lock xlblk_control_lock */
+ counter = atomic_read(&xlblk_control_count);
+ atomic_inc(&xlblk_control_count);
+ /* release lock xlblk_control_lock */
+ }
+ if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_SEG,
+ (char *) &xlseg_disk_info,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *)NULL) )
+ BUG();
+ HYPERVISOR_block_io_op();
+ while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+ printk (KERN_ALERT "vhd block device probe:\n");
+ for ( i = 0; i < xlseg_disk_info.count; i++ )
+ {
+ printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
+ i, xlseg_disk_info.disks[i].type,
+ xlseg_disk_info.disks[i].capacity);
+ }
+
+ SET_MODULE_OWNER(&xenolinux_segment_fops);
+ result = register_blkdev(xlseg_major, "segment", &xenolinux_segment_fops);
+ if (result < 0) {
+ printk (KERN_ALERT "xenolinux segment: can't get major %d\n",
+ xlseg_major);
+ return result;
+ }
+
+ /* initialize global arrays in drivers/block/ll_rw_block.c */
+ for (i = 0; i < XLSEG_MAX; i++)
+ {
+ xlseg_blk_size[i] = xlseg_disk_info.disks[0].capacity ;
+ xlseg_blksize_size[i] = 512;
+ xlseg_hardsect_size[i] = 512;
+ xlseg_max_sectors[i] = 128;
+ }
+ xlseg_read_ahead = 8;
+
+ blk_size[xlseg_major] = xlseg_blk_size;
+ blksize_size[xlseg_major] = xlseg_blksize_size;
+ hardsect_size[xlseg_major] = xlseg_hardsect_size;
+ read_ahead[xlseg_major] = xlseg_read_ahead;
+ max_sectors[xlseg_major] = xlseg_max_sectors;
+
+ blk_init_queue(BLK_DEFAULT_QUEUE(xlseg_major), do_xlseg_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(xlseg_major), 0);
+
+ xlseg_register_disk(0, xlseg_disk_info.disks[0].capacity);
+
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver installed [device: %d]\n",
+ xlseg_major);
+ return 0;
+}
+
+void xlseg_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 */
+
+#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
+
+ 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 = xlseg_major;
+ gd->major_name = XLSEG_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_segment_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);
+
+ xlseg_disk_info.disks[idx].gendisk = gd;
+
+ register_disk(gd, MKDEV(xlseg_major, 0), 1<<IDE_PARTN_BITS,
+ &xenolinux_segment_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 xlseg_cleanup(void)
+{
+ /* CHANGE FOR MULTIQUEUE */
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlseg_major));
+
+ /* clean up global arrays */
+ read_ahead[xlseg_major] = 0;
+
+ if (blk_size[xlseg_major])
+ kfree(blk_size[xlseg_major]);
+ blk_size[xlseg_major] = NULL;
+
+ if (blksize_size[xlseg_major])
+ kfree(blksize_size[xlseg_major]);
+ blksize_size[xlseg_major] = NULL;
+
+ if (hardsect_size[xlseg_major])
+ kfree(hardsect_size[xlseg_major]);
+ hardsect_size[xlseg_major] = NULL;
+
+ /* XXX: free each gendisk */
+ if (unregister_blkdev(xlseg_major, "block"))
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver uninstalled w/ errs\n");
+ else
+ printk(KERN_ALERT
+ "XenoLinux Virtual Segment Device Driver uninstalled\n");
+
+ return;
+}
+
+
+#ifdef MODULE
+module_init(xlseg_init);
+module_exit(xlseg_cleanup);
+#endif
diff --git a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
new file mode 100644
index 0000000000..8525d7855e
--- /dev/null
+++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
@@ -0,0 +1,280 @@
+/*
+ * xl_segment_proc.c
+ *
+ * XenoLinux virtual disk proc interface .
+ */
+
+
+#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 */
+
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
+
+/******************************************************************/
+
+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_WRITE;
+ }
+ 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 */
+ }
+ if (hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
+ 0, 0, (kdev_t) 0,
+ (struct gendisk *)NULL))
+ BUG();
+ HYPERVISOR_block_io_op();
+
+ while (atomic_read(&xlblk_control_count) != counter) barrier();
+
+ return count;
+}
+
+/******************************************************************/
+
+int __init xlseg_proc_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 Monitor installed\n");
+ return 0;
+}
+
+static void __exit xlseg_proc_cleanup(void)
+{
+ printk(KERN_ALERT "XenoLinux Virtual Disk Device Monitor uninstalled\n");
+}
+
+#ifdef MODULE
+module_init(xlseg_proc_init);
+module_exit(xlseg_proc_cleanup);
+#endif
diff --git a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
index 4fd98e94a5..842dd069f1 100644
--- a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
+++ b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c
@@ -1504,6 +1504,8 @@ int __init blk_dev_init(void)
#ifdef CONFIG_XENOLINUX_BLOCK
xlblk_init();
+ xlseg_init();
+ xlseg_proc_init();
#endif
return 0;
diff --git a/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h b/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
index 0be65ab99d..e7fa201955 100644
--- a/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
+++ b/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h
@@ -328,6 +328,13 @@ static void floppy_off(unsigned int nr);
/* #define DEVICE_INTR */
#define DEVICE_NR(device) (MINOR(device))
+#elif (MAJOR_NR == XLSEG_MAJOR)
+
+#define DEVICE_NAME "xeno segment"
+#define DEVICE_REQUEST do_xlseg_request
+/* #define DEVICE_INTR */
+#define DEVICE_NR(device) (MINOR(device))
+
#endif /* MAJOR_NR == whatever */
/* provide DEVICE_xxx defaults, if not explicitly defined