ia64/xen-unstable

changeset 1002:b27a29e3c9ce

bitkeeper revision 1.649 (3fdf2aeaeVXAAcKlXMdFTCQuwOYD_g)

xl_vbd.c, xl_block.h, xl_block.c:
Fixes to Xenolinux blkdev code.
author kaf24@scramble.cl.cam.ac.uk
date Tue Dec 16 15:55:22 2003 +0000 (2003-12-16)
parents 70a2962f5aeb
children ebd0aaef31e3 8e10a7fe0e35
files xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c
line diff
     1.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c	Fri Dec 12 16:43:28 2003 +0000
     1.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.c	Tue Dec 16 15:55:22 2003 +0000
     1.3 @@ -58,7 +58,7 @@ static inline void signal_requests_to_xe
     1.4  
     1.5  static inline xl_disk_t *xldev_to_xldisk(kdev_t xldev)
     1.6  {
     1.7 -    struct gendisk *gd = xldev_to_gendisk(xldev);
     1.8 +    struct gendisk *gd = get_gendisk(xldev);
     1.9      return (xl_disk_t *)gd->real_devices + 
    1.10          (MINOR(xldev) >> gd->minor_shift);
    1.11  }
    1.12 @@ -67,26 +67,37 @@ static inline xl_disk_t *xldev_to_xldisk
    1.13  int xenolinux_block_open(struct inode *inode, struct file *filep)
    1.14  {
    1.15      short xldev = inode->i_rdev; 
    1.16 -    struct gendisk *gd = xldev_to_gendisk(xldev);
    1.17 +    struct gendisk *gd = get_gendisk(xldev);
    1.18      xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev);
    1.19      short minor = MINOR(xldev); 
    1.20  
    1.21 -    if(!gd->part[minor].nr_sects) { 
    1.22 -	/* Device either doesn't exist, or has zero capacity; we use 
    1.23 -	   a few cheesy heuristics to return the relevant error code */
    1.24 -	if(disk->capacity || (minor & (gd->max_p - 1))) { 
    1.25 -	    // we have a real device, but no such partition, or we just 
    1.26 -	    // have a partition number so guess this is the problem 
    1.27 -	    return -ENXIO;     // no such device or address 
    1.28 -	} else if (gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) {
    1.29 -	    // this is a removable device => assume that media is missing 
    1.30 -	    return -ENOMEDIUM; // media not present (this is a guess) 
    1.31 -	} else 
    1.32 -	    // just go for the general 'no such device' error
    1.33 -	    return -ENODEV;    // no such device
    1.34 +    if ( gd->part[minor].nr_sects == 0 )
    1.35 +    { 
    1.36 +        /*
    1.37 +         * Device either doesn't exist, or has zero capacity; we use a few
    1.38 +         * cheesy heuristics to return the relevant error code
    1.39 +         */
    1.40 +        if ( (gd->sizes[minor >> gd->minor_shift] != 0) ||
    1.41 +             ((minor & (gd->max_p - 1)) != 0) )
    1.42 +        { 
    1.43 +            /*
    1.44 +             * We have a real device, but no such partition, or we just have a
    1.45 +             * partition number so guess this is the problem.
    1.46 +             */
    1.47 +            return -ENXIO;     /* no such device or address */
    1.48 +        }
    1.49 +        else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE )
    1.50 +        {
    1.51 +            /* This is a removable device => assume that media is missing. */ 
    1.52 +            return -ENOMEDIUM; /* media not present (this is a guess) */
    1.53 +        } 
    1.54 +        else
    1.55 +        { 
    1.56 +            /* Just go for the general 'no such device' error. */
    1.57 +            return -ENODEV;    /* no such device */
    1.58 +        }
    1.59      }
    1.60  
    1.61 -
    1.62      disk->usage++;
    1.63      DPRINTK("xenolinux_block_open\n");
    1.64      return 0;
    1.65 @@ -103,7 +114,7 @@ int xenolinux_block_release(struct inode
    1.66  
    1.67  
    1.68  int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
    1.69 -			  unsigned command, unsigned long argument)
    1.70 +                          unsigned command, unsigned long argument)
    1.71  {
    1.72      kdev_t dev = inode->i_rdev;
    1.73      struct hd_geometry *geo = (struct hd_geometry *)argument;
    1.74 @@ -115,21 +126,21 @@ int xenolinux_block_ioctl(struct inode *
    1.75      DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n",
    1.76                    command, (long) argument, dev); 
    1.77    
    1.78 -    gd = xldev_to_gendisk(dev);
    1.79 +    gd = get_gendisk(dev);
    1.80      part = &gd->part[MINOR(dev)]; 
    1.81  
    1.82      switch ( command )
    1.83      {
    1.84      case BLKGETSIZE:
    1.85          DPRINTK_IOCTL("   BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); 
    1.86 -	return put_user(part->nr_sects, (unsigned long *) argument);
    1.87 +        return put_user(part->nr_sects, (unsigned long *) argument);
    1.88  
    1.89      case BLKRRPART:                               /* re-read partition table */
    1.90          DPRINTK_IOCTL("   BLKRRPART: %x\n", BLKRRPART); 
    1.91          return xenolinux_block_revalidate(dev);
    1.92  
    1.93      case BLKSSZGET:
    1.94 -	return hardsect_size[MAJOR(dev)][MINOR(dev)]; 
    1.95 +        return hardsect_size[MAJOR(dev)][MINOR(dev)]; 
    1.96  
    1.97      case BLKBSZGET:                                        /* get block size */
    1.98          DPRINTK_IOCTL("   BLKBSZGET: %x\n", BLKBSZGET);
    1.99 @@ -137,35 +148,35 @@ int xenolinux_block_ioctl(struct inode *
   1.100  
   1.101      case BLKBSZSET:                                        /* set block size */
   1.102          DPRINTK_IOCTL("   BLKBSZSET: %x\n", BLKBSZSET);
   1.103 -	break;
   1.104 +        break;
   1.105  
   1.106      case BLKRASET:                                         /* set read-ahead */
   1.107          DPRINTK_IOCTL("   BLKRASET: %x\n", BLKRASET);
   1.108 -	break;
   1.109 +        break;
   1.110  
   1.111      case BLKRAGET:                                         /* get read-ahead */
   1.112          DPRINTK_IOCTL("   BLKRAFET: %x\n", BLKRAGET);
   1.113 -	break;
   1.114 +        break;
   1.115  
   1.116      case HDIO_GETGEO:
   1.117          /* note: these values are complete garbage */
   1.118          DPRINTK_IOCTL("   HDIO_GETGEO: %x\n", HDIO_GETGEO);
   1.119 -	if (!argument) return -EINVAL;
   1.120 -	if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
   1.121 -	if (put_user(0xff,  (byte *)&geo->heads)) return -EFAULT;
   1.122 -	if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   1.123 -	if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT;
   1.124 -	return 0;
   1.125 +        if (!argument) return -EINVAL;
   1.126 +        if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
   1.127 +        if (put_user(0xff,  (byte *)&geo->heads)) return -EFAULT;
   1.128 +        if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   1.129 +        if (put_user(0x106, (unsigned short *)&geo->cylinders)) return -EFAULT;
   1.130 +        return 0;
   1.131  
   1.132      case HDIO_GETGEO_BIG: 
   1.133          /* note: these values are complete garbage */
   1.134          DPRINTK_IOCTL("   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG);
   1.135 -	if (!argument) return -EINVAL;
   1.136 -	if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
   1.137 -	if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
   1.138 -	if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   1.139 -	if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
   1.140 -	return 0;
   1.141 +        if (!argument) return -EINVAL;
   1.142 +        if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
   1.143 +        if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
   1.144 +        if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   1.145 +        if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
   1.146 +        return 0;
   1.147  
   1.148      case CDROMMULTISESSION:
   1.149          DPRINTK("FIXME: support multisession CDs later\n");
   1.150 @@ -175,7 +186,7 @@ int xenolinux_block_ioctl(struct inode *
   1.151  
   1.152      default:
   1.153          printk("ioctl %08x not supported by xl_block\n", command);
   1.154 -	return -ENOSYS;
   1.155 +        return -ENOSYS;
   1.156      }
   1.157      
   1.158      return 0;
   1.159 @@ -190,13 +201,20 @@ int xenolinux_block_check(kdev_t dev)
   1.160  
   1.161  int xenolinux_block_revalidate(kdev_t dev)
   1.162  {
   1.163 -    struct gendisk *gd = xldev_to_gendisk(dev);
   1.164 +    struct gendisk *gd = get_gendisk(dev);
   1.165      xl_disk_t *disk = xldev_to_xldisk(dev);
   1.166 -    unsigned long flags;
   1.167 +    unsigned long flags, capacity = gd->part[MINOR(dev)].nr_sects;
   1.168      int i, disk_nr = MINOR(dev) >> gd->minor_shift; 
   1.169      
   1.170      DPRINTK("xenolinux_block_revalidate: %d\n", dev);
   1.171  
   1.172 +    /*
   1.173 +     * We didn't construct this VBD by reading a partition table. This
   1.174 +     * function can only do bad things to us.
   1.175 +     */
   1.176 +    if ( capacity == 0 )
   1.177 +        return -EINVAL;
   1.178 +
   1.179      spin_lock_irqsave(&io_request_lock, flags);
   1.180      if ( disk->usage > 1 )
   1.181      {
   1.182 @@ -212,27 +230,9 @@ int xenolinux_block_revalidate(kdev_t de
   1.183          gd->part[MINOR(dev+i)].nr_sects = 0;
   1.184      }
   1.185  
   1.186 -#if 0
   1.187 -    /* VBDs can change under our feet. Check if that has happened. */
   1.188 -    if ( MAJOR(dev) == XLVIRT_MAJOR )
   1.189 -    {
   1.190 -        xen_disk_info_t *xdi = kmalloc(sizeof(*xdi), GFP_KERNEL);
   1.191 -        if ( xdi != NULL )
   1.192 -        {
   1.193 -            memset(xdi, 0, sizeof(*xdi));
   1.194 -            xenolinux_control_msg(XEN_BLOCK_PROBE, 
   1.195 -                                  (char *)xdi, sizeof(*xdi));
   1.196 -            for ( i = 0; i < xdi->count; i++ )
   1.197 -                if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) &&
   1.198 -                     ((xdi->disks[i].device & XENDEV_IDX_MASK) == disk_nr) )
   1.199 -                    ((xl_disk_t *)gd->real_devices)[disk_nr].capacity =
   1.200 -                        xdi->disks[i].capacity;
   1.201 -            kfree(xdi);
   1.202 -        }
   1.203 -    }
   1.204 -#endif
   1.205 +    /* XXX Should perhaps revalidate VBDs here */
   1.206  
   1.207 -    grok_partitions(gd, disk_nr, gd->nr_real, disk->capacity);
   1.208 +    grok_partitions(gd, disk_nr, gd->nr_real, capacity);
   1.209  
   1.210      return 0;
   1.211  }
   1.212 @@ -271,14 +271,12 @@ static int hypervisor_request(unsigned l
   1.213  
   1.214      case XEN_BLOCK_READ:
   1.215      case XEN_BLOCK_WRITE:
   1.216 -
   1.217 -	/* Get the appropriate gendisk */
   1.218 -	gd = xldev_to_gendisk(device); 
   1.219 +        gd = get_gendisk(device); 
   1.220  
   1.221 -	/* Update the sector_number we'll pass down as appropriate; note 
   1.222 -	   that we could sanity check that resulting sector will be in 
   1.223 -	   this partition, but this will happen in xen anyhow */
   1.224 -	sector_number += gd->part[MINOR(device)].start_sect;
   1.225 +        /* Update the sector_number we'll pass down as appropriate; note 
   1.226 +           that we could sanity check that resulting sector will be in 
   1.227 +           this partition, but this will happen in xen anyhow */
   1.228 +        sector_number += gd->part[MINOR(device)].start_sect;
   1.229  
   1.230          if ( (sg_operation == operation) &&
   1.231               (sg_dev == device) &&
   1.232 @@ -339,9 +337,9 @@ void do_xlblk_request(request_queue_t *r
   1.233  
   1.234      while ( !rq->plugged && !list_empty(&rq->queue_head))
   1.235      {
   1.236 -	if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 
   1.237 -	    goto out;
   1.238 -		
   1.239 +        if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) 
   1.240 +            goto out;
   1.241 +  
   1.242          DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
   1.243                  req, req->cmd, req->sector,
   1.244                  req->current_nr_sectors, req->nr_sectors, req->bh);
   1.245 @@ -351,11 +349,11 @@ void do_xlblk_request(request_queue_t *r
   1.246          if ((rw != READ) && (rw != WRITE))
   1.247              panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw);
   1.248  
   1.249 -	req->errors = 0;
   1.250 +        req->errors = 0;
   1.251  
   1.252          bh = req->bh;
   1.253          while ( bh != NULL )
   1.254 -	{
   1.255 +        {
   1.256              next_bh = bh->b_reqnext;
   1.257              bh->b_reqnext = NULL;
   1.258  
   1.259 @@ -364,12 +362,12 @@ void do_xlblk_request(request_queue_t *r
   1.260                  (rw == READ) ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
   1.261                  bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev);
   1.262  
   1.263 -	    if(full) { 
   1.264 +            if(full) { 
   1.265  
   1.266 -		bh->b_reqnext = next_bh;
   1.267 -		pending_queues[nr_pending++] = rq;
   1.268 -		if ( nr_pending >= MAX_PENDING ) BUG();
   1.269 -		goto out; 
   1.270 +                bh->b_reqnext = next_bh;
   1.271 +                pending_queues[nr_pending++] = rq;
   1.272 +                if ( nr_pending >= MAX_PENDING ) BUG();
   1.273 +                goto out; 
   1.274  
   1.275              }
   1.276  
   1.277 @@ -430,15 +428,15 @@ static void xlblk_response_int(int irq, 
   1.278      if ( state == STATE_CLOSED )
   1.279          return;
   1.280      
   1.281 -    spin_lock_irqsave(&io_request_lock, flags);	    
   1.282 +    spin_lock_irqsave(&io_request_lock, flags);     
   1.283  
   1.284      for ( i  = resp_cons;
   1.285 -	  i != blk_ring->resp_prod;
   1.286 -	  i  = BLK_RING_INC(i) )
   1.287 +          i != blk_ring->resp_prod;
   1.288 +          i  = BLK_RING_INC(i) )
   1.289      {
   1.290 -	blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp;
   1.291 -	switch (bret->operation)
   1.292 -	{
   1.293 +        blk_ring_resp_entry_t *bret = &blk_ring->ring[i].resp;
   1.294 +        switch (bret->operation)
   1.295 +        {
   1.296          case XEN_BLOCK_READ:
   1.297          case XEN_BLOCK_WRITE:
   1.298              if ( bret->status )
   1.299 @@ -452,11 +450,11 @@ static void xlblk_response_int(int irq, 
   1.300                  bh->b_reqnext = NULL;
   1.301                  bh->b_end_io(bh, !bret->status);
   1.302              }
   1.303 -	    break;
   1.304 -	    
   1.305 +            break;
   1.306 +     
   1.307          default:
   1.308              BUG();
   1.309 -	}
   1.310 +        }
   1.311      }
   1.312      
   1.313      resp_cons = i;
   1.314 @@ -501,8 +499,8 @@ int __init xlblk_init(void)
   1.315                          SA_SAMPLE_RANDOM, "blkdev", NULL);
   1.316      if ( error )
   1.317      {
   1.318 -	printk(KERN_ALERT "Could not allocate receive interrupt\n");
   1.319 -	goto fail;
   1.320 +        printk(KERN_ALERT "Could not allocate receive interrupt\n");
   1.321 +        goto fail;
   1.322      }
   1.323  
   1.324      /* Setup our [empty] disk information structure */
     2.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h	Fri Dec 12 16:43:28 2003 +0000
     2.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h	Tue Dec 16 15:55:22 2003 +0000
     2.3 @@ -47,7 +47,6 @@
     2.4   */
     2.5  typedef struct xl_disk {
     2.6      int usage;
     2.7 -    unsigned long capacity;
     2.8  } xl_disk_t;
     2.9  
    2.10  /* Generic layer. */
    2.11 @@ -55,7 +54,7 @@ extern int xenolinux_control_msg(int ope
    2.12  extern int xenolinux_block_open(struct inode *inode, struct file *filep);
    2.13  extern int xenolinux_block_release(struct inode *inode, struct file *filep);
    2.14  extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
    2.15 -				 unsigned command, unsigned long argument);
    2.16 +                                 unsigned command, unsigned long argument);
    2.17  extern int xenolinux_block_check(kdev_t dev);
    2.18  extern int xenolinux_block_revalidate(kdev_t dev);
    2.19  extern void do_xlblk_request (request_queue_t *rq); 
    2.20 @@ -64,6 +63,5 @@ extern void do_xlblk_request (request_qu
    2.21  /* Virtual block-device subsystem. */
    2.22  extern int  xlvbd_init(xen_disk_info_t *xdi);
    2.23  extern void xlvbd_cleanup(void); 
    2.24 -extern struct gendisk *xldev_to_gendisk(kdev_t xldev);
    2.25  
    2.26  #endif /* __XL_BLOCK_H__ */
     3.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c	Fri Dec 12 16:43:28 2003 +0000
     3.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c	Tue Dec 16 15:55:22 2003 +0000
     3.3 @@ -6,16 +6,9 @@
     3.4   */
     3.5  
     3.6  #include "xl_block.h"
     3.7 -
     3.8 -// #define MAJOR_NR XLVIRT_MAJOR
     3.9  #include <linux/blk.h>
    3.10  
    3.11 -/* Copied from linux/ide.h */
    3.12 -typedef unsigned char byte; 
    3.13 -
    3.14 -#define XLVBD_MAX_MAJORS  64  /* total number of vbds we support */
    3.15 -
    3.16 -struct gendisk *xlvbd_gendisk[XLVBD_MAX_MAJORS] = { NULL };
    3.17 +#define GENHD_FL_XENO     2
    3.18  
    3.19  /* For convenience we distinguish between ide, scsi and 'other' (i.e. 
    3.20  ** potentially combinations of the two) in the naming scheme and in a 
    3.21 @@ -29,7 +22,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_
    3.22  #define XLSCSI_DEVS_PER_MAJOR 16
    3.23  #define XLVBD_DEVS_PER_MAJOR  16
    3.24  
    3.25 -
    3.26  #define XLIDE_PARTN_SHIFT  6    /* amount to shift minor to get 'real' minor */
    3.27  #define XLIDE_MAX_PART    (1 << XLIDE_PARTN_SHIFT)     /* minors per ide vbd */
    3.28  
    3.29 @@ -39,7 +31,6 @@ struct gendisk *xlvbd_gendisk[XLVBD_MAX_
    3.30  #define XLVBD_PARTN_SHIFT  6    /* amount to shift minor to get 'real' minor */
    3.31  #define XLVBD_MAX_PART    (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */
    3.32  
    3.33 -
    3.34  /* the below are for the use of the generic drivers/block/ll_rw_block.c code */
    3.35  static int xlide_blksize_size[256];
    3.36  static int xlide_hardsect_size[256];
    3.37 @@ -51,7 +42,6 @@ static int xlvbd_blksize_size[256];
    3.38  static int xlvbd_hardsect_size[256];
    3.39  static int xlvbd_max_sectors[256];
    3.40  
    3.41 -
    3.42  static struct block_device_operations xlvbd_block_fops = 
    3.43  {
    3.44      open:               xenolinux_block_open,
    3.45 @@ -61,290 +51,262 @@ static struct block_device_operations xl
    3.46      revalidate:         xenolinux_block_revalidate,
    3.47  };
    3.48  
    3.49 -
    3.50 -typedef unsigned char bool; 
    3.51 -
    3.52 -/* 
    3.53 -** Set up all the linux device goop for the virtual block devices (vbd's)
    3.54 -** that xen tells us about. Note that although from xen's pov VBDs are 
    3.55 -** addressed simply an opaque 16-bit device number, the domain creation 
    3.56 -** tools conventionally allocate these numbers to correspond to those 
    3.57 -** used by 'real' linux -- this is just for convenience as it means e.g. 
    3.58 -** that the same /etc/fstab can be used when booting with or without xen.
    3.59 -*/
    3.60 +/*
    3.61 + * Set up all the linux device goop for the virtual block devices (vbd's) that 
    3.62 + * xen tells us about. Note that although from xen's pov VBDs are addressed 
    3.63 + * simply an opaque 16-bit device number, the domain creation tools 
    3.64 + * conventionally allocate these numbers to correspond to those used by 'real' 
    3.65 + * linux -- this is just for convenience as it means e.g. that the same 
    3.66 + * /etc/fstab can be used when booting with or without xen.
    3.67 + */
    3.68  int __init xlvbd_init(xen_disk_info_t *xdi)
    3.69  {
    3.70      int i, result, max_part; 
    3.71      struct gendisk *gd = NULL;
    3.72      kdev_t device; 
    3.73      unsigned short major, minor, partno; 
    3.74 -    bool is_ide, is_scsi; 
    3.75 +    int is_ide, is_scsi; 
    3.76      char *major_name; 
    3.77      unsigned char buf[64]; 
    3.78 -    int majors[256]; 
    3.79  
    3.80      SET_MODULE_OWNER(&xlvbd_block_fops);
    3.81  
    3.82      /* Initialize the global arrays. */
    3.83 -    for (i = 0; i < 256; i++) 
    3.84 +    for ( i = 0; i < 256; i++ ) 
    3.85 +    {
    3.86 +        /* from the generic ide code (drivers/ide/ide-probe.c, etc) */
    3.87 +        xlide_blksize_size[i]  = 1024;
    3.88 +        xlide_hardsect_size[i] = 512;
    3.89 +        xlide_max_sectors[i]   = 128;  /* 'hwif->rqsize' if we knew it */
    3.90 +
    3.91 +        /* from the generic scsi disk code (drivers/scsi/sd.c) */
    3.92 +        xlscsi_blksize_size[i]  = 1024; /* XXX 512; */
    3.93 +        xlscsi_hardsect_size[i] = 512;
    3.94 +        xlscsi_max_sectors[i]   = 128*8; /* XXX 128; */
    3.95 +
    3.96 +        /* we don't really know what to set these too since it depends */
    3.97 +        xlvbd_blksize_size[i]  = 512;
    3.98 +        xlvbd_hardsect_size[i] = 512;
    3.99 +        xlvbd_max_sectors[i]   = 128;
   3.100 +    }
   3.101 +
   3.102 +    /*
   3.103 +     * We need to loop through each major device we've been told about and: 
   3.104 +     * a) register the appropriate blkdev 
   3.105 +     * b) setup the indexed-by-major global arrays (blk_size[], 
   3.106 +     *    blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) 
   3.107 +     * c) setup the block queue + make it sensible
   3.108 +     * d) create an appropriate gendisk structure, and 
   3.109 +     * e) register the gendisk 
   3.110 +     */
   3.111 +    for ( i = 0; i < xdi->count; i++ )
   3.112      {
   3.113 -	/* from the generic ide code (drivers/ide/ide-probe.c, etc) */
   3.114 -	xlide_blksize_size[i]  = 1024;
   3.115 -	xlide_hardsect_size[i] = 512;
   3.116 -	xlide_max_sectors[i]   = 128;  /* 'hwif->rqsize' if we knew it */
   3.117 +        device = xdi->disks[i].device;
   3.118 +        major  = MAJOR(device); 
   3.119 +        minor  = MINOR(device);
   3.120 +        is_ide = IDE_DISK_MAJOR(major);  /* is this an ide device? */
   3.121 +        is_scsi= SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
   3.122 +
   3.123 +        if ( is_ide )
   3.124 +        { 
   3.125 +            major_name = XLIDE_MAJOR_NAME; 
   3.126 +            max_part   = XLIDE_MAX_PART;
   3.127 +        }
   3.128 +        else if ( is_scsi )
   3.129 +        { 
   3.130 +            major_name = XLSCSI_MAJOR_NAME;
   3.131 +            max_part   = XLSCSI_MAX_PART;
   3.132 +        }
   3.133 +        else
   3.134 +        { 
   3.135 +            major_name = XLVBD_MAJOR_NAME;
   3.136 +            max_part   = XLVBD_MAX_PART;
   3.137 +        }
   3.138 +
   3.139 +        partno = minor & (max_part - 1); 
   3.140 +
   3.141 +        if ( (gd = get_gendisk(device)) == NULL )
   3.142 +        {
   3.143 +            result = register_blkdev(major, major_name, &xlvbd_block_fops);
   3.144 +            if ( result < 0 )
   3.145 +            {
   3.146 +                printk(KERN_ALERT "XL VBD: can't get major %d\n", major);
   3.147 +                continue; 
   3.148 +            }
   3.149  
   3.150 -	/* from the generic scsi disk code (drivers/scsi/sd.c) */
   3.151 -	xlscsi_blksize_size[i]  = 1024; //XXX 512;
   3.152 -	xlscsi_hardsect_size[i] = 512;
   3.153 -	xlscsi_max_sectors[i]   = 128*8; //XXX 128;
   3.154 +            if( is_ide )
   3.155 +            { 
   3.156 +                blksize_size[major]  = xlide_blksize_size;
   3.157 +                hardsect_size[major] = xlide_hardsect_size;
   3.158 +                max_sectors[major]   = xlide_max_sectors;
   3.159 +                read_ahead[major]    = 8; /* from drivers/ide/ide-probe.c */
   3.160 +            } 
   3.161 +            else if ( is_scsi )
   3.162 +            { 
   3.163 +                blksize_size[major]  = xlscsi_blksize_size;
   3.164 +                hardsect_size[major] = xlscsi_hardsect_size;
   3.165 +                max_sectors[major]   = xlscsi_max_sectors;
   3.166 +                read_ahead[major]    = 0; /* XXX 8; -- guessing */
   3.167 +            }
   3.168 +            else
   3.169 +            { 
   3.170 +                blksize_size[major]  = xlvbd_blksize_size;
   3.171 +                hardsect_size[major] = xlvbd_hardsect_size;
   3.172 +                max_sectors[major]   = xlvbd_max_sectors;
   3.173 +                read_ahead[major]    = 8;
   3.174 +            }
   3.175 +
   3.176 +            blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
   3.177 +
   3.178 +            /*
   3.179 +             * Turn off barking 'headactive' mode. We dequeue buffer heads as
   3.180 +             * soon as we pass them down to Xen.
   3.181 +             */
   3.182 +            blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
   3.183  
   3.184 -	/* we don't really know what to set these too since it depends */
   3.185 -	xlvbd_blksize_size[i]  = 512;
   3.186 -	xlvbd_hardsect_size[i] = 512;
   3.187 -	xlvbd_max_sectors[i]   = 128;
   3.188 -    }
   3.189 +            /* Construct an appropriate gendisk structure. */
   3.190 +            gd             = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
   3.191 +            gd->major      = major;
   3.192 +            gd->major_name = major_name; 
   3.193 +    
   3.194 +            gd->max_p      = max_part; 
   3.195 +            if ( is_ide )
   3.196 +            { 
   3.197 +                gd->minor_shift  = XLIDE_PARTN_SHIFT; 
   3.198 +                gd->nr_real      = XLIDE_DEVS_PER_MAJOR; 
   3.199 +            } 
   3.200 +            else if ( is_scsi )
   3.201 +            { 
   3.202 +                gd->minor_shift  = XLSCSI_PARTN_SHIFT; 
   3.203 +                gd->nr_real      = XLSCSI_DEVS_PER_MAJOR; 
   3.204 +            }
   3.205 +            else
   3.206 +            { 
   3.207 +                gd->minor_shift  = XLVBD_PARTN_SHIFT; 
   3.208 +                gd->nr_real      = XLVBD_DEVS_PER_MAJOR; 
   3.209 +            }
   3.210 +
   3.211 +            /* 
   3.212 +            ** The sizes[] and part[] arrays hold the sizes and other 
   3.213 +            ** information about every partition with this 'major' (i.e. 
   3.214 +            ** every disk sharing the 8 bit prefix * max partns per disk) 
   3.215 +            */
   3.216 +            gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL);
   3.217 +            gd->part  = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), 
   3.218 +                                GFP_KERNEL);
   3.219 +            memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int));
   3.220 +            memset(gd->part,  0, max_part * gd->nr_real 
   3.221 +                   * sizeof(struct hd_struct));
   3.222  
   3.223  
   3.224 -    /* keep track of which majors we've seen so far */
   3.225 -    for (i = 0; i < 256; i++) 
   3.226 -	majors[i] = 0; 
   3.227 +            gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), 
   3.228 +                                       GFP_KERNEL);
   3.229 +            memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t));
   3.230  
   3.231 -    /* 
   3.232 -    ** We need to loop through each major device we've been told about and: 
   3.233 -    ** a) register the appropriate blkdev 
   3.234 -    ** b) setup the indexed-by-major global arrays (blk_size[], 
   3.235 -    **    blksize_size[], hardsect_size[], max_sectors[], read_ahead[]) 
   3.236 -    ** c) setup the block queue + make it sensible
   3.237 -    ** d) create an appropriate gendisk structure, and 
   3.238 -    ** e) register the gendisk 
   3.239 -    */
   3.240 -    for (i = 0; i < xdi->count; i++)
   3.241 -    {
   3.242 -	device = xdi->disks[i].device;
   3.243 -	major  = MAJOR(device); 
   3.244 -	minor  = MINOR(device);
   3.245 -	is_ide = IDE_DISK_MAJOR(major);  /* is this an ide device? */
   3.246 -	is_scsi= SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
   3.247 -	
   3.248 -	if(is_ide) { 
   3.249 -	    major_name = XLIDE_MAJOR_NAME; 
   3.250 -	    max_part   = XLIDE_MAX_PART;
   3.251 -	} else if(is_scsi) { 
   3.252 -	    major_name = XLSCSI_MAJOR_NAME;
   3.253 -	    max_part   = XLSCSI_MAX_PART;
   3.254 -	} else { 
   3.255 -	    major_name = XLVBD_MAJOR_NAME;
   3.256 -	    max_part   = XLVBD_MAX_PART;
   3.257 -	}
   3.258 +            gd->next   = NULL;            
   3.259 +            gd->fops   = &xlvbd_block_fops;
   3.260  
   3.261 -	/* 
   3.262 -	** XXX SMH: conventionally we assume a minor device if the 
   3.263 -	** corresponding linux device number would be a minor device; 
   3.264 -	** minor devices require slightly different handling than 
   3.265 -	** 'full' devices (e.g. in terms of partition table handling). 
   3.266 -	*/
   3.267 -	partno = minor & (max_part - 1); 
   3.268 -
   3.269 -	if(!majors[major]) {
   3.270 -
   3.271 -	    result = register_blkdev(major, major_name, &xlvbd_block_fops);
   3.272 -	    if (result < 0) {
   3.273 -		printk(KERN_ALERT "XL VBD: can't get major %d\n", major);
   3.274 -		continue; 
   3.275 -	    }
   3.276 +            gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), 
   3.277 +                                 GFP_KERNEL);
   3.278 +            gd->flags  = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL);
   3.279 +    
   3.280 +            memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr));
   3.281 +            memset(gd->flags, 0, gd->nr_real *  sizeof(*gd->flags));
   3.282  
   3.283 -	    blk_size[major]      = NULL;
   3.284 -	    if(is_ide) { 
   3.285 -		blksize_size[major]  = xlide_blksize_size;
   3.286 -		hardsect_size[major] = xlide_hardsect_size;
   3.287 -		max_sectors[major]   = xlide_max_sectors;
   3.288 -		read_ahead[major]    = 8; // from drivers/ide/ide-probe.c
   3.289 -	    } else if(is_scsi) { 
   3.290 -		blksize_size[major]  = xlscsi_blksize_size;
   3.291 -		hardsect_size[major] = xlscsi_hardsect_size;
   3.292 -		max_sectors[major]   = xlscsi_max_sectors;
   3.293 -		read_ahead[major]    = 0; // XXX 8; -- guessing 
   3.294 -	    } else { 
   3.295 -		blksize_size[major]  = xlvbd_blksize_size;
   3.296 -		hardsect_size[major] = xlvbd_hardsect_size;
   3.297 -		max_sectors[major]   = xlvbd_max_sectors;
   3.298 -		read_ahead[major]    = 8;
   3.299 -	    }
   3.300 -	
   3.301 -	    blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
   3.302 -	
   3.303 -	    /*
   3.304 -	     * Turn off barking 'headactive' mode. We dequeue buffer heads as
   3.305 -	     * soon as we pass them down to Xen.
   3.306 -	     */
   3.307 -	    blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
   3.308 +            add_gendisk(gd);
   3.309 +
   3.310 +            blk_size[major] = gd->sizes;
   3.311 +        }
   3.312 +
   3.313 +        if ( XD_READONLY(xdi->disks[i].info) )
   3.314 +            set_device_ro(device, 1); 
   3.315  
   3.316 -	    /* Construct an appropriate gendisk structure. */
   3.317 -	    gd             = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
   3.318 -	    gd->major      = major;
   3.319 -	    gd->major_name = major_name; 
   3.320 -	    
   3.321 -	    gd->max_p      = max_part; 
   3.322 -	    if(is_ide) { 
   3.323 -		gd->minor_shift  = XLIDE_PARTN_SHIFT; 
   3.324 -		gd->nr_real      = XLIDE_DEVS_PER_MAJOR; 
   3.325 -	    } else if(is_scsi) { 
   3.326 -		gd->minor_shift  = XLSCSI_PARTN_SHIFT; 
   3.327 -		gd->nr_real      = XLSCSI_DEVS_PER_MAJOR; 
   3.328 -	    } else { 
   3.329 -		gd->minor_shift  = XLVBD_PARTN_SHIFT; 
   3.330 -		gd->nr_real      = XLVBD_DEVS_PER_MAJOR; 
   3.331 -	    }
   3.332 -
   3.333 -	    /* 
   3.334 -	    ** The sizes[] and part[] arrays hold the sizes and other 
   3.335 -	    ** information about every partition with this 'major' (i.e. 
   3.336 -	    ** every disk sharing the 8 bit prefix * max partns per disk) 
   3.337 -	    */
   3.338 -	    gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL);
   3.339 -	    gd->part  = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct), 
   3.340 -				     GFP_KERNEL);
   3.341 -	    memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int));
   3.342 -	    memset(gd->part,  0, max_part * gd->nr_real 
   3.343 -		   * sizeof(struct hd_struct));
   3.344 -
   3.345 -
   3.346 -	    gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t), 
   3.347 -				       GFP_KERNEL);
   3.348 -	    memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t));
   3.349 -
   3.350 -	    gd->next   = NULL;            
   3.351 -	    gd->fops   = &xlvbd_block_fops;
   3.352 -
   3.353 -	    gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr), 
   3.354 -				 GFP_KERNEL);
   3.355 -	    gd->flags  = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL);
   3.356 -	    
   3.357 -	    memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr));
   3.358 -	    memset(gd->flags, 0, gd->nr_real *  sizeof(*gd->flags));
   3.359 -
   3.360 -	    /* 
   3.361 -	    ** Keep track of gendisk both locally and in the global array. 
   3.362 -	    ** XXX SMH: can probably do without local copy -- FIXME later 
   3.363 -	    */
   3.364 -	    xlvbd_gendisk[i] = gd;
   3.365 -	    add_gendisk(gd);
   3.366 +        gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XENO;
   3.367 +        
   3.368 +        if ( partno != 0 )
   3.369 +        { 
   3.370 +            /* Need to skankily setup 'partition' information */
   3.371 +            gd->part[partno].start_sect = 0; 
   3.372 +            gd->part[partno].nr_sects   = xdi->disks[i].capacity; 
   3.373 +            gd->sizes[partno]           = xdi->disks[i].capacity; 
   3.374 +        }
   3.375 +        else
   3.376 +        { 
   3.377 +            /* Some final fix-ups depending on the device type */
   3.378 +            switch ( XD_TYPE(xdi->disks[i].info) )
   3.379 +            { 
   3.380 +            case XD_TYPE_CDROM:
   3.381 +            case XD_TYPE_FLOPPY: 
   3.382 +            case XD_TYPE_TAPE:
   3.383 +                gd->part[minor].nr_sects = xdi->disks[i].capacity;
   3.384 +                gd->sizes[minor] = xdi->disks[i].capacity>>(BLOCK_SIZE_BITS-9);
   3.385 +                gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; 
   3.386 +                printk(KERN_ALERT 
   3.387 +                       "Skipping partition check on %s /dev/%s\n", 
   3.388 +                       XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : 
   3.389 +                       (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : 
   3.390 +                        "floppy"), disk_name(gd, MINOR(device), buf)); 
   3.391 +                break; 
   3.392  
   3.393 -	    /* XXX SMH: not clear on what 'real_devices' is indexed by; 
   3.394 -	       hence using unit number for now but in old code was 'disk' aka 
   3.395 -	       sequence number assigned by xen during probe = barfle? */
   3.396 -	    ((xl_disk_t *)gd->real_devices)[minor>>gd->minor_shift].capacity =
   3.397 -	    xdi->disks[i].capacity;
   3.398 -
   3.399 -	    
   3.400 -	    /* remember that we've done this major */
   3.401 -	    majors[major] = 1; 
   3.402 -	} else 
   3.403 -	    /* Continue the setup of this gendisk */
   3.404 -	    gd = get_gendisk(device); 
   3.405 -
   3.406 -	if(XD_READONLY(xdi->disks[i].info)) 
   3.407 -	    set_device_ro(device, 1); 
   3.408 -
   3.409 -	if(partno) { 
   3.410 -
   3.411 -	    /* Need to skankily setup 'partition' information */
   3.412 -	    gd->part[partno].start_sect = 0; 
   3.413 -	    gd->part[partno].nr_sects   = xdi->disks[i].capacity; 
   3.414 -	    gd->sizes[partno]           = xdi->disks[i].capacity; 
   3.415 -
   3.416 -	} else { 
   3.417 +            case XD_TYPE_DISK: 
   3.418 +                register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, 
   3.419 +                              xdi->disks[i].capacity);
   3.420 +                break; 
   3.421  
   3.422 -	    /* Some final fix-ups depending on the device type */
   3.423 -	    switch (XD_TYPE(xdi->disks[i].info)) 
   3.424 -	    { 
   3.425 -
   3.426 -	    case XD_TYPE_CDROM:
   3.427 -	    case XD_TYPE_FLOPPY: 
   3.428 -	    case XD_TYPE_TAPE:
   3.429 -		gd->flags[minor >> gd->minor_shift] = GENHD_FL_REMOVABLE; 
   3.430 -		printk(KERN_ALERT 
   3.431 -		       "Skipping partition check on %s /dev/%s\n", 
   3.432 -		       XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" : 
   3.433 -		       (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" : 
   3.434 -			"floppy"), disk_name(gd, MINOR(device), buf)); 
   3.435 -		break; 
   3.436 -		
   3.437 -	    case XD_TYPE_DISK: 
   3.438 -		register_disk(gd, device, gd->nr_real, &xlvbd_block_fops, 
   3.439 -			      xdi->disks[i].capacity);
   3.440 -		break; 
   3.441 -		
   3.442 -	    default: 
   3.443 -		printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 
   3.444 -		       XD_TYPE(xdi->disks[i].info)); 
   3.445 -		break; 
   3.446 -	    }
   3.447 -
   3.448 -	}
   3.449 -	    
   3.450 -	printk(KERN_ALERT "XenoLinux Virtual Block Device Driver "
   3.451 -	       "installed [device: %04x]\n", device);
   3.452 +            default: 
   3.453 +                printk(KERN_ALERT "XenoLinux: unknown device type %d\n", 
   3.454 +                       XD_TYPE(xdi->disks[i].info)); 
   3.455 +                break; 
   3.456 +            }
   3.457 +        }
   3.458 +    
   3.459 +        printk(KERN_ALERT "XenoLinux Virtual Block Device Driver "
   3.460 +               "installed [device: %04x]\n", device);
   3.461      }
   3.462  
   3.463      return 0;
   3.464  }
   3.465  
   3.466 -/* 
   3.467 -** XXX SMH: crappy linear scan routine to map from a device number bac k
   3.468 -** to the relevant gendisk; could be made better if and when it becomes 
   3.469 -** an issue but for now we expect success within a few loop iterations. 
   3.470 -*/
   3.471 -struct gendisk *xldev_to_gendisk(kdev_t xldev)
   3.472 -{
   3.473 -    int i; 
   3.474 -    short major = MAJOR(xldev); 
   3.475 -    
   3.476 -    for(i = 0; i < XLVBD_MAX_MAJORS; i++) { 
   3.477 -	if(xlvbd_gendisk[i]->major == major)
   3.478 -	    return xlvbd_gendisk[i]; 
   3.479 -    }
   3.480 -    
   3.481 -    /* didn't find it -- death */
   3.482 -    BUG();
   3.483 -    return NULL; 
   3.484 -}
   3.485 -
   3.486  void xlvbd_cleanup(void)
   3.487  {
   3.488 -    bool is_ide, is_scsi; 
   3.489 +    int is_ide, is_scsi, i; 
   3.490      struct gendisk *gd; 
   3.491      char *major_name; 
   3.492      int major; 
   3.493  
   3.494 -    for(major = 0; major < XLVBD_MAX_MAJORS; major++) { 
   3.495 -
   3.496 -	if(!(gd = xlvbd_gendisk[major]))
   3.497 -	    continue; 
   3.498 -
   3.499 -	is_ide = IDE_DISK_MAJOR(major);  /* is this an ide device? */
   3.500 -	is_scsi= SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
   3.501 +    for ( major = 0; major < MAX_BLKDEV; major++ )
   3.502 +    {
   3.503 +        if ( (gd = get_gendisk(MKDEV(major, 0))) == NULL )
   3.504 +            continue; 
   3.505  
   3.506 -	blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); 
   3.507 -	
   3.508 -	if(is_ide) { 
   3.509 -	    major_name = XLIDE_MAJOR_NAME; 
   3.510 -	} else if(is_scsi) { 
   3.511 -	    major_name = XLSCSI_MAJOR_NAME;
   3.512 -	} else { 
   3.513 -	    major_name = XLVBD_MAJOR_NAME;
   3.514 -	}
   3.515 +        /*
   3.516 +         * If this is a 'Xeno' blkdev then at least one unit will have the Xeno
   3.517 +         * flag set.
   3.518 +         */
   3.519 +        for ( i = 0; i < gd->nr_real; i++ )
   3.520 +            if ( gd->flags[i] & GENHD_FL_XENO )
   3.521 +                break;
   3.522 +        if ( i == gd->nr_real )
   3.523 +            continue;
   3.524 +        
   3.525 +        is_ide  = IDE_DISK_MAJOR(major);  /* is this an ide device? */
   3.526 +        is_scsi = SCSI_BLK_MAJOR(major);  /* is this a scsi device? */
   3.527  
   3.528 -	if (unregister_blkdev(major, major_name) != 0) 
   3.529 -	    printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:"
   3.530 -		   "major device %04x uninstalled w/ errors\n", major); 
   3.531 +        blk_cleanup_queue(BLK_DEFAULT_QUEUE(major)); 
   3.532  
   3.533 +        if ( is_ide ) 
   3.534 +            major_name = XLIDE_MAJOR_NAME; 
   3.535 +        else if ( is_scsi )
   3.536 +            major_name = XLSCSI_MAJOR_NAME;
   3.537 +        else 
   3.538 +            major_name = XLVBD_MAJOR_NAME;
   3.539 +
   3.540 +        if ( unregister_blkdev(major, major_name) != 0 ) 
   3.541 +            printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:"
   3.542 +                   "major device %04x uninstalled w/ errors\n", major); 
   3.543      }
   3.544 -
   3.545 -    return; 
   3.546  }
   3.547  
   3.548 -
   3.549  #ifdef MODULE
   3.550  module_init(xlvbd_init);
   3.551  module_exit(xlvbd_cleanup);