ia64/xen-unstable

changeset 261:8d7cbb78020d

bitkeeper revision 1.108 (3e676eb6Jy0anfrUlVCNnVZnDDSlQg)

virtual block device support
author ach61@labyrinth.cl.cam.ac.uk
date Thu Mar 06 15:52:22 2003 +0000 (2003-03-06)
parents d5a6350b99c8
children 9888f92572ba
files .rootkeys xen/drivers/block/xen_block.c xen/drivers/block/xen_segment.c xen/include/hypervisor-ifs/block.h xen/include/hypervisor-ifs/xeno-major.h xen/include/xeno/major.h xen/include/xeno/segment.h xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c xenolinux-2.4.21-pre4-sparse/include/linux/blk.h xenolinux-2.4.21-pre4-sparse/include/linux/major.h xenolinux-2.4.21-pre4-sparse/init/do_mounts.c
line diff
     1.1 --- a/.rootkeys	Wed Mar 05 20:14:40 2003 +0000
     1.2 +++ b/.rootkeys	Thu Mar 06 15:52:22 2003 +0000
     1.3 @@ -382,6 +382,7 @@ 3ddb79c3uPGcP_l_2xyGgBSWd5aC-Q xen/inclu
     1.4  3ddb79c2YTaZwOqWin9-QNgHge5RVw xen/include/hypervisor-ifs/block.h
     1.5  3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h
     1.6  3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h
     1.7 +3e676eb5yHx7feWgYoqlwD2Z9WsY1w xen/include/hypervisor-ifs/xeno-major.h
     1.8  3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h
     1.9  3ddb79c4R4iVwqIIeychVQYmIH4FUg xen/include/scsi/scsi_ioctl.h
    1.10  3ddb79c4yw_mfd4Uikn3v_IOPRpa1Q xen/include/scsi/scsicam.h
    1.11 @@ -476,7 +477,8 @@ 3e6377fbMjXWAQd0XN0FWv4fDEo6fg xenolinux
    1.12  3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
    1.13  3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
    1.14  3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
    1.15 -3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
    1.16 +3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
    1.17 +3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
    1.18  3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
    1.19  3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/console.c
    1.20  3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/Makefile
     2.1 --- a/xen/drivers/block/xen_block.c	Wed Mar 05 20:14:40 2003 +0000
     2.2 +++ b/xen/drivers/block/xen_block.c	Thu Mar 06 15:52:22 2003 +0000
     2.3 @@ -41,7 +41,8 @@ static atomic_t nr_pending;
     2.4  static void io_schedule(unsigned long unused);
     2.5  static int do_block_io_op_domain(struct task_struct *p, int max_to_do);
     2.6  static void dispatch_rw_block_io(struct task_struct *p, int index);
     2.7 -static void dispatch_probe_block_io(struct task_struct *p, int index);
     2.8 +static void dispatch_probe_blk(struct task_struct *p, int index);
     2.9 +static void dispatch_probe_seg(struct task_struct *p, int index);
    2.10  static void dispatch_debug_block_io(struct task_struct *p, int index);
    2.11  static void dispatch_create_segment(struct task_struct *p, int index);
    2.12  static void dispatch_delete_segment(struct task_struct *p, int index);
    2.13 @@ -202,8 +203,12 @@ static int do_block_io_op_domain(struct 
    2.14  	    dispatch_rw_block_io(p, i);
    2.15  	    break;
    2.16  
    2.17 -	case XEN_BLOCK_PROBE:
    2.18 -	    dispatch_probe_block_io(p, i);
    2.19 +	case XEN_BLOCK_PROBE_BLK:
    2.20 +	    dispatch_probe_blk(p, i);
    2.21 +	    break;
    2.22 +
    2.23 +	case XEN_BLOCK_PROBE_SEG:
    2.24 +	    dispatch_probe_seg(p, i);
    2.25  	    break;
    2.26  
    2.27  	case XEN_BLOCK_DEBUG:
    2.28 @@ -248,6 +253,7 @@ static void dispatch_create_segment(stru
    2.29  
    2.30    xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
    2.31    result = xen_segment_create(xvd);
    2.32 +
    2.33    make_response(p, blk_ring->ring[index].req.id, 
    2.34  		XEN_BLOCK_SEG_CREATE, result); 
    2.35    return;
    2.36 @@ -258,7 +264,7 @@ static void dispatch_delete_segment(stru
    2.37      DPRINTK("dispatch_delete_segment: unimplemented\n"); 
    2.38  }
    2.39  
    2.40 -static void dispatch_probe_block_io(struct task_struct *p, int index)
    2.41 +static void dispatch_probe_blk(struct task_struct *p, int index)
    2.42  {
    2.43      extern void ide_probe_devices(xen_disk_info_t *xdi, int *count, 
    2.44  				  drive_t xdrives[]);
    2.45 @@ -269,7 +275,19 @@ static void dispatch_probe_block_io(stru
    2.46      ide_probe_devices(xdi, &num_xdrives, xdrives);
    2.47      /* scsi_probe_devices(xdi, &num_xdrives, xdrives); */          /* future */
    2.48  
    2.49 -    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, 0);
    2.50 +    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, 0);
    2.51 +}
    2.52 +
    2.53 +static void dispatch_probe_seg(struct task_struct *p, int index)
    2.54 +{
    2.55 +    extern void xen_segment_probe(xen_disk_info_t *xdi, int *count);
    2.56 +    blk_ring_t *blk_ring = p->blk_ring_base;
    2.57 +    xen_disk_info_t *xdi;
    2.58 +
    2.59 +    xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);    
    2.60 +    xen_segment_probe(xdi, &num_xdrives);
    2.61 +
    2.62 +    make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG, 0);
    2.63  }
    2.64  
    2.65  static void dispatch_rw_block_io(struct task_struct *p, int index)
    2.66 @@ -279,8 +297,11 @@ static void dispatch_rw_block_io(struct 
    2.67      struct buffer_head *bh;
    2.68      int operation;
    2.69      unsigned short size;
    2.70 +    unsigned long  block_number = 0L;
    2.71 +    unsigned long  sector_number = 0L;
    2.72      unsigned long buffer, pfn;
    2.73      struct pfn_info *page;
    2.74 +    int xen_device, phys_device = 0;
    2.75  
    2.76      operation = (blk_ring->ring[index].req.operation == XEN_BLOCK_WRITE) ? 
    2.77          WRITE : READ;
    2.78 @@ -345,11 +366,50 @@ static void dispatch_rw_block_io(struct 
    2.79  
    2.80      /* set just the important bits of the buffer header */
    2.81      memset (bh, 0, sizeof (struct buffer_head));
    2.82 +
    2.83 +    /* map from virtual xeno devices to physical ide & scsi devices */
    2.84 +    xen_device = blk_ring->ring[index].req.device;
    2.85 +    if (IS_XHD_MAJOR(xen_device))
    2.86 +    {
    2.87 +      if (xen_device == XHDA_MAJOR)    	 phys_device = MKDEV(IDE0_MAJOR, 0);
    2.88 +      else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
    2.89 +      else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
    2.90 +      else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
    2.91 +      else
    2.92 +      {
    2.93 +	printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
    2.94 +		xen_device);
    2.95 +	BUG();
    2.96 +      }
    2.97 +
    2.98 +      block_number = blk_ring->ring[index].req.block_number;
    2.99 +      sector_number = blk_ring->ring[index].req.sector_number;
   2.100 +    }
   2.101 +    else if (IS_VHD_MAJOR(xen_device))
   2.102 +    {
   2.103 +      int s;
   2.104 +      if (s = xen_segment_map_request(&phys_device, &block_number, 
   2.105 +				      &sector_number,
   2.106 +				      p, operation, xen_device,
   2.107 +				      blk_ring->ring[index].req.block_number,
   2.108 +				      blk_ring->ring[index].req.sector_number))
   2.109 +      {
   2.110 +	printk ("dispatch_rw_block_io: xen_segment_map_request status: %d\n",
   2.111 +		s);
   2.112 +	goto bad_descriptor;
   2.113 +      }
   2.114 +    }
   2.115 +    else
   2.116 +    {
   2.117 +      printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
   2.118 +	      xen_device);
   2.119 +      BUG();
   2.120 +    }
   2.121      
   2.122 -    bh->b_blocknr       = blk_ring->ring[index].req.block_number;
   2.123 +    bh->b_blocknr       = block_number;
   2.124      bh->b_size          = size;
   2.125 -    bh->b_dev           = blk_ring->ring[index].req.device; 
   2.126 -    bh->b_rsector       = blk_ring->ring[index].req.sector_number;
   2.127 +    bh->b_dev           = phys_device;
   2.128 +    bh->b_rsector       = sector_number;
   2.129      bh->b_data          = phys_to_virt(buffer);
   2.130      bh->b_count.counter = 1;
   2.131      bh->b_end_io        = end_block_io_op;
   2.132 @@ -373,6 +433,7 @@ static void dispatch_rw_block_io(struct 
   2.133      return;
   2.134  
   2.135   bad_descriptor:
   2.136 +    printk (KERN_ALERT "dispatch rw blockio bad descriptor\n");
   2.137      make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
   2.138      return;
   2.139  } 
   2.140 @@ -407,8 +468,23 @@ static void make_response(struct task_st
   2.141  
   2.142  static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs) 
   2.143  {
   2.144 -    printk("Dumping block queue stats: nr_pending = %d\n",
   2.145 -           atomic_read(&nr_pending));
   2.146 +  struct task_struct *p;
   2.147 +  blk_ring_t *blk_ring ;
   2.148 +
   2.149 +  printk("Dumping block queue stats: nr_pending = %d\n",
   2.150 +	 atomic_read(&nr_pending));
   2.151 +
   2.152 +  p = current->next_task;
   2.153 +  do
   2.154 +  {
   2.155 +    printk (KERN_ALERT "Domain: %d\n", p->domain);
   2.156 +    blk_ring = p->blk_ring_base;
   2.157 +
   2.158 +    printk("  req_prod:%d, resp_prod:%d, req_cons:%d\n",
   2.159 +	   blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
   2.160 +
   2.161 +    p = p->next_task;
   2.162 +  } while (p != current);
   2.163  }
   2.164  
   2.165  /* Start-of-day initialisation for a new domain. */
   2.166 @@ -419,7 +495,11 @@ void init_blkdev_info(struct task_struct
   2.167      clear_page(p->blk_ring_base);
   2.168      SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
   2.169      p->blkdev_list.next = NULL;
   2.170 +
   2.171 +    memset(p->segment_list, 0, sizeof(p->segment_list));
   2.172      p->segment_count = 0;
   2.173 +
   2.174 +    xen_refresh_segment_list(p);      /* get any previously created segments */
   2.175  }
   2.176  
   2.177  /* End-of-day teardown for a domain. XXX Outstanding requests? */
     3.1 --- a/xen/drivers/block/xen_segment.c	Wed Mar 05 20:14:40 2003 +0000
     3.2 +++ b/xen/drivers/block/xen_segment.c	Thu Mar 06 15:52:22 2003 +0000
     3.3 @@ -9,8 +9,12 @@
     3.4  #include <xeno/slab.h>
     3.5  #include <xeno/segment.h>
     3.6  #include <xeno/sched.h>
     3.7 +#include <xeno/blkdev.h>
     3.8  #include <xeno/keyhandler.h>
     3.9 +#include <asm/current.h>
    3.10 +#include <asm/domain_page.h>
    3.11  #include <hypervisor-ifs/block.h>
    3.12 +#include <hypervisor-ifs/xeno-major.h>
    3.13  
    3.14  int     num_xdrives;
    3.15  drive_t xdrives[XEN_MAX_DISK_COUNT];
    3.16 @@ -18,6 +22,104 @@ drive_t xdrives[XEN_MAX_DISK_COUNT];
    3.17  segment_t xsegments[XEN_MAX_SEGMENTS];
    3.18  
    3.19  /*
    3.20 + * xen_segment_map_request
    3.21 + *
    3.22 + * xen_device must be a valid device.
    3.23 + */
    3.24 +
    3.25 +int xen_segment_map_request(int *phys_device,                         /* out */
    3.26 +			    unsigned long *block_number,              /* out */
    3.27 +			    unsigned long *sector_number,             /* out */
    3.28 +			    struct task_struct *domain,
    3.29 +			    int operation,
    3.30 +			    int xen_device,
    3.31 +			    int xen_block_number,
    3.32 +			    int xen_sector_number)
    3.33 +{
    3.34 +  segment_t *seg;
    3.35 +  int segment_number;                   /* segment number within this domain */
    3.36 +  int sum; 
    3.37 +  int loop;
    3.38 +
    3.39 +  segment_number = xen_device - XLSEG_MAJOR;
    3.40 +  seg = domain->segment_list[segment_number];
    3.41 +
    3.42 +  if (seg == NULL)
    3.43 +  {
    3.44 +    return 1;                                       /* oops.  no vhd exists! */
    3.45 +  }
    3.46 +
    3.47 +  /* check domain permissions */
    3.48 +  if (seg->domain != domain->domain)
    3.49 +  {
    3.50 +    return 2;                                  /* domain doesn't own segment */
    3.51 +  }
    3.52 +
    3.53 +  /* check rw access */
    3.54 +  if ((operation == WRITE && seg->mode != XEN_SEGMENT_RW) ||
    3.55 +      (operation == READ  && seg->mode == XEN_SEGMENT_UNUSED))
    3.56 +  {
    3.57 +    return 3;                                            /* access violation */
    3.58 +  }
    3.59 +
    3.60 +  /* find extent, check size */
    3.61 +  sum = 0; 
    3.62 +  loop = 0;
    3.63 +  while (loop < seg->num_extents && sum <= xen_block_number)
    3.64 +  {
    3.65 +    sum += seg->extents[loop++].size;
    3.66 +  }
    3.67 +  sum -= seg->extents[--loop].size;                                /* rewind */
    3.68 +
    3.69 +  if (sum + seg->extents[loop].size <= xen_block_number)
    3.70 +  {
    3.71 +    return 4;                   /* tried to read past the end of the segment */
    3.72 +  }
    3.73 +  *block_number = xen_block_number - sum + seg->extents[loop].offset;
    3.74 +  *sector_number = xen_sector_number - sum + seg->extents[loop].offset;;
    3.75 +
    3.76 +  /* get physical device from xdrives */
    3.77 +  *phys_device = MKDEV(xdrives[seg->extents[loop].disk].major, 0);
    3.78 +
    3.79 +  /*
    3.80 +  printk ("%d %lx %lx %lx %lx :  %lx %lx %lx %lx\n",
    3.81 +	  operation,
    3.82 +	  *block_number, xen_block_number, sum, seg->extents[loop].offset,
    3.83 +	  *sector_number, xen_sector_number, sum, seg->extents[loop].offset
    3.84 +	  );
    3.85 +  */
    3.86 +
    3.87 +  return 0;
    3.88 +}
    3.89 +
    3.90 +/*
    3.91 + * xen_segment_probe
    3.92 + *
    3.93 + * return a list of segments to the guestos
    3.94 + */
    3.95 +void xen_segment_probe (xen_disk_info_t *raw_xdi, int *count)
    3.96 +{
    3.97 +  int loop, i;
    3.98 +  xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi));
    3.99 +
   3.100 +  for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
   3.101 +  {
   3.102 +    if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
   3.103 +    {
   3.104 +      xdi->disks[xdi->count].type = XEN_DISK_VIRTUAL;
   3.105 +      for (i = 0; i < xsegments[loop].num_extents; i++)
   3.106 +      {
   3.107 +	xdi->disks[xdi->count].capacity += xsegments[loop].extents[i].size;
   3.108 +      }
   3.109 +      xdi->count++;
   3.110 +    }
   3.111 +  }
   3.112 +
   3.113 +  unmap_domain_mem(xdi);
   3.114 +  return;
   3.115 +}
   3.116 +
   3.117 +/*
   3.118   * xen_refresh_segment_list
   3.119   *
   3.120   * find all segments associated with a domain and assign
   3.121 @@ -59,7 +161,8 @@ int xen_segment_create(xv_disk_t *xvd_in
   3.122    }
   3.123    if (idx == XEN_MAX_SEGMENTS)
   3.124    {
   3.125 -    printk (KERN_ALERT "error: xen_segment_create unable to find free slot\n");
   3.126 +    printk (KERN_ALERT "xen_segment_create: unable to find free slot\n");
   3.127 +    unmap_domain_mem(xvd);
   3.128      return 1;
   3.129    }
   3.130  
   3.131 @@ -76,8 +179,16 @@ int xen_segment_create(xv_disk_t *xvd_in
   3.132      xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
   3.133      xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
   3.134      xsegments[idx].extents[loop].size = xvd->extents[loop].size;
   3.135 +    if (xsegments[idx].extents[loop].size == 0) 
   3.136 +    {
   3.137 +      printk (KERN_ALERT "xen_segment_create: extent %d is zero length\n",
   3.138 +	      loop);
   3.139 +      unmap_domain_mem(xvd);
   3.140 +      return 1;
   3.141 +    }
   3.142    }
   3.143  
   3.144 +  unmap_domain_mem(xvd);
   3.145    return 0;
   3.146  }
   3.147  
   3.148 @@ -96,6 +207,7 @@ int xen_segment_delete(struct task_struc
   3.149  static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs) 
   3.150  {
   3.151    int loop, i;
   3.152 +  struct task_struct *p;
   3.153  
   3.154    printk (KERN_ALERT "xdrives\n");
   3.155    for (loop = 0; loop < num_xdrives; loop++)
   3.156 @@ -103,7 +215,7 @@ static void dump_segments(u_char key, vo
   3.157      printk (KERN_ALERT " %2d: major: 0x%d\n", loop, xdrives[loop].major);
   3.158    }
   3.159    
   3.160 -  printk (KERN_ALERT "segments\n");
   3.161 +  printk (KERN_ALERT "segment list\n");
   3.162    for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
   3.163    {
   3.164      if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
   3.165 @@ -122,6 +234,22 @@ static void dump_segments(u_char key, vo
   3.166        } 
   3.167      }
   3.168    }
   3.169 +
   3.170 +  printk (KERN_ALERT "segments by domain\n");
   3.171 +  p = current->next_task;
   3.172 +  do
   3.173 +  {
   3.174 +    printk (KERN_ALERT "  domain: %d\n", p->domain);
   3.175 +    for (loop = 0; loop < p->segment_count; loop++)
   3.176 +    {
   3.177 +      printk (KERN_ALERT "    mode:%d domain:%d seg:%d exts:%d\n",
   3.178 +	      p->segment_list[loop]->mode,
   3.179 +	      p->segment_list[loop]->domain,
   3.180 +	      p->segment_list[loop]->segment_number,
   3.181 +	      p->segment_list[loop]->num_extents);
   3.182 +    }
   3.183 +    p = p->next_task;
   3.184 +  } while (p != current);
   3.185  }
   3.186  
   3.187  /*
     4.1 --- a/xen/include/hypervisor-ifs/block.h	Wed Mar 05 20:14:40 2003 +0000
     4.2 +++ b/xen/include/hypervisor-ifs/block.h	Thu Mar 06 15:52:22 2003 +0000
     4.3 @@ -22,10 +22,11 @@
     4.4  #define XEN_BLOCK_WRITE 1
     4.5  #define XEN_BLOCK_READA 2                                /* currently unused */
     4.6  #define XEN_BLOCK_SPECIAL 4                              /* currently unused */
     4.7 -#define XEN_BLOCK_PROBE 8      /* determine io configuration from hypervisor */
     4.8 -#define XEN_BLOCK_DEBUG 16                                          /* debug */
     4.9 +#define XEN_BLOCK_PROBE_BLK  8             /* get xhd config from hypervisor */
    4.10 +#define XEN_BLOCK_DEBUG      16                                     /* debug */
    4.11  #define XEN_BLOCK_SEG_CREATE 32                      /* create segment (vhd) */
    4.12  #define XEN_BLOCK_SEG_DELETE 64                      /* delete segment (vhd) */
    4.13 +#define XEN_BLOCK_PROBE_SEG  128           /* get vhd config from hypervisor */
    4.14  
    4.15  #define BLK_RING_SIZE        128
    4.16  #define BLK_RING_MAX_ENTRIES (BLK_RING_SIZE - 2)
    4.17 @@ -70,6 +71,7 @@ typedef struct blk_ring_st
    4.18  
    4.19  #define XEN_DISK_IDE  1
    4.20  #define XEN_DISK_SCSI 2
    4.21 +#define XEN_DISK_VIRTUAL 3                                            /* vhd */
    4.22  
    4.23  typedef struct xen_disk                                     /* physical disk */
    4.24  {
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/include/hypervisor-ifs/xeno-major.h	Thu Mar 06 15:52:22 2003 +0000
     5.3 @@ -0,0 +1,37 @@
     5.4 +/*
     5.5 + * xeno_major.h
     5.6 + *
     5.7 + * shared definitions for block IO.
     5.8 + */
     5.9 +
    5.10 +/*
    5.11 + * this belongs in xenolinux/include/linux/major.h except that
    5.12 + * xen also needs access...
    5.13 + */
    5.14 +
    5.15 +
    5.16 +#ifndef __XENO_MAJOR_H__
    5.17 +#define __XENO_MAJOR_H__
    5.18 +
    5.19 +
    5.20 +#define XLBLK_MAJOR	123                   /* XenoLinux Block Device: xhd */
    5.21 +#define XHDA_MAJOR      123
    5.22 +#define XHDB_MAJOR      124
    5.23 +#define XHDC_MAJOR      125
    5.24 +#define XHDD_MAJOR      126
    5.25 +#define XLSEG_MAJOR     234                 /* XenoLinux Segment Device: vhd */
    5.26 +#define VHDA_MAJOR      234
    5.27 +#define VHDB_MAJOR      235
    5.28 +#define VHDC_MAJOR      236
    5.29 +#define VHDD_MAJOR      237
    5.30 +
    5.31 +
    5.32 +/*
    5.33 + * XenoLinux Block Device Tests
    5.34 + */
    5.35 +#define IS_XHD_MAJOR(M) ( (M) == XHDA_MAJOR || (M) == XHDB_MAJOR || \
    5.36 +                          (M) == XHDC_MAJOR || (M) == XHDD_MAJOR ? 1 : 0)
    5.37 +#define IS_VHD_MAJOR(M) ( (M) == VHDA_MAJOR || (M) == VHDB_MAJOR || \
    5.38 +                          (M) == VHDC_MAJOR || (M) == VHDD_MAJOR ? 1 : 0)
    5.39 +
    5.40 +#endif
     6.1 --- a/xen/include/xeno/major.h	Wed Mar 05 20:14:40 2003 +0000
     6.2 +++ b/xen/include/xeno/major.h	Thu Mar 06 15:52:22 2003 +0000
     6.3 @@ -144,6 +144,9 @@
     6.4  
     6.5  #define	UMEM_MAJOR	116	/* http://www.umem.com/ Battery Backed RAM */
     6.6  
     6.7 +/* note: 123, 124, 125, 126 and 234, 235, 236, 237 are defined in xeno_major */
     6.8 +#include <hypervisor-ifs/xeno-major.h>
     6.9 +
    6.10  #define RTF_MAJOR	150
    6.11  #define RAW_MAJOR	162
    6.12  
     7.1 --- a/xen/include/xeno/segment.h	Wed Mar 05 20:14:40 2003 +0000
     7.2 +++ b/xen/include/xeno/segment.h	Thu Mar 06 15:52:22 2003 +0000
     7.3 @@ -6,6 +6,14 @@
     7.4  void xen_segment_initialize(void);
     7.5  void xen_refresh_segment_list (struct task_struct *p);
     7.6  int xen_segment_create(xv_disk_t *xvd);
     7.7 +int xen_segment_map_request(int *phys_device,                         /* out */
     7.8 +			    unsigned long *block_number,              /* out */
     7.9 +			    unsigned long *sector_number,             /* out */
    7.10 +			    struct task_struct *domain,
    7.11 +			    int operation,
    7.12 +			    int xen_device,
    7.13 +			    int xen_block_number,
    7.14 +			    int xen_sector_number);
    7.15  
    7.16  #define XEN_MAX_SEGMENTS 100     /* total number of segments across all doms */
    7.17  
    7.18 @@ -37,8 +45,8 @@ typedef struct extent
    7.19  } extent_t;
    7.20  
    7.21  #define XEN_SEGMENT_UNUSED 0                                /* bzero default */
    7.22 -#define XEN_SEGMENT_RO XEN_DISK_READ_WRITE
    7.23 -#define XEN_SEGMENT_RW XEN_DISK_READ_ONLY
    7.24 +#define XEN_SEGMENT_RO XEN_DISK_READ_ONLY
    7.25 +#define XEN_SEGMENT_RW XEN_DISK_READ_WRITE
    7.26  
    7.27  typedef struct segment
    7.28  {
     8.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile	Wed Mar 05 20:14:40 2003 +0000
     8.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile	Thu Mar 06 15:52:22 2003 +0000
     8.3 @@ -1,3 +1,3 @@
     8.4  O_TARGET := blk.o
     8.5 -obj-y := xl_block.o xl_segment.o xl_block_test.o
     8.6 +obj-y := xl_block.o xl_segment.o xl_segment_proc.o xl_block_test.o
     8.7  include $(TOPDIR)/Rules.make
     9.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c	Wed Mar 05 20:14:40 2003 +0000
     9.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c	Thu Mar 06 15:52:22 2003 +0000
     9.3 @@ -1,7 +1,7 @@
     9.4  /******************************************************************************
     9.5   * xl_block.c
     9.6   * 
     9.7 - * Xenolinux virtual block-device driver.
     9.8 + * Xenolinux virtual block-device driver (xhd).
     9.9   * 
    9.10   */
    9.11  
    9.12 @@ -32,8 +32,6 @@ static int xlblk_major = XLBLK_MAJOR;
    9.13  /* Copied from linux/ide.h */
    9.14  typedef unsigned char	byte; 
    9.15  
    9.16 -void xlblk_ide_register_disk(int, unsigned long);
    9.17 -
    9.18  #define XLBLK_MAX 32 /* Maximum minor devices we support */
    9.19  #define XLBLK_MAJOR_NAME "xhd"
    9.20  #define IDE_PARTN_BITS 6                           /* from ide.h::PARTN_BITS */
    9.21 @@ -58,15 +56,18 @@ static int xlblk_max_sectors[XLBLK_MAX];
    9.22  
    9.23  static blk_ring_t *blk_ring;
    9.24  static unsigned int resp_cons; /* Response consumer for comms ring. */
    9.25 -static xen_disk_info_t xen_disk_info;
    9.26 +static xen_disk_info_t xlblk_disk_info;
    9.27  atomic_t xlblk_control_count;
    9.28  
    9.29 -int hypervisor_request(void *         id,
    9.30 -                       int            operation,
    9.31 -                       char *         buffer,
    9.32 -                       unsigned long  block_number,
    9.33 -                       unsigned short block_size,
    9.34 -                       kdev_t         device);
    9.35 +void xlblk_ide_register_disk(int, unsigned long);
    9.36 +void do_xlseg_requestX (request_queue_t *rq);
    9.37 +int hypervisor_request(void *          id,
    9.38 +                       int             operation,
    9.39 +                       char *          buffer,
    9.40 +                       unsigned long   block_number,
    9.41 +                       unsigned short  block_size,
    9.42 +                       kdev_t          device,
    9.43 +		       struct gendisk *gd);
    9.44  
    9.45  
    9.46  /* ------------------------------------------------------------------------
    9.47 @@ -103,22 +104,39 @@ static int xenolinux_block_ioctl(struct 
    9.48    
    9.49      switch (command)
    9.50      {
    9.51 -    case BLKGETSIZE:
    9.52 +    case BLKGETSIZE:                                             /* get size */
    9.53          DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, 
    9.54 -                      (long) xen_disk_info.disks[0].capacity); 
    9.55 -	return put_user(xen_disk_info.disks[0].capacity, 
    9.56 +                      (long) xlblk_disk_info.disks[0].capacity); 
    9.57 +	return put_user(xlblk_disk_info.disks[0].capacity, 
    9.58  			(unsigned long *) argument);
    9.59  
    9.60 -    case BLKRRPART:
    9.61 +    case BLKRRPART:                               /* re-read partition table */
    9.62          DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART); 
    9.63  	break;
    9.64  
    9.65 -    case BLKSSZGET:
    9.66 +    case BLKBSZGET:                                        /* get block size */
    9.67 +        DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
    9.68 +	break;
    9.69 +
    9.70 +    case BLKBSZSET:                                        /* set block size */
    9.71 +        DPRINTK_IOCTL("   BLKBSZSET: %x\n", BLKBSZSET);
    9.72 +	break;
    9.73 +
    9.74 +    case BLKRASET:                                         /* set read-ahead */
    9.75 +        DPRINTK_IOCTL("   BLKRASET: %x\n", BLKRASET);
    9.76 +	break;
    9.77 +
    9.78 +    case BLKRAGET:                                         /* get read-ahead */
    9.79 +        DPRINTK_IOCTL("   BLKRAFET: %x\n", BLKRAGET);
    9.80 +	break;
    9.81 +
    9.82 +    case BLKSSZGET:                                       /* get sector size */
    9.83          DPRINTK_IOCTL("   BLKSSZGET: %x 0x%x\n", BLKSSZGET,
    9.84                        xlblk_hardsect_size[minor_dev]);
    9.85  	return xlblk_hardsect_size[minor_dev]; 
    9.86  
    9.87      case HDIO_GETGEO:
    9.88 +        /* note: these values are complete garbage */
    9.89          DPRINTK_IOCTL("   HDIO_GETGEO: %x\n", HDIO_GETGEO);
    9.90  	if (!argument) return -EINVAL;
    9.91  	if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
    9.92 @@ -128,13 +146,13 @@ static int xenolinux_block_ioctl(struct 
    9.93  	return 0;
    9.94  
    9.95      case HDIO_GETGEO_BIG: 
    9.96 +        /* note: these values are complete garbage */
    9.97          DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
    9.98  	if (!argument) return -EINVAL;
    9.99  	if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
   9.100  	if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
   9.101  	if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   9.102  	if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
   9.103 -
   9.104  	return 0;
   9.105  
   9.106      default:
   9.107 @@ -163,26 +181,27 @@ static int xenolinux_block_revalidate(kd
   9.108   * request block io 
   9.109   * 
   9.110   * id: for guest use only.
   9.111 - * operation: XEN_BLOCK_READ, XEN_BLOCK_WRITE or XEN_BLOCK_PROBE
   9.112 + * operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*}
   9.113   * buffer: buffer to read/write into. this should be a
   9.114   *   virtual address in the guest os.
   9.115   * block_number:  block to read
   9.116   * block_size:  size of each block
   9.117 - * device:  ide/hda is 768 or 0x300           should be disk#!!!
   9.118 + * device:  xhd or vhd
   9.119 + * gd: partition information if XEN_BLOCK_{READ,WRITE}
   9.120   */
   9.121 -int hypervisor_request(void *         id,
   9.122 -                       int            operation,
   9.123 -                       char *         buffer,
   9.124 -                       unsigned long  block_number,
   9.125 -                       unsigned short block_size,
   9.126 -                       kdev_t         device)
   9.127 +int hypervisor_request(void *          id,
   9.128 +                       int             operation,
   9.129 +                       char *          buffer,
   9.130 +                       unsigned long   block_number,
   9.131 +                       unsigned short  block_size,
   9.132 +                       kdev_t          device,
   9.133 +		       struct gendisk *gd)
   9.134  {
   9.135      int position;
   9.136      void *buffer_ma; 
   9.137      kdev_t phys_device = (kdev_t) 0;
   9.138      unsigned long sector_number = 0;
   9.139 -    struct gendisk *gd;     
   9.140 -
   9.141 + 
   9.142      /*
   9.143       * Bail if there's no room in the request communication ring. This may be 
   9.144       * because we have a whole bunch of outstanding responses to process. No 
   9.145 @@ -197,21 +216,38 @@ int hypervisor_request(void *         id
   9.146      {
   9.147      case XEN_BLOCK_SEG_CREATE:
   9.148      case XEN_BLOCK_SEG_DELETE:
   9.149 -    case XEN_BLOCK_PROBE:
   9.150 +    case XEN_BLOCK_PROBE_BLK:
   9.151 +    case XEN_BLOCK_PROBE_SEG:
   9.152  	phys_device = (kdev_t) 0;
   9.153  	sector_number = 0;
   9.154          break;
   9.155  
   9.156      case XEN_BLOCK_READ:
   9.157      case XEN_BLOCK_WRITE:
   9.158 -	if ( MAJOR(device) != XLBLK_MAJOR ) 
   9.159 +        /* only accept requests for xhd and vhd devices */
   9.160 +	if (!IS_XHD_MAJOR(MAJOR(device)) && !IS_VHD_MAJOR(MAJOR(device)))
   9.161  	    panic("error: xl_block::hypervisor_request: "
   9.162                    "unknown device [0x%x]\n", device);
   9.163 -        phys_device = MKDEV(IDE0_MAJOR, 0);
   9.164 -	/* Compute real buffer location on disk */
   9.165 +	phys_device = MAJOR(device);
   9.166 +
   9.167 +	/* Compute real buffer location on disk.
   9.168 +	 * note: gd will be null when we read the partition table.
   9.169 +	 */
   9.170  	sector_number = block_number;
   9.171 -	if ( (gd = (struct gendisk *)xen_disk_info.disks[0].gendisk) != NULL )
   9.172 -	    sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
   9.173 +	if ( gd != NULL )
   9.174 +	{
   9.175 +	  sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
   9.176 +	}
   9.177 +
   9.178 +	/*
   9.179 +	if (IS_VHD_MAJOR(MAJOR(device)))
   9.180 +	{
   9.181 +	  printk (KERN_ALERT "%lx + %lx = %lx (%x)\n",
   9.182 +		  block_number,
   9.183 +		  gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect,
   9.184 +		  sector_number, device);
   9.185 +	}
   9.186 +	*/
   9.187          break;
   9.188  
   9.189      default:
   9.190 @@ -266,8 +302,9 @@ static void do_xlblk_request (request_qu
   9.191  	{
   9.192              full = hypervisor_request(
   9.193                  bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
   9.194 -                bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev);
   9.195 -            
   9.196 +                bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
   9.197 +		(struct gendisk *)xlblk_disk_info.disks[0].gendisk);
   9.198 +
   9.199              if ( full ) goto out;
   9.200  
   9.201              queued++;
   9.202 @@ -334,6 +371,7 @@ static void xlblk_response_int(int irq, 
   9.203  	    
   9.204  	  case XEN_BLOCK_SEG_CREATE :
   9.205  	  case XEN_BLOCK_SEG_DELETE :
   9.206 +	  case XEN_BLOCK_PROBE_SEG :
   9.207  	    atomic_dec(&xlblk_control_count);
   9.208  	    break;
   9.209  	  
   9.210 @@ -345,7 +383,9 @@ static void xlblk_response_int(int irq, 
   9.211      resp_cons = i;
   9.212  
   9.213      /* KAF: We can push work down at this point. We have the lock. */
   9.214 -    do_xlblk_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
   9.215 +    /* aho: okay, so this is a bit of a hack.  we'll kick every queue... */
   9.216 +    do_xlblk_request(BLK_DEFAULT_QUEUE(XLBLK_MAJOR));
   9.217 +    do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
   9.218      
   9.219      spin_unlock_irqrestore(&io_request_lock, flags);
   9.220  }
   9.221 @@ -368,20 +408,23 @@ int __init xlblk_init(void)
   9.222  	goto fail;
   9.223      }
   9.224  
   9.225 -    memset (&xen_disk_info, 0, sizeof(xen_disk_info));
   9.226 -    xen_disk_info.count = 0;
   9.227 +    /* probe for disk information */
   9.228 +    memset (&xlblk_disk_info, 0, sizeof(xlblk_disk_info));
   9.229 +    xlblk_disk_info.count = 0;
   9.230  
   9.231 -    if ( hypervisor_request(NULL, XEN_BLOCK_PROBE, (char *) &xen_disk_info,
   9.232 -                            0, 0, (kdev_t) 0) )
   9.233 +    if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_BLK, 
   9.234 +			    (char *) &xlblk_disk_info,
   9.235 +                            0, 0, (kdev_t) 0, 
   9.236 +			    (struct gendisk *) NULL))
   9.237          BUG();
   9.238      HYPERVISOR_block_io_op();
   9.239      while ( blk_ring->resp_prod != 1 ) barrier();
   9.240 -    printk (KERN_ALERT "block device probe:\n");
   9.241 -    for ( i = 0; i < xen_disk_info.count; i++ )
   9.242 +    printk (KERN_ALERT "xhd block device probe:\n");
   9.243 +    for ( i = 0; i < xlblk_disk_info.count; i++ )
   9.244      { 
   9.245  	printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
   9.246 -		i, xen_disk_info.disks[i].type, 
   9.247 -		xen_disk_info.disks[i].capacity);
   9.248 +		i, xlblk_disk_info.disks[i].type, 
   9.249 +		xlblk_disk_info.disks[i].capacity);
   9.250      }
   9.251      
   9.252      SET_MODULE_OWNER(&xenolinux_block_fops);
   9.253 @@ -394,7 +437,7 @@ int __init xlblk_init(void)
   9.254  
   9.255      /* initialize global arrays in drivers/block/ll_rw_block.c */
   9.256      for (i = 0; i < XLBLK_MAX; i++) {
   9.257 -	xlblk_blk_size[i]      = xen_disk_info.disks[0].capacity;
   9.258 +	xlblk_blk_size[i]      = xlblk_disk_info.disks[0].capacity;
   9.259  	xlblk_blksize_size[i]  = 512;
   9.260  	xlblk_hardsect_size[i] = 512;
   9.261  	xlblk_max_sectors[i]   = 128;
   9.262 @@ -415,7 +458,7 @@ int __init xlblk_init(void)
   9.263       */
   9.264      blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
   9.265  
   9.266 -    xlblk_ide_register_disk(0, xen_disk_info.disks[0].capacity);
   9.267 +    xlblk_ide_register_disk(0, xlblk_disk_info.disks[0].capacity);
   9.268  
   9.269      printk(KERN_ALERT 
   9.270  	   "XenoLinux Virtual Block Device Driver installed [device: %d]\n",
   9.271 @@ -461,13 +504,26 @@ void xlblk_ide_register_disk(int idx, un
   9.272  
   9.273      add_gendisk(gd);
   9.274  
   9.275 -    xen_disk_info.disks[idx].gendisk = gd;
   9.276 +    xlblk_disk_info.disks[idx].gendisk = gd;
   9.277  
   9.278 -    /* default disk size is just a big number.  in the future, we
   9.279 -       need a message to probe the devices to determine the actual size */
   9.280      register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
   9.281  		  &xenolinux_block_fops, capacity);
   9.282  
   9.283 +    {
   9.284 +      int loop = 0;
   9.285 +      printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
   9.286 +      for (loop = 0; loop < minors; loop++)
   9.287 +      {
   9.288 +	if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
   9.289 +	{
   9.290 +	  printk (KERN_ALERT 
   9.291 +		  "  %2d: 0x%6lx %8ld    0x%6lx %7ld\n", loop,
   9.292 +		  gd->part[loop].start_sect, gd->part[loop].start_sect,
   9.293 +		  gd->part[loop].nr_sects, gd->part[loop].nr_sects);
   9.294 +	}
   9.295 +      }
   9.296 +    }
   9.297 +
   9.298      return;
   9.299  }
   9.300  
    10.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c	Wed Mar 05 20:14:40 2003 +0000
    10.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c	Thu Mar 06 15:52:22 2003 +0000
    10.3 @@ -206,7 +206,8 @@ int proc_write_bdt(struct file *file, co
    10.4    /* submit request */
    10.5    hypervisor_request(0, meta.operation, meta.buffer, 
    10.6  		     meta.block_number, meta.block_size,
    10.7 -		     meta.device);
    10.8 +		     meta.device, 
    10.9 +		     (struct gendisk *) NULL);
   10.10    HYPERVISOR_block_io_op();
   10.11    mdelay(1000); /* should wait for a proper acknowledgement/response. */
   10.12  
    11.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c	Wed Mar 05 20:14:40 2003 +0000
    11.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c	Thu Mar 06 15:52:22 2003 +0000
    11.3 @@ -1,274 +1,432 @@
    11.4 -/*
    11.5 +/******************************************************************************
    11.6   * xl_segment.c
    11.7   * 
    11.8 - * XenoLinux virtual disk driver.
    11.9 + * Xenolinux virtual block-device driver (vhd).
   11.10 + * 
   11.11   */
   11.12  
   11.13 -
   11.14  #include <linux/config.h>
   11.15  #include <linux/module.h>
   11.16  
   11.17 -#include <linux/proc_fs.h>
   11.18 -#include <linux/delay.h>
   11.19 -#include <asm/uaccess.h>
   11.20 -#include <asm/atomic.h>
   11.21 +#include <linux/kernel.h>
   11.22 +#include <linux/sched.h>
   11.23 +#include <linux/slab.h>
   11.24 +#include <linux/string.h>
   11.25 +#include <linux/errno.h>
   11.26 +
   11.27 +#include <linux/fs.h>
   11.28 +#include <linux/hdreg.h>
   11.29 +#include <linux/blkdev.h>
   11.30 +#include <linux/major.h>
   11.31  
   11.32  #include <asm/hypervisor-ifs/block.h>
   11.33  #include <asm/hypervisor-ifs/hypervisor-if.h>
   11.34 +#include <asm/io.h>
   11.35 +#include <asm/atomic.h>
   11.36 +#include <asm/uaccess.h>
   11.37  
   11.38 -static struct proc_dir_entry *vhd;
   11.39 -xv_disk_t xvd;
   11.40 +#define MAJOR_NR XLSEG_MAJOR   /* force defns in blk.h, must precede include */
   11.41 +static int xlseg_major = XLSEG_MAJOR;
   11.42 +#include <linux/blk.h>
   11.43 +
   11.44 +/* Copied from linux/ide.h */
   11.45 +typedef unsigned char	byte; 
   11.46 +
   11.47 +#define XLSEG_MAX 32 /* Maximum minor devices we support */
   11.48 +#define XLSEG_MAJOR_NAME "xhd"
   11.49 +
   11.50 +static int xlseg_blk_size[XLSEG_MAX];
   11.51 +static int xlseg_blksize_size[XLSEG_MAX];
   11.52 +static int xlseg_read_ahead; 
   11.53 +static int xlseg_hardsect_size[XLSEG_MAX];
   11.54 +static int xlseg_max_sectors[XLSEG_MAX];
   11.55  
   11.56  extern atomic_t xlblk_control_count;                           /* xl_block.c */
   11.57  
   11.58 -/******************************************************************/
   11.59 +int hypervisor_request(void *          id,
   11.60 +                       int             operation,
   11.61 +                       char *          buffer,
   11.62 +                       unsigned long   block_number,
   11.63 +                       unsigned short  block_size,
   11.64 +                       kdev_t          device,
   11.65 +		       struct gendisk *gd);
   11.66 +void xlseg_register_disk(int idx, unsigned long capacity);
   11.67  
   11.68 -static int proc_read_vhd(char *page, char **start, off_t off,
   11.69 -			 int count, int *eof, void *data)
   11.70 +#if 0
   11.71 +#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
   11.72 +#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
   11.73 +#else
   11.74 +#define DPRINTK(_f, _a...) ((void)0)
   11.75 +#define DPRINTK_IOCTL(_f, _a...) ((void)0)
   11.76 +#endif
   11.77 +
   11.78 +static xen_disk_info_t xlseg_disk_info;
   11.79 +
   11.80 +/* ------------------------------------------------------------------------
   11.81 + */
   11.82 +
   11.83 +static int xenolinux_segment_open(struct inode *inode, struct file *filep)
   11.84  {
   11.85 -  return 0;
   11.86 +    DPRINTK("xenolinux_segment_release\n");
   11.87 +    return 0;
   11.88 +}
   11.89 +
   11.90 +static int xenolinux_segment_release(struct inode *inode, struct file *filep)
   11.91 +{
   11.92 +    DPRINTK("xenolinux_segment_release\n");
   11.93 +    return 0;
   11.94  }
   11.95  
   11.96 -#define isdelim(c) \
   11.97 -  (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
   11.98 -
   11.99 -char *get_string(char *string)                          /* a bit like strtok */
  11.100 +static int xenolinux_segment_ioctl(struct inode *inode, struct file *filep,
  11.101 +				   unsigned command, unsigned long argument)
  11.102  {
  11.103 -  static char *temp;
  11.104 -  int loop = 0;
  11.105 +    int minor_dev;
  11.106 +    struct hd_geometry *geo = (struct hd_geometry *)argument;
  11.107 +    struct gendisk *gd = (struct gendisk *)xlseg_disk_info.disks[0].gendisk;
  11.108 +
  11.109 +    DPRINTK("xenolinux_segment_ioctl\n"); 
  11.110  
  11.111 -  if (string != NULL)	
  11.112 -    temp = string;
  11.113 -  else
  11.114 -    string = temp;
  11.115 +    /* check permissions */
  11.116 +    if (!capable(CAP_SYS_ADMIN)) return -EPERM;
  11.117 +    if (!inode)                  return -EINVAL;
  11.118 +    minor_dev = MINOR(inode->i_rdev);
  11.119 +    if (minor_dev >= XLSEG_MAX)  return -ENODEV;
  11.120 +    
  11.121 +    DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
  11.122 +                  command, (long) argument, minor_dev); 
  11.123 +  
  11.124 +    switch (command)
  11.125 +    {
  11.126 +      case BLKGETSIZE:
  11.127 +	if (gd != NULL)
  11.128 +	{
  11.129 +	  printk(KERN_ALERT "minordev: %d\n", minor_dev);
  11.130 +	  printk(KERN_ALERT "[0] start: %lx\n", gd->part[0].start_sect);
  11.131 +	  printk(KERN_ALERT "[0] count: %lx\n", gd->part[0].nr_sects);
  11.132 +	  printk(KERN_ALERT "[1] start: %lx\n", gd->part[1].start_sect);
  11.133 +	  printk(KERN_ALERT "[1] count: %lx\n", gd->part[1].nr_sects);
  11.134 +	  printk(KERN_ALERT "[2] start: %lx\n", gd->part[2].start_sect);
  11.135 +	  printk(KERN_ALERT "[2] count: %lx\n", gd->part[2].nr_sects);
  11.136 +	  
  11.137 +	  DPRINTK_IOCTL("   BLKGETSIZE gd: %x %lx\n", BLKGETSIZE, 
  11.138 +			gd->part[minor_dev].nr_sects);
  11.139 +	  return put_user(gd->part[minor_dev].nr_sects,
  11.140 +			  (unsigned long *)argument);
  11.141 +	}
  11.142 +	else
  11.143 +	{
  11.144 +	  DPRINTK_IOCTL("   BLKGETSIZE disk: %x %lx\n", BLKGETSIZE, 
  11.145 +			xlseg_disk_info.disks[0].capacity);
  11.146 +	  return put_user(xlseg_disk_info.disks[0].capacity,
  11.147 +			  (unsigned long *) argument);
  11.148 +	}
  11.149 +		      
  11.150 +      case BLKRRPART:
  11.151 +        DPRINTK_IOCTL("   BLKRRPART: \n"); 
  11.152 +	/* we don't have re-validate drive yet...  so you need to reboot! */
  11.153 +	break;
  11.154  
  11.155 - try_again:
  11.156 +      case BLKSSZGET:
  11.157 +        DPRINTK_IOCTL("   BLKSSZGET: %d\n",
  11.158 +		      xlseg_hardsect_size[minor_dev]);
  11.159 +	return xlseg_hardsect_size[minor_dev]; 
  11.160 +
  11.161 +      case HDIO_GETGEO:
  11.162 +        /* note: these values are complete garbage */
  11.163 +        DPRINTK_IOCTL("   HDIO_GETGEO: \n");
  11.164 +	if (!argument) return -EINVAL;
  11.165 +	if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
  11.166 +	if (put_user(0xff,  (byte *)&geo->heads)) return -EFAULT;
  11.167 +	if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  11.168 +	if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT;
  11.169 +	return 0;
  11.170 +
  11.171 +      case HDIO_GETGEO_BIG: 
  11.172 +        /* note: these values are complete garbage */
  11.173 +        DPRINTK_IOCTL("   HDIO_GETGEO_BIG\n");
  11.174 +	if (!argument) return -EINVAL;
  11.175 +	if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
  11.176 +	if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
  11.177 +	if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  11.178 +	if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
  11.179 +	return 0;
  11.180 +
  11.181 +      default:
  11.182 +        DPRINTK_IOCTL("   eh? unknown ioctl\n");
  11.183 +	break;
  11.184 +    }
  11.185 +    
  11.186 +    return 0;
  11.187 +}
  11.188  
  11.189 -  while (!isdelim(string[loop]))
  11.190 -  {
  11.191 -    if (string[loop] == '\0')
  11.192 -      return NULL;
  11.193 -    loop++;
  11.194 -  }
  11.195 +static int xenolinux_segment_check(kdev_t dev)
  11.196 +{
  11.197 +    DPRINTK("xenolinux_segment_check\n");
  11.198 +    return 0;
  11.199 +}
  11.200 +
  11.201 +static int xenolinux_segment_revalidate(kdev_t dev)
  11.202 +{
  11.203 +    DPRINTK("xenolinux_segment_revalidate\n"); 
  11.204 +    return 0;
  11.205 +}
  11.206 +
  11.207 +void do_xlseg_requestX (request_queue_t *rq)
  11.208 +{
  11.209 +  /* this is a bit dumb.  do_xlseg_request is defined in blk.h
  11.210 +     and this is thus static. but we have cooperative
  11.211 +     device drivers... */
  11.212 +  do_xlseg_request(rq);
  11.213 +}
  11.214 +
  11.215 +/*
  11.216 + * do_xlseg_request
  11.217 + * read a block; request is in a request queue
  11.218 + */
  11.219 +static void do_xlseg_request (request_queue_t *rq)
  11.220 +{
  11.221 +    struct request *req;
  11.222 +    struct buffer_head *bh;
  11.223 +    int rw, nsect, full, queued = 0;
  11.224 +    
  11.225 +    /*     DPRINTK("do_xlseg_request for '%s'\n", DEVICE_NAME); */
  11.226 +
  11.227 +    while ( !rq->plugged && !QUEUE_EMPTY )
  11.228 +    {
  11.229 +	if ( (req = CURRENT) == NULL ) goto out;
  11.230 +		
  11.231 +        DPRINTK("do_xlseg_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
  11.232 +                req, req->cmd, req->sector,
  11.233 +                req->current_nr_sectors, req->nr_sectors, req->bh);
  11.234 +
  11.235 +        rw = req->cmd;
  11.236 +        if ( rw == READA ) rw = READ;
  11.237 +        if ((rw != READ) && (rw != WRITE))
  11.238 +            panic("XenoLinux Virtual Segment Device: bad cmd: %d\n", rw);
  11.239  
  11.240 -  string[loop] = '\0';	
  11.241 -  temp = (string + loop + 1);
  11.242 +	req->errors = 0;
  11.243 +
  11.244 +        bh = req->bh;
  11.245 +        while ( bh != NULL )
  11.246 +	{
  11.247 +            full = hypervisor_request(
  11.248 +                bh, (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
  11.249 +                bh->b_data, bh->b_rsector, bh->b_size, bh->b_dev,
  11.250 +		(struct gendisk *)xlseg_disk_info.disks[0].gendisk);
  11.251 +            
  11.252 +            if ( full ) 
  11.253 +	    {
  11.254 +	      goto out;
  11.255 +	    }
  11.256 +
  11.257 +            queued++;
  11.258  
  11.259 -  if (loop == 0)
  11.260 -  {
  11.261 -    string = temp;
  11.262 -    goto try_again;
  11.263 -  }
  11.264 +            /* Dequeue the buffer head from the request. */
  11.265 +            nsect = bh->b_size >> 9;
  11.266 +            req->bh = bh->b_reqnext;
  11.267 +            bh->b_reqnext = NULL;
  11.268 +            bh = req->bh;
  11.269 +            
  11.270 +            if ( bh != NULL )
  11.271 +            {
  11.272 +                /* There's another buffer head to do. Update the request. */
  11.273 +                req->hard_sector += nsect;
  11.274 +                req->hard_nr_sectors -= nsect;
  11.275 +                req->sector = req->hard_sector;
  11.276 +                req->nr_sectors = req->hard_nr_sectors;
  11.277 +                req->current_nr_sectors = bh->b_size >> 9;
  11.278 +                req->buffer = bh->b_data;
  11.279 +            }
  11.280 +            else
  11.281 +            {
  11.282 +                /* That was the last buffer head. Finalise the request. */
  11.283 +                if ( end_that_request_first(req, 1, "XenSeg") ) BUG();
  11.284 +                blkdev_dequeue_request(req);
  11.285 +                end_that_request_last(req);
  11.286 +            }
  11.287 +        }
  11.288 +    }
  11.289  
  11.290 -  return string;
  11.291 + out:
  11.292 +    if ( queued != 0 ) HYPERVISOR_block_io_op();
  11.293  }
  11.294  
  11.295  
  11.296 -#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
  11.297 -unsigned long to_number(char *string)                                /* atoi */
  11.298 -{
  11.299 -  unsigned long value = 0;
  11.300 -
  11.301 -  if (string == NULL) return 0;
  11.302 -
  11.303 -  while (!isdigit(*string) && *string != '\0') string++;
  11.304 -
  11.305 -  while (isdigit(*string))
  11.306 -  {
  11.307 -    value = value * 10 + (*string - '0');
  11.308 -    string++;
  11.309 -  }
  11.310 -
  11.311 -  return value;
  11.312 -}
  11.313 -
  11.314 -static int proc_write_vhd(struct file *file, const char *buffer,
  11.315 -			  unsigned long count, void *data)
  11.316 +static struct block_device_operations xenolinux_segment_fops = 
  11.317  {
  11.318 -  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
  11.319 -  char *string;
  11.320 -  int loop;
  11.321 -  int counter;
  11.322 -  xv_disk_t xvd;
  11.323 -
  11.324 -  memset (&xvd, 0, sizeof(xvd));
  11.325 -
  11.326 -  if (copy_from_user(local, buffer, count))
  11.327 -  {
  11.328 -    return -EFAULT;
  11.329 -  }
  11.330 -  local[count] = '\0';
  11.331 -
  11.332 -  string = get_string(local);                             /* look for Domain */
  11.333 -  if (string == NULL)                                        /* empty string */
  11.334 -  {
  11.335 -    return count;
  11.336 -  }
  11.337 -  if (*string != 'd' && *string != 'D')
  11.338 -  {
  11.339 -    printk (KERN_ALERT 
  11.340 -	    "error: domain specifier missing [%s]. should be \"domain\".\n",
  11.341 -	    string);
  11.342 -    return count;
  11.343 -  }
  11.344 -
  11.345 -  string = get_string(NULL);                                /* domain number */
  11.346 -  if (string == NULL)
  11.347 -  {
  11.348 -    printk (KERN_ALERT "error: domain number missing\n");
  11.349 -    return count;
  11.350 -  }
  11.351 -  xvd.domain = (int) to_number(string);
  11.352 -
  11.353 -  string = get_string(NULL);
  11.354 -  if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
  11.355 -  {
  11.356 -    xvd.mode = XEN_DISK_READ_ONLY;
  11.357 -  }
  11.358 -  else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
  11.359 -  {
  11.360 -    xvd.mode = XEN_DISK_READ_ONLY;
  11.361 -  }
  11.362 -  else
  11.363 -  {
  11.364 -    printk (KERN_ALERT 
  11.365 -	    "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
  11.366 -	    string);
  11.367 -    return count;
  11.368 -  }
  11.369 -
  11.370 -  string = get_string(NULL);                             /* look for Segment */
  11.371 -  if (string == NULL || (*string != 's' && *string != 'S'))
  11.372 -  {
  11.373 -    printk (KERN_ALERT 
  11.374 -	    "error: segment specifier missing [%s]. should be \"segment\".\n",
  11.375 -	    string);
  11.376 -    return count;
  11.377 -  }
  11.378 -
  11.379 -  string = get_string(NULL);                               /* segment number */
  11.380 -  if (string == NULL)
  11.381 -  {
  11.382 -    printk (KERN_ALERT "error: segment number missing\n");
  11.383 -    return count;
  11.384 -  }
  11.385 -  xvd.segment = (int) to_number(string);
  11.386 +    open:               xenolinux_segment_open,
  11.387 +    release:            xenolinux_segment_release,
  11.388 +    ioctl:              xenolinux_segment_ioctl,
  11.389 +    check_media_change: xenolinux_segment_check,
  11.390 +    revalidate:         xenolinux_segment_revalidate,
  11.391 +};
  11.392  
  11.393 -  string = get_string(NULL);                             /* look for Extents */
  11.394 -  if (string == NULL || (*string != 'e' && *string != 'E'))
  11.395 -  {
  11.396 -    printk (KERN_ALERT 
  11.397 -	    "error: extents specifier missing [%s]. should be \"extents\".\n",
  11.398 -	    string);
  11.399 -    return count;
  11.400 -  }
  11.401 -
  11.402 -  string = get_string(NULL);                            /* number of extents */
  11.403 -  if (string == NULL)
  11.404 -  {
  11.405 -    printk (KERN_ALERT "error: number of extents missing\n");
  11.406 -    return count;
  11.407 -  }
  11.408 -  xvd.ext_count = (int) to_number(string);
  11.409 -
  11.410 -  /* ignore parenthesis */
  11.411 -
  11.412 -  for (loop = 0; loop < xvd.ext_count; loop++)
  11.413 -  {
  11.414 -    string = get_string(NULL);                              /* look for Disk */
  11.415 -    if (string == NULL || (*string != 'd' && *string != 'D'))
  11.416 -    {
  11.417 -      printk (KERN_ALERT 
  11.418 -	      "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
  11.419 -	      string);
  11.420 -      return count;
  11.421 -    }
  11.422 -    string = get_string(NULL);                                /* disk number */
  11.423 -    if (string == NULL)
  11.424 -    {
  11.425 -      printk (KERN_ALERT "error: disk number missing\n");
  11.426 -      return count;
  11.427 -    }
  11.428 -    xvd.extents[loop].disk = (int) to_number(string);
  11.429 -
  11.430 -    string = get_string(NULL);                            /* look for Offset */
  11.431 -    if (string == NULL || (*string != 'o' && *string != 'O'))
  11.432 -    {
  11.433 -      printk (KERN_ALERT 
  11.434 -	      "error: disk offset missing [%s]. should be \"offset\".\n",
  11.435 -	    string);
  11.436 -      return count;
  11.437 -    }
  11.438 -    string = get_string(NULL);                                     /* offset */
  11.439 -    if (string == NULL)
  11.440 -    {
  11.441 -      printk (KERN_ALERT "error: offset missing\n");
  11.442 -      return count;
  11.443 -    }
  11.444 -    xvd.extents[loop].offset =  to_number(string);
  11.445 -
  11.446 -    string = get_string(NULL);                              /* look for Size */
  11.447 -    if (string == NULL || (*string != 's' && *string != 'S'))
  11.448 -    {
  11.449 -      printk (KERN_ALERT 
  11.450 -	      "error: extent size missing [%s]. should be \"size\".\n",
  11.451 -	    string);
  11.452 -      return count;
  11.453 -    }
  11.454 -    string = get_string(NULL);                                       /* size */
  11.455 -    if (string == NULL)
  11.456 -    {
  11.457 -      printk (KERN_ALERT "error: extent size missing\n");
  11.458 -      return count;
  11.459 -    }
  11.460 -    xvd.extents[loop].size =  to_number(string);
  11.461 -  }
  11.462 -
  11.463 -  {
  11.464 -    /* get lock xlblk_control_lock     */
  11.465 -    counter = atomic_read(&xlblk_control_count);
  11.466 -    atomic_inc(&xlblk_control_count);
  11.467 -    /* release lock xlblk_control_lock */
  11.468 -  }
  11.469 -
  11.470 -  hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
  11.471 -		      0, 0, (kdev_t) 0);
  11.472 -  HYPERVISOR_block_io_op();
  11.473 -
  11.474 -  while (atomic_read(&xlblk_control_count) != counter) barrier();
  11.475 -
  11.476 -  /* while ( blk_ring->resp_prod != 1 ) barrier(); */
  11.477 -
  11.478 -  /*  mdelay(1000); */
  11.479 -
  11.480 -  return count;
  11.481 -}
  11.482 -
  11.483 -/******************************************************************/
  11.484  
  11.485  int __init xlseg_init(void)
  11.486  {
  11.487 -  vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
  11.488 -  if (vhd == NULL)
  11.489 -  {
  11.490 -    panic ("xlseg_init: unable to create vhd proc entry\n");
  11.491 -  }
  11.492 -  vhd->data       = NULL;
  11.493 -  vhd->read_proc  = proc_read_vhd;
  11.494 -  vhd->write_proc = proc_write_vhd;
  11.495 -  vhd->owner      = THIS_MODULE;
  11.496 +    int i, result;
  11.497 +    int counter;
  11.498 +
  11.499 +    /* probe for disk information */
  11.500 +    memset (&xlseg_disk_info, 0, sizeof(xlseg_disk_info));
  11.501 +    xlseg_disk_info.count = 0;
  11.502 +
  11.503 +
  11.504 +    {
  11.505 +      /* get lock xlblk_control_lock     */
  11.506 +      counter = atomic_read(&xlblk_control_count);
  11.507 +      atomic_inc(&xlblk_control_count);
  11.508 +      /* release lock xlblk_control_lock */
  11.509 +    }
  11.510 +    if ( hypervisor_request(NULL, XEN_BLOCK_PROBE_SEG, 
  11.511 +			    (char *) &xlseg_disk_info,
  11.512 +                            0, 0, (kdev_t) 0,
  11.513 +			    (struct gendisk *)NULL) )
  11.514 +        BUG();
  11.515 +    HYPERVISOR_block_io_op();
  11.516 +    while (atomic_read(&xlblk_control_count) != counter) barrier();
  11.517 +
  11.518 +    printk (KERN_ALERT "vhd block device probe:\n");
  11.519 +    for ( i = 0; i < xlseg_disk_info.count; i++ )
  11.520 +    { 
  11.521 +	printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
  11.522 +		i, xlseg_disk_info.disks[i].type, 
  11.523 +		xlseg_disk_info.disks[i].capacity);
  11.524 +    }
  11.525 +
  11.526 +    SET_MODULE_OWNER(&xenolinux_segment_fops);
  11.527 +    result = register_blkdev(xlseg_major, "segment", &xenolinux_segment_fops);
  11.528 +    if (result < 0) {
  11.529 +	printk (KERN_ALERT "xenolinux segment: can't get major %d\n",
  11.530 +		xlseg_major);
  11.531 +	return result;
  11.532 +    }
  11.533 +
  11.534 +    /* initialize global arrays in drivers/block/ll_rw_block.c */
  11.535 +    for (i = 0; i < XLSEG_MAX; i++) 
  11.536 +    {
  11.537 +      xlseg_blk_size[i]      = xlseg_disk_info.disks[0].capacity ;
  11.538 +      xlseg_blksize_size[i]  = 512;
  11.539 +      xlseg_hardsect_size[i] = 512;
  11.540 +      xlseg_max_sectors[i]   = 128;
  11.541 +    }
  11.542 +    xlseg_read_ahead  = 8; 
  11.543 +
  11.544 +    blk_size[xlseg_major]      = xlseg_blk_size;
  11.545 +    blksize_size[xlseg_major]  = xlseg_blksize_size;
  11.546 +    hardsect_size[xlseg_major] = xlseg_hardsect_size;
  11.547 +    read_ahead[xlseg_major]    = xlseg_read_ahead; 
  11.548 +    max_sectors[xlseg_major]   = xlseg_max_sectors;
  11.549 +
  11.550 +    blk_init_queue(BLK_DEFAULT_QUEUE(xlseg_major), do_xlseg_request);
  11.551 +
  11.552 +    /*
  11.553 +     * Turn off barking 'headactive' mode. We dequeue buffer heads as
  11.554 +     * soon as we pass them down to Xen.
  11.555 +     */
  11.556 +    blk_queue_headactive(BLK_DEFAULT_QUEUE(xlseg_major), 0);
  11.557 +
  11.558 +    xlseg_register_disk(0, xlseg_disk_info.disks[0].capacity);
  11.559  
  11.560 -  memset(&xvd, 0, sizeof(xvd));
  11.561 +    printk(KERN_ALERT 
  11.562 +	   "XenoLinux Virtual Segment Device Driver installed [device: %d]\n",
  11.563 +	   xlseg_major);
  11.564 +    return 0;
  11.565 +}
  11.566 +
  11.567 +void xlseg_register_disk(int idx, unsigned long capacity)
  11.568 +{
  11.569 +    int units;
  11.570 +    int minors;
  11.571 +    struct gendisk *gd;
  11.572 +
  11.573 +    /* plagarized from ide-probe.c::init_gendisk */
  11.574 +    
  11.575 +    units = 2; /* from ide.h::MAX_DRIVES */
  11.576 +
  11.577 +#define IDE_PARTN_BITS 6                           /* from ide.h::PARTN_BITS */
  11.578  
  11.579 -  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver installed\n");
  11.580 -  return 0;
  11.581 +    minors    = units * (1<<IDE_PARTN_BITS);
  11.582 +    gd        = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
  11.583 +    gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
  11.584 +    gd->part  = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
  11.585 +    memset(gd->part, 0, minors * sizeof(struct hd_struct));
  11.586 +    
  11.587 +    gd->major        = xlseg_major;  
  11.588 +    gd->major_name   = XLSEG_MAJOR_NAME;
  11.589 +    gd->minor_shift  = IDE_PARTN_BITS; 
  11.590 +    gd->max_p	     = 1<<IDE_PARTN_BITS;
  11.591 +    gd->nr_real	     = units;           
  11.592 +    gd->real_devices = NULL;          
  11.593 +    gd->next	     = NULL;            
  11.594 +    gd->fops         = &xenolinux_segment_fops;
  11.595 +    gd->de_arr       = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
  11.596 +    gd->flags	     = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
  11.597 +
  11.598 +    if (gd->de_arr)  
  11.599 +	memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
  11.600 +
  11.601 +    if (gd->flags) 
  11.602 +	memset (gd->flags, 0, sizeof *gd->flags * units);
  11.603 +
  11.604 +    add_gendisk(gd);
  11.605 +
  11.606 +    xlseg_disk_info.disks[idx].gendisk = gd;
  11.607 +
  11.608 +    register_disk(gd, MKDEV(xlseg_major, 0), 1<<IDE_PARTN_BITS,
  11.609 +		  &xenolinux_segment_fops, capacity);
  11.610 +
  11.611 +    {
  11.612 +      int loop = 0;
  11.613 +      printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
  11.614 +      for (loop = 0; loop < minors; loop++)
  11.615 +      {
  11.616 +	if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
  11.617 +	{
  11.618 +	  printk (KERN_ALERT 
  11.619 +		  "  %2d: 0x%6lx %8ld    0x%6lx %7ld\n", loop,
  11.620 +		  gd->part[loop].start_sect, gd->part[loop].start_sect,
  11.621 +		  gd->part[loop].nr_sects, gd->part[loop].nr_sects);
  11.622 +	}
  11.623 +      }
  11.624 +    }
  11.625 +
  11.626 +    return;
  11.627  }
  11.628  
  11.629 +
  11.630  static void __exit xlseg_cleanup(void)
  11.631  {
  11.632 -  printk(KERN_ALERT "XenoLinux Virtual Disk Device Driver uninstalled\n");
  11.633 +    /* CHANGE FOR MULTIQUEUE */
  11.634 +    blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlseg_major));
  11.635 +
  11.636 +    /* clean up global arrays */
  11.637 +    read_ahead[xlseg_major] = 0;
  11.638 +
  11.639 +    if (blk_size[xlseg_major]) 
  11.640 +	kfree(blk_size[xlseg_major]);
  11.641 +    blk_size[xlseg_major] = NULL;
  11.642 +
  11.643 +    if (blksize_size[xlseg_major]) 
  11.644 +	kfree(blksize_size[xlseg_major]);
  11.645 +    blksize_size[xlseg_major] = NULL;
  11.646 +
  11.647 +    if (hardsect_size[xlseg_major]) 
  11.648 +	kfree(hardsect_size[xlseg_major]);
  11.649 +    hardsect_size[xlseg_major] = NULL;
  11.650 +    
  11.651 +    /* XXX: free each gendisk */
  11.652 +    if (unregister_blkdev(xlseg_major, "block"))
  11.653 +	printk(KERN_ALERT
  11.654 +	       "XenoLinux Virtual Segment Device Driver uninstalled w/ errs\n");
  11.655 +    else
  11.656 +	printk(KERN_ALERT 
  11.657 +	       "XenoLinux Virtual Segment Device Driver uninstalled\n");
  11.658 +
  11.659 +    return;
  11.660  }
  11.661  
  11.662 +
  11.663  #ifdef MODULE
  11.664  module_init(xlseg_init);
  11.665  module_exit(xlseg_cleanup);
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c	Thu Mar 06 15:52:22 2003 +0000
    12.3 @@ -0,0 +1,280 @@
    12.4 +/*
    12.5 + * xl_segment_proc.c
    12.6 + * 
    12.7 + * XenoLinux virtual disk proc interface .
    12.8 + */
    12.9 +
   12.10 +
   12.11 +#include <linux/config.h>
   12.12 +#include <linux/module.h>
   12.13 +
   12.14 +#include <linux/proc_fs.h>
   12.15 +#include <linux/delay.h>
   12.16 +#include <asm/uaccess.h>
   12.17 +#include <asm/atomic.h>
   12.18 +
   12.19 +#include <asm/hypervisor-ifs/block.h>
   12.20 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   12.21 +
   12.22 +static struct proc_dir_entry *vhd;
   12.23 +xv_disk_t xvd;
   12.24 +
   12.25 +extern atomic_t xlblk_control_count;                           /* xl_block.c */
   12.26 +
   12.27 +int hypervisor_request(void *          id,
   12.28 +                       int             operation,
   12.29 +                       char *          buffer,
   12.30 +                       unsigned long   block_number,
   12.31 +                       unsigned short  block_size,
   12.32 +                       kdev_t          device,
   12.33 +		       struct gendisk *gd);
   12.34 +
   12.35 +/******************************************************************/
   12.36 +
   12.37 +static int proc_read_vhd(char *page, char **start, off_t off,
   12.38 +			 int count, int *eof, void *data)
   12.39 +{
   12.40 +  return 0;
   12.41 +}
   12.42 +
   12.43 +#define isdelim(c) \
   12.44 +  (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
   12.45 +
   12.46 +char *get_string(char *string)                          /* a bit like strtok */
   12.47 +{
   12.48 +  static char *temp;
   12.49 +  int loop = 0;
   12.50 +
   12.51 +  if (string != NULL)	
   12.52 +    temp = string;
   12.53 +  else
   12.54 +    string = temp;
   12.55 +
   12.56 + try_again:
   12.57 +
   12.58 +  while (!isdelim(string[loop]))
   12.59 +  {
   12.60 +    if (string[loop] == '\0')
   12.61 +      return NULL;
   12.62 +    loop++;
   12.63 +  }
   12.64 +
   12.65 +  string[loop] = '\0';	
   12.66 +  temp = (string + loop + 1);
   12.67 +
   12.68 +  if (loop == 0)
   12.69 +  {
   12.70 +    string = temp;
   12.71 +    goto try_again;
   12.72 +  }
   12.73 +
   12.74 +  return string;
   12.75 +}
   12.76 +
   12.77 +
   12.78 +#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
   12.79 +unsigned long to_number(char *string)                                /* atoi */
   12.80 +{
   12.81 +  unsigned long value = 0;
   12.82 +
   12.83 +  if (string == NULL) return 0;
   12.84 +
   12.85 +  while (!isdigit(*string) && *string != '\0') string++;
   12.86 +
   12.87 +  while (isdigit(*string))
   12.88 +  {
   12.89 +    value = value * 10 + (*string - '0');
   12.90 +    string++;
   12.91 +  }
   12.92 +
   12.93 +  return value;
   12.94 +}
   12.95 +
   12.96 +static int proc_write_vhd(struct file *file, const char *buffer,
   12.97 +			  unsigned long count, void *data)
   12.98 +{
   12.99 +  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
  12.100 +  char *string;
  12.101 +  int loop;
  12.102 +  int counter;
  12.103 +  xv_disk_t xvd;
  12.104 +
  12.105 +  memset (&xvd, 0, sizeof(xvd));
  12.106 +
  12.107 +  if (copy_from_user(local, buffer, count))
  12.108 +  {
  12.109 +    return -EFAULT;
  12.110 +  }
  12.111 +  local[count] = '\0';
  12.112 +
  12.113 +  string = get_string(local);                             /* look for Domain */
  12.114 +  if (string == NULL)                                        /* empty string */
  12.115 +  {
  12.116 +    return count;
  12.117 +  }
  12.118 +  if (*string != 'd' && *string != 'D')
  12.119 +  {
  12.120 +    printk (KERN_ALERT 
  12.121 +	    "error: domain specifier missing [%s]. should be \"domain\".\n",
  12.122 +	    string);
  12.123 +    return count;
  12.124 +  }
  12.125 +
  12.126 +  string = get_string(NULL);                                /* domain number */
  12.127 +  if (string == NULL)
  12.128 +  {
  12.129 +    printk (KERN_ALERT "error: domain number missing\n");
  12.130 +    return count;
  12.131 +  }
  12.132 +  xvd.domain = (int) to_number(string);
  12.133 +
  12.134 +  string = get_string(NULL);
  12.135 +  if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
  12.136 +  {
  12.137 +    xvd.mode = XEN_DISK_READ_ONLY;
  12.138 +  }
  12.139 +  else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
  12.140 +  {
  12.141 +    xvd.mode = XEN_DISK_READ_WRITE;
  12.142 +  }
  12.143 +  else
  12.144 +  {
  12.145 +    printk (KERN_ALERT 
  12.146 +	    "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
  12.147 +	    string);
  12.148 +    return count;
  12.149 +  }
  12.150 +
  12.151 +  string = get_string(NULL);                             /* look for Segment */
  12.152 +  if (string == NULL || (*string != 's' && *string != 'S'))
  12.153 +  {
  12.154 +    printk (KERN_ALERT 
  12.155 +	    "error: segment specifier missing [%s]. should be \"segment\".\n",
  12.156 +	    string);
  12.157 +    return count;
  12.158 +  }
  12.159 +
  12.160 +  string = get_string(NULL);                               /* segment number */
  12.161 +  if (string == NULL)
  12.162 +  {
  12.163 +    printk (KERN_ALERT "error: segment number missing\n");
  12.164 +    return count;
  12.165 +  }
  12.166 +  xvd.segment = (int) to_number(string);
  12.167 +
  12.168 +  string = get_string(NULL);                             /* look for Extents */
  12.169 +  if (string == NULL || (*string != 'e' && *string != 'E'))
  12.170 +  {
  12.171 +    printk (KERN_ALERT 
  12.172 +	    "error: extents specifier missing [%s]. should be \"extents\".\n",
  12.173 +	    string);
  12.174 +    return count;
  12.175 +  }
  12.176 +
  12.177 +  string = get_string(NULL);                            /* number of extents */
  12.178 +  if (string == NULL)
  12.179 +  {
  12.180 +    printk (KERN_ALERT "error: number of extents missing\n");
  12.181 +    return count;
  12.182 +  }
  12.183 +  xvd.ext_count = (int) to_number(string);
  12.184 +
  12.185 +  /* ignore parenthesis */
  12.186 +
  12.187 +  for (loop = 0; loop < xvd.ext_count; loop++)
  12.188 +  {
  12.189 +    string = get_string(NULL);                              /* look for Disk */
  12.190 +    if (string == NULL || (*string != 'd' && *string != 'D'))
  12.191 +    {
  12.192 +      printk (KERN_ALERT 
  12.193 +	      "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
  12.194 +	      string);
  12.195 +      return count;
  12.196 +    }
  12.197 +    string = get_string(NULL);                                /* disk number */
  12.198 +    if (string == NULL)
  12.199 +    {
  12.200 +      printk (KERN_ALERT "error: disk number missing\n");
  12.201 +      return count;
  12.202 +    }
  12.203 +    xvd.extents[loop].disk = (int) to_number(string);
  12.204 +
  12.205 +    string = get_string(NULL);                            /* look for Offset */
  12.206 +    if (string == NULL || (*string != 'o' && *string != 'O'))
  12.207 +    {
  12.208 +      printk (KERN_ALERT 
  12.209 +	      "error: disk offset missing [%s]. should be \"offset\".\n",
  12.210 +	    string);
  12.211 +      return count;
  12.212 +    }
  12.213 +    string = get_string(NULL);                                     /* offset */
  12.214 +    if (string == NULL)
  12.215 +    {
  12.216 +      printk (KERN_ALERT "error: offset missing\n");
  12.217 +      return count;
  12.218 +    }
  12.219 +    xvd.extents[loop].offset =  to_number(string);
  12.220 +
  12.221 +    string = get_string(NULL);                              /* look for Size */
  12.222 +    if (string == NULL || (*string != 's' && *string != 'S'))
  12.223 +    {
  12.224 +      printk (KERN_ALERT 
  12.225 +	      "error: extent size missing [%s]. should be \"size\".\n",
  12.226 +	    string);
  12.227 +      return count;
  12.228 +    }
  12.229 +    string = get_string(NULL);                                       /* size */
  12.230 +    if (string == NULL)
  12.231 +    {
  12.232 +      printk (KERN_ALERT "error: extent size missing\n");
  12.233 +      return count;
  12.234 +    }
  12.235 +    xvd.extents[loop].size =  to_number(string);
  12.236 +  }
  12.237 +
  12.238 +  {
  12.239 +    /* get lock xlblk_control_lock     */
  12.240 +    counter = atomic_read(&xlblk_control_count);
  12.241 +    atomic_inc(&xlblk_control_count);
  12.242 +    /* release lock xlblk_control_lock */
  12.243 +  }
  12.244 +  if (hypervisor_request (NULL, XEN_BLOCK_SEG_CREATE, (char *)&xvd,
  12.245 +			  0, 0, (kdev_t) 0,
  12.246 +			  (struct gendisk *)NULL))
  12.247 +    BUG();
  12.248 +  HYPERVISOR_block_io_op();
  12.249 +
  12.250 +  while (atomic_read(&xlblk_control_count) != counter) barrier();
  12.251 +
  12.252 +  return count;
  12.253 +}
  12.254 +
  12.255 +/******************************************************************/
  12.256 +
  12.257 +int __init xlseg_proc_init(void)
  12.258 +{
  12.259 +  vhd = create_proc_entry("xeno/dom0/vhd", 0644, NULL);
  12.260 +  if (vhd == NULL)
  12.261 +  {
  12.262 +    panic ("xlseg_init: unable to create vhd proc entry\n");
  12.263 +  }
  12.264 +  vhd->data       = NULL;
  12.265 +  vhd->read_proc  = proc_read_vhd;
  12.266 +  vhd->write_proc = proc_write_vhd;
  12.267 +  vhd->owner      = THIS_MODULE;
  12.268 +
  12.269 +  memset(&xvd, 0, sizeof(xvd));
  12.270 +
  12.271 +  printk(KERN_ALERT "XenoLinux Virtual Disk Device Monitor installed\n");
  12.272 +  return 0;
  12.273 +}
  12.274 +
  12.275 +static void __exit xlseg_proc_cleanup(void)
  12.276 +{
  12.277 +  printk(KERN_ALERT "XenoLinux Virtual Disk Device Monitor uninstalled\n");
  12.278 +}
  12.279 +
  12.280 +#ifdef MODULE
  12.281 +module_init(xlseg_proc_init);
  12.282 +module_exit(xlseg_proc_cleanup);
  12.283 +#endif
    13.1 --- a/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c	Wed Mar 05 20:14:40 2003 +0000
    13.2 +++ b/xenolinux-2.4.21-pre4-sparse/drivers/block/ll_rw_blk.c	Thu Mar 06 15:52:22 2003 +0000
    13.3 @@ -1505,6 +1505,7 @@ int __init blk_dev_init(void)
    13.4  #ifdef CONFIG_XENOLINUX_BLOCK
    13.5      xlblk_init();
    13.6      xlseg_init();
    13.7 +    xlseg_proc_init();
    13.8  #endif
    13.9  
   13.10  	return 0;
    14.1 --- a/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h	Wed Mar 05 20:14:40 2003 +0000
    14.2 +++ b/xenolinux-2.4.21-pre4-sparse/include/linux/blk.h	Thu Mar 06 15:52:22 2003 +0000
    14.3 @@ -328,6 +328,13 @@ static void floppy_off(unsigned int nr);
    14.4  /* #define DEVICE_INTR */
    14.5  #define DEVICE_NR(device) (MINOR(device))
    14.6  
    14.7 +#elif (MAJOR_NR == XLSEG_MAJOR)
    14.8 +
    14.9 +#define DEVICE_NAME "xeno segment"
   14.10 +#define DEVICE_REQUEST do_xlseg_request
   14.11 +/* #define DEVICE_INTR */
   14.12 +#define DEVICE_NR(device) (MINOR(device))
   14.13 +
   14.14  #endif /* MAJOR_NR == whatever */
   14.15  
   14.16  /* provide DEVICE_xxx defaults, if not explicitly defined
    15.1 --- a/xenolinux-2.4.21-pre4-sparse/include/linux/major.h	Wed Mar 05 20:14:40 2003 +0000
    15.2 +++ b/xenolinux-2.4.21-pre4-sparse/include/linux/major.h	Thu Mar 06 15:52:22 2003 +0000
    15.3 @@ -145,7 +145,8 @@
    15.4  
    15.5  #define	UMEM_MAJOR	116	/* http://www.umem.com/ Battery Backed RAM */
    15.6  
    15.7 -#define XLBLK_MAJOR	123	/* XenoLinux Block Device */
    15.8 +/* note: 123, 124, 125, 126 and 234, 235, 236, 237 are defined in xeno_major */
    15.9 +#include <asm/hypervisor-ifs/xeno-major.h>
   15.10  
   15.11  #define RTF_MAJOR	150
   15.12  #define RAW_MAJOR	162
    16.1 --- a/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c	Wed Mar 05 20:14:40 2003 +0000
    16.2 +++ b/xenolinux-2.4.21-pre4-sparse/init/do_mounts.c	Thu Mar 06 15:52:22 2003 +0000
    16.3 @@ -235,6 +235,10 @@ static struct dev_name_struct {
    16.4          { "xhdb",    0x7C00 },
    16.5          { "xhdc",    0x7D00 },
    16.6          { "xhdd",    0x7E00 },
    16.7 +        { "vhda",    0xEA00 },
    16.8 +        { "vhdb",    0xEB00 },
    16.9 +        { "vhdc",    0xEC00 },
   16.10 +        { "vhdd",    0xED00 },
   16.11  #endif
   16.12  	{ "nftla", 0x5d00 },
   16.13  	{ "nftlb", 0x5d10 },