ia64/xen-unstable

changeset 145:f86685fc9147

bitkeeper revision 1.22.4.1 (3e4a8cb8Aw-XeXojqgYl10tZjNiQyA)

Initial 'debugging' support (aka keyboard and serial rx int handlers :-)
Also current state of Alex's IDE stuff (not yet completely working). You
need to config this up to use it.
author smh22@boulderdash.cl.cam.ac.uk
date Wed Feb 12 18:04:40 2003 +0000 (2003-02-12)
parents 4c6ae683ed61
children b15e9e05e112
files .rootkeys BitKeeper/etc/ignore xen-2.4.16/drivers/block/xen_block.c xen-2.4.16/drivers/char/Makefile xen-2.4.16/drivers/char/xen_kbd.c xen-2.4.16/drivers/char/xen_serial.c xen-2.4.16/drivers/ide/ide-disk.c.orig xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_block.c xenolinux-2.4.16-sparse/drivers/block/Config.in xenolinux-2.4.16-sparse/fs/partitions/check.c xenolinux-2.4.16-sparse/fs/partitions/msdos.c xenolinux-2.4.16-sparse/include/linux/blk.h xenolinux-2.4.16-sparse/include/linux/major.h xenolinux-2.4.16-sparse/init/main.c
line diff
     1.1 --- a/.rootkeys	Mon Feb 10 13:28:26 2003 +0000
     1.2 +++ b/.rootkeys	Wed Feb 12 18:04:40 2003 +0000
     1.3 @@ -57,8 +57,13 @@ 3ddb79be04dyXzyXqDbMRS_1funwXQ xen-2.4.1
     1.4  3ddb79beME_0abStePF6fU8XLuQnWw xen-2.4.16/drivers/block/elevator.c
     1.5  3ddb79beNQVrdGyoI4njXhgAjD6a4A xen-2.4.16/drivers/block/genhd.c
     1.6  3ddb79beyWwLRP_BiM2t1JKgr_plEw xen-2.4.16/drivers/block/ll_rw_blk.c
     1.7 +3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen-2.4.16/drivers/block/xen_block.c
     1.8 +3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen-2.4.16/drivers/char/Makefile
     1.9 +3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen-2.4.16/drivers/char/xen_kbd.c
    1.10 +3e4a8cb7nMChlro4wvOBo76n__iCFA xen-2.4.16/drivers/char/xen_serial.c
    1.11  3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen-2.4.16/drivers/ide/Makefile
    1.12  3ddb79bdErDn_WC3G-fWxKNR3viLnA xen-2.4.16/drivers/ide/ide-disk.c
    1.13 +3e4a8cb7DcFFHW_fG_OHbY_6f3lPWw xen-2.4.16/drivers/ide/ide-disk.c.orig
    1.14  3ddb79bdIPNW36FrlId94jTXaW8HoA xen-2.4.16/drivers/ide/ide-dma.c
    1.15  3ddb79be5Ysvhn4se_Z-LQY_hI6UPw xen-2.4.16/drivers/ide/ide-features.c
    1.16  3ddb79bdh1ohsWYRH_KdaXr7cqs12w xen-2.4.16/drivers/ide/ide-geometry.c
    1.17 @@ -267,9 +272,12 @@ 3ddb79b8L4xnwrcvWk6nAbgKVbNkSA xenolinux
    1.18  3ddb79b7v_Be34as7_mlzFlw65hOjQ xenolinux-2.4.16-sparse/arch/xeno/defconfig
    1.19  3ddb79b7KUvtx0knQJoRaBDZQeNidg xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile
    1.20  3ddb79b6Rc0uAOGFthIFxq1KGWZ_Iw xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c
    1.21 +3e4a8cb7JECr--r1ipnrkd7NKdbUqQ xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c
    1.22 +3e4a8cb7SLWsLTXQjv7ng6-3hL4pCA xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c
    1.23  3ddb79b7LLVJBGynxHSOh9A9l97sug xenolinux-2.4.16-sparse/arch/xeno/drivers/console/Makefile
    1.24  3ddb79b7UG2QiRAU-Wvc1Y_BLigu1Q xenolinux-2.4.16-sparse/arch/xeno/drivers/console/console.c
    1.25  3ddb79b75eo4PRXkT6Th9popt_SJhg xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/Makefile
    1.26 +3e4a8cb79dT0F4q5T4GEqMj4CtAquQ xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_block.c
    1.27  3ddb79b7Xyaoep6U0kLvx6Kx7OauDw xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c
    1.28  3df9ce13K7qSLBtHV-01QHPW62649Q xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_memory.c
    1.29  3ddb79b7PulSkF9m3c7K5MkxHRf4hA xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_ops.h
    1.30 @@ -313,10 +321,13 @@ 3ddb79b85fpsKT8A9WYnuJg03b715g xenolinux
    1.31  3ddb79b83Zj7Xn2QVhU4HeMuAC9FjA xenolinux-2.4.16-sparse/arch/xeno/mm/init.c
    1.32  3df9ce13TRWIv0Mawm15zESP7jcT7A xenolinux-2.4.16-sparse/arch/xeno/mm/mmu_context.c
    1.33  3ddb79b7aKdTkbr3u6aze8tVwGh_TQ xenolinux-2.4.16-sparse/arch/xeno/vmlinux.lds
    1.34 +3e4a8cb7lpFFwT1Iu9zXWc8Ew4klFA xenolinux-2.4.16-sparse/drivers/block/Config.in
    1.35  3ddb79bbx682YH6vR2zbVOXwg73ULg xenolinux-2.4.16-sparse/drivers/block/ll_rw_blk.c
    1.36  3ddb79bcJfHdwrPsjqgI33_OsGdVCg xenolinux-2.4.16-sparse/drivers/block/rd.c
    1.37  3ddb79bcpVu-IbnqwQqpRqsEbLpsuw xenolinux-2.4.16-sparse/drivers/char/tty_io.c
    1.38  3e15d5273gfR2fbcYe05kqBSAvCX_w xenolinux-2.4.16-sparse/fs/exec.c
    1.39 +3e4a8cb7kqfJTMeOpPcYxqxv7N18DA xenolinux-2.4.16-sparse/fs/partitions/check.c
    1.40 +3e4a8cb7p079Xxly4uNcouacMSjJLw xenolinux-2.4.16-sparse/fs/partitions/msdos.c
    1.41  3ddb79b8VFtfWSCrXKPN2K21zd_vtw xenolinux-2.4.16-sparse/include/asm-xeno/a.out.h
    1.42  3ddb79b8Zzi13p3OAPV25QgiC3THAQ xenolinux-2.4.16-sparse/include/asm-xeno/apic.h
    1.43  3ddb79baZDlsdV_m6C5CXnWMl15p1g xenolinux-2.4.16-sparse/include/asm-xeno/apicdef.h
    1.44 @@ -422,7 +433,10 @@ 3ddb79bb3cMSs_k2X5Oq2hOIBvmPYA xenolinux
    1.45  3ddb79ba2qYtIQAT_-vCFkkZUXu_UQ xenolinux-2.4.16-sparse/include/asm-xeno/user.h
    1.46  3ddb79bbqhb9X9qWOz5Bv4wOzrkITg xenolinux-2.4.16-sparse/include/asm-xeno/vga.h
    1.47  3ddb79bbA52x94o6uwDYsbzrH2hjzA xenolinux-2.4.16-sparse/include/asm-xeno/xor.h
    1.48 +3e4a8cb7ON8EclY3NN3YPXyMT941hA xenolinux-2.4.16-sparse/include/linux/blk.h
    1.49 +3e4a8cb7GJrKD0z7EF0VZOhdEa01Mw xenolinux-2.4.16-sparse/include/linux/major.h
    1.50  3ddb79bb_7YG4U75ZmEic9YXWTW7Vw xenolinux-2.4.16-sparse/include/linux/sunrpc/debug.h
    1.51 +3e4a8cb7j05wwb1uPZgY16s68o7qAw xenolinux-2.4.16-sparse/init/main.c
    1.52  3ddb79bcxkVPfWlZ1PQKvDrfArzOVw xenolinux-2.4.16-sparse/kernel/panic.c
    1.53  3ddb79bbP31im-mx2NbfthSeqty1Dg xenolinux-2.4.16-sparse/mk
    1.54  3e15d52e0_j129JPvo7xfYGndVFpwQ xenolinux-2.4.16-sparse/mm/memory.c
     2.1 --- a/BitKeeper/etc/ignore	Mon Feb 10 13:28:26 2003 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Wed Feb 12 18:04:40 2003 +0000
     2.3 @@ -3,3 +3,19 @@ PENDING/*
     2.4  xen-2.4.16/common/kernel.c.old
     2.5  xen-2.4.16/common/kernel.c.ok-ish
     2.6  xen-2.4.16/size.image
     2.7 +xen-2.4.16/drivers/block/ll_rw_blk.c.orig
     2.8 +xen-2.4.16/drivers/ide/ide-disk.c.orig
     2.9 +xen-2.4.16/drivers/ide/ide-probe.c.orig
    2.10 +xen-2.4.16/drivers/ide/ide-taskfile.c.orig
    2.11 +xen-2.4.16/drivers/ide/ide.c.orig
    2.12 +xen-2.4.16/drivers/net/e1000/e1000.o
    2.13 +xen-2.4.16/drivers/net/e1000/e1000_ethtool.o
    2.14 +xen-2.4.16/drivers/net/e1000/e1000_hw.o
    2.15 +xen-2.4.16/drivers/net/e1000/e1000_main.o
    2.16 +xen-2.4.16/drivers/net/e1000/e1000_param.o
    2.17 +xen-2.4.16/include/hypervisor-ifs/block.h.orig
    2.18 +xen-2.4.16/include/xeno/blkdev.h.orig
    2.19 +xen-2.4.16/include/xeno/sched.h.orig
    2.20 +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile.orig
    2.21 +xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c.orig
    2.22 +xenolinux-2.4.16-sparse/scripts/kconfig.tk
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen-2.4.16/drivers/block/xen_block.c	Wed Feb 12 18:04:40 2003 +0000
     3.3 @@ -0,0 +1,620 @@
     3.4 +/*
     3.5 + * xen-block.c
     3.6 + *
     3.7 + * process incoming block io requests from guestos's.
     3.8 + */
     3.9 +
    3.10 +#include <xeno/config.h>
    3.11 +#include <xeno/types.h>
    3.12 +#include <xeno/lib.h>
    3.13 +#include <xeno/sched.h>
    3.14 +#include <xeno/blkdev.h>
    3.15 +#include <xeno/event.h>                                    /* mark_hyp_event */
    3.16 +#include <hypervisor-ifs/block.h>
    3.17 +#include <hypervisor-ifs/hypervisor-if.h>
    3.18 +#include <asm-i386/io.h>
    3.19 +#include <asm/spinlock.h>
    3.20 +
    3.21 +#define XEN_BLK_DEBUG 0
    3.22 +#define XEN_BLK_DEBUG_LEVEL KERN_ALERT
    3.23 +
    3.24 +#define XEN_BLK_REQUEST_LIST_SIZE 256                      /* very arbitrary */
    3.25 +
    3.26 +typedef struct blk_request
    3.27 +{
    3.28 +  struct list_head queue;
    3.29 +  struct buffer_head *bh;
    3.30 +  blk_ring_entry_t request;
    3.31 +  struct task_struct *domain;                           /* requesting domain */
    3.32 +} blk_request_t;
    3.33 +
    3.34 +static int pending_work;                  /* which domains have work for us? */
    3.35 +blk_request_t blk_request_list[XEN_BLK_REQUEST_LIST_SIZE];
    3.36 +struct list_head free_queue;                              /* unused requests */
    3.37 +struct list_head pending_queue;                      /* waiting for hardware */
    3.38 +struct list_head io_done_queue;       /* request completed. send to guest os */
    3.39 +spinlock_t free_queue_lock;
    3.40 +spinlock_t pending_queue_lock;
    3.41 +spinlock_t io_done_queue_lock;
    3.42 +
    3.43 +/* some definitions */
    3.44 +void dumpx (char *buffer, int count);
    3.45 +void printx (char * string);
    3.46 +long do_block_io_op_domain (struct task_struct* task);
    3.47 +int dispatch_rw_block_io (int index);
    3.48 +int dispatch_probe_block_io (int index);
    3.49 +int dispatch_debug_block_io (int index);
    3.50 +
    3.51 +/*
    3.52 + * end_block_io_op
    3.53 + *
    3.54 + * IO has completed.  Need to notify the guest operating system.
    3.55 + * Called from hardware interrupt.
    3.56 + */
    3.57 +
    3.58 +void end_block_io_op(struct buffer_head * bh)
    3.59 +{
    3.60 +  unsigned long cpu_mask;
    3.61 +  /* struct list_head *list;*/
    3.62 +  blk_request_t *blk_request = NULL;
    3.63 +  unsigned long flags;                                           /* irq save */
    3.64 +
    3.65 +#if 0
    3.66 +  printk("{E}"); 
    3.67 +#endif
    3.68 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
    3.69 +			     "XEN end_block_io_op,  bh: %lx\n",
    3.70 +			     (unsigned long)bh);
    3.71 +
    3.72 +  {
    3.73 +    char temp[100];
    3.74 +    sprintf(temp, "endio  bh: 0x%p, blkno: 0x%lx",
    3.75 +	    bh, bh->b_blocknr);
    3.76 +    printx(temp);
    3.77 +  }
    3.78 +
    3.79 +  spin_lock_irqsave(&pending_queue_lock, flags);
    3.80 +  /*
    3.81 +  list_for_each (list, &pending_queue)
    3.82 +  {
    3.83 +    blk_request = list_entry(list, blk_request_t, queue);
    3.84 +    if (blk_request->bh == bh)      
    3.85 +    {
    3.86 +      break;
    3.87 +    }
    3.88 +  }
    3.89 +  */
    3.90 +  blk_request = (blk_request_t *)bh->b_xen_request;
    3.91 +  if (blk_request == NULL)
    3.92 +  {
    3.93 +    printk (KERN_ALERT
    3.94 +	    "   block io interrupt received for unknown buffer [0x%lx]\n",
    3.95 +	    (unsigned long) bh);
    3.96 +    spin_unlock_irqrestore(&pending_queue_lock, flags);
    3.97 +    return;
    3.98 +  }
    3.99 +  list_del(&blk_request->queue);
   3.100 +  spin_unlock_irqrestore(&pending_queue_lock, flags);
   3.101 +
   3.102 +  spin_lock_irqsave(&io_done_queue_lock, flags);
   3.103 +  list_add_tail(&blk_request->queue, &io_done_queue);
   3.104 +  spin_unlock_irqrestore(&io_done_queue_lock, flags);
   3.105 +
   3.106 +  /* enqueue work */
   3.107 +  cpu_mask = mark_hyp_event(blk_request->domain, _HYP_EVENT_BLK_RX);
   3.108 +
   3.109 +  return;
   3.110 +}
   3.111 +
   3.112 +/*
   3.113 + * flush_blk_queue
   3.114 + *
   3.115 + * Called by the hypervisor synchronously when there is something to do
   3.116 + * (block transfers have completed)
   3.117 + */
   3.118 +
   3.119 +void flush_blk_queue(void)
   3.120 +{
   3.121 +  blk_request_t *blk_request;
   3.122 +  int position = 0;
   3.123 +  blk_ring_t *blk_ring;
   3.124 +  unsigned long flags;
   3.125 +  int loop;
   3.126 +
   3.127 +#if 0
   3.128 +  printk("{F}"); 
   3.129 +#endif
   3.130 +  /*
   3.131 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
   3.132 +			     "XEN flush_blk_queue\n");
   3.133 +  */
   3.134 +
   3.135 +  clear_bit(_HYP_EVENT_BLK_RX, &current->hyp_events);
   3.136 +
   3.137 +  /* NEED LOCK? */
   3.138 +  spin_lock_irqsave(&io_done_queue_lock, flags);
   3.139 +  while (!list_empty(&io_done_queue))
   3.140 +  {
   3.141 +    blk_request = list_entry(io_done_queue.next, blk_request_t, queue);
   3.142 +    list_del (&blk_request->queue);
   3.143 +    spin_unlock_irqrestore(&io_done_queue_lock, flags);
   3.144 +
   3.145 +    /* place on ring for guest os */ 
   3.146 +    blk_ring = blk_request->domain->blk_ring_base;
   3.147 +    position = blk_ring->rx_prod;
   3.148 +
   3.149 +    if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
   3.150 +			       "XEN flush_blk_queue [%d]\n", position);
   3.151 +
   3.152 +    memcpy(&blk_ring->rx_ring[position], &blk_request->request,
   3.153 +	   sizeof(blk_ring_entry_t));
   3.154 +    blk_ring->rx_prod = BLK_RX_RING_INC(blk_ring->rx_prod);
   3.155 +
   3.156 +    /* notify appropriate guest os */
   3.157 +    set_bit(_EVENT_BLK_RX,
   3.158 +	    &blk_request->domain->shared_info->events);
   3.159 +
   3.160 +    if (0)
   3.161 +    {
   3.162 +      int temp;
   3.163 +      struct buffer_head *bh = blk_request->bh;
   3.164 +      char * vbuffer = bh->b_data;
   3.165 +
   3.166 +      printk (KERN_ALERT "XEN return block 0x%lx\n", bh->b_blocknr);
   3.167 +
   3.168 +      for (temp = 0; temp < bh->b_size; temp++)
   3.169 +      {
   3.170 +	if (temp % 16 == 0)       printk ("[%04x]  ", temp);
   3.171 +	else if (temp % 4 == 0)   printk (" ");
   3.172 +	                          printk ("%02x",
   3.173 +					  vbuffer[temp] & 255);
   3.174 +	if ((temp + 1) % 16 == 0) printk ("\n");
   3.175 +      }
   3.176 +      printk ("\n\n");
   3.177 +    }
   3.178 +
   3.179 +    /* free the buffer header allocated in do_block_io_op */
   3.180 +    if (blk_request->bh)
   3.181 +    {
   3.182 +      kfree(blk_request->bh);                     /* alloc in do_block_io_op */
   3.183 +    }
   3.184 +
   3.185 +    spin_lock_irqsave(&free_queue_lock, flags);
   3.186 +    list_add_tail(&blk_request->queue, &free_queue);
   3.187 +    spin_unlock_irqrestore(&free_queue_lock, flags);
   3.188 +
   3.189 +    spin_lock_irqsave(&io_done_queue_lock, flags);
   3.190 +  }
   3.191 +  spin_unlock_irqrestore(&io_done_queue_lock, flags);
   3.192 +
   3.193 +  /*
   3.194 +   * now check if there is any pending work from any domain
   3.195 +   * that we were previously unable to process.
   3.196 +   *
   3.197 +   * NOTE: the current algorithm will check _every_ domain
   3.198 +   * and wake up _every_ domain that has pending work.
   3.199 +   * In the future, we should stop waking up domains once
   3.200 +   * there isn't any space for their requests any more
   3.201 +   * ALSO, we need to maintain a counter of the last domain
   3.202 +   * that we woke up for fairness... we shouldn't restart
   3.203 +   * at domain 0 every time (although we might want to special
   3.204 +   * case domain 0);
   3.205 +   */
   3.206 +  for (loop = 0; loop < XEN_BLOCK_MAX_DOMAINS; loop++)
   3.207 +  {
   3.208 +    int domain = pending_work & (1 << loop);
   3.209 +
   3.210 +    if (domain)
   3.211 +    {
   3.212 +      struct task_struct *mytask = current;
   3.213 +
   3.214 +      /*
   3.215 +      printk (KERN_ALERT 
   3.216 +	      "flush_blk_queue  pending_work: %x  domain: %d  loop: %d\n",
   3.217 +	      pending_work, domain, loop);
   3.218 +      */
   3.219 +      /* IS THERE A BETTER WAY OF FINDING THE TASK STRUCT FOR A 
   3.220 +       * PARTICULAR DOMAIN? 
   3.221 +       *
   3.222 +       * WHAT IF THE TASK GOES AWAY BEFORE WE HAVE A CHANCE TO
   3.223 +       * FINISH PROCESSING ALL OF ITS REQUESTS?
   3.224 +       */
   3.225 +      while (mytask->domain != loop)
   3.226 +      {
   3.227 +	mytask = mytask->next_task;
   3.228 +      }
   3.229 +      do_block_io_op_domain(mytask);
   3.230 +
   3.231 +      pending_work = pending_work & !(1 << loop);
   3.232 +      /*
   3.233 +      printk (KERN_ALERT 
   3.234 +	      "                 pending_work: %x  domain: %d  loop: %d\n",
   3.235 +	      pending_work, domain, loop);
   3.236 +      */
   3.237 +    }
   3.238 +  }
   3.239 +}
   3.240 +
   3.241 +/*
   3.242 + * do_block_io_op
   3.243 + *
   3.244 + * Accept a block io request from a guest operating system.
   3.245 + * There is an entry in the hypervisor_call_table (xen/arch/i386/entry.S).
   3.246 + */
   3.247 +
   3.248 +long do_block_io_op (void)
   3.249 +{
   3.250 +  return do_block_io_op_domain(current);
   3.251 +}
   3.252 +
   3.253 +/*
   3.254 + * do_block_io_op
   3.255 + *
   3.256 + * handle the requests for a particular domain
   3.257 + */
   3.258 +
   3.259 +long do_block_io_op_domain (struct task_struct* task)
   3.260 +{
   3.261 +  blk_ring_t *blk_ring = task->blk_ring_base;
   3.262 +  int loop;
   3.263 +
   3.264 +#if 0
   3.265 +  printk("{%d}", current->domain); 
   3.266 +#endif
   3.267 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
   3.268 +			     "XEN do_block_io_op %d %d\n",
   3.269 +			     blk_ring->tx_cons, blk_ring->tx_prod);
   3.270 +
   3.271 +  for (loop = blk_ring->tx_cons;
   3.272 +       loop != blk_ring->tx_prod;
   3.273 +       loop = BLK_TX_RING_INC(loop))
   3.274 +  {
   3.275 +    int status = 1;
   3.276 +
   3.277 +    switch (blk_ring->tx_ring[loop].operation)
   3.278 +    {
   3.279 +      case XEN_BLOCK_READ :
   3.280 +      case XEN_BLOCK_WRITE :
   3.281 +      {
   3.282 +	status = dispatch_rw_block_io(loop);
   3.283 +	break;
   3.284 +      }
   3.285 +      case XEN_BLOCK_PROBE :
   3.286 +      {
   3.287 +	status = dispatch_probe_block_io(loop);
   3.288 +	break;
   3.289 +      }
   3.290 +      case XEN_BLOCK_DEBUG :
   3.291 +      {
   3.292 +	status = dispatch_debug_block_io(loop);
   3.293 +	break;
   3.294 +      }
   3.295 +      default :
   3.296 +      {
   3.297 +	printk (KERN_ALERT "error: unknown block io operation [%d]\n",
   3.298 +		blk_ring->tx_ring[loop].operation);
   3.299 +	BUG();
   3.300 +      }
   3.301 +    }
   3.302 +
   3.303 +    if (status)
   3.304 +    {
   3.305 +      /* unable to successfully issue / complete command, maybe because
   3.306 +       * another resource (e.g. disk request buffers) is unavailable.
   3.307 +       * stop removing items from the communications ring and try 
   3.308 +       * again later 
   3.309 +       */
   3.310 +
   3.311 +      /*
   3.312 +      printk ("do_block_io_op_domain  domain:%d, pending_work: %x\n",
   3.313 +	      task->domain, pending_work);
   3.314 +      */
   3.315 +      pending_work = pending_work | (1 << task->domain);
   3.316 +      /*
   3.317 +      printk ("do_block_io_op_domain  domain:%d, pending_work: %x\n",
   3.318 +	      task->domain, pending_work);
   3.319 +      */
   3.320 +      break;
   3.321 +    }
   3.322 +  }
   3.323 +
   3.324 +  blk_ring->tx_cons = loop;
   3.325 +
   3.326 +  return 0L;
   3.327 +}
   3.328 +
   3.329 +int dispatch_debug_block_io (int index)
   3.330 +{
   3.331 +  struct task_struct *task;
   3.332 +  blk_ring_t *blk_ring = current->blk_ring_base;
   3.333 +  char * buffer;
   3.334 +  char output[1000];
   3.335 +
   3.336 +  int foobar = (unsigned long)blk_ring->tx_ring[index].block_number;
   3.337 +
   3.338 +  printk (KERN_ALERT "dispatch_debug_block_io %d\n", foobar);
   3.339 +
   3.340 +  buffer = phys_to_virt(blk_ring->tx_ring[index].buffer);
   3.341 +  strcpy (buffer, "DEBUG\n");
   3.342 +
   3.343 +  task = current;
   3.344 +  sprintf (buffer, "current %d\n", current->domain);
   3.345 +  sprintf (buffer, "%s  tx: prod: %d, cons: %d, size: %d\n", buffer,
   3.346 +	   blk_ring->tx_prod, blk_ring->tx_cons, blk_ring->tx_ring_size);
   3.347 +  sprintf (buffer, "%s  rx: prod: %d, cons: %d, size: %d\n", buffer,
   3.348 +	   blk_ring->rx_prod, blk_ring->rx_cons, blk_ring->rx_ring_size);
   3.349 +
   3.350 +  task = task->next_task;
   3.351 +  while (task != current)
   3.352 +  {
   3.353 +    blk_ring = task->blk_ring_base;
   3.354 +    sprintf (buffer, "%stask %d\n", buffer, task->domain);
   3.355 +    if (blk_ring != NULL)
   3.356 +    {
   3.357 +      sprintf (buffer, "%s  tx: prod: %d, cons: %d, size: %d\n",
   3.358 +	       buffer, blk_ring->tx_prod, blk_ring->tx_cons, 
   3.359 +	       blk_ring->tx_ring_size);
   3.360 +      sprintf (buffer, "%s  rx: prod: %d, cons: %d, size: %d\n",
   3.361 +	       buffer, blk_ring->rx_prod, blk_ring->rx_cons, 
   3.362 +	       blk_ring->rx_ring_size);
   3.363 +    }
   3.364 +    task = task->next_task;
   3.365 +  }
   3.366 +  dumpx(output, foobar);
   3.367 +  sprintf (buffer, "%s%s\n", buffer, output);
   3.368 +
   3.369 +  return 0;
   3.370 +}
   3.371 +
   3.372 +int dispatch_probe_block_io (int index)
   3.373 +{
   3.374 +  blk_ring_t *blk_ring = current->blk_ring_base;
   3.375 +  xen_disk_info_t *xdi;
   3.376 +
   3.377 +  xdi = phys_to_virt(blk_ring->tx_ring[index].buffer);
   3.378 +
   3.379 +  ide_probe_devices(xdi);
   3.380 +
   3.381 +  return 0;
   3.382 +}
   3.383 +
   3.384 +int dispatch_rw_block_io (int index)
   3.385 +{
   3.386 +  blk_ring_t *blk_ring = current->blk_ring_base;
   3.387 +  struct buffer_head *bh;
   3.388 +  struct request_queue *rq;
   3.389 +  int operation;
   3.390 +  blk_request_t *blk_request;
   3.391 +  unsigned long flags;
   3.392 +
   3.393 +    /*
   3.394 +     * check to make sure that the block request seems at least
   3.395 +     * a bit legitimate
   3.396 +     */
   3.397 +    if ((blk_ring->tx_ring[index].block_size & (0x200 - 1)) != 0)
   3.398 +    {
   3.399 +      printk(KERN_ALERT
   3.400 +	     "    error: dodgy block size: %d\n", 
   3.401 +	     blk_ring->tx_ring[index].block_size);
   3.402 +      BUG();
   3.403 +    }
   3.404 +
   3.405 +    if (XEN_BLK_DEBUG) 
   3.406 +    {
   3.407 +    printk(XEN_BLK_DEBUG_LEVEL
   3.408 +	   "    tx_cons: %d  tx_prod %d  index: %d     op: %s, pri: %s\n",
   3.409 +	   blk_ring->tx_cons, blk_ring->tx_prod, index,
   3.410 +	   (blk_ring->tx_ring[index].operation == XEN_BLOCK_READ ? "read" : "write"),
   3.411 +	   (blk_ring->tx_ring[index].priority == XEN_BLOCK_SYNC ? "sync" : "async"));
   3.412 +    }
   3.413 +
   3.414 +    {
   3.415 +      char temp[100];
   3.416 +      sprintf(temp, "issue  buf: 0x%p, bh: 0x%p, blkno: 0x%lx",
   3.417 +	      blk_ring->tx_ring[index].buffer, bh,
   3.418 +	      (unsigned long)blk_ring->tx_ring[index].block_number);
   3.419 +      printx(temp);
   3.420 +    }
   3.421 +
   3.422 +    /* find an empty request slot */
   3.423 +    spin_lock_irqsave(&free_queue_lock, flags);
   3.424 +    if (list_empty(&free_queue))
   3.425 +    {
   3.426 +      /*      printk (KERN_ALERT "dispatch_rw_block_io EMPTY FREE LIST!! %d\n", index); */
   3.427 +      spin_unlock_irqrestore(&free_queue_lock, flags);
   3.428 +      return 1;
   3.429 +    }
   3.430 +    blk_request = list_entry(free_queue.next, blk_request_t, queue);
   3.431 +    list_del(&blk_request->queue);
   3.432 +    spin_unlock_irqrestore(&free_queue_lock, flags);
   3.433 +
   3.434 +    /* place request on pending list */
   3.435 +    spin_lock_irqsave(&pending_queue_lock, flags);
   3.436 +    list_add_tail(&blk_request->queue, &pending_queue);
   3.437 +    spin_unlock_irqrestore(&pending_queue_lock, flags);
   3.438 +
   3.439 +    /* we'll be doing this frequently, would a cache be appropriate? */
   3.440 +    /* free in flush_blk_queue */
   3.441 +    bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head), 
   3.442 +					GFP_KERNEL);
   3.443 +    if (!bh)
   3.444 +    {
   3.445 +      printk(KERN_ALERT "ERROR: bh is null\n");
   3.446 +      BUG();
   3.447 +    }
   3.448 +
   3.449 +    /* set just the important bits of the buffer header */
   3.450 +    memset (bh, 0, sizeof (struct buffer_head));
   3.451 +
   3.452 +    bh->b_blocknr = blk_ring->tx_ring[index].block_number;   /* block number */
   3.453 +    bh->b_size = blk_ring->tx_ring[index].block_size;          /* block size */
   3.454 +    bh->b_dev = blk_ring->tx_ring[index].device;   /* device (B_FREE = free) */
   3.455 +    bh->b_rsector = blk_ring->tx_ring[index].sector_number; /* sector number */
   3.456 +                                                    
   3.457 +    bh->b_data = phys_to_virt(blk_ring->tx_ring[index].buffer);
   3.458 +                                                          /* ptr to data blk */
   3.459 +    bh->b_count.counter = 1;                       /* users using this block */
   3.460 +    bh->b_xen_request = (void *)blk_request;           /* save block request */
   3.461 +    
   3.462 +
   3.463 +    if (blk_ring->tx_ring[index].operation == XEN_BLOCK_WRITE)
   3.464 +    {
   3.465 +      bh->b_state = ((1 << BH_JBD) |                  /* buffer state bitmap */
   3.466 +		     (1 << BH_Mapped) |
   3.467 +		     (1 << BH_Req) |
   3.468 +		     (1 << BH_Dirty) |
   3.469 +		     (1 << BH_Uptodate));
   3.470 +      operation = WRITE;
   3.471 +    }
   3.472 +    else
   3.473 +    {
   3.474 +      bh->b_state = (1 << BH_Mapped);                 /* buffer state bitmap */
   3.475 +      operation = READ;
   3.476 +    }
   3.477 +
   3.478 +    /* save meta data about request */
   3.479 +    memcpy(&blk_request->request,                    /* NEED COPY_FROM_USER? */
   3.480 +	   &blk_ring->tx_ring[index], sizeof(blk_ring_entry_t));
   3.481 +    blk_request->bh = bh;
   3.482 +    blk_request->domain = current;                    /* save current domain */
   3.483 +
   3.484 +    /* dispatch single block request */
   3.485 +    ll_rw_block(operation, 1, &bh);                        /* linux top half */
   3.486 +    rq = blk_get_queue(bh->b_rdev);                         
   3.487 +    generic_unplug_device(rq);                          /* linux bottom half */
   3.488 +
   3.489 +    return 0;
   3.490 +}
   3.491 +
   3.492 +/*
   3.493 + * initialize_block_io
   3.494 + *
   3.495 + * initialize everything for block io 
   3.496 + * called from arch/i386/setup.c::start_of_day
   3.497 + */
   3.498 +
   3.499 +void initialize_block_io ()
   3.500 +{
   3.501 +  int loop;
   3.502 +
   3.503 +  INIT_LIST_HEAD(&free_queue);
   3.504 +  INIT_LIST_HEAD(&pending_queue);
   3.505 +  INIT_LIST_HEAD(&io_done_queue);
   3.506 +  
   3.507 +  spin_lock_init(&free_queue_lock);
   3.508 +  spin_lock_init(&pending_queue_lock);
   3.509 +  spin_lock_init(&io_done_queue_lock);
   3.510 +
   3.511 +  for (loop = 0; loop < XEN_BLK_REQUEST_LIST_SIZE; loop++)
   3.512 +  {
   3.513 +    list_add_tail(&blk_request_list[loop].queue, &free_queue);
   3.514 +  }
   3.515 +
   3.516 +  /*
   3.517 +   * if bit i is true then domain i has work for us to do.
   3.518 +   */
   3.519 +  pending_work = 0;
   3.520 +
   3.521 +  return;
   3.522 +}
   3.523 +
   3.524 +
   3.525 +#ifdef DEBUG
   3.526 +
   3.527 +/*
   3.528 + * debug dump_queue
   3.529 + * arguments: queue head, name of queue
   3.530 + */
   3.531 +void dump_queue(struct list_head *queue, char *name)
   3.532 +{
   3.533 +  struct list_head *list;
   3.534 +  int loop = 0;
   3.535 +
   3.536 +  printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
   3.537 +	  (unsigned long) queue->next, (unsigned long) queue->prev);
   3.538 +  list_for_each (list, queue)
   3.539 +  {
   3.540 +    printk ("  %s %d : %lx   n: %lx, p: %lx\n", name, loop++, 
   3.541 +	    (unsigned long)list,
   3.542 +	    (unsigned long)list->next, (unsigned long)list->prev);
   3.543 +  }
   3.544 +}
   3.545 +
   3.546 +void dump_queue_head(struct list_head *queue, char *name)
   3.547 +{
   3.548 +  struct list_head *list;
   3.549 +  int loop = 0;
   3.550 +
   3.551 +  printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
   3.552 +	  (unsigned long) queue->next, (unsigned long) queue->prev);
   3.553 +  list_for_each (list, queue)
   3.554 +  {
   3.555 +    printk ("      %d : %lx   n: %lx, p: %lx\n", loop++, 
   3.556 +	    (unsigned long)list,
   3.557 +	    (unsigned long)list->next, (unsigned long)list->prev);
   3.558 +    if (loop >= 5) return;
   3.559 +  }
   3.560 +}
   3.561 +
   3.562 +#endif /* DEBUG */
   3.563 +
   3.564 +
   3.565 +#define debug_block_size 200000
   3.566 +#define debug_output_size 10
   3.567 +
   3.568 +static int    countx = 0;
   3.569 +static char * arrayx[debug_block_size];
   3.570 +static int    outputx = 0;
   3.571 +
   3.572 +void
   3.573 +printx (char * string)
   3.574 +{
   3.575 +  char * s;
   3.576 +
   3.577 +  s = (char *) kmalloc(strlen(string), GFP_KERNEL);
   3.578 +  strcpy (s, string);
   3.579 +  arrayx[countx++] = s;
   3.580 +
   3.581 +  if (countx >= debug_block_size)
   3.582 +  {
   3.583 +    countx = 0;
   3.584 +    printk (KERN_ALERT "printx wrap\n");
   3.585 +  }
   3.586 +
   3.587 +}
   3.588 +
   3.589 +void
   3.590 +dumpx (char *buffer, int count)
   3.591 +{
   3.592 +  int loop;
   3.593 +  int start;
   3.594 +
   3.595 +  sprintf (buffer, "debug dump\n");
   3.596 +
   3.597 +  /*
   3.598 +  for (loop = outputx;
   3.599 +       loop < outputx + debug_output_size && loop < countx; 
   3.600 +       loop ++)
   3.601 +  {
   3.602 +    sprintf (buffer, "%s%02d:%s\n", buffer, loop, arrayx[loop]);
   3.603 +  }
   3.604 +  outputx = loop;
   3.605 +  */
   3.606 +  
   3.607 +  if (count == 0 || count > countx)
   3.608 +  {
   3.609 +    start = 0;
   3.610 +  }
   3.611 +  else
   3.612 +  {
   3.613 +    start = countx - count;
   3.614 +  }
   3.615 +
   3.616 +  printk (KERN_ALERT "DUMPX BUFFER\n");
   3.617 +  for (loop = start; loop < countx; loop++)
   3.618 +  {
   3.619 +    printk (KERN_ALERT "%4d %s\n", loop, arrayx[loop]);
   3.620 +  }
   3.621 +  printk (KERN_ALERT "DUMPX bye bye\n");
   3.622 +}
   3.623 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen-2.4.16/drivers/char/Makefile	Wed Feb 12 18:04:40 2003 +0000
     4.3 @@ -0,0 +1,8 @@
     4.4 +
     4.5 +include $(BASEDIR)/Rules.mk
     4.6 +
     4.7 +default: $(OBJS)
     4.8 +	$(LD) -r -o driver.o $(OBJS)
     4.9 +
    4.10 +clean:
    4.11 +	rm -f *.o *~ core
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen-2.4.16/drivers/char/xen_kbd.c	Wed Feb 12 18:04:40 2003 +0000
     5.3 @@ -0,0 +1,113 @@
     5.4 +#include <asm-i386/io.h>
     5.5 +
     5.6 +#define KEYBOARD_IRQ 1
     5.7 +
     5.8 +#define KBD_STATUS_REG	     0x64 /* Status register (R) */
     5.9 +#define KBD_CNTL_REG	     0x64 /* Controller command register (W) */
    5.10 +#define KBD_DATA_REG	     0x60 /* Keyboard data register (R/W) */
    5.11 +
    5.12 +/* register status bits */
    5.13 +#define KBD_STAT_OBF 	     0x01 /* Keyboard output buffer full */
    5.14 +#define KBD_STAT_IBF 	     0x02 /* Keyboard input buffer full */
    5.15 +#define KBD_STAT_SELFTEST    0x04 /* Self test successful */
    5.16 +#define KBD_STAT_CMD	     0x08 /* Last write was a command write (0=data) */
    5.17 +
    5.18 +#define KBD_STAT_UNLOCKED    0x10 /* Zero if keyboard locked */
    5.19 +#define KBD_STAT_MOUSE_OBF   0x20 /* Mouse output buffer full */
    5.20 +#define KBD_STAT_GTO 	     0x40 /* General receive/xmit timeout */
    5.21 +#define KBD_STAT_PERR 	     0x80 /* Parity error */
    5.22 +
    5.23 +#define kbd_read_input() inb(KBD_DATA_REG)
    5.24 +#define kbd_read_status() inb(KBD_STATUS_REG)
    5.25 +
    5.26 +
    5.27 +static void
    5.28 +dispatch_scancode (unsigned char scancode)
    5.29 +{
    5.30 +    /*
    5.31 +     * we could be a bit more clever here, but why?
    5.32 +     * just add a jump to your debug routine for the appropriate character.
    5.33 +     */
    5.34 +    switch (scancode)
    5.35 +    {
    5.36 +    case 0x01 :                                                       /* esc */
    5.37 +	printk ("<esc>");
    5.38 +	break;
    5.39 +    case 0x9e :                                                         /* a */
    5.40 +	printk ("a");
    5.41 +	break;
    5.42 +    case 0x9f :                                                         /* s */
    5.43 +	printk ("s");
    5.44 +	break;
    5.45 +    case 0xae :                                                         /* c */
    5.46 +	printk ("c");
    5.47 +	break;
    5.48 +    case 0xb0 :                                                         /* b */
    5.49 +	printk ("b");
    5.50 +	break;
    5.51 +    case 0xbb :                                                        /* f1 */
    5.52 +	printk ("<f1>");
    5.53 +	break;
    5.54 +    case 0xbc :                                                        /* f2 */
    5.55 +	printk ("<f2>");
    5.56 +	break;
    5.57 +    case 0xbd :                                                        /* f3 */
    5.58 +	printk ("<f3>");
    5.59 +	break;
    5.60 +    case 0xbe :                                                        /* f4 */
    5.61 +	printk ("<f4>");
    5.62 +	break;
    5.63 +    case 0xbf :                                                        /* f5 */
    5.64 +	/* xen_block_dump_state(); */
    5.65 +	break;
    5.66 +    default :
    5.67 +	/* printk ("%x ", scancode); */
    5.68 +    }
    5.69 +
    5.70 +    return; 
    5.71 +}
    5.72 +
    5.73 +
    5.74 +/* regs should be struct pt_regs */
    5.75 +
    5.76 +static void keyboard_interrupt(int irq, void *dev_id, void *regs)
    5.77 +{
    5.78 +    unsigned char status = kbd_read_status();
    5.79 +    unsigned int work = 10000;
    5.80 +    
    5.81 +    while ((--work > 0) && (status & KBD_STAT_OBF))
    5.82 +    {
    5.83 +	unsigned char scancode;
    5.84 +	
    5.85 +	scancode = kbd_read_input();
    5.86 +	
    5.87 +	if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
    5.88 +	{
    5.89 +	    if (status & KBD_STAT_MOUSE_OBF)
    5.90 +		/* mouse event, ignore */;
    5.91 +	    else
    5.92 +		dispatch_scancode (scancode);
    5.93 +	}
    5.94 +	status = kbd_read_status();
    5.95 +    }
    5.96 +    
    5.97 +    if (!work)
    5.98 +	printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", status);
    5.99 +    
   5.100 +    return;
   5.101 +}
   5.102 +
   5.103 +
   5.104 +extern int request_irq(unsigned int, 
   5.105 +		       void (*handler)(int, void *, struct pt_regs *),
   5.106 +		       unsigned long, const char *, void *);
   5.107 +
   5.108 +
   5.109 +void initialize_keyboard()
   5.110 +{
   5.111 +    if(!request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL))
   5.112 +	printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); 
   5.113 +
   5.114 +    return; 
   5.115 +}
   5.116 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen-2.4.16/drivers/char/xen_serial.c	Wed Feb 12 18:04:40 2003 +0000
     6.3 @@ -0,0 +1,93 @@
     6.4 +#include <asm-i386/io.h>
     6.5 +
     6.6 +/* Register offsets */
     6.7 +#define NS16550_RBR	0x00	/* receive buffer	*/
     6.8 +#define NS16550_THR	0x00	/* transmit holding	*/
     6.9 +#define NS16550_IER	0x01	/* interrupt enable	*/
    6.10 +#define NS16550_IIR	0x02	/* interrupt identity	*/
    6.11 +#define NS16550_FCR     0x02    /* FIFO control         */
    6.12 +#define NS16550_LCR	0x03	/* line control		*/
    6.13 +#define NS16550_MCR	0x04	/* MODEM control	*/
    6.14 +#define NS16550_LSR	0x05	/* line status		*/
    6.15 +#define NS16550_MSR	0x06	/* MODEM status		*/
    6.16 +#define NS16550_SCR	0x07	/* scratch		*/
    6.17 +#define NS16550_DDL	0x00	/* divisor latch (ls) ( DLAB=1)	*/
    6.18 +#define NS16550_DLM	0x01	/* divisor latch (ms) ( DLAB=1)	*/
    6.19 +
    6.20 +/* Interrupt enable register */
    6.21 +#define NS16550_IER_ERDAI	0x01	/* rx data recv'd	*/
    6.22 +#define NS16550_IER_ETHREI	0x02	/* tx reg. empty	*/
    6.23 +#define NS16550_IER_ELSI	0x04	/* rx line status	*/
    6.24 +#define NS16550_IER_EMSI	0x08	/* MODEM status		*/
    6.25 +
    6.26 +/* FIFO control register */
    6.27 +#define NS16550_FCR_ENABLE      0x01    /* enable FIFO          */
    6.28 +#define NS16550_FCR_CLRX        0x02    /* clear Rx FIFO        */
    6.29 +#define NS16550_FCR_CLTX        0x04    /* clear Tx FIFO        */
    6.30 +#define NS16550_FCR_DMA         0x10    /* enter DMA mode       */
    6.31 +#define NS16550_FCR_TRG1        0x00    /* Rx FIFO trig lev 1   */
    6.32 +#define NS16550_FCR_TRG4        0x40    /* Rx FIFO trig lev 4   */
    6.33 +#define NS16550_FCR_TRG8        0x80    /* Rx FIFO trig lev 8   */
    6.34 +#define NS16550_FCR_TRG14       0xc0    /* Rx FIFO trig lev 14  */
    6.35 +
    6.36 +/* MODEM control register */
    6.37 +#define NS16550_MCR_DTR 	0x01	/* Data Terminal Ready	*/
    6.38 +#define NS16550_MCR_RTS 	0x02	/* Request to Send	*/
    6.39 +#define NS16550_MCR_OUT1        0x04    /* OUT1: unused         */
    6.40 +#define NS16550_MCR_OUT2        0x08    /* OUT2: interrupt mask */
    6.41 +#define NS16550_MCR_LOOP	0x10	/* Loop			*/
    6.42 +
    6.43 +#define SERIAL_BASE 0x3f8  /* XXX SMH: horrible hardwired COM1   */
    6.44 +#define SERAIL_ECHO 0      /* XXX SMH: set to 1 for 'echo' on rx */
    6.45 +
    6.46 +
    6.47 +
    6.48 +static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
    6.49 +{
    6.50 +    int c; 
    6.51 +
    6.52 +    /* XXX SMH: should probably check this is an RX interrupt :-) */
    6.53 +
    6.54 +    /* clear the interrupt by reading the character */
    6.55 +    c = inb(SERIAL_BASE + NS16550_RBR );
    6.56 +
    6.57 +    if (c==0x04) {
    6.58 +	/* This is 'debug me please' => just dump info and halt machine */
    6.59 +	printk("serial_rx_int: got EOT => halting machine.\n"); 
    6.60 +	printk("<not actually halting for now>\n"); 
    6.61 +    }
    6.62 +
    6.63 +#ifdef SERIAL_ECHO
    6.64 +    printk("%c", c); 
    6.65 +#endif
    6.66 +
    6.67 +    return; 
    6.68 +}
    6.69 +
    6.70 +
    6.71 +extern int request_irq(unsigned int, 
    6.72 +		       void (*handler)(int, void *, struct pt_regs *),
    6.73 +		       unsigned long, const char *, void *);
    6.74 +
    6.75 +
    6.76 +void initialize_serial() 
    6.77 +{
    6.78 +    int fifo = 1;  /* must be a ns16550a at least, surely? */
    6.79 +
    6.80 +    if(fifo) {
    6.81 +	/* Clear FIFOs, enable, trigger at 1 byte */
    6.82 +	outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
    6.83 +	     NS16550_FCR_CLRX  | NS16550_FCR_CLTX, SERIAL_BASE+NS16550_FCR);
    6.84 +    }
    6.85 +
    6.86 +    outb(NS16550_MCR_OUT2, SERIAL_BASE + NS16550_MCR);   /* Modem control */
    6.87 +    outb(NS16550_IER_ERDAI, SERIAL_BASE + NS16550_IER ); /* Setup interrupts */
    6.88 +
    6.89 +    /* XXX SMH: this is a hack; probably is IRQ4 but grab both anyway */
    6.90 +    if(!request_irq(4, serial_rx_int, 0, "serial", 0x1234))
    6.91 +	printk("initialize_serial: failed to get IRQ4 :-(\n"); 
    6.92 +    if(!request_irq(3, serial_rx_int, 0, "serial", 0x5678))
    6.93 +	printk("initialize_serial: failed to get IRQ3 :-(\n"); 
    6.94 +    
    6.95 +    return; 
    6.96 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen-2.4.16/drivers/ide/ide-disk.c.orig	Wed Feb 12 18:04:40 2003 +0000
     7.3 @@ -0,0 +1,1550 @@
     7.4 +/*
     7.5 + *  linux/drivers/ide/ide-disk.c	Version 1.10	June 9, 2000
     7.6 + *
     7.7 + *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
     7.8 + */
     7.9 +
    7.10 +/*
    7.11 + *  Mostly written by Mark Lord <mlord@pobox.com>
    7.12 + *                and Gadi Oxman <gadio@netvision.net.il>
    7.13 + *                and Andre Hedrick <andre@linux-ide.org>
    7.14 + *
    7.15 + * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
    7.16 + *
    7.17 + * Version 1.00		move disk only code from ide.c to ide-disk.c
    7.18 + *			support optional byte-swapping of all data
    7.19 + * Version 1.01		fix previous byte-swapping code
    7.20 + * Version 1.02		remove ", LBA" from drive identification msgs
    7.21 + * Version 1.03		fix display of id->buf_size for big-endian
    7.22 + * Version 1.04		add /proc configurable settings and S.M.A.R.T support
    7.23 + * Version 1.05		add capacity support for ATA3 >= 8GB
    7.24 + * Version 1.06		get boot-up messages to show full cyl count
    7.25 + * Version 1.07		disable door-locking if it fails
    7.26 + * Version 1.08		fixed CHS/LBA translations for ATA4 > 8GB,
    7.27 + *			process of adding new ATA4 compliance.
    7.28 + *			fixed problems in allowing fdisk to see
    7.29 + *			the entire disk.
    7.30 + * Version 1.09		added increment of rq->sector in ide_multwrite
    7.31 + *			added UDMA 3/4 reporting
    7.32 + * Version 1.10		request queue changes, Ultra DMA 100
    7.33 + * Version 1.11		added 48-bit lba
    7.34 + * Version 1.12		adding taskfile io access method
    7.35 + */
    7.36 +
    7.37 +#define IDEDISK_VERSION	"1.12"
    7.38 +
    7.39 +#undef REALLY_SLOW_IO		/* most systems can safely undef this */
    7.40 +
    7.41 +#include <xeno/config.h>
    7.42 +#include <xeno/module.h>
    7.43 +#include <xeno/types.h>
    7.44 +#include <xeno/lib.h>
    7.45 +#include <xeno/timer.h>
    7.46 +#include <xeno/mm.h>
    7.47 +#include <xeno/interrupt.h>
    7.48 +#include <xeno/major.h>
    7.49 +#include <xeno/errno.h>
    7.50 +#include <xeno/genhd.h>
    7.51 +#include <xeno/slab.h>
    7.52 +#include <xeno/delay.h>
    7.53 +#include <xeno/ide.h>
    7.54 +
    7.55 +#include <asm/byteorder.h>
    7.56 +#include <asm/irq.h>
    7.57 +#include <asm/uaccess.h>
    7.58 +#include <asm/io.h>
    7.59 +
    7.60 +#ifdef CONFIG_BLK_DEV_PDC4030
    7.61 +#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
    7.62 +#else
    7.63 +#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
    7.64 +#endif
    7.65 +
    7.66 +#ifdef CONFIG_IDE_TASKFILE_IO
    7.67 +#  undef __TASKFILE__IO /* define __TASKFILE__IO */
    7.68 +#else /* CONFIG_IDE_TASKFILE_IO */
    7.69 +#  undef __TASKFILE__IO
    7.70 +#endif /* CONFIG_IDE_TASKFILE_IO */
    7.71 +
    7.72 +#ifndef __TASKFILE__IO
    7.73 +
    7.74 +static void idedisk_bswap_data (void *buffer, int wcount)
    7.75 +{
    7.76 +	u16 *p = buffer;
    7.77 +
    7.78 +	while (wcount--) {
    7.79 +		*p = *p << 8 | *p >> 8; p++;
    7.80 +		*p = *p << 8 | *p >> 8; p++;
    7.81 +	}
    7.82 +}
    7.83 +
    7.84 +static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
    7.85 +{
    7.86 +	ide_input_data(drive, buffer, wcount);
    7.87 +	if (drive->bswap)
    7.88 +		idedisk_bswap_data(buffer, wcount);
    7.89 +}
    7.90 +
    7.91 +static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
    7.92 +{
    7.93 +	if (drive->bswap) {
    7.94 +		idedisk_bswap_data(buffer, wcount);
    7.95 +		ide_output_data(drive, buffer, wcount);
    7.96 +		idedisk_bswap_data(buffer, wcount);
    7.97 +	} else
    7.98 +		ide_output_data(drive, buffer, wcount);
    7.99 +}
   7.100 +
   7.101 +#endif /* __TASKFILE__IO */
   7.102 +
   7.103 +/*
   7.104 + * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
   7.105 + * value for this drive (from its reported identification information).
   7.106 + *
   7.107 + * Returns:	1 if lba_capacity looks sensible
   7.108 + *		0 otherwise
   7.109 + *
   7.110 + * It is called only once for each drive.
   7.111 + */
   7.112 +static int lba_capacity_is_ok (struct hd_driveid *id)
   7.113 +{
   7.114 +	unsigned long lba_sects, chs_sects, head, tail;
   7.115 +
   7.116 +	if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
   7.117 +		printk("48-bit Drive: %llu \n", id->lba_capacity_2);
   7.118 +		return 1;
   7.119 +	}
   7.120 +
   7.121 +	/*
   7.122 +	 * The ATA spec tells large drives to return
   7.123 +	 * C/H/S = 16383/16/63 independent of their size.
   7.124 +	 * Some drives can be jumpered to use 15 heads instead of 16.
   7.125 +	 * Some drives can be jumpered to use 4092 cyls instead of 16383.
   7.126 +	 */
   7.127 +	if ((id->cyls == 16383
   7.128 +	     || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
   7.129 +	    id->sectors == 63 &&
   7.130 +	    (id->heads == 15 || id->heads == 16) &&
   7.131 +	    id->lba_capacity >= 16383*63*id->heads)
   7.132 +		return 1;
   7.133 +
   7.134 +	lba_sects   = id->lba_capacity;
   7.135 +	chs_sects   = id->cyls * id->heads * id->sectors;
   7.136 +
   7.137 +	/* perform a rough sanity check on lba_sects:  within 10% is OK */
   7.138 +	if ((lba_sects - chs_sects) < chs_sects/10)
   7.139 +		return 1;
   7.140 +
   7.141 +	/* some drives have the word order reversed */
   7.142 +	head = ((lba_sects >> 16) & 0xffff);
   7.143 +	tail = (lba_sects & 0xffff);
   7.144 +	lba_sects = (head | (tail << 16));
   7.145 +	if ((lba_sects - chs_sects) < chs_sects/10) {
   7.146 +		id->lba_capacity = lba_sects;
   7.147 +		return 1;	/* lba_capacity is (now) good */
   7.148 +	}
   7.149 +
   7.150 +	return 0;	/* lba_capacity value may be bad */
   7.151 +}
   7.152 +
   7.153 +#ifndef __TASKFILE__IO
   7.154 +
   7.155 +/*
   7.156 + * read_intr() is the handler for disk read/multread interrupts
   7.157 + */
   7.158 +static ide_startstop_t read_intr (ide_drive_t *drive)
   7.159 +{
   7.160 +	byte stat;
   7.161 +	int i;
   7.162 +	unsigned int msect, nsect;
   7.163 +	struct request *rq;
   7.164 +
   7.165 +	/* new way for dealing with premature shared PCI interrupts */
   7.166 +	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
   7.167 +		if (stat & (ERR_STAT|DRQ_STAT)) {
   7.168 +			return ide_error(drive, "read_intr", stat);
   7.169 +		}
   7.170 +		/* no data yet, so wait for another interrupt */
   7.171 +		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
   7.172 +		return ide_started;
   7.173 +	}
   7.174 +	msect = drive->mult_count;
   7.175 +	
   7.176 +read_next:
   7.177 +	rq = HWGROUP(drive)->rq;
   7.178 +	if (msect) {
   7.179 +		if ((nsect = rq->current_nr_sectors) > msect)
   7.180 +			nsect = msect;
   7.181 +		msect -= nsect;
   7.182 +	} else
   7.183 +		nsect = 1;
   7.184 +	idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
   7.185 +#ifdef DEBUG
   7.186 +	printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
   7.187 +		drive->name, rq->sector, rq->sector+nsect-1,
   7.188 +		(unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
   7.189 +#endif
   7.190 +	rq->sector += nsect;
   7.191 +	rq->buffer += nsect<<9;
   7.192 +	rq->errors = 0;
   7.193 +	i = (rq->nr_sectors -= nsect);
   7.194 +	if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
   7.195 +		ide_end_request(1, HWGROUP(drive));
   7.196 +	if (i > 0) {
   7.197 +		if (msect)
   7.198 +			goto read_next;
   7.199 +		ide_set_handler (drive, &read_intr, WAIT_CMD, NULL);
   7.200 +                return ide_started;
   7.201 +	}
   7.202 +        return ide_stopped;
   7.203 +}
   7.204 +
   7.205 +/*
   7.206 + * write_intr() is the handler for disk write interrupts
   7.207 + */
   7.208 +static ide_startstop_t write_intr (ide_drive_t *drive)
   7.209 +{
   7.210 +	byte stat;
   7.211 +	int i;
   7.212 +	ide_hwgroup_t *hwgroup = HWGROUP(drive);
   7.213 +	struct request *rq = hwgroup->rq;
   7.214 +
   7.215 +	if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
   7.216 +		printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
   7.217 +        } else {
   7.218 +#ifdef DEBUG
   7.219 +		printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
   7.220 +			drive->name, rq->sector, (unsigned long) rq->buffer,
   7.221 +			rq->nr_sectors-1);
   7.222 +#endif
   7.223 +		if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
   7.224 +			rq->sector++;
   7.225 +			rq->buffer += 512;
   7.226 +			rq->errors = 0;
   7.227 +			i = --rq->nr_sectors;
   7.228 +			--rq->current_nr_sectors;
   7.229 +			if (((long)rq->current_nr_sectors) <= 0)
   7.230 +				ide_end_request(1, hwgroup);
   7.231 +			if (i > 0) {
   7.232 +				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
   7.233 +				ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
   7.234 +                                return ide_started;
   7.235 +			}
   7.236 +                        return ide_stopped;
   7.237 +		}
   7.238 +		return ide_stopped;	/* the original code did this here (?) */
   7.239 +	}
   7.240 +	return ide_error(drive, "write_intr", stat);
   7.241 +}
   7.242 +
   7.243 +/*
   7.244 + * ide_multwrite() transfers a block of up to mcount sectors of data
   7.245 + * to a drive as part of a disk multiple-sector write operation.
   7.246 + *
   7.247 + * Returns 0 on success.
   7.248 + *
   7.249 + * Note that we may be called from two contexts - the do_rw_disk context
   7.250 + * and IRQ context. The IRQ can happen any time after we've output the
   7.251 + * full "mcount" number of sectors, so we must make sure we update the
   7.252 + * state _before_ we output the final part of the data!
   7.253 + */
   7.254 +int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
   7.255 +{
   7.256 + 	ide_hwgroup_t	*hwgroup= HWGROUP(drive);
   7.257 + 	struct request	*rq = &hwgroup->wrq;
   7.258 + 
   7.259 +  	do {
   7.260 +  		char *buffer;
   7.261 +  		int nsect = rq->current_nr_sectors;
   7.262 + 
   7.263 +		if (nsect > mcount)
   7.264 +			nsect = mcount;
   7.265 +		mcount -= nsect;
   7.266 +		buffer = rq->buffer;
   7.267 +
   7.268 +		rq->sector += nsect;
   7.269 +		rq->buffer += nsect << 9;
   7.270 +		rq->nr_sectors -= nsect;
   7.271 +		rq->current_nr_sectors -= nsect;
   7.272 +
   7.273 +		/* Do we move to the next bh after this? */
   7.274 +		if (!rq->current_nr_sectors) {
   7.275 +			struct buffer_head *bh = rq->bh->b_reqnext;
   7.276 +
   7.277 +			/* end early early we ran out of requests */
   7.278 +			if (!bh) {
   7.279 +				mcount = 0;
   7.280 +			} else {
   7.281 +				rq->bh = bh;
   7.282 +				rq->current_nr_sectors = bh->b_size >> 9;
   7.283 +				rq->buffer             = bh->b_data;
   7.284 +			}
   7.285 +		}
   7.286 +
   7.287 +		/*
   7.288 +		 * Ok, we're all setup for the interrupt
   7.289 +		 * re-entering us on the last transfer.
   7.290 +		 */
   7.291 +		idedisk_output_data(drive, buffer, nsect<<7);
   7.292 +	} while (mcount);
   7.293 +
   7.294 +        return 0;
   7.295 +}
   7.296 +
   7.297 +/*
   7.298 + * multwrite_intr() is the handler for disk multwrite interrupts
   7.299 + */
   7.300 +static ide_startstop_t multwrite_intr (ide_drive_t *drive)
   7.301 +{
   7.302 +	byte stat;
   7.303 +	int i;
   7.304 +	ide_hwgroup_t *hwgroup = HWGROUP(drive);
   7.305 +	struct request *rq = &hwgroup->wrq;
   7.306 +
   7.307 +	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
   7.308 +		if (stat & DRQ_STAT) {
   7.309 +			/*
   7.310 +			 *	The drive wants data. Remember rq is the copy
   7.311 +			 *	of the request
   7.312 +			 */
   7.313 +			if (rq->nr_sectors) {
   7.314 +				if (ide_multwrite(drive, drive->mult_count))
   7.315 +					return ide_stopped;
   7.316 +				ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
   7.317 +				return ide_started;
   7.318 +			}
   7.319 +		} else {
   7.320 +			/*
   7.321 +			 *	If the copy has all the blocks completed then
   7.322 +			 *	we can end the original request.
   7.323 +			 */
   7.324 +			if (!rq->nr_sectors) {	/* all done? */
   7.325 +				rq = hwgroup->rq;
   7.326 +				for (i = rq->nr_sectors; i > 0;){
   7.327 +					i -= rq->current_nr_sectors;
   7.328 +					ide_end_request(1, hwgroup);
   7.329 +				}
   7.330 +				return ide_stopped;
   7.331 +			}
   7.332 +		}
   7.333 +		return ide_stopped;	/* the original code did this here (?) */
   7.334 +	}
   7.335 +	return ide_error(drive, "multwrite_intr", stat);
   7.336 +}
   7.337 +#endif /* __TASKFILE__IO */
   7.338 +
   7.339 +#ifdef __TASKFILE__IO
   7.340 +
   7.341 +static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
   7.342 +static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
   7.343 +static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block);
   7.344 +
   7.345 +/*
   7.346 + * do_rw_disk() issues READ and WRITE commands to a disk,
   7.347 + * using LBA if supported, or CHS otherwise, to address sectors.
   7.348 + * It also takes care of issuing special DRIVE_CMDs.
   7.349 + */
   7.350 +static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
   7.351 +{
   7.352 +	if (rq->cmd == READ)
   7.353 +		goto good_command;
   7.354 +	if (rq->cmd == WRITE)
   7.355 +		goto good_command;
   7.356 +
   7.357 +	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
   7.358 +	ide_end_request(0, HWGROUP(drive));
   7.359 +	return ide_stopped;
   7.360 +
   7.361 +good_command:
   7.362 +
   7.363 +#ifdef CONFIG_BLK_DEV_PDC4030
   7.364 +	if (IS_PDC4030_DRIVE) {
   7.365 +		extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
   7.366 +		return promise_rw_disk(drive, rq, block);
   7.367 +	}
   7.368 +#endif /* CONFIG_BLK_DEV_PDC4030 */
   7.369 +
   7.370 +	if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))	/* 48-bit LBA */
   7.371 +		return lba_48_rw_disk(drive, rq, (unsigned long long) block);
   7.372 +	if (drive->select.b.lba)		/* 28-bit LBA */
   7.373 +		return lba_28_rw_disk(drive, rq, (unsigned long) block);
   7.374 +
   7.375 +	/* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */
   7.376 +	return chs_rw_disk(drive, rq, (unsigned long) block);
   7.377 +}
   7.378 +
   7.379 +static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
   7.380 +{
   7.381 +	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
   7.382 +
   7.383 +#if 1
   7.384 +	lba48bit = drive->addressing;
   7.385 +#endif
   7.386 +
   7.387 +	if ((cmd == READ) && (drive->using_dma))
   7.388 +		return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
   7.389 +	else if ((cmd == READ) && (drive->mult_count))
   7.390 +		return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
   7.391 +	else if (cmd == READ)
   7.392 +		return (lba48bit) ? WIN_READ_EXT : WIN_READ;
   7.393 +	else if ((cmd == WRITE) && (drive->using_dma))
   7.394 +		return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
   7.395 +	else if ((cmd == WRITE) && (drive->mult_count))
   7.396 +		return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
   7.397 +	else if (cmd == WRITE)
   7.398 +		return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
   7.399 +	else
   7.400 +		return WIN_NOP;
   7.401 +}
   7.402 +
   7.403 +static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
   7.404 +{
   7.405 +	struct hd_drive_task_hdr	taskfile;
   7.406 +	struct hd_drive_hob_hdr		hobfile;
   7.407 +	ide_task_t			args;
   7.408 +
   7.409 +	task_ioreg_t command	= get_command(drive, rq->cmd);
   7.410 +	unsigned int track	= (block / drive->sect);
   7.411 +	unsigned int sect	= (block % drive->sect) + 1;
   7.412 +	unsigned int head	= (track % drive->head);
   7.413 +	unsigned int cyl	= (track / drive->head);
   7.414 +
   7.415 +	memset(&taskfile, 0, sizeof(task_struct_t));
   7.416 +	memset(&hobfile, 0, sizeof(hob_struct_t));
   7.417 +
   7.418 +	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;
   7.419 +	taskfile.sector_number	= sect;
   7.420 +	taskfile.low_cylinder	= cyl;
   7.421 +	taskfile.high_cylinder	= (cyl>>8);
   7.422 +	taskfile.device_head	= head;
   7.423 +	taskfile.device_head	|= drive->select.all;
   7.424 +	taskfile.command	= command;
   7.425 +
   7.426 +#ifdef DEBUG
   7.427 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
   7.428 +	if (lba)	printk("LBAsect=%lld, ", block);
   7.429 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
   7.430 +	printk("sectors=%ld, ", rq->nr_sectors);
   7.431 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
   7.432 +#endif
   7.433 +
   7.434 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
   7.435 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
   7.436 +	args.command_type	= ide_cmd_type_parser(&args);
   7.437 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
   7.438 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
   7.439 +	args.posthandler	= NULL;
   7.440 +	args.rq			= (struct request *) rq;
   7.441 +	args.block		= block;
   7.442 +	rq->special		= NULL;
   7.443 +	rq->special		= (ide_task_t *)&args;
   7.444 +
   7.445 +	return do_rw_taskfile(drive, &args);
   7.446 +}
   7.447 +
   7.448 +static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
   7.449 +{
   7.450 +	struct hd_drive_task_hdr	taskfile;
   7.451 +	struct hd_drive_hob_hdr		hobfile;
   7.452 +	ide_task_t			args;
   7.453 +
   7.454 +	task_ioreg_t command	= get_command(drive, rq->cmd);
   7.455 +
   7.456 +	memset(&taskfile, 0, sizeof(task_struct_t));
   7.457 +	memset(&hobfile, 0, sizeof(hob_struct_t));
   7.458 +
   7.459 +	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;
   7.460 +	taskfile.sector_number	= block;
   7.461 +	taskfile.low_cylinder	= (block>>=8);
   7.462 +	taskfile.high_cylinder	= (block>>=8);
   7.463 +	taskfile.device_head	= ((block>>8)&0x0f);
   7.464 +	taskfile.device_head	|= drive->select.all;
   7.465 +	taskfile.command	= command;
   7.466 +
   7.467 +
   7.468 +#ifdef DEBUG
   7.469 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
   7.470 +	if (lba)	printk("LBAsect=%lld, ", block);
   7.471 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
   7.472 +	printk("sectors=%ld, ", rq->nr_sectors);
   7.473 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
   7.474 +#endif
   7.475 +
   7.476 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
   7.477 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
   7.478 +	args.command_type	= ide_cmd_type_parser(&args);
   7.479 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
   7.480 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
   7.481 +	args.posthandler	= NULL;
   7.482 +	args.rq			= (struct request *) rq;
   7.483 +	args.block		= block;
   7.484 +	rq->special		= NULL;
   7.485 +	rq->special		= (ide_task_t *)&args;
   7.486 +
   7.487 +	return do_rw_taskfile(drive, &args);
   7.488 +}
   7.489 +
   7.490 +/*
   7.491 + * 268435455  == 137439 MB or 28bit limit
   7.492 + * 320173056  == 163929 MB or 48bit addressing
   7.493 + * 1073741822 == 549756 MB or 48bit addressing fake drive
   7.494 + */
   7.495 +
   7.496 +static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block)
   7.497 +{
   7.498 +	struct hd_drive_task_hdr	taskfile;
   7.499 +	struct hd_drive_hob_hdr		hobfile;
   7.500 +	ide_task_t			args;
   7.501 +
   7.502 +	task_ioreg_t command	= get_command(drive, rq->cmd);
   7.503 +
   7.504 +	memset(&taskfile, 0, sizeof(task_struct_t));
   7.505 +	memset(&hobfile, 0, sizeof(hob_struct_t));
   7.506 +
   7.507 +	taskfile.sector_count	= rq->nr_sectors;
   7.508 +	hobfile.sector_count	= (rq->nr_sectors>>8);
   7.509 +
   7.510 +	if (rq->nr_sectors == 65536) {
   7.511 +		taskfile.sector_count	= 0x00;
   7.512 +		hobfile.sector_count	= 0x00;
   7.513 +	}
   7.514 +
   7.515 +	taskfile.sector_number	= block;	/* low lba */
   7.516 +	taskfile.low_cylinder	= (block>>=8);	/* mid lba */
   7.517 +	taskfile.high_cylinder	= (block>>=8);	/* hi  lba */
   7.518 +	hobfile.sector_number	= (block>>=8);	/* low lba */
   7.519 +	hobfile.low_cylinder	= (block>>=8);	/* mid lba */
   7.520 +	hobfile.high_cylinder	= (block>>=8);	/* hi  lba */
   7.521 +	taskfile.device_head	= drive->select.all;
   7.522 +	hobfile.device_head	= taskfile.device_head;
   7.523 +	hobfile.control		= (drive->ctl|0x80);
   7.524 +	taskfile.command	= command;
   7.525 +
   7.526 +#ifdef DEBUG
   7.527 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
   7.528 +	if (lba)	printk("LBAsect=%lld, ", block);
   7.529 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
   7.530 +	printk("sectors=%ld, ", rq->nr_sectors);
   7.531 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
   7.532 +#endif
   7.533 +
   7.534 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
   7.535 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
   7.536 +	args.command_type	= ide_cmd_type_parser(&args);
   7.537 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
   7.538 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
   7.539 +	args.posthandler	= NULL;
   7.540 +	args.rq			= (struct request *) rq;
   7.541 +	args.block		= block;
   7.542 +	rq->special		= NULL;
   7.543 +	rq->special		= (ide_task_t *)&args;
   7.544 +
   7.545 +	return do_rw_taskfile(drive, &args);
   7.546 +}
   7.547 +
   7.548 +#else /* !__TASKFILE__IO */
   7.549 +/*
   7.550 + * do_rw_disk() issues READ and WRITE commands to a disk,
   7.551 + * using LBA if supported, or CHS otherwise, to address sectors.
   7.552 + * It also takes care of issuing special DRIVE_CMDs.
   7.553 + */
   7.554 +static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
   7.555 +{
   7.556 +	if (IDE_CONTROL_REG)
   7.557 +		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
   7.558 +
   7.559 +#ifdef CONFIG_BLK_DEV_PDC4030
   7.560 +	if (drive->select.b.lba || IS_PDC4030_DRIVE) {
   7.561 +#else /* !CONFIG_BLK_DEV_PDC4030 */
   7.562 +	if (drive->select.b.lba) {
   7.563 +#endif /* CONFIG_BLK_DEV_PDC4030 */
   7.564 +
   7.565 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
   7.566 +			task_ioreg_t tasklets[10];
   7.567 +
   7.568 +			tasklets[0] = 0;
   7.569 +			tasklets[1] = 0;
   7.570 +			tasklets[2] = rq->nr_sectors;
   7.571 +			tasklets[3] = (rq->nr_sectors>>8);
   7.572 +			if (rq->nr_sectors == 65536) {
   7.573 +				tasklets[2] = 0x00;
   7.574 +				tasklets[3] = 0x00;
   7.575 +			}
   7.576 +			tasklets[4] = (task_ioreg_t) block;
   7.577 +			tasklets[5] = (task_ioreg_t) (block>>8);
   7.578 +			tasklets[6] = (task_ioreg_t) (block>>16);
   7.579 +			tasklets[7] = (task_ioreg_t) (block>>24);
   7.580 +			tasklets[8] = (task_ioreg_t) 0;
   7.581 +			tasklets[9] = (task_ioreg_t) 0;
   7.582 +//			tasklets[8] = (task_ioreg_t) (block>>32);
   7.583 +//			tasklets[9] = (task_ioreg_t) (block>>40);
   7.584 +#ifdef DEBUG
   7.585 +			printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n",
   7.586 +				drive->name,
   7.587 +				(rq->cmd==READ)?"read":"writ",
   7.588 +				block,
   7.589 +				rq->nr_sectors,
   7.590 +				(unsigned long) rq->buffer,
   7.591 +				block);
   7.592 +			printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
   7.593 +				drive->name, tasklets[3], tasklets[2],
   7.594 +				tasklets[9], tasklets[8], tasklets[7],
   7.595 +				tasklets[6], tasklets[5], tasklets[4]);
   7.596 +#endif
   7.597 +			OUT_BYTE(tasklets[1], IDE_FEATURE_REG);
   7.598 +			OUT_BYTE(tasklets[3], IDE_NSECTOR_REG);
   7.599 +			OUT_BYTE(tasklets[7], IDE_SECTOR_REG);
   7.600 +			OUT_BYTE(tasklets[8], IDE_LCYL_REG);
   7.601 +			OUT_BYTE(tasklets[9], IDE_HCYL_REG);
   7.602 +
   7.603 +			OUT_BYTE(tasklets[0], IDE_FEATURE_REG);
   7.604 +			OUT_BYTE(tasklets[2], IDE_NSECTOR_REG);
   7.605 +			OUT_BYTE(tasklets[4], IDE_SECTOR_REG);
   7.606 +			OUT_BYTE(tasklets[5], IDE_LCYL_REG);
   7.607 +			OUT_BYTE(tasklets[6], IDE_HCYL_REG);
   7.608 +			OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG);
   7.609 +		} else {
   7.610 +#ifdef DEBUG
   7.611 +			printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
   7.612 +				drive->name, (rq->cmd==READ)?"read":"writ",
   7.613 +				block, rq->nr_sectors, (unsigned long) rq->buffer);
   7.614 +#endif
   7.615 +			OUT_BYTE(0x00, IDE_FEATURE_REG);
   7.616 +			OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
   7.617 +			OUT_BYTE(block,IDE_SECTOR_REG);
   7.618 +			OUT_BYTE(block>>=8,IDE_LCYL_REG);
   7.619 +			OUT_BYTE(block>>=8,IDE_HCYL_REG);
   7.620 +			OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
   7.621 +		}
   7.622 +	} else {
   7.623 +		unsigned int sect,head,cyl,track;
   7.624 +		track = block / drive->sect;
   7.625 +		sect  = block % drive->sect + 1;
   7.626 +		OUT_BYTE(sect,IDE_SECTOR_REG);
   7.627 +		head  = track % drive->head;
   7.628 +		cyl   = track / drive->head;
   7.629 +
   7.630 +		OUT_BYTE(0x00, IDE_FEATURE_REG);
   7.631 +		OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
   7.632 +		OUT_BYTE(cyl,IDE_LCYL_REG);
   7.633 +		OUT_BYTE(cyl>>8,IDE_HCYL_REG);
   7.634 +		OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
   7.635 +#ifdef DEBUG
   7.636 +		printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
   7.637 +			drive->name, (rq->cmd==READ)?"read":"writ", cyl,
   7.638 +			head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
   7.639 +#endif
   7.640 +	}
   7.641 +#ifdef CONFIG_BLK_DEV_PDC4030
   7.642 +	if (IS_PDC4030_DRIVE) {
   7.643 +		extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *);
   7.644 +		return do_pdc4030_io (drive, rq);
   7.645 +	}
   7.646 +#endif /* CONFIG_BLK_DEV_PDC4030 */
   7.647 +	if (rq->cmd == READ) {
   7.648 +#ifdef CONFIG_BLK_DEV_IDEDMA
   7.649 +		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
   7.650 +			return ide_started;
   7.651 +#endif /* CONFIG_BLK_DEV_IDEDMA */
   7.652 +		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
   7.653 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
   7.654 +			OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG);
   7.655 +		} else {
   7.656 +			OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
   7.657 +		}
   7.658 +		return ide_started;
   7.659 +	}
   7.660 +	if (rq->cmd == WRITE) {
   7.661 +		ide_startstop_t startstop;
   7.662 +#ifdef CONFIG_BLK_DEV_IDEDMA
   7.663 +		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
   7.664 +			return ide_started;
   7.665 +#endif /* CONFIG_BLK_DEV_IDEDMA */
   7.666 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
   7.667 +			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG);
   7.668 +		} else {
   7.669 +			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
   7.670 +		}
   7.671 +		if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
   7.672 +			printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,
   7.673 +				drive->mult_count ? "MULTWRITE" : "WRITE");
   7.674 +			return startstop;
   7.675 +		}
   7.676 +		if (!drive->unmask)
   7.677 +			__cli();	/* local CPU only */
   7.678 +		if (drive->mult_count) {
   7.679 +			ide_hwgroup_t *hwgroup = HWGROUP(drive);
   7.680 +	/*
   7.681 +	 * Ugh.. this part looks ugly because we MUST set up
   7.682 +	 * the interrupt handler before outputting the first block
   7.683 +	 * of data to be written.  If we hit an error (corrupted buffer list)
   7.684 +	 * in ide_multwrite(), then we need to remove the handler/timer
   7.685 +	 * before returning.  Fortunately, this NEVER happens (right?).
   7.686 +	 *
   7.687 +	 * Except when you get an error it seems...
   7.688 +	 */
   7.689 +			hwgroup->wrq = *rq; /* scratchpad */
   7.690 +			ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
   7.691 +			if (ide_multwrite(drive, drive->mult_count)) {
   7.692 +				unsigned long flags;
   7.693 +				spin_lock_irqsave(&io_request_lock, flags);
   7.694 +				hwgroup->handler = NULL;
   7.695 +				del_timer(&hwgroup->timer);
   7.696 +				spin_unlock_irqrestore(&io_request_lock, flags);
   7.697 +				return ide_stopped;
   7.698 +			}
   7.699 +		} else {
   7.700 +			ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
   7.701 +			idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);
   7.702 +		}
   7.703 +		return ide_started;
   7.704 +	}
   7.705 +	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
   7.706 +	ide_end_request(0, HWGROUP(drive));
   7.707 +	return ide_stopped;
   7.708 +}
   7.709 +
   7.710 +#endif /* __TASKFILE__IO */
   7.711 +
   7.712 +static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
   7.713 +{
   7.714 +	MOD_INC_USE_COUNT;
   7.715 +	if (drive->removable && drive->usage == 1) {
   7.716 +		struct hd_drive_task_hdr taskfile;
   7.717 +		struct hd_drive_hob_hdr hobfile;
   7.718 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
   7.719 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
   7.720 +		taskfile.command = WIN_DOORLOCK;
   7.721 +		check_disk_change(inode->i_rdev);
   7.722 +		/*
   7.723 +		 * Ignore the return code from door_lock,
   7.724 +		 * since the open() has already succeeded,
   7.725 +		 * and the door_lock is irrelevant at this point.
   7.726 +		 */
   7.727 +		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
   7.728 +			drive->doorlocking = 0;
   7.729 +	}
   7.730 +	return 0;
   7.731 +}
   7.732 +
   7.733 +static int do_idedisk_flushcache(ide_drive_t *drive);
   7.734 +
   7.735 +static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
   7.736 +{
   7.737 +	if (drive->removable && !drive->usage) {
   7.738 +		struct hd_drive_task_hdr taskfile;
   7.739 +		struct hd_drive_hob_hdr hobfile;
   7.740 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
   7.741 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
   7.742 +		taskfile.command = WIN_DOORUNLOCK;
   7.743 +		invalidate_bdev(inode->i_bdev, 0);
   7.744 +		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
   7.745 +			drive->doorlocking = 0;
   7.746 +	}
   7.747 +	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
   7.748 +		if (do_idedisk_flushcache(drive))
   7.749 +			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
   7.750 +				drive->name);
   7.751 +	MOD_DEC_USE_COUNT;
   7.752 +}
   7.753 +
   7.754 +static int idedisk_media_change (ide_drive_t *drive)
   7.755 +{
   7.756 +	return drive->removable;	/* if removable, always assume it was changed */
   7.757 +}
   7.758 +
   7.759 +static void idedisk_revalidate (ide_drive_t *drive)
   7.760 +{
   7.761 +	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
   7.762 +			1<<PARTN_BITS,
   7.763 +			current_capacity(drive));
   7.764 +}
   7.765 +
   7.766 +/*
   7.767 + * Queries for true maximum capacity of the drive.
   7.768 + * Returns maximum LBA address (> 0) of the drive, 0 if failed.
   7.769 + */
   7.770 +static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
   7.771 +{
   7.772 +	ide_task_t args;
   7.773 +	unsigned long addr = 0;
   7.774 +
   7.775 +	if (!(drive->id->command_set_1 & 0x0400) &&
   7.776 +	    !(drive->id->cfs_enable_2 & 0x0100))
   7.777 +		return addr;
   7.778 +
   7.779 +	/* Create IDE/ATA command request structure */
   7.780 +	memset(&args, 0, sizeof(ide_task_t));
   7.781 +	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
   7.782 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
   7.783 +	args.handler				= task_no_data_intr;
   7.784 +
   7.785 +	/* submit command request */
   7.786 +	ide_raw_taskfile(drive, &args, NULL);
   7.787 +
   7.788 +	/* if OK, compute maximum address value */
   7.789 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
   7.790 +		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
   7.791 +		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
   7.792 +		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
   7.793 +		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
   7.794 +	}
   7.795 +	addr++;	/* since the return value is (maxlba - 1), we add 1 */
   7.796 +	return addr;
   7.797 +}
   7.798 +
   7.799 +static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
   7.800 +{
   7.801 +	ide_task_t args;
   7.802 +	unsigned long long addr = 0;
   7.803 +
   7.804 +	/* Create IDE/ATA command request structure */
   7.805 +	memset(&args, 0, sizeof(ide_task_t));
   7.806 +
   7.807 +	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
   7.808 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
   7.809 +	args.handler				= task_no_data_intr;
   7.810 +
   7.811 +        /* submit command request */
   7.812 +        ide_raw_taskfile(drive, &args, NULL);
   7.813 +
   7.814 +	/* if OK, compute maximum address value */
   7.815 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
   7.816 +		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
   7.817 +			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
   7.818 +  			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); 
   7.819 +		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
   7.820 +			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
   7.821 +			    (args.tfRegister[IDE_SECTOR_OFFSET]);
   7.822 +		addr = ((__u64)high << 24) | low;
   7.823 +	}
   7.824 +	addr++;	/* since the return value is (maxlba - 1), we add 1 */
   7.825 +	return addr;
   7.826 +}
   7.827 +
   7.828 +#ifdef CONFIG_IDEDISK_STROKE
   7.829 +/*
   7.830 + * Sets maximum virtual LBA address of the drive.
   7.831 + * Returns new maximum virtual LBA address (> 0) or 0 on failure.
   7.832 + */
   7.833 +static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
   7.834 +{
   7.835 +	ide_task_t args;
   7.836 +	unsigned long addr_set = 0;
   7.837 +	
   7.838 +	addr_req--;
   7.839 +	/* Create IDE/ATA command request structure */
   7.840 +	memset(&args, 0, sizeof(ide_task_t));
   7.841 +	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
   7.842 +	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
   7.843 +	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
   7.844 +	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
   7.845 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
   7.846 +	args.handler				= task_no_data_intr;
   7.847 +	/* submit command request */
   7.848 +	ide_raw_taskfile(drive, &args, NULL);
   7.849 +	/* if OK, read new maximum address value */
   7.850 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
   7.851 +		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
   7.852 +			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
   7.853 +			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
   7.854 +			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
   7.855 +	}
   7.856 +	addr_set++;
   7.857 +	return addr_set;
   7.858 +}
   7.859 +
   7.860 +static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
   7.861 +{
   7.862 +	ide_task_t args;
   7.863 +	unsigned long long addr_set = 0;
   7.864 +
   7.865 +	addr_req--;
   7.866 +	/* Create IDE/ATA command request structure */
   7.867 +	memset(&args, 0, sizeof(ide_task_t));
   7.868 +	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
   7.869 +	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
   7.870 +	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
   7.871 +	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
   7.872 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
   7.873 +	args.hobRegister[IDE_SECTOR_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
   7.874 +	args.hobRegister[IDE_LCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
   7.875 +	args.hobRegister[IDE_HCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
   7.876 +	args.hobRegister[IDE_SELECT_OFFSET_HOB]	= 0x40;
   7.877 +	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
   7.878 +        args.handler				= task_no_data_intr;
   7.879 +	/* submit command request */
   7.880 +	ide_raw_taskfile(drive, &args, NULL);
   7.881 +	/* if OK, compute maximum address value */
   7.882 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
   7.883 +		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
   7.884 +			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
   7.885 +			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
   7.886 +		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
   7.887 +			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
   7.888 +			    (args.tfRegister[IDE_SECTOR_OFFSET]);
   7.889 +		addr_set = ((__u64)high << 24) | low;
   7.890 +	}
   7.891 +	return addr_set;
   7.892 +}
   7.893 +
   7.894 +/*
   7.895 + * Tests if the drive supports Host Protected Area feature.
   7.896 + * Returns true if supported, false otherwise.
   7.897 + */
   7.898 +static inline int idedisk_supports_host_protected_area(ide_drive_t *drive)
   7.899 +{
   7.900 +	int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;
   7.901 +	printk("%s: host protected area => %d\n", drive->name, flag);
   7.902 +	return flag;
   7.903 +}
   7.904 +
   7.905 +#endif /* CONFIG_IDEDISK_STROKE */
   7.906 +
   7.907 +/*
   7.908 + * Compute drive->capacity, the full capacity of the drive
   7.909 + * Called with drive->id != NULL.
   7.910 + *
   7.911 + * To compute capacity, this uses either of
   7.912 + *
   7.913 + *    1. CHS value set by user       (whatever user sets will be trusted)
   7.914 + *    2. LBA value from target drive (require new ATA feature)
   7.915 + *    3. LBA value from system BIOS  (new one is OK, old one may break)
   7.916 + *    4. CHS value from system BIOS  (traditional style)
   7.917 + *
   7.918 + * in above order (i.e., if value of higher priority is available,
   7.919 + * reset will be ignored).
   7.920 + */
   7.921 +static void init_idedisk_capacity (ide_drive_t  *drive)
   7.922 +{
   7.923 +	struct hd_driveid *id = drive->id;
   7.924 +	unsigned long capacity = drive->cyl * drive->head * drive->sect;
   7.925 +	unsigned long set_max = idedisk_read_native_max_address(drive);
   7.926 +	unsigned long long capacity_2 = capacity;
   7.927 +	unsigned long long set_max_ext;
   7.928 +
   7.929 +	drive->capacity48 = 0;
   7.930 +	drive->select.b.lba = 0;
   7.931 +
   7.932 +	if (id->cfs_enable_2 & 0x0400) {
   7.933 +		capacity_2 = id->lba_capacity_2;
   7.934 +		drive->head		= drive->bios_head = 255;
   7.935 +		drive->sect		= drive->bios_sect = 63;
   7.936 +		drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);
   7.937 +		drive->select.b.lba	= 1;
   7.938 +		set_max_ext = idedisk_read_native_max_address_ext(drive);
   7.939 +		if (set_max_ext > capacity_2) {
   7.940 +#ifdef CONFIG_IDEDISK_STROKE
   7.941 +			set_max_ext = idedisk_read_native_max_address_ext(drive);
   7.942 +			set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);
   7.943 +			if (set_max_ext) {
   7.944 +				drive->capacity48 = capacity_2 = set_max_ext;
   7.945 +				drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect);
   7.946 +				drive->select.b.lba = 1;
   7.947 +				drive->id->lba_capacity_2 = capacity_2;
   7.948 +                        }
   7.949 +#else /* !CONFIG_IDEDISK_STROKE */
   7.950 +			printk("%s: setmax_ext LBA %llu, native  %llu\n",
   7.951 +				drive->name, set_max_ext, capacity_2);
   7.952 +#endif /* CONFIG_IDEDISK_STROKE */
   7.953 +		}
   7.954 +		drive->bios_cyl		= drive->cyl;
   7.955 +		drive->capacity48	= capacity_2;
   7.956 +		drive->capacity		= (unsigned long) capacity_2;
   7.957 +		return;
   7.958 +	/* Determine capacity, and use LBA if the drive properly supports it */
   7.959 +	} else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
   7.960 +		capacity = id->lba_capacity;
   7.961 +		drive->cyl = capacity / (drive->head * drive->sect);
   7.962 +		drive->select.b.lba = 1;
   7.963 +	}
   7.964 +
   7.965 +	if (set_max > capacity) {
   7.966 +#ifdef CONFIG_IDEDISK_STROKE
   7.967 +		set_max = idedisk_read_native_max_address(drive);
   7.968 +		set_max = idedisk_set_max_address(drive, set_max);
   7.969 +		if (set_max) {
   7.970 +			drive->capacity = capacity = set_max;
   7.971 +			drive->cyl = set_max / (drive->head * drive->sect);
   7.972 +			drive->select.b.lba = 1;
   7.973 +			drive->id->lba_capacity = capacity;
   7.974 +		}
   7.975 +#else /* !CONFIG_IDEDISK_STROKE */
   7.976 +		printk("%s: setmax LBA %lu, native  %lu\n",
   7.977 +			drive->name, set_max, capacity);
   7.978 +#endif /* CONFIG_IDEDISK_STROKE */
   7.979 +	}
   7.980 +
   7.981 +	drive->capacity = capacity;
   7.982 +
   7.983 +	if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
   7.984 +                drive->capacity48 = id->lba_capacity_2;
   7.985 +		drive->head = 255;
   7.986 +		drive->sect = 63;
   7.987 +		drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect);
   7.988 +	}
   7.989 +}
   7.990 +
   7.991 +static unsigned long idedisk_capacity (ide_drive_t *drive)
   7.992 +{
   7.993 +	if (drive->id->cfs_enable_2 & 0x0400)
   7.994 +		return (drive->capacity48 - drive->sect0);
   7.995 +	return (drive->capacity - drive->sect0);
   7.996 +}
   7.997 +
   7.998 +static ide_startstop_t idedisk_special (ide_drive_t *drive)
   7.999 +{
  7.1000 +	special_t *s = &drive->special;
  7.1001 +
  7.1002 +	if (s->b.set_geometry) {
  7.1003 +		struct hd_drive_task_hdr taskfile;
  7.1004 +		struct hd_drive_hob_hdr hobfile;
  7.1005 +		ide_handler_t *handler = NULL;
  7.1006 +
  7.1007 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1008 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1009 +
  7.1010 +		s->b.set_geometry	= 0;
  7.1011 +		taskfile.sector_number	= drive->sect;
  7.1012 +		taskfile.low_cylinder	= drive->cyl;
  7.1013 +		taskfile.high_cylinder	= drive->cyl>>8;
  7.1014 +		taskfile.device_head	= ((drive->head-1)|drive->select.all)&0xBF;
  7.1015 +		if (!IS_PDC4030_DRIVE) {
  7.1016 +			taskfile.sector_count	= drive->sect;
  7.1017 +			taskfile.command	= WIN_SPECIFY;
  7.1018 +			handler			= ide_handler_parser(&taskfile, &hobfile);
  7.1019 +		}
  7.1020 +		do_taskfile(drive, &taskfile, &hobfile, handler);
  7.1021 +	} else if (s->b.recalibrate) {
  7.1022 +		s->b.recalibrate = 0;
  7.1023 +		if (!IS_PDC4030_DRIVE) {
  7.1024 +			struct hd_drive_task_hdr taskfile;
  7.1025 +			struct hd_drive_hob_hdr hobfile;
  7.1026 +			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1027 +			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1028 +			taskfile.sector_count	= drive->sect;
  7.1029 +			taskfile.command	= WIN_RESTORE;
  7.1030 +			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
  7.1031 +		}
  7.1032 +	} else if (s->b.set_multmode) {
  7.1033 +		s->b.set_multmode = 0;
  7.1034 +		if (drive->id && drive->mult_req > drive->id->max_multsect)
  7.1035 +			drive->mult_req = drive->id->max_multsect;
  7.1036 +		if (!IS_PDC4030_DRIVE) {
  7.1037 +			struct hd_drive_task_hdr taskfile;
  7.1038 +			struct hd_drive_hob_hdr hobfile;
  7.1039 +			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1040 +			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1041 +			taskfile.sector_count	= drive->mult_req;
  7.1042 +			taskfile.command	= WIN_SETMULT;
  7.1043 +			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
  7.1044 +		}
  7.1045 +	} else if (s->all) {
  7.1046 +		int special = s->all;
  7.1047 +		s->all = 0;
  7.1048 +		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
  7.1049 +		return ide_stopped;
  7.1050 +	}
  7.1051 +	return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
  7.1052 +}
  7.1053 +
  7.1054 +static void idedisk_pre_reset (ide_drive_t *drive)
  7.1055 +{
  7.1056 +	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
  7.1057 +
  7.1058 +	drive->special.all = 0;
  7.1059 +	drive->special.b.set_geometry = legacy;
  7.1060 +	drive->special.b.recalibrate  = legacy;
  7.1061 +	if (OK_TO_RESET_CONTROLLER)
  7.1062 +		drive->mult_count = 0;
  7.1063 +	if (!drive->keep_settings && !drive->using_dma)
  7.1064 +		drive->mult_req = 0;
  7.1065 +	if (drive->mult_req != drive->mult_count)
  7.1066 +		drive->special.b.set_multmode = 1;
  7.1067 +}
  7.1068 +
  7.1069 +#ifdef CONFIG_PROC_FS
  7.1070 +
  7.1071 +static int smart_enable(ide_drive_t *drive)
  7.1072 +{
  7.1073 +	struct hd_drive_task_hdr taskfile;
  7.1074 +	struct hd_drive_hob_hdr hobfile;
  7.1075 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1076 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1077 +	taskfile.feature	= SMART_ENABLE;
  7.1078 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
  7.1079 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
  7.1080 +	taskfile.command	= WIN_SMART;
  7.1081 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1082 +}
  7.1083 +
  7.1084 +static int get_smart_values(ide_drive_t *drive, byte *buf)
  7.1085 +{
  7.1086 +	struct hd_drive_task_hdr taskfile;
  7.1087 +	struct hd_drive_hob_hdr hobfile;
  7.1088 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1089 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1090 +	taskfile.feature	= SMART_READ_VALUES;
  7.1091 +	taskfile.sector_count	= 0x01;
  7.1092 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
  7.1093 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
  7.1094 +	taskfile.command	= WIN_SMART;
  7.1095 +	(void) smart_enable(drive);
  7.1096 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
  7.1097 +}
  7.1098 +
  7.1099 +static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
  7.1100 +{
  7.1101 +	struct hd_drive_task_hdr taskfile;
  7.1102 +	struct hd_drive_hob_hdr hobfile;
  7.1103 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1104 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1105 +	taskfile.feature	= SMART_READ_THRESHOLDS;
  7.1106 +	taskfile.sector_count	= 0x01;
  7.1107 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
  7.1108 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
  7.1109 +	taskfile.command	= WIN_SMART;
  7.1110 +	(void) smart_enable(drive);
  7.1111 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
  7.1112 +}
  7.1113 +
  7.1114 +static int proc_idedisk_read_cache
  7.1115 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
  7.1116 +{
  7.1117 +	ide_drive_t	*drive = (ide_drive_t *) data;
  7.1118 +	char		*out = page;
  7.1119 +	int		len;
  7.1120 +
  7.1121 +	if (drive->id)
  7.1122 +		len = sprintf(out,"%i\n", drive->id->buf_size / 2);
  7.1123 +	else
  7.1124 +		len = sprintf(out,"(none)\n");
  7.1125 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
  7.1126 +}
  7.1127 +
  7.1128 +static int proc_idedisk_read_smart_thresholds
  7.1129 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
  7.1130 +{
  7.1131 +	ide_drive_t	*drive = (ide_drive_t *)data;
  7.1132 +	int		len = 0, i = 0;
  7.1133 +
  7.1134 +	if (!get_smart_thresholds(drive, page)) {
  7.1135 +		unsigned short *val = (unsigned short *) page;
  7.1136 +		char *out = ((char *)val) + (SECTOR_WORDS * 4);
  7.1137 +		page = out;
  7.1138 +		do {
  7.1139 +			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
  7.1140 +			val += 1;
  7.1141 +		} while (i < (SECTOR_WORDS * 2));
  7.1142 +		len = out - page;
  7.1143 +	}
  7.1144 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
  7.1145 +}
  7.1146 +
  7.1147 +static int proc_idedisk_read_smart_values
  7.1148 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
  7.1149 +{
  7.1150 +	ide_drive_t	*drive = (ide_drive_t *)data;
  7.1151 +	int		len = 0, i = 0;
  7.1152 +
  7.1153 +	if (!get_smart_values(drive, page)) {
  7.1154 +		unsigned short *val = (unsigned short *) page;
  7.1155 +		char *out = ((char *)val) + (SECTOR_WORDS * 4);
  7.1156 +		page = out;
  7.1157 +		do {
  7.1158 +			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
  7.1159 +			val += 1;
  7.1160 +		} while (i < (SECTOR_WORDS * 2));
  7.1161 +		len = out - page;
  7.1162 +	}
  7.1163 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
  7.1164 +}
  7.1165 +
  7.1166 +static ide_proc_entry_t idedisk_proc[] = {
  7.1167 +	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },
  7.1168 +	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },
  7.1169 +	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },
  7.1170 +	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },
  7.1171 +	{ NULL, 0, NULL, NULL }
  7.1172 +};
  7.1173 +
  7.1174 +#else
  7.1175 +
  7.1176 +#define	idedisk_proc	NULL
  7.1177 +
  7.1178 +#endif	/* CONFIG_PROC_FS */
  7.1179 +
  7.1180 +static int set_multcount(ide_drive_t *drive, int arg)
  7.1181 +{
  7.1182 +#ifdef __TASKFILE__IO
  7.1183 +	struct hd_drive_task_hdr taskfile;
  7.1184 +	struct hd_drive_hob_hdr hobfile;
  7.1185 +
  7.1186 +	if (drive->special.b.set_multmode)
  7.1187 +		return -EBUSY;
  7.1188 +
  7.1189 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1190 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1191 +	taskfile.sector_count	= drive->mult_req;
  7.1192 +	taskfile.command	= WIN_SETMULT;
  7.1193 +	drive->mult_req		= arg;
  7.1194 +	drive->special.b.set_multmode = 1;
  7.1195 +	ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1196 +#else /* !__TASKFILE__IO */
  7.1197 +	struct request rq;
  7.1198 +
  7.1199 +	if (drive->special.b.set_multmode)
  7.1200 +		return -EBUSY;
  7.1201 +	ide_init_drive_cmd (&rq);
  7.1202 +	rq.cmd = IDE_DRIVE_CMD;
  7.1203 +	drive->mult_req = arg;
  7.1204 +	drive->special.b.set_multmode = 1;
  7.1205 +	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
  7.1206 +#endif /* __TASKFILE__IO */
  7.1207 +	return (drive->mult_count == arg) ? 0 : -EIO;
  7.1208 +}
  7.1209 +
  7.1210 +static int set_nowerr(ide_drive_t *drive, int arg)
  7.1211 +{
  7.1212 +	if (ide_spin_wait_hwgroup(drive))
  7.1213 +		return -EBUSY;
  7.1214 +	drive->nowerr = arg;
  7.1215 +	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
  7.1216 +	spin_unlock_irq(&io_request_lock);
  7.1217 +	return 0;
  7.1218 +}
  7.1219 +
  7.1220 +static int write_cache (ide_drive_t *drive, int arg)
  7.1221 +{
  7.1222 +	struct hd_drive_task_hdr taskfile;
  7.1223 +	struct hd_drive_hob_hdr hobfile;
  7.1224 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1225 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1226 +	taskfile.feature	= (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
  7.1227 +	taskfile.command	= WIN_SETFEATURES;
  7.1228 +
  7.1229 +	if (!(drive->id->cfs_enable_2 & 0x3000))
  7.1230 +		return 1;
  7.1231 +
  7.1232 +	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1233 +	drive->wcache = arg;
  7.1234 +	return 0;
  7.1235 +}
  7.1236 +
  7.1237 +static int do_idedisk_standby (ide_drive_t *drive)
  7.1238 +{
  7.1239 +	struct hd_drive_task_hdr taskfile;
  7.1240 +	struct hd_drive_hob_hdr hobfile;
  7.1241 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1242 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1243 +	taskfile.command	= WIN_STANDBYNOW1;
  7.1244 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1245 +}
  7.1246 +
  7.1247 +static int do_idedisk_flushcache (ide_drive_t *drive)
  7.1248 +{
  7.1249 +	struct hd_drive_task_hdr taskfile;
  7.1250 +	struct hd_drive_hob_hdr hobfile;
  7.1251 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1252 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1253 +	if (drive->id->cfs_enable_2 & 0x2400) {
  7.1254 +		taskfile.command	= WIN_FLUSH_CACHE_EXT;
  7.1255 +	} else {
  7.1256 +		taskfile.command	= WIN_FLUSH_CACHE;
  7.1257 +	}
  7.1258 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1259 +}
  7.1260 +
  7.1261 +static int set_acoustic (ide_drive_t *drive, int arg)
  7.1262 +{
  7.1263 +	struct hd_drive_task_hdr taskfile;
  7.1264 +	struct hd_drive_hob_hdr hobfile;
  7.1265 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  7.1266 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  7.1267 +
  7.1268 +	taskfile.feature	= (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
  7.1269 +	taskfile.sector_count	= arg;
  7.1270 +
  7.1271 +	taskfile.command	= WIN_SETFEATURES;
  7.1272 +	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
  7.1273 +	drive->acoustic = arg;
  7.1274 +	return 0;
  7.1275 +}
  7.1276 +
  7.1277 +static int probe_lba_addressing (ide_drive_t *drive, int arg)
  7.1278 +{
  7.1279 +	drive->addressing =  0;
  7.1280 +
  7.1281 +	if (!(drive->id->cfs_enable_2 & 0x0400))
  7.1282 +                return -EIO;
  7.1283 +
  7.1284 +	drive->addressing = arg;
  7.1285 +	return 0;
  7.1286 +}
  7.1287 +
  7.1288 +static int set_lba_addressing (ide_drive_t *drive, int arg)
  7.1289 +{
  7.1290 +	return (probe_lba_addressing(drive, arg));
  7.1291 +}
  7.1292 +
  7.1293 +static void idedisk_add_settings(ide_drive_t *drive)
  7.1294 +{
  7.1295 +	struct hd_driveid *id = drive->id;
  7.1296 +#if 0
  7.1297 +	int major = HWIF(drive)->major;
  7.1298 +	int minor = drive->select.b.unit << PARTN_BITS;
  7.1299 +#endif
  7.1300 +
  7.1301 +	ide_add_setting(drive,	"bios_cyl",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->bios_cyl,		NULL);
  7.1302 +	ide_add_setting(drive,	"bios_head",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	255,				1,	1,	&drive->bios_head,		NULL);
  7.1303 +	ide_add_setting(drive,	"bios_sect",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	63,				1,	1,	&drive->bios_sect,		NULL);
  7.1304 +	ide_add_setting(drive,	"address",		SETTING_RW,					HDIO_GET_ADDRESS,	HDIO_SET_ADDRESS,	TYPE_INTA,	0,	2,				1,	1,	&drive->addressing,	set_lba_addressing);
  7.1305 +	ide_add_setting(drive,	"bswap",		SETTING_READ,					-1,			-1,			TYPE_BYTE,	0,	1,				1,	1,	&drive->bswap,			NULL);
  7.1306 +	ide_add_setting(drive,	"multcount",		id ? SETTING_RW : SETTING_READ,			HDIO_GET_MULTCOUNT,	HDIO_SET_MULTCOUNT,	TYPE_BYTE,	0,	id ? id->max_multsect : 0,	1,	1,	&drive->mult_count,		set_multcount);
  7.1307 +	ide_add_setting(drive,	"nowerr",		SETTING_RW,					HDIO_GET_NOWERR,	HDIO_SET_NOWERR,	TYPE_BYTE,	0,	1,				1,	1,	&drive->nowerr,			set_nowerr);
  7.1308 +#if 0
  7.1309 +	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	1,	&read_ahead[major],		NULL);
  7.1310 +	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	4096,			PAGE_SIZE,	1024,	&max_readahead[major][minor],	NULL);
  7.1311 +	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	1,	&max_sectors[major][minor],	NULL);
  7.1312 +#endif
  7.1313 +	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);
  7.1314 +	ide_add_setting(drive,	"wcache",		SETTING_RW,					HDIO_GET_WCACHE,	HDIO_SET_WCACHE,	TYPE_BYTE,	0,	1,				1,	1,	&drive->wcache,			write_cache);
  7.1315 +	ide_add_setting(drive,	"acoustic",		SETTING_RW,					HDIO_GET_ACOUSTIC,	HDIO_SET_ACOUSTIC,	TYPE_BYTE,	0,	254,				1,	1,	&drive->acoustic,		set_acoustic);
  7.1316 + 	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL);
  7.1317 + 	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
  7.1318 +}
  7.1319 +
  7.1320 +static void idedisk_setup (ide_drive_t *drive)
  7.1321 +{
  7.1322 +	int i;
  7.1323 +	
  7.1324 +	struct hd_driveid *id = drive->id;
  7.1325 +	unsigned long capacity;
  7.1326 +	
  7.1327 +	idedisk_add_settings(drive);
  7.1328 +
  7.1329 +	if (id == NULL)
  7.1330 +		return;
  7.1331 +
  7.1332 +	/*
  7.1333 +	 * CompactFlash cards and their brethern look just like hard drives
  7.1334 +	 * to us, but they are removable and don't have a doorlock mechanism.
  7.1335 +	 */
  7.1336 +	if (drive->removable && !drive_is_flashcard(drive)) {
  7.1337 +		/*
  7.1338 +		 * Removable disks (eg. SYQUEST); ignore 'WD' drives 
  7.1339 +		 */
  7.1340 +		if (id->model[0] != 'W' || id->model[1] != 'D') {
  7.1341 +			drive->doorlocking = 1;
  7.1342 +		}
  7.1343 +	}
  7.1344 +	for (i = 0; i < MAX_DRIVES; ++i) {
  7.1345 +		ide_hwif_t *hwif = HWIF(drive);
  7.1346 +
  7.1347 +		if (drive != &hwif->drives[i]) continue;
  7.1348 +#ifdef DEVFS_MUST_DIE
  7.1349 +		hwif->gd->de_arr[i] = drive->de;
  7.1350 +#endif
  7.1351 +		if (drive->removable)
  7.1352 +			hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
  7.1353 +		break;
  7.1354 +	}
  7.1355 +
  7.1356 +	/* Extract geometry if we did not already have one for the drive */
  7.1357 +	if (!drive->cyl || !drive->head || !drive->sect) {
  7.1358 +		drive->cyl     = drive->bios_cyl  = id->cyls;
  7.1359 +		drive->head    = drive->bios_head = id->heads;
  7.1360 +		drive->sect    = drive->bios_sect = id->sectors;
  7.1361 +	}
  7.1362 +
  7.1363 +	/* Handle logical geometry translation by the drive */
  7.1364 +	if ((id->field_valid & 1) && id->cur_cyls &&
  7.1365 +	    id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
  7.1366 +		drive->cyl  = id->cur_cyls;
  7.1367 +		drive->head = id->cur_heads;
  7.1368 +		drive->sect = id->cur_sectors;
  7.1369 +	}
  7.1370 +
  7.1371 +	/* Use physical geometry if what we have still makes no sense */
  7.1372 +	if (drive->head > 16 && id->heads && id->heads <= 16) {
  7.1373 +		drive->cyl  = id->cyls;
  7.1374 +		drive->head = id->heads;
  7.1375 +		drive->sect = id->sectors;
  7.1376 +	}
  7.1377 +
  7.1378 +	/* calculate drive capacity, and select LBA if possible */
  7.1379 +	init_idedisk_capacity (drive);
  7.1380 +
  7.1381 +	/*
  7.1382 +	 * if possible, give fdisk access to more of the drive,
  7.1383 +	 * by correcting bios_cyls:
  7.1384 +	 */
  7.1385 +	capacity = idedisk_capacity (drive);
  7.1386 +	if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
  7.1387 +	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head)
  7.1388 +		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
  7.1389 +	printk (KERN_INFO "XEN %s: %ld sectors", drive->name, capacity);
  7.1390 +
  7.1391 +	/* Give size in megabytes (MB), not mebibytes (MiB). */
  7.1392 +	/* We compute the exact rounded value, avoiding overflow. */
  7.1393 +	printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950);
  7.1394 +
  7.1395 +	/* Only print cache size when it was specified */
  7.1396 +	if (id->buf_size)
  7.1397 +		printk (" w/%dKiB Cache", id->buf_size/2);
  7.1398 +
  7.1399 +	printk(", CHS=%d/%d/%d", 
  7.1400 +	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
  7.1401 +#ifdef CONFIG_BLK_DEV_IDEDMA
  7.1402 +	if (drive->using_dma)
  7.1403 +		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
  7.1404 +#endif /* CONFIG_BLK_DEV_IDEDMA */
  7.1405 +	printk("\n");
  7.1406 +
  7.1407 +	drive->mult_count = 0;
  7.1408 +	if (id->max_multsect) {
  7.1409 +#ifdef CONFIG_IDEDISK_MULTI_MODE
  7.1410 +		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
  7.1411 +		id->multsect_valid = id->multsect ? 1 : 0;
  7.1412 +		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
  7.1413 +		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
  7.1414 +#else	/* original, pre IDE-NFG, per request of AC */
  7.1415 +		drive->mult_req = INITIAL_MULT_COUNT;
  7.1416 +		if (drive->mult_req > id->max_multsect)
  7.1417 +			drive->mult_req = id->max_multsect;
  7.1418 +		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
  7.1419 +			drive->special.b.set_multmode = 1;
  7.1420 +#endif	/* CONFIG_IDEDISK_MULTI_MODE */
  7.1421 +	}
  7.1422 +	drive->no_io_32bit = id->dword_io ? 1 : 0;
  7.1423 +	if (drive->id->cfs_enable_2 & 0x3000)
  7.1424 +		write_cache(drive, (id->cfs_enable_2 & 0x3000));
  7.1425 +	(void) probe_lba_addressing(drive, 1);
  7.1426 +}
  7.1427 +
  7.1428 +static int idedisk_cleanup (ide_drive_t *drive)
  7.1429 +{
  7.1430 +	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
  7.1431 +		if (do_idedisk_flushcache(drive))
  7.1432 +			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
  7.1433 +				drive->name);
  7.1434 +	return ide_unregister_subdriver(drive);
  7.1435 +}
  7.1436 +
  7.1437 +int idedisk_reinit(ide_drive_t *drive);
  7.1438 +
  7.1439 +/*
  7.1440 + *      IDE subdriver functions, registered with ide.c
  7.1441 + */
  7.1442 +static ide_driver_t idedisk_driver = {
  7.1443 +	name:			"ide-disk",
  7.1444 +	version:		IDEDISK_VERSION,
  7.1445 +	media:			ide_disk,
  7.1446 +	busy:			0,
  7.1447 +	supports_dma:		1,
  7.1448 +	supports_dsc_overlap:	0,
  7.1449 +	cleanup:		idedisk_cleanup,
  7.1450 +	standby:		do_idedisk_standby,
  7.1451 +	flushcache:		do_idedisk_flushcache,
  7.1452 +	do_request:		do_rw_disk,
  7.1453 +	end_request:		NULL,
  7.1454 +	ioctl:			NULL,
  7.1455 +	open:			idedisk_open,
  7.1456 +	release:		idedisk_release,
  7.1457 +	media_change:		idedisk_media_change,
  7.1458 +	revalidate:		idedisk_revalidate,
  7.1459 +	pre_reset:		idedisk_pre_reset,
  7.1460 +	capacity:		idedisk_capacity,
  7.1461 +	special:		idedisk_special,
  7.1462 +	/*proc:			idedisk_proc,*/
  7.1463 +	reinit:			idedisk_reinit,
  7.1464 +	ata_prebuilder:		NULL,
  7.1465 +	atapi_prebuilder:	NULL,
  7.1466 +};
  7.1467 +
  7.1468 +int idedisk_init (void);
  7.1469 +static ide_module_t idedisk_module = {
  7.1470 +	IDE_DRIVER_MODULE,
  7.1471 +	idedisk_init,
  7.1472 +	&idedisk_driver,
  7.1473 +	NULL
  7.1474 +};
  7.1475 +
  7.1476 +MODULE_DESCRIPTION("ATA DISK Driver");
  7.1477 +
  7.1478 +int idedisk_reinit (ide_drive_t *drive)
  7.1479 +{
  7.1480 +	int failed = 0;
  7.1481 +
  7.1482 +	MOD_INC_USE_COUNT;
  7.1483 +
  7.1484 +	if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
  7.1485 +		printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
  7.1486 +		return 1;
  7.1487 +	}
  7.1488 +	DRIVER(drive)->busy++;
  7.1489 +	idedisk_setup(drive);
  7.1490 +	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
  7.1491 +		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
  7.1492 +		(void) idedisk_cleanup(drive);
  7.1493 +		DRIVER(drive)->busy--;
  7.1494 +		return 1;
  7.1495 +	}
  7.1496 +	DRIVER(drive)->busy--;
  7.1497 +	failed--;
  7.1498 +
  7.1499 +	ide_register_module(&idedisk_module);
  7.1500 +	MOD_DEC_USE_COUNT;
  7.1501 +	return 0;
  7.1502 +}
  7.1503 +
  7.1504 +static void __exit idedisk_exit (void)
  7.1505 +{
  7.1506 +	ide_drive_t *drive;
  7.1507 +	int failed = 0;
  7.1508 +
  7.1509 +	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
  7.1510 +		if (idedisk_cleanup (drive)) {
  7.1511 +			printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
  7.1512 +			failed++;
  7.1513 +		}
  7.1514 +		/* We must remove proc entries defined in this module.
  7.1515 +		   Otherwise we oops while accessing these entries */
  7.1516 +#ifdef CONFIG_PROC_FS
  7.1517 +		if (drive->proc)
  7.1518 +			ide_remove_proc_entries(drive->proc, idedisk_proc);
  7.1519 +#endif
  7.1520 +	}
  7.1521 +	ide_unregister_module(&idedisk_module);
  7.1522 +}
  7.1523 +
  7.1524 +int idedisk_init (void)
  7.1525 +{
  7.1526 +	ide_drive_t *drive;
  7.1527 +	int failed = 0;
  7.1528 +	
  7.1529 +	MOD_INC_USE_COUNT;
  7.1530 +	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
  7.1531 +		if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
  7.1532 +			printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
  7.1533 +			continue;
  7.1534 +		}
  7.1535 +		DRIVER(drive)->busy++;
  7.1536 +		idedisk_setup(drive);
  7.1537 +		if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
  7.1538 +			printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
  7.1539 +			(void) idedisk_cleanup(drive);
  7.1540 +			DRIVER(drive)->busy--;
  7.1541 +			continue;
  7.1542 +		}
  7.1543 +		DRIVER(drive)->busy--;
  7.1544 +		failed--;
  7.1545 +	}
  7.1546 +	ide_register_module(&idedisk_module);
  7.1547 +	MOD_DEC_USE_COUNT;
  7.1548 +	return 0;
  7.1549 +}
  7.1550 +
  7.1551 +module_init(idedisk_init);
  7.1552 +module_exit(idedisk_exit);
  7.1553 +MODULE_LICENSE("GPL");
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c	Wed Feb 12 18:04:40 2003 +0000
     8.3 @@ -0,0 +1,827 @@
     8.4 +#include <linux/config.h>
     8.5 +#include <linux/module.h>
     8.6 +
     8.7 +#include <linux/kernel.h>
     8.8 +#include <linux/sched.h>
     8.9 +#include <linux/slab.h>
    8.10 +#include <linux/string.h>
    8.11 +#include <linux/errno.h>
    8.12 +
    8.13 +#include <linux/fs.h>
    8.14 +#include <linux/hdreg.h>                               /* HDIO_GETGEO, et al */
    8.15 +#include <linux/blkdev.h>
    8.16 +#include <linux/major.h>
    8.17 +
    8.18 +/* NOTE: this is drive independent, so no inclusion of ide.h */
    8.19 +
    8.20 +#include <asm/hypervisor-ifs/block.h>
    8.21 +#include <asm/hypervisor-ifs/hypervisor-if.h>
    8.22 +#include <asm/io.h>
    8.23 +#include <asm/uaccess.h>                                       /* put_user() */
    8.24 +
    8.25 +#define MAJOR_NR XLBLK_MAJOR   /* force defns in blk.h, must preceed include */
    8.26 +static int xlblk_major = XLBLK_MAJOR;
    8.27 +
    8.28 +#include <linux/blk.h>           /* must come after definition of MAJOR_NR!! */
    8.29 +
    8.30 +/* instead of including linux/ide.h to pick up the definitiong of byte
    8.31 + * (and consequently screwing up blk.h, we'll just copy the definition */
    8.32 +typedef unsigned char	byte; 
    8.33 +
    8.34 +void xlblk_ide_register_disk(int, unsigned long);
    8.35 +
    8.36 +#define XLBLK_MAX 2                                        /* very arbitrary */
    8.37 +#define XLBLK_MAJOR_NAME "blk"
    8.38 +#define IDE_PARTN_BITS 6                           /* from ide.h::PARTN_BITS */
    8.39 +#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1)     /* from ide.h::PARTN_MASK */
    8.40 +static int xlblk_blk_size[XLBLK_MAX];
    8.41 +static int xlblk_blksize_size[XLBLK_MAX];
    8.42 +static int xlblk_hardsect_size[XLBLK_MAX];
    8.43 +static int xlblk_read_ahead[XLBLK_MAX];
    8.44 +static int xlblk_max_sectors[XLBLK_MAX];
    8.45 +
    8.46 +#define XLBLK_RX_IRQ _EVENT_BLK_RX
    8.47 +#define XLBLK_TX_IRQ _EVENT_BLK_TX
    8.48 +
    8.49 +typedef struct xlblk_device
    8.50 +{
    8.51 +  struct buffer_head *bh;
    8.52 +  unsigned int tx_count;                  /* number of used slots in tx ring */
    8.53 +} xlblk_device_t;
    8.54 +
    8.55 +xlblk_device_t xlblk_device;
    8.56 +
    8.57 +/* USE_REQUEST_QUEUE = 1  use (multiple) request queues
    8.58 + *                   = 0  don't use IO request queue 
    8.59 + */
    8.60 +#define USE_REQUEST_QUEUE 1
    8.61 +
    8.62 +#define XLBLK_DEBUG       0
    8.63 +#define XLBLK_DEBUG_IOCTL 0
    8.64 +
    8.65 +/* 
    8.66 + * disk management
    8.67 + */
    8.68 +
    8.69 +xen_disk_info_t xen_disk_info;
    8.70 +
    8.71 +/* some declarations */
    8.72 +void hypervisor_request(void *         id,
    8.73 +			int            operation,
    8.74 +			char *         buffer,
    8.75 +			unsigned long  block_number,
    8.76 +			unsigned short block_size,
    8.77 +			kdev_t         device,
    8.78 +			int            mode);
    8.79 +
    8.80 +
    8.81 +/* ------------------------------------------------------------------------
    8.82 + */
    8.83 +
    8.84 +static int xenolinux_block_open(struct inode *inode, struct file *filep)
    8.85 +{
    8.86 +  if (XLBLK_DEBUG) {
    8.87 +    printk (KERN_ALERT "xenolinux_block_open\n"); }
    8.88 +  return 0;
    8.89 +}
    8.90 +
    8.91 +static int xenolinux_block_release(struct inode *inode, struct file *filep)
    8.92 +{
    8.93 +  if (XLBLK_DEBUG) {
    8.94 +    printk (KERN_ALERT "xenolinux_block_release\n"); }
    8.95 +  return 0;
    8.96 +}
    8.97 +
    8.98 +static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
    8.99 +			  unsigned command, unsigned long argument)
   8.100 +{
   8.101 +  int minor_dev;
   8.102 +
   8.103 +  if (XLBLK_DEBUG_IOCTL)
   8.104 +  {
   8.105 +    printk (KERN_ALERT "xenolinux_block_ioctl\n"); 
   8.106 +  }
   8.107 +
   8.108 +  /* check permissions */
   8.109 +  if (!capable(CAP_SYS_ADMIN)) return -EPERM;
   8.110 +  if (!inode)                  return -EINVAL;
   8.111 +  minor_dev = MINOR(inode->i_rdev);
   8.112 +  if (minor_dev >= XLBLK_MAX)  return -ENODEV;
   8.113 +
   8.114 +  if (XLBLK_DEBUG_IOCTL)
   8.115 +  {
   8.116 +    printk (KERN_ALERT  
   8.117 +	    "   command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
   8.118 +	    command, (long) argument, minor_dev); 
   8.119 +  }
   8.120 +  
   8.121 +  switch (command)
   8.122 +  {
   8.123 +    case BLKGETSIZE :
   8.124 +    {
   8.125 +      if (XLBLK_DEBUG_IOCTL)
   8.126 +      {
   8.127 +	printk (KERN_ALERT
   8.128 +		"   BLKGETSIZE: %x %lx\n", BLKGETSIZE, 
   8.129 +		(long) xen_disk_info.disks[0].capacity); 
   8.130 +      }
   8.131 +      return put_user(xen_disk_info.disks[0].capacity, 
   8.132 +		      (unsigned long *) argument);
   8.133 +    }
   8.134 +    case BLKRRPART :
   8.135 +    {
   8.136 +      if (XLBLK_DEBUG_IOCTL) {
   8.137 +	printk (KERN_ALERT "   BLKRRPART: %x\n", BLKRRPART); }
   8.138 +      break;
   8.139 +    }
   8.140 +    case BLKSSZGET :
   8.141 +    {
   8.142 +      if (XLBLK_DEBUG_IOCTL) {
   8.143 +	printk (KERN_ALERT "   BLKSSZGET: %x 0x%x\n", BLKSSZGET,
   8.144 +		xlblk_hardsect_size[minor_dev]); }
   8.145 +      return xlblk_hardsect_size[minor_dev]; 
   8.146 +    }
   8.147 +    case HDIO_GETGEO :
   8.148 +    {
   8.149 +      struct hd_geometry *geo = (struct hd_geometry *)argument;
   8.150 +
   8.151 +      if (XLBLK_DEBUG_IOCTL) {
   8.152 +	printk (KERN_ALERT "   HDIO_GETGEO: %x\n", HDIO_GETGEO); }
   8.153 +
   8.154 +      if (!argument) return -EINVAL;
   8.155 +      /*
   8.156 +      if (put_user(0x80,  (byte *)&geo->heads)) return -EFAULT;
   8.157 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   8.158 +      if (put_user(0x20b, (unsigned short *) &geo->cylinders)) return -EFAULT;
   8.159 +      */
   8.160 +      if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
   8.161 +      if (put_user(0xff,  (byte *)&geo->heads)) return -EFAULT;
   8.162 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   8.163 +      if (put_user(0x106, (unsigned short *) &geo->cylinders)) return -EFAULT;
   8.164 +
   8.165 +      return 0;
   8.166 +    }
   8.167 +    case HDIO_GETGEO_BIG :
   8.168 +    {
   8.169 +      struct hd_big_geometry *geo = (struct hd_big_geometry *) argument;
   8.170 +
   8.171 +      if (XLBLK_DEBUG_IOCTL) {
   8.172 +	printk (KERN_ALERT "   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); }
   8.173 +
   8.174 +      if (!argument) return -EINVAL;
   8.175 +      /*
   8.176 +      if (put_user(0x80,  (byte *)&geo->heads))   return -EFAULT;
   8.177 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   8.178 +      if (put_user(0x20b, (unsigned int *) &geo->cylinders)) return -EFAULT;
   8.179 +      */
   8.180 +      if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
   8.181 +      if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
   8.182 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
   8.183 +      if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
   8.184 +
   8.185 +      return 0;
   8.186 +    }
   8.187 +    default :
   8.188 +    {
   8.189 +      if (XLBLK_DEBUG_IOCTL) {
   8.190 +	printk (KERN_ALERT "   eh? unknown ioctl\n"); }
   8.191 +      break;
   8.192 +    }
   8.193 +  }
   8.194 +
   8.195 +  return 0;
   8.196 +}
   8.197 +
   8.198 +static int xenolinux_block_check(kdev_t dev)
   8.199 +{
   8.200 +  if (XLBLK_DEBUG) {
   8.201 +    printk (KERN_ALERT "xenolinux_block_check\n"); }
   8.202 +  return 0;
   8.203 +}
   8.204 +
   8.205 +static int xenolinux_block_revalidate(kdev_t dev)
   8.206 +{
   8.207 +  if (XLBLK_DEBUG) {
   8.208 +    printk (KERN_ALERT "xenolinux_block_revalidate\n"); }
   8.209 +  return 0;
   8.210 +}
   8.211 +
   8.212 +/*
   8.213 + * hypervisor_request
   8.214 + *
   8.215 + * request block io 
   8.216 + * 
   8.217 + * id: for guest use only.
   8.218 + * operation: XEN_BLOCK_READ, XEN_BLOCK_WRITE or XEN_BLOCK_PROBE
   8.219 + * buffer: buffer to read/write into. this should be a
   8.220 + *   virtual address in the guest os.
   8.221 + * block_number:  block to read
   8.222 + * block_size:  size of each block
   8.223 + * device:  ide/hda is 768 or 0x300
   8.224 + * mode: XEN_BLOCK_SYNC or XEN_BLOCK_ASYNC.  async requests
   8.225 + *   will queue until a sync request is issued.
   8.226 + */
   8.227 +
   8.228 +void hypervisor_request(void *         id,
   8.229 +			int            operation,
   8.230 +			char *         buffer,
   8.231 +			unsigned long  block_number,
   8.232 +			unsigned short block_size,
   8.233 +			kdev_t         device,
   8.234 +			int            mode)
   8.235 +{
   8.236 +  blk_ring_t *blk_ring = start_info.blk_ring;
   8.237 +  int position;
   8.238 +  void *buffer_pa, *buffer_ma; 
   8.239 +  kdev_t phys_device = (kdev_t) 0;
   8.240 +  unsigned long sector_number = 0;
   8.241 +
   8.242 +#if 0
   8.243 +  printk(KERN_ALERT "[%x]", id); 
   8.244 +  printk (KERN_ALERT
   8.245 +	  "xlblk_req: id:%p op:%d, bf:%p, blk:%lu, sz:%u, dev:%x\n",
   8.246 +	  id, operation, buffer, block_number, block_size, device);
   8.247 +#endif
   8.248 +
   8.249 +  /* XXX SMH: now need to convert guest virtual address to machine address */
   8.250 +  buffer_pa = (void *)virt_to_phys((unsigned long)buffer); 
   8.251 +  buffer_ma = (void *)phys_to_machine((unsigned long)buffer_pa); 
   8.252 +
   8.253 +#if 0
   8.254 +  printk(KERN_ALERT "va %p => pa %p => ma %p\n", buffer, buffer_pa, buffer_ma);
   8.255 +#endif
   8.256 +
   8.257 +  if (operation == XEN_BLOCK_PROBE)
   8.258 +  {
   8.259 +    phys_device = (kdev_t) 0;
   8.260 +    sector_number = 0;
   8.261 +  }
   8.262 +  else if (operation == XEN_BLOCK_READ || operation == XEN_BLOCK_WRITE)
   8.263 +  {
   8.264 +    /*
   8.265 +     * map logial major device to the physical device number 
   8.266 +     *
   8.267 +     *           XLBLK_MAJOR -> IDE0_MAJOR  (123 -> 3)
   8.268 +     */
   8.269 +    if (MAJOR(device) == XLBLK_MAJOR)
   8.270 +    {
   8.271 +      phys_device = MKDEV(IDE0_MAJOR, 0);
   8.272 +    }
   8.273 +    else
   8.274 +    {
   8.275 +      printk (KERN_ALERT
   8.276 +	      "error: xl_block::hypervisor_request: unknown device [0x%x]\n", 
   8.277 +	      device);
   8.278 +      BUG();
   8.279 +    }
   8.280 +  
   8.281 +    /*
   8.282 +     * compute real buffer location on disk
   8.283 +     * (from ll_rw_block.c::submit_bh)
   8.284 +     */
   8.285 +    {
   8.286 +      int idx = 0;
   8.287 +
   8.288 +      struct gendisk *gd = (struct gendisk *) xen_disk_info.disks[idx].gendisk;
   8.289 +      unsigned int minor = MINOR(device);
   8.290 +
   8.291 +      sector_number = block_number /* * block_size >> 9 */;
   8.292 +
   8.293 +      if (gd != NULL)                     /* if we have a partition table... */
   8.294 +      {
   8.295 +	sector_number += gd->part[minor & IDE_PARTN_MASK].start_sect;
   8.296 +      }
   8.297 +    }
   8.298 +  }
   8.299 +
   8.300 +  /*
   8.301 +   * CHECK TO SEE IF THERE IS SPACE IN THE RING
   8.302 +   */
   8.303 +  if (BLK_TX_RING_INC(blk_ring->tx_prod) == blk_ring->tx_cons)
   8.304 +  {
   8.305 +    printk (KERN_ALERT "hypervisor_request: tx_cons: %d, tx_prod:%d",
   8.306 +	    blk_ring->tx_cons, blk_ring->tx_prod);
   8.307 +  }
   8.308 +
   8.309 +  /* fill out a communications ring structure 
   8.310 +     and then trap into the hypervisor */
   8.311 +  position = blk_ring->tx_prod;
   8.312 +  blk_ring->tx_ring[position].id            = id;
   8.313 +  blk_ring->tx_ring[position].priority      = mode;
   8.314 +  blk_ring->tx_ring[position].operation     = operation;
   8.315 +  blk_ring->tx_ring[position].buffer        = buffer_ma;
   8.316 +  blk_ring->tx_ring[position].block_number  = block_number;
   8.317 +  blk_ring->tx_ring[position].block_size    = block_size;
   8.318 +  blk_ring->tx_ring[position].device        = phys_device;
   8.319 +  blk_ring->tx_ring[position].sector_number = sector_number;
   8.320 +
   8.321 +  blk_ring->tx_prod = BLK_TX_RING_INC(blk_ring->tx_prod);
   8.322 +
   8.323 +  if (mode == XEN_BLOCK_SYNC)
   8.324 +  {
   8.325 +    /* trap into hypervisor */
   8.326 +    HYPERVISOR_block_io_op();
   8.327 +  }
   8.328 +  else if (mode == XEN_BLOCK_ASYNC)
   8.329 +  {
   8.330 +    /* for now, do nothing.  the request will go in the ring and
   8.331 +       the next sync request will trigger the hypervisor to act */
   8.332 +  }
   8.333 +  else
   8.334 +  {
   8.335 +    /* ummm, unknown mode. */
   8.336 +    BUG();
   8.337 +  }
   8.338 +
   8.339 +  return;
   8.340 +}
   8.341 +
   8.342 +
   8.343 +/*
   8.344 + * do_xlblk_request
   8.345 + *
   8.346 + * read a block; request is in a request queue
   8.347 + *
   8.348 + * TO DO: should probably release the io_request_lock and then re-acquire
   8.349 + *        (see LDD p. 338)
   8.350 + */
   8.351 +
   8.352 +static void do_xlblk_request (request_queue_t *rq)
   8.353 +{
   8.354 +  struct request *req;
   8.355 +
   8.356 +  if (XLBLK_DEBUG)
   8.357 +  {
   8.358 +    printk (KERN_ALERT "xlblk.c::do_xlblk_request for '%s'\n", DEVICE_NAME); 
   8.359 +  }
   8.360 +
   8.361 +  while (!QUEUE_EMPTY)
   8.362 +  {
   8.363 +    struct buffer_head *bh;
   8.364 +    unsigned long offset;
   8.365 +    unsigned long length;
   8.366 +    int rw;
   8.367 +
   8.368 +    req = CURRENT;
   8.369 +
   8.370 +    if (XLBLK_DEBUG)
   8.371 +    {
   8.372 +      printk (KERN_ALERT
   8.373 +	      "do_xlblk_request %p: cmd %i, sec %lx, (%li) bh:%p\n",
   8.374 +	      req, req->cmd, req->sector,
   8.375 +	      req->current_nr_sectors, req->bh);
   8.376 +    }
   8.377 +
   8.378 +    /* is there space in the tx ring for this request?
   8.379 +     * if the ring is full, then leave the request in the queue
   8.380 +     *
   8.381 +     * THIS IS A BIT BOGUS SINCE XEN COULD BE UPDATING TX_CONS
   8.382 +     * AT THE SAME TIME
   8.383 +     */
   8.384 +    {
   8.385 +      blk_ring_t *blk_ring = start_info.blk_ring;
   8.386 +      
   8.387 +      if (BLK_RX_RING_INC(blk_ring->tx_prod) == blk_ring->tx_cons)
   8.388 +      {
   8.389 +	printk (KERN_ALERT "OOPS, TX LOOKS FULL  cons: %d  prod: %d\n",
   8.390 +		blk_ring->tx_cons, blk_ring->tx_prod);
   8.391 +	break;
   8.392 +      }
   8.393 +    }
   8.394 +
   8.395 +    req->errors = 0;
   8.396 +    blkdev_dequeue_request(req);
   8.397 +
   8.398 +    bh = req->bh;
   8.399 +
   8.400 +    while (bh)
   8.401 +    {
   8.402 +
   8.403 +    offset = bh->b_rsector << 9;
   8.404 +    length = bh->b_size;
   8.405 +    
   8.406 +    rw = req->cmd;
   8.407 +    if (rw == READA)  rw= READ;
   8.408 +    if ((rw != READ) && (rw != WRITE))
   8.409 +    {
   8.410 +      printk (KERN_ALERT
   8.411 +	      "XenoLinux Virtual Block Device: bad command: %d\n", rw);
   8.412 +      BUG();
   8.413 +    }
   8.414 +
   8.415 +    /*
   8.416 +    if (XLBLK_DEBUG)
   8.417 +    {
   8.418 +      printk (KERN_ALERT "xlblk.c::do_xlblk_request\n");
   8.419 +      printk (KERN_ALERT "  b_blocknr: 0x%lx %ld\n", 
   8.420 +                         bh->b_blocknr, bh->b_blocknr);
   8.421 +      printk (KERN_ALERT "  b_size:    0x%x  %d\n", bh->b_size, bh->b_size);
   8.422 +      printk (KERN_ALERT "  b_dev:     0x%x  %d\n", bh->b_dev, bh->b_dev);
   8.423 +      printk (KERN_ALERT "  b_rsector: 0x%lx %ld\n", 
   8.424 +                         bh->b_rsector, bh->b_rsector);
   8.425 +    }
   8.426 +    */
   8.427 +
   8.428 +    hypervisor_request (req, rw == READ ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
   8.429 +			bh->b_data, bh->b_rsector, bh->b_size, 
   8.430 +			bh->b_dev, XEN_BLOCK_SYNC);
   8.431 +
   8.432 +      bh = bh->b_reqnext;
   8.433 +    }
   8.434 +  }
   8.435 +
   8.436 +  return;
   8.437 +}
   8.438 +
   8.439 +/*
   8.440 + * xenolinux_block_request
   8.441 + *
   8.442 + * read a block without using a request queue
   8.443 + */
   8.444 +
   8.445 +static int xenolinux_block_request(request_queue_t *rq,
   8.446 +				   int rw,
   8.447 +				   struct buffer_head *bh)
   8.448 +{
   8.449 +  unsigned int minor;
   8.450 +  unsigned long offset;
   8.451 +  unsigned long length;
   8.452 +
   8.453 +  if (XLBLK_DEBUG) {
   8.454 +    printk (KERN_ALERT "xlblk.c::xenolinux_block_request: %lx %d %lx\n",
   8.455 +	    (unsigned long) rq, rw, (unsigned long) bh); }
   8.456 +  /*
   8.457 +  printk (KERN_ALERT "xlblk.c::xlblk_request: op:%d bh:%p sect:%lu sz:%u\n",
   8.458 +	  rw,  bh, bh->b_rsector, bh->b_size);
   8.459 +  */
   8.460 +
   8.461 +  minor = MINOR(bh->b_rdev);
   8.462 +
   8.463 +  offset = bh->b_rsector << 9;
   8.464 +  length = bh->b_size;
   8.465 +
   8.466 +  if (rw == READA)  rw= READ;
   8.467 +  if ((rw != READ) && (rw != WRITE))
   8.468 +  {
   8.469 +    printk (KERN_ALERT 
   8.470 +	    "XenoLinux Virtual Block Device: bad command: %d\n", rw);
   8.471 +    goto fail;
   8.472 +  }
   8.473 +
   8.474 +  hypervisor_request (bh, rw == READ ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
   8.475 +		      bh->b_data, bh->b_rsector, bh->b_size, 
   8.476 +		      bh->b_dev, XEN_BLOCK_SYNC);
   8.477 +
   8.478 +  return 0;
   8.479 +
   8.480 + fail:
   8.481 +  return 0;
   8.482 +}
   8.483 +
   8.484 +static struct block_device_operations xenolinux_block_fops = 
   8.485 +{
   8.486 +    open:               xenolinux_block_open,
   8.487 +    release:            xenolinux_block_release,
   8.488 +    ioctl:              xenolinux_block_ioctl,
   8.489 +    check_media_change: xenolinux_block_check,
   8.490 +    revalidate:         xenolinux_block_revalidate,
   8.491 +};
   8.492 +
   8.493 +static void xlblk_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
   8.494 +{
   8.495 +  xlblk_device_t *dev = (xlblk_device_t *)dev_id;
   8.496 +  blk_ring_t *blk_ring = start_info.blk_ring;
   8.497 +  struct buffer_head *bh;
   8.498 +  struct request *req;
   8.499 +  int loop;
   8.500 +
   8.501 +  for (loop = blk_ring->rx_cons;
   8.502 +       loop != blk_ring->rx_prod;
   8.503 +       loop = BLK_RX_RING_INC(loop))
   8.504 +  {
   8.505 +    blk_ring_entry_t *bret = &blk_ring->rx_ring[loop];
   8.506 +    void *buffer_pa, *buffer_va; 
   8.507 +
   8.508 +    buffer_pa = machine_to_phys((unsigned long)bret->buffer); 
   8.509 +    buffer_va = phys_to_virt((unsigned long)buffer_pa); 
   8.510 +    
   8.511 +#if 0
   8.512 +    printk(KERN_ALERT "xlblk_rx_int: buffer ma %p => pa %p => va %p\n", 
   8.513 +	   bret->buffer, buffer_pa, buffer_va); 
   8.514 +
   8.515 +
   8.516 +    if (XLBLK_DEBUG)
   8.517 +    {
   8.518 +      printk (KERN_ALERT 
   8.519 +	      "xlblock::xlblk_rx_int [%s]\n",
   8.520 +	      (bret->operation == XEN_BLOCK_READ) ? "read" : "write");
   8.521 +      printk (KERN_ALERT 
   8.522 +	      "   vbuf: %lx, pbuf: %lx, blockno: %lx, size: %x, device %x\n",
   8.523 +	      (unsigned long) buffer_va, (unsigned long) bret->buffer,
   8.524 +	      bret->block_number, bret->block_size, bret->device);
   8.525 +      printk (KERN_ALERT "   bret: %p  bh: %p\n", bret, bret->id); 
   8.526 +    }
   8.527 +
   8.528 +    /*
   8.529 +    printk (KERN_ALERT
   8.530 +	    "xlblk_rx: id:%p op:%d, bf:%p, blk:%lu, sz:%u, dev:%x\n",
   8.531 +	    bret->id, bret->operation, bret->buffer, bret->block_number,
   8.532 +	    bret->block_size, bret->device);
   8.533 +    */
   8.534 +#endif
   8.535 +
   8.536 +    if (USE_REQUEST_QUEUE)
   8.537 +    {
   8.538 +      req = (struct request *)bret->id;
   8.539 +      printk(KERN_ALERT "|%x|", req); 
   8.540 +
   8.541 +      if (!end_that_request_first(req, 1, "NAME"))
   8.542 +      {
   8.543 +	blkdev_dequeue_request(req);
   8.544 +
   8.545 +	/* should be end_that_request_last(req)
   8.546 +	   to wake up waiting processes (with complete) */
   8.547 +	blkdev_release_request(req);
   8.548 +      }
   8.549 +
   8.550 +      /*
   8.551 +	if (XLBLK_DEBUG)
   8.552 +	{
   8.553 +	  int temp;
   8.554 +	  printk(KERN_ALERT 
   8.555 +		 "buff: 0x%p, blkno: 0x%lx, size: 0x%x, device 0x%x [%p]\n",
   8.556 +		 vbuffer, bret->block_number, bret->block_size, bret->device,
   8.557 +		 bh->b_end_io); 
   8.558 +
   8.559 +	  for (temp = 0; temp < bret->block_size; temp++)
   8.560 +	  {
   8.561 +	    if (temp % 16 == 0)       printk ("[%4x]  ", temp);
   8.562 +	    else if (temp % 4 == 0)   printk (" ");
   8.563 +	                              printk ("%02x",
   8.564 +					      vbuffer[temp] & 255);
   8.565 +            if ((temp + 1) % 16 == 0) printk ("\n");
   8.566 +	  }
   8.567 +	  printk ("\n\n");
   8.568 +	}
   8.569 +      */
   8.570 +
   8.571 +#ifdef BOGUS
   8.572 +      req = (struct request *)bret->id;
   8.573 +      while ((bh = req->bh) != NULL)
   8.574 +      {
   8.575 +	req->bh = bh->b_reqnext;
   8.576 +	bh->b_reqnext = NULL;
   8.577 +	bh->b_end_io(bh,1);
   8.578 +      }
   8.579 +      blkdev_release_request(req);
   8.580 +#endif /* BOGUS  */
   8.581 +    }
   8.582 +    else
   8.583 +    {
   8.584 +      bh = (struct buffer_head *)bret->id;
   8.585 +      bh->b_end_io(bh,1);
   8.586 +
   8.587 +      /*
   8.588 +	if (XLBLK_DEBUG)
   8.589 +	{
   8.590 +	  int temp;
   8.591 +#if 0
   8.592 +	  printk(KERN_ALERT 
   8.593 +		 "buff: 0x%p, blkno: 0x%lx, size: 0x%x, device 0x%x [%p]\n",
   8.594 +		 vbuffer, bret->block_number, bret->block_size, bret->device,
   8.595 +		 bh->b_end_io); 
   8.596 +#endif
   8.597 +
   8.598 +	  for (temp = 0; temp < bret->block_size; temp++)
   8.599 +	  {
   8.600 +	    if (temp % 16 == 0)       printk ("[%4x]  ", temp);
   8.601 +	    else if (temp % 4 == 0)   printk (" ");
   8.602 +	                              printk ("%02x",
   8.603 +					      vbuffer[temp] & 255);
   8.604 +            if ((temp + 1) % 16 == 0) printk ("\n");
   8.605 +	  }
   8.606 +	  printk ("\n\n");
   8.607 +	}
   8.608 +      */    
   8.609 +    }
   8.610 +  }
   8.611 +
   8.612 +  blk_ring->rx_cons = loop;
   8.613 +}
   8.614 +
   8.615 +static void xlblk_tx_int(int irq, void *dev_id, struct pt_regs *ptregs)
   8.616 +{
   8.617 +  if (XLBLK_DEBUG) {
   8.618 +    printk (KERN_ALERT "--- xlblock::xlblk_tx_int\n"); }
   8.619 +}
   8.620 +
   8.621 +int __init xlblk_init(void)
   8.622 +{
   8.623 +  blk_ring_t *blk_ring = start_info.blk_ring;
   8.624 +  int loop, error, result;
   8.625 +
   8.626 +  /*
   8.627 +   * initialize memory rings to communicate with hypervisor 
   8.628 +   */
   8.629 +
   8.630 +  if ( blk_ring == NULL ) return -ENOMEM;
   8.631 +
   8.632 +  blk_ring->tx_prod = blk_ring->tx_cons = 0;
   8.633 +  blk_ring->rx_prod = blk_ring->rx_cons = 0;
   8.634 +  blk_ring->tx_ring = NULL;
   8.635 +  blk_ring->rx_ring = NULL;
   8.636 +
   8.637 +  blk_ring->tx_ring = kmalloc(BLK_TX_RING_SIZE * sizeof(blk_ring_entry_t),
   8.638 +			      GFP_KERNEL);
   8.639 +  blk_ring->rx_ring = kmalloc(BLK_RX_RING_SIZE * sizeof(blk_ring_entry_t),
   8.640 +			      GFP_KERNEL);
   8.641 +
   8.642 +  if ((blk_ring->tx_ring == NULL) ||
   8.643 +      (blk_ring->rx_ring == NULL))
   8.644 +  {
   8.645 +    printk (KERN_ALERT 
   8.646 +	    "error, could not allocate ring memory for block device\n");
   8.647 +    error = -ENOBUFS;
   8.648 +    goto fail;
   8.649 +  }
   8.650 +
   8.651 +  /*
   8.652 +   * setup soft interrupts to communicate with hypervisor
   8.653 +   */
   8.654 +
   8.655 +  error = request_irq(XLBLK_RX_IRQ, xlblk_rx_int, 0, "xlblk-rx", 
   8.656 +		      &xlblk_device);
   8.657 +  if (error)
   8.658 +  {
   8.659 +    printk(KERN_ALERT "Could not allocate receive interrupt\n");
   8.660 +    goto fail;
   8.661 +  }
   8.662 +
   8.663 +  error = request_irq(XLBLK_TX_IRQ, xlblk_tx_int, 0, "xlblk-tx", 
   8.664 +		      &xlblk_device);
   8.665 +  if (error)
   8.666 +  {
   8.667 +    printk(KERN_ALERT "Could not allocate transmit interrupt\n");
   8.668 +    free_irq(XLBLK_RX_IRQ, &xlblk_device);
   8.669 +    goto fail;
   8.670 +  }
   8.671 +
   8.672 +  /*
   8.673 +   * get information about physical drives
   8.674 +   *
   8.675 +   */
   8.676 +  {
   8.677 +    /* NOTE: this should only occur in domain 0 */
   8.678 +    memset (&xen_disk_info, 0, sizeof(xen_disk_info));
   8.679 +    xen_disk_info.count = 0;
   8.680 +
   8.681 +    hypervisor_request(NULL, XEN_BLOCK_PROBE, (char *) &xen_disk_info,
   8.682 +		       0, 0, (kdev_t) 0, XEN_BLOCK_SYNC);
   8.683 +
   8.684 +    {
   8.685 +      int loop;
   8.686 +      for (loop = 0; loop < xen_disk_info.count; loop++)
   8.687 +      {
   8.688 +	printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
   8.689 +		loop, xen_disk_info.disks[loop].type, 
   8.690 +		xen_disk_info.disks[loop].capacity);
   8.691 +      }
   8.692 +    }
   8.693 +  }
   8.694 +
   8.695 +  /*
   8.696 +   * initialize device driver
   8.697 +   */
   8.698 +
   8.699 +  SET_MODULE_OWNER(&xenolinux_block_fops);
   8.700 +
   8.701 +  result = register_blkdev(xlblk_major, "block", &xenolinux_block_fops);
   8.702 +  if (result < 0)
   8.703 +  {
   8.704 +    printk (KERN_ALERT "xenolinux block: can't get major %d\n", xlblk_major);
   8.705 +    return result;
   8.706 +  }
   8.707 +
   8.708 +  /* initialize global arrays in drivers/block/ll_rw_block.c */
   8.709 +  blk_size[xlblk_major] = xlblk_blk_size;
   8.710 +  blksize_size[xlblk_major] = xlblk_blksize_size;
   8.711 +  hardsect_size[xlblk_major] = xlblk_hardsect_size;
   8.712 +  read_ahead[xlblk_major] = xlblk_read_ahead;
   8.713 +  max_sectors[xlblk_major] = xlblk_max_sectors;
   8.714 +  for (loop = 0; loop < XLBLK_MAX; loop++)
   8.715 +  {
   8.716 +    xlblk_blk_size[loop] = xen_disk_info.disks[0].capacity;
   8.717 +    xlblk_blksize_size[loop] = 512;
   8.718 +    xlblk_hardsect_size[loop] = 512;
   8.719 +    xlblk_read_ahead[loop] = 8; 
   8.720 +    xlblk_max_sectors[loop] = 128;
   8.721 +  }
   8.722 +
   8.723 +  if (USE_REQUEST_QUEUE)
   8.724 +  {
   8.725 +    /* NEED TO MODIFY THIS TO HANDLE MULTIPLE QUEUES
   8.726 +     * also, should replace do_xlblk_request with blk.h::DEVICE_REQUEST
   8.727 +     */
   8.728 +    blk_init_queue(BLK_DEFAULT_QUEUE(xlblk_major), do_xlblk_request);
   8.729 +    blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
   8.730 +  }
   8.731 +  else
   8.732 +  {
   8.733 +    /* we don't use __make_request in ll_rw_blk */
   8.734 +    blk_queue_make_request(BLK_DEFAULT_QUEUE(xlblk_major), 
   8.735 +			   xenolinux_block_request);
   8.736 +  }
   8.737 +  xlblk_ide_register_disk(0, xen_disk_info.disks[0].capacity);
   8.738 +
   8.739 +  /*
   8.740 +   * completion 
   8.741 +   */
   8.742 +  printk(KERN_ALERT 
   8.743 +	 "XenoLinux Virtual Block Device Driver installed [device: %d]\n",
   8.744 +	 xlblk_major);
   8.745 +  return 0;
   8.746 +
   8.747 + fail:
   8.748 +  if (blk_ring->tx_ring) kfree(blk_ring->tx_ring);
   8.749 +  if (blk_ring->rx_ring) kfree(blk_ring->rx_ring);
   8.750 +  return error;
   8.751 +}
   8.752 +
   8.753 +void xlblk_ide_register_disk(int idx, unsigned long capacity)
   8.754 +{
   8.755 +  int units;
   8.756 +  int minors;
   8.757 +  struct gendisk *gd;
   8.758 +
   8.759 +  /* plagarized from ide-probe.c::init_gendisk */
   8.760 +
   8.761 +  units = 2;                                       /* from ide.h::MAX_DRIVES */
   8.762 +
   8.763 +  minors    = units * (1<<IDE_PARTN_BITS);
   8.764 +  gd        = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
   8.765 +  gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
   8.766 +  gd->part  = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
   8.767 +  memset(gd->part, 0, minors * sizeof(struct hd_struct));
   8.768 +
   8.769 +  gd->major       = xlblk_major;                  /* our major device number */
   8.770 +  gd->major_name  = XLBLK_MAJOR_NAME;          /* treated special in genhd.c */
   8.771 +  gd->minor_shift = IDE_PARTN_BITS;               /* num bits for partitions */
   8.772 +  gd->max_p	  = 1<<IDE_PARTN_BITS;         /* 1 + max partitions / drive */
   8.773 +  gd->nr_real	  = units;                        /* current num real drives */
   8.774 +  gd->real_devices= NULL;                /* ptr to internal data (was: hwif) */
   8.775 +  gd->next	  = NULL;                       /* linked list of major devs */
   8.776 +  gd->fops        = &xenolinux_block_fops;                /* file operations */
   8.777 +  gd->de_arr      = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
   8.778 +  gd->flags	  = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
   8.779 +  if (gd->de_arr)   memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
   8.780 +  if (gd->flags)    memset (gd->flags, 0, sizeof *gd->flags * units);
   8.781 +  add_gendisk(gd);
   8.782 +
   8.783 +  xen_disk_info.disks[idx].gendisk = gd;
   8.784 +
   8.785 +  /* default disk size is just a big number.  in the future, we
   8.786 +     need a message to probe the devices to determine the actual size */
   8.787 +  register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
   8.788 +		&xenolinux_block_fops, capacity);
   8.789 +
   8.790 +  return;
   8.791 +}
   8.792 +
   8.793 +static void __exit xlblk_cleanup(void)
   8.794 +{
   8.795 +  /* CHANGE FOR MULTIQUEUE */
   8.796 +  blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major));
   8.797 +
   8.798 +  /* clean up global arrays */
   8.799 +  read_ahead[xlblk_major] = 0;
   8.800 +  if (blk_size[xlblk_major]) kfree(blk_size[xlblk_major]);
   8.801 +  blk_size[xlblk_major] = NULL;
   8.802 +  if (blksize_size[xlblk_major]) kfree(blksize_size[xlblk_major]);
   8.803 +  blksize_size[xlblk_major] = NULL;
   8.804 +  if (hardsect_size[xlblk_major]) kfree(hardsect_size[xlblk_major]);
   8.805 +  hardsect_size[xlblk_major] = NULL;
   8.806 +
   8.807 +  /*
   8.808 +   *
   8.809 +   * TODO: FOR EACH GENDISK, FREE 
   8.810 +   *
   8.811 +   */
   8.812 +
   8.813 +  if (unregister_blkdev(xlblk_major, "block"))
   8.814 +  {
   8.815 +    printk(KERN_ALERT
   8.816 +	   "XenoLinux Virtual Block Device Driver uninstalled with errors\n");
   8.817 +  }
   8.818 +  else
   8.819 +  {
   8.820 +    printk(KERN_ALERT "XenoLinux Virtual Block Device Driver uninstalled\n");
   8.821 +  }
   8.822 +
   8.823 +  return;
   8.824 +}
   8.825 +
   8.826 +
   8.827 +#ifdef MODULE
   8.828 +module_init(xlblk_init);
   8.829 +module_exit(xlblk_cleanup);
   8.830 +#endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c	Wed Feb 12 18:04:40 2003 +0000
     9.3 @@ -0,0 +1,233 @@
     9.4 +/******************************************************************************
     9.5 + * xenolinux_block_test.c
     9.6 + * 
     9.7 + */
     9.8 +#define EXPORT_SYMTAB
     9.9 +
    9.10 +#include <linux/config.h>
    9.11 +#include <linux/module.h>
    9.12 +
    9.13 +#include <linux/kernel.h>
    9.14 +#include <linux/init.h>
    9.15 +#include <linux/proc_fs.h>
    9.16 +#include <linux/sched.h>
    9.17 +#include <asm/uaccess.h>
    9.18 +#include <linux/slab.h>
    9.19 +#include <linux/string.h>
    9.20 +#include <linux/errno.h>
    9.21 +
    9.22 +#include <asm/hypervisor-ifs/block.h>
    9.23 +#include <asm/hypervisor-ifs/hypervisor-if.h>
    9.24 +
    9.25 +/******************************************************************/
    9.26 +
    9.27 +static struct proc_dir_entry *bdt;
    9.28 +static blk_ring_entry_t meta;
    9.29 +static char * data;
    9.30 +
    9.31 +static int proc_read_bdt(char *page, char **start, off_t off,
    9.32 +			 int count, int *eof, void *data)
    9.33 +{
    9.34 +  switch (meta.operation)
    9.35 +  {
    9.36 +    case XEN_BLOCK_READ :
    9.37 +    case XEN_BLOCK_WRITE :
    9.38 +    {
    9.39 +      return proc_dump_block(page, start, off, count, eof, data);
    9.40 +    }
    9.41 +    case XEN_BLOCK_DEBUG :
    9.42 +    {
    9.43 +      return proc_dump_debug(page, start, off, count, eof, data);
    9.44 +    }
    9.45 +    default :
    9.46 +    {
    9.47 +      printk(KERN_ALERT 
    9.48 +	     "block device test error: unknown operation [%c]\n",
    9.49 +	     meta.operation);
    9.50 +      return -EINVAL;
    9.51 +    }
    9.52 +  }
    9.53 +}
    9.54 +
    9.55 +int proc_dump_debug(char *page, char **start, off_t off,
    9.56 +		    int count, int *eof, void *data)
    9.57 +{
    9.58 +  char header[100];
    9.59 +  char dump[1024];
    9.60 +
    9.61 +  sprintf (header, "Block Device Test: Debug Dump\n\n");
    9.62 +  
    9.63 +  sprintf (dump, "%s\n", meta.buffer);
    9.64 +  
    9.65 +  if (data)
    9.66 +  {
    9.67 +    kfree(data);
    9.68 +  }
    9.69 +
    9.70 +  strncpy (page, dump, count);
    9.71 +  return strlen(page);
    9.72 +}
    9.73 +
    9.74 +int proc_dump_block(char *page, char **start, off_t off,
    9.75 +		    int count, int *eof, void *data)
    9.76 +{
    9.77 +  char header[100];
    9.78 +  char dump[1024];
    9.79 +  char temp[100];
    9.80 +  int loop;
    9.81 +
    9.82 +  sprintf (header, "Block Device Test\n\n%s  blk num: %ld 0x%lx;  size: %d 0x%x;  device: 0x%x\n",
    9.83 +	   meta.operation == XEN_BLOCK_WRITE ? "write" : "read",
    9.84 +	   meta.block_number, meta.block_number,
    9.85 +	   meta.block_size, meta.block_size,
    9.86 +	   meta.device);
    9.87 +  
    9.88 +  sprintf (dump, "%s", header);
    9.89 +
    9.90 +  if (meta.buffer)
    9.91 +  {
    9.92 +    for (loop = 0; loop < 100; loop++)
    9.93 +    {
    9.94 +      int i = meta.buffer[loop];
    9.95 +    
    9.96 +      if (loop % 8 == 0)
    9.97 +      {
    9.98 +	sprintf (temp, "[%2d] ", loop);
    9.99 +	strcat(dump, temp);
   9.100 +      }
   9.101 +      else if (loop % 2 == 0)
   9.102 +      {
   9.103 +	strcat(dump, " ");
   9.104 +      }
   9.105 +
   9.106 +      sprintf (temp, " 0x%02x", i & 255);
   9.107 +      strcat(dump, temp);
   9.108 +      if ((loop + 1) % 8 == 0)
   9.109 +      {
   9.110 +	strcat(dump, "\n");
   9.111 +      }
   9.112 +    }
   9.113 +    strcat(dump, "\n\n");
   9.114 +  }
   9.115 +  
   9.116 +  if (data)
   9.117 +  {
   9.118 +    kfree(data);
   9.119 +  }
   9.120 +
   9.121 +  strncpy (page, dump, count);
   9.122 +  return strlen(page);
   9.123 +}
   9.124 +
   9.125 +int proc_write_bdt(struct file *file, const char *buffer,
   9.126 +		   unsigned long count, void *data)
   9.127 +{
   9.128 +  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
   9.129 +  char  opcode;
   9.130 +  int  block_number = 0;
   9.131 +  int  block_size = 0;
   9.132 +  int  device = 0;
   9.133 +  int  mode;
   9.134 +
   9.135 +  if (copy_from_user(local, buffer, count))
   9.136 +  {
   9.137 +    return -EFAULT;
   9.138 +  }
   9.139 +  local[count] = '\0';
   9.140 +
   9.141 +  sscanf(local, "%c %i %i %i", 
   9.142 +	 &opcode, &block_number, &block_size, &device);
   9.143 +
   9.144 +  if (opcode == 'r' || opcode == 'R')
   9.145 +  {
   9.146 +    meta.operation = XEN_BLOCK_READ;
   9.147 +  }
   9.148 +  else if (opcode == 'w' || opcode == 'W')
   9.149 +  {
   9.150 +    meta.operation = XEN_BLOCK_WRITE;
   9.151 +  }
   9.152 +  else if (opcode == 'd' || opcode == 'D')
   9.153 +  {
   9.154 +    meta.operation = XEN_BLOCK_DEBUG;
   9.155 +    block_size = 10000;
   9.156 +  }
   9.157 +  else
   9.158 +  {
   9.159 +    printk(KERN_ALERT 
   9.160 +	   "block device test error: unknown opcode [%c]\n", opcode);
   9.161 +    return -EINVAL;
   9.162 +  }
   9.163 +
   9.164 +  if (opcode == 'r' || opcode == 'w' ||
   9.165 +      opcode == 'd' || opcode == 'D')
   9.166 +  {
   9.167 +    mode = XEN_BLOCK_SYNC;
   9.168 +  }
   9.169 +  else /* (opcode == 'R' || opcode == 'W') */
   9.170 +  {
   9.171 +    mode = XEN_BLOCK_ASYNC;
   9.172 +  }
   9.173 +
   9.174 +  if (data)
   9.175 +  {
   9.176 +    kfree(data);
   9.177 +  }
   9.178 +  data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
   9.179 +  if (data == NULL)
   9.180 +  {
   9.181 +    kfree(local);
   9.182 +    return -ENOMEM;
   9.183 +  }
   9.184 +
   9.185 +  meta.block_number = block_number;
   9.186 +  meta.block_size   = block_size;
   9.187 +  meta.device       = device;
   9.188 +  meta.buffer       = data;
   9.189 +
   9.190 +  /* submit request */
   9.191 +  hypervisor_request(0, meta.operation, meta.buffer, 
   9.192 +		     meta.block_number, meta.block_size,
   9.193 +		     meta.device, mode);
   9.194 +
   9.195 +  kfree(local);
   9.196 +  return count;
   9.197 +}
   9.198 +			 
   9.199 +
   9.200 +static int __init init_module(void)
   9.201 +{
   9.202 +  int return_value = 0;
   9.203 +
   9.204 +  /* create proc entry */
   9.205 +  bdt = create_proc_entry("bdt", 0644, NULL);
   9.206 +  if (bdt == NULL)
   9.207 +  {
   9.208 +    return_value = -ENOMEM;
   9.209 +    goto error;
   9.210 +  }
   9.211 +  bdt->data       = NULL;
   9.212 +  bdt->read_proc  = proc_read_bdt;
   9.213 +  bdt->write_proc = proc_write_bdt;
   9.214 +  bdt->owner      = THIS_MODULE;
   9.215 +
   9.216 +  memset(&meta, 0, sizeof(meta));
   9.217 +  
   9.218 +  /* success */
   9.219 +  printk(KERN_ALERT "XenoLinux Block Device Test installed\n");
   9.220 +  return 0;
   9.221 +
   9.222 + error:
   9.223 +  return return_value;
   9.224 +}
   9.225 +
   9.226 +static void __exit cleanup_module(void)
   9.227 +{
   9.228 +  if (data)
   9.229 +  {
   9.230 +    kfree(data);
   9.231 +  }
   9.232 +  printk(KERN_ALERT "XenoLinux Block Device Test uninstalled\n");
   9.233 +}
   9.234 +
   9.235 +module_init(init_module);
   9.236 +module_exit(cleanup_module);
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_block.c	Wed Feb 12 18:04:40 2003 +0000
    10.3 @@ -0,0 +1,27 @@
    10.4 +/*
    10.5 + * domain 0 block driver interface
    10.6 + *
    10.7 + */
    10.8 +
    10.9 +#include <linux/config.h>
   10.10 +#include <linux/module.h>
   10.11 +#include <linux/kernel.h>
   10.12 +#include <linux/sched.h>
   10.13 +
   10.14 +static int __init init_module(void)
   10.15 +{
   10.16 +  request_module("xl_block");
   10.17 +  printk("Successfully installed domain 0 block interface\n");
   10.18 +
   10.19 +
   10.20 +  return 0;
   10.21 +}
   10.22 +
   10.23 +static void __exit cleanup_module(void)
   10.24 +{
   10.25 +  printk("Successfully de-installed domain-0 block interface\n");
   10.26 +  return 0;
   10.27 +}
   10.28 +
   10.29 +module_init(init_module);
   10.30 +module_exit(cleanup_module);
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xenolinux-2.4.16-sparse/drivers/block/Config.in	Wed Feb 12 18:04:40 2003 +0000
    11.3 @@ -0,0 +1,51 @@
    11.4 +#
    11.5 +# Block device driver configuration
    11.6 +#
    11.7 +mainmenu_option next_comment
    11.8 +comment 'Block devices'
    11.9 +
   11.10 +tristate 'Normal PC floppy disk support' CONFIG_BLK_DEV_FD
   11.11 +if [ "$CONFIG_AMIGA" = "y" ]; then
   11.12 +   tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
   11.13 +fi
   11.14 +if [ "$CONFIG_ATARI" = "y" ]; then
   11.15 +   tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
   11.16 +fi
   11.17 +if [ "$CONFIG_MAC" = "y" ]; then
   11.18 +   dep_bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP $CONFIG_EXPERIMENTAL
   11.19 +fi
   11.20 +if [ "$CONFIG_MCA" = "y" ]; then
   11.21 +   tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2
   11.22 +fi
   11.23 +if [ "$CONFIG_ZORRO" = "y" ]; then
   11.24 +   tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
   11.25 +fi
   11.26 +if [ "$CONFIG_ATARI" = "y" ]; then
   11.27 +   tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
   11.28 +   if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
   11.29 +      comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
   11.30 +      bool '  Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
   11.31 +      tristate '  Atari SLM laser printer support' CONFIG_ATARI_SLM
   11.32 +   fi
   11.33 +fi
   11.34 +dep_tristate 'XT hard disk support' CONFIG_BLK_DEV_XD $CONFIG_ISA
   11.35 +dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT
   11.36 +if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   11.37 +   source drivers/block/paride/Config.in
   11.38 +fi
   11.39 +dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
   11.40 +dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
   11.41 +dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
   11.42 +
   11.43 +tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
   11.44 +dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
   11.45 +
   11.46 +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
   11.47 +if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
   11.48 +   int '  Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
   11.49 +fi
   11.50 +dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
   11.51 +
   11.52 +bool 'XenoLinux virtual block device support' CONFIG_XENOLINUX_BLOCK
   11.53 +
   11.54 +endmenu
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xenolinux-2.4.16-sparse/fs/partitions/check.c	Wed Feb 12 18:04:40 2003 +0000
    12.3 @@ -0,0 +1,443 @@
    12.4 +/*
    12.5 + *  Code extracted from drivers/block/genhd.c
    12.6 + *  Copyright (C) 1991-1998  Linus Torvalds
    12.7 + *  Re-organised Feb 1998 Russell King
    12.8 + *
    12.9 + *  We now have independent partition support from the
   12.10 + *  block drivers, which allows all the partition code to
   12.11 + *  be grouped in one location, and it to be mostly self
   12.12 + *  contained.
   12.13 + *
   12.14 + *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
   12.15 + */
   12.16 +
   12.17 +#include <linux/config.h>
   12.18 +#include <linux/fs.h>
   12.19 +#include <linux/genhd.h>
   12.20 +#include <linux/kernel.h>
   12.21 +#include <linux/major.h>
   12.22 +#include <linux/blk.h>
   12.23 +#include <linux/init.h>
   12.24 +#include <linux/raid/md.h>
   12.25 +
   12.26 +#include "check.h"
   12.27 +
   12.28 +#include "acorn.h"
   12.29 +#include "amiga.h"
   12.30 +#include "atari.h"
   12.31 +#include "ldm.h"
   12.32 +#include "mac.h"
   12.33 +#include "msdos.h"
   12.34 +#include "osf.h"
   12.35 +#include "sgi.h"
   12.36 +#include "sun.h"
   12.37 +#include "ibm.h"
   12.38 +#include "ultrix.h"
   12.39 +
   12.40 +extern int *blk_size[];
   12.41 +
   12.42 +#define CHECK_DEBUG 0
   12.43 +
   12.44 +int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
   12.45 +
   12.46 +static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
   12.47 +#ifdef CONFIG_ACORN_PARTITION
   12.48 +	acorn_partition,
   12.49 +#endif
   12.50 +#ifdef CONFIG_LDM_PARTITION
   12.51 +	ldm_partition,		/* this must come before msdos */
   12.52 +#endif
   12.53 +#ifdef CONFIG_MSDOS_PARTITION
   12.54 +	msdos_partition,
   12.55 +#endif
   12.56 +#ifdef CONFIG_OSF_PARTITION
   12.57 +	osf_partition,
   12.58 +#endif
   12.59 +#ifdef CONFIG_SUN_PARTITION
   12.60 +	sun_partition,
   12.61 +#endif
   12.62 +#ifdef CONFIG_AMIGA_PARTITION
   12.63 +	amiga_partition,
   12.64 +#endif
   12.65 +#ifdef CONFIG_ATARI_PARTITION
   12.66 +	atari_partition,
   12.67 +#endif
   12.68 +#ifdef CONFIG_MAC_PARTITION
   12.69 +	mac_partition,
   12.70 +#endif
   12.71 +#ifdef CONFIG_SGI_PARTITION
   12.72 +	sgi_partition,
   12.73 +#endif
   12.74 +#ifdef CONFIG_ULTRIX_PARTITION
   12.75 +	ultrix_partition,
   12.76 +#endif
   12.77 +#ifdef CONFIG_IBM_PARTITION
   12.78 +	ibm_partition,
   12.79 +#endif
   12.80 +	NULL
   12.81 +};
   12.82 +
   12.83 +/*
   12.84 + *	This is ucking fugly but its probably the best thing for 2.4.x
   12.85 + *	Take it as a clear reminder than we should put the device name
   12.86 + *	generation in the object kdev_t points to in 2.5.
   12.87 + */
   12.88 + 
   12.89 +#ifdef CONFIG_ARCH_S390
   12.90 +int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
   12.91 +EXPORT_SYMBOL(genhd_dasd_name);
   12.92 +#endif
   12.93 +
   12.94 +/*
   12.95 + * disk_name() is used by partition check code and the md driver.
   12.96 + * It formats the devicename of the indicated disk into
   12.97 + * the supplied buffer (of size at least 32), and returns
   12.98 + * a pointer to that same buffer (for convenience).
   12.99 + */
  12.100 +
  12.101 +char *disk_name (struct gendisk *hd, int minor, char *buf)
  12.102 +{
  12.103 +	const char *maj = hd->major_name;
  12.104 +	unsigned int unit = (minor >> hd->minor_shift);
  12.105 +	unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
  12.106 +
  12.107 +	if ((unit < hd->nr_real) && hd->part[minor].de) {
  12.108 +		int pos;
  12.109 +
  12.110 +		pos = devfs_generate_path (hd->part[minor].de, buf, 64);
  12.111 +		if (pos >= 0)
  12.112 +			return buf + pos;
  12.113 +	}
  12.114 +
  12.115 +#ifdef CONFIG_ARCH_S390
  12.116 +	if (genhd_dasd_name
  12.117 +	    && genhd_dasd_name (buf, unit, part, hd) == 0)
  12.118 +		return buf;
  12.119 +#endif
  12.120 +	/*
  12.121 +	 * IDE devices use multiple major numbers, but the drives
  12.122 +	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
  12.123 +	 * This requires special handling here.
  12.124 +	 */
  12.125 +	switch (hd->major) {
  12.126 +		case IDE9_MAJOR:
  12.127 +			unit += 2;
  12.128 +		case IDE8_MAJOR:
  12.129 +			unit += 2;
  12.130 +		case IDE7_MAJOR:
  12.131 +			unit += 2;
  12.132 +		case IDE6_MAJOR:
  12.133 +			unit += 2;
  12.134 +		case IDE5_MAJOR:
  12.135 +			unit += 2;
  12.136 +		case IDE4_MAJOR:
  12.137 +			unit += 2;
  12.138 +		case IDE3_MAJOR:
  12.139 +			unit += 2;
  12.140 +		case IDE2_MAJOR:
  12.141 +			unit += 2;
  12.142 +		case IDE1_MAJOR:
  12.143 +			unit += 2;
  12.144 +		case IDE0_MAJOR:
  12.145 +			maj = "hd";
  12.146 +			break;
  12.147 +		case MD_MAJOR:
  12.148 +			sprintf(buf, "%s%d", maj, unit);
  12.149 +			return buf;
  12.150 +	}
  12.151 +	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
  12.152 +		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
  12.153 +		if (unit+'a' > 'z') {
  12.154 +			unit -= 26;
  12.155 +			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
  12.156 +			if (part)
  12.157 +				sprintf(buf + 4, "%d", part);
  12.158 +			return buf;
  12.159 +		}
  12.160 +	}
  12.161 +	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
  12.162 +		int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
  12.163 + 		if (part == 0)
  12.164 + 			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  12.165 + 		else
  12.166 + 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  12.167 + 		return buf;
  12.168 + 	}
  12.169 +	if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
  12.170 +                int ctlr = hd->major - COMPAQ_CISS_MAJOR;
  12.171 +                if (part == 0)
  12.172 +                        sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  12.173 +                else
  12.174 +                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  12.175 +                return buf;
  12.176 +	}
  12.177 +	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
  12.178 +		int ctlr = hd->major - DAC960_MAJOR;
  12.179 + 		if (part == 0)
  12.180 + 			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  12.181 + 		else
  12.182 + 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  12.183 + 		return buf;
  12.184 + 	}
  12.185 +	if (hd->major == ATARAID_MAJOR) {
  12.186 +		int disk = minor >> hd->minor_shift;
  12.187 +		int part = minor & (( 1 << hd->minor_shift) - 1);
  12.188 +		if (part == 0)
  12.189 +			sprintf(buf, "%s/d%d", maj, disk);
  12.190 +		else
  12.191 +			sprintf(buf, "%s/d%dp%d", maj, disk, part);
  12.192 +		return buf;
  12.193 +	}
  12.194 +	if (part)
  12.195 +		sprintf(buf, "%s%c%d", maj, unit+'a', part);
  12.196 +	else
  12.197 +		sprintf(buf, "%s%c", maj, unit+'a');
  12.198 +	return buf;
  12.199 +}
  12.200 +
  12.201 +/*
  12.202 + * Add a partitions details to the devices partition description.
  12.203 + */
  12.204 +void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
  12.205 +{
  12.206 +#ifndef CONFIG_DEVFS_FS
  12.207 +	char buf[40];
  12.208 +#endif
  12.209 +
  12.210 +	hd->part[minor].start_sect = start;
  12.211 +	hd->part[minor].nr_sects   = size;
  12.212 +#ifdef CONFIG_DEVFS_FS
  12.213 +	printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  12.214 +#else
  12.215 +	if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
  12.216 +	    (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
  12.217 +		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  12.218 +	else
  12.219 +		printk(" %s", disk_name(hd, minor, buf));
  12.220 +#endif
  12.221 +}
  12.222 +
  12.223 +static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
  12.224 +{
  12.225 +	devfs_handle_t de = NULL;
  12.226 +	static int first_time = 1;
  12.227 +	unsigned long first_sector;
  12.228 +	struct block_device *bdev;
  12.229 +	char buf[64];
  12.230 +	int i;
  12.231 +
  12.232 +  if (CHECK_DEBUG) printk (KERN_ALERT "check.c::check_partition\n");
  12.233 +
  12.234 +	if (first_time)
  12.235 +		printk(KERN_INFO "Partition check:\n");
  12.236 +	first_time = 0;
  12.237 +	first_sector = hd->part[MINOR(dev)].start_sect;
  12.238 +
  12.239 +	/*
  12.240 +	 * This is a kludge to allow the partition check to be
  12.241 +	 * skipped for specific drives (e.g. IDE CD-ROM drives)
  12.242 +	 */
  12.243 +	if ((int)first_sector == -1) {
  12.244 +		hd->part[MINOR(dev)].start_sect = 0;
  12.245 +		return;
  12.246 +	}
  12.247 +
  12.248 +	if (hd->de_arr)
  12.249 +		de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
  12.250 +	i = devfs_generate_path (de, buf, sizeof buf);
  12.251 +	if (i >= 0)
  12.252 +		printk(KERN_INFO " /dev/%s:", buf + i);
  12.253 +	else
  12.254 +		printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
  12.255 +	bdev = bdget(kdev_t_to_nr(dev));
  12.256 +	bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
  12.257 +	bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
  12.258 +	for (i = 0; check_part[i]; i++) {
  12.259 +		int res;
  12.260 +		res = check_part[i](hd, bdev, first_sector, first_part_minor);
  12.261 +		if (res) {
  12.262 +			if (res < 0 &&  warn_no_part)
  12.263 +				printk(" unable to read partition table\n");
  12.264 +			goto setup_devfs;
  12.265 +		}
  12.266 +	}
  12.267 +
  12.268 +	printk(" unknown partition table\n");
  12.269 +setup_devfs:
  12.270 +	invalidate_bdev(bdev, 1);
  12.271 +	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  12.272 +	bdput(bdev);
  12.273 +	i = first_part_minor - 1;
  12.274 +	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
  12.275 +}
  12.276 +
  12.277 +#ifdef CONFIG_DEVFS_FS
  12.278 +static void devfs_register_partition (struct gendisk *dev, int minor, int part)
  12.279 +{
  12.280 +	int devnum = minor >> dev->minor_shift;
  12.281 +	devfs_handle_t dir;
  12.282 +	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  12.283 +	char devname[16];
  12.284 +
  12.285 +	if (dev->part[minor + part].de) return;
  12.286 +	dir = devfs_get_parent (dev->part[minor].de);
  12.287 +	if (!dir) return;
  12.288 +	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  12.289 +		devfs_flags |= DEVFS_FL_REMOVABLE;
  12.290 +	sprintf (devname, "part%d", part);
  12.291 +	dev->part[minor + part].de =
  12.292 +	    devfs_register (dir, devname, devfs_flags,
  12.293 +			    dev->major, minor + part,
  12.294 +			    S_IFBLK | S_IRUSR | S_IWUSR,
  12.295 +			    dev->fops, NULL);
  12.296 +}
  12.297 +
  12.298 +static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
  12.299 +
  12.300 +static void devfs_register_disc (struct gendisk *dev, int minor)
  12.301 +{
  12.302 +	int pos = 0;
  12.303 +	int devnum = minor >> dev->minor_shift;
  12.304 +	devfs_handle_t dir, slave;
  12.305 +	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  12.306 +	char dirname[64], symlink[16];
  12.307 +	static devfs_handle_t devfs_handle;
  12.308 +
  12.309 +	if (dev->part[minor].de) return;
  12.310 +	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  12.311 +		devfs_flags |= DEVFS_FL_REMOVABLE;
  12.312 +	if (dev->de_arr) {
  12.313 +		dir = dev->de_arr[devnum];
  12.314 +		if (!dir)  /*  Aware driver wants to block disc management  */
  12.315 +			return;
  12.316 +		pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
  12.317 +		if (pos < 0) return;
  12.318 +		strncpy (dirname + pos, "../", 3);
  12.319 +	}
  12.320 +	else {
  12.321 +		/*  Unaware driver: construct "real" directory  */
  12.322 +		sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
  12.323 +		dir = devfs_mk_dir (NULL, dirname + 3, NULL);
  12.324 +	}
  12.325 +	if (!devfs_handle)
  12.326 +		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
  12.327 +	dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
  12.328 +	sprintf (symlink, "disc%d", dev->part[minor].number);
  12.329 +	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
  12.330 +			  dirname + pos, &slave, NULL);
  12.331 +	dev->part[minor].de =
  12.332 +	    devfs_register (dir, "disc", devfs_flags, dev->major, minor,
  12.333 +			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
  12.334 +	devfs_auto_unregister (dev->part[minor].de, slave);
  12.335 +	if (!dev->de_arr)
  12.336 +		devfs_auto_unregister (slave, dir);
  12.337 +}
  12.338 +#endif  /*  CONFIG_DEVFS_FS  */
  12.339 +
  12.340 +void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
  12.341 +{
  12.342 +#ifdef CONFIG_DEVFS_FS
  12.343 +	int part;
  12.344 +
  12.345 +	if (!unregister)
  12.346 +		devfs_register_disc (dev, minor);
  12.347 +	for (part = 1; part < dev->max_p; part++) {
  12.348 +		if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
  12.349 +			devfs_unregister (dev->part[part + minor].de);
  12.350 +			dev->part[part + minor].de = NULL;
  12.351 +			continue;
  12.352 +		}
  12.353 +		devfs_register_partition (dev, minor, part);
  12.354 +	}
  12.355 +	if (unregister) {
  12.356 +		devfs_unregister (dev->part[minor].de);
  12.357 +		dev->part[minor].de = NULL;
  12.358 +		devfs_dealloc_unique_number (&disc_numspace,
  12.359 +					     dev->part[minor].number);
  12.360 +	}
  12.361 +#endif  /*  CONFIG_DEVFS_FS  */
  12.362 +}
  12.363 +
  12.364 +/*
  12.365 + * This function will re-read the partition tables for a given device,
  12.366 + * and set things back up again.  There are some important caveats,
  12.367 + * however.  You must ensure that no one is using the device, and no one
  12.368 + * can start using the device while this function is being executed.
  12.369 + *
  12.370 + * Much of the cleanup from the old partition tables should have already been
  12.371 + * done
  12.372 + */
  12.373 +
  12.374 +void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
  12.375 +	struct block_device_operations *ops, long size)
  12.376 +{
  12.377 +  if (CHECK_DEBUG)
  12.378 +  {
  12.379 +    if (gdev != NULL)
  12.380 +    printk (KERN_ALERT 
  12.381 +	    "check.c::register_disk gdev:%p dev:%d min:%u ops:%p sz:%ld\n",
  12.382 +	    gdev, dev, minors, ops, size);
  12.383 +  }
  12.384 +
  12.385 +	if (!gdev)
  12.386 +		return;
  12.387 +
  12.388 +	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
  12.389 +}
  12.390 +
  12.391 +void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
  12.392 +{
  12.393 +	int i;
  12.394 +	int first_minor	= drive << dev->minor_shift;
  12.395 +	int end_minor	= first_minor + dev->max_p;
  12.396 +
  12.397 +  if (CHECK_DEBUG) printk (KERN_ALERT "check.c::grok_partitions\n");
  12.398 +
  12.399 +	if(!dev->sizes)
  12.400 +		blk_size[dev->major] = NULL;
  12.401 +
  12.402 +	dev->part[first_minor].nr_sects = size;
  12.403 +	/* No such device or no minors to use for partitions */
  12.404 +	if (!size || minors == 1)
  12.405 +		return;
  12.406 +
  12.407 +	if (dev->sizes) {
  12.408 +		dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
  12.409 +		for (i = first_minor + 1; i < end_minor; i++)
  12.410 +			dev->sizes[i] = 0;
  12.411 +	}
  12.412 +	blk_size[dev->major] = dev->sizes;
  12.413 +	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
  12.414 +
  12.415 + 	/*
  12.416 + 	 * We need to set the sizes array before we will be able to access
  12.417 + 	 * any of the partitions on this device.
  12.418 + 	 */
  12.419 +	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
  12.420 +		for (i = first_minor; i < end_minor; i++)
  12.421 +			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
  12.422 +	}
  12.423 +}
  12.424 +
  12.425 +unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
  12.426 +{
  12.427 +	struct address_space *mapping = bdev->bd_inode->i_mapping;
  12.428 +	int sect = PAGE_CACHE_SIZE / 512;
  12.429 +	struct page *page;
  12.430 +
  12.431 +	page = read_cache_page(mapping, n/sect,
  12.432 +			(filler_t *)mapping->a_ops->readpage, NULL);
  12.433 +	if (!IS_ERR(page)) {
  12.434 +		wait_on_page(page);
  12.435 +		if (!Page_Uptodate(page))
  12.436 +			goto fail;
  12.437 +		if (PageError(page))
  12.438 +			goto fail;
  12.439 +		p->v = page;
  12.440 +		return (unsigned char *)page_address(page) + 512 * (n % sect);
  12.441 +fail:
  12.442 +		page_cache_release(page);
  12.443 +	}
  12.444 +	p->v = NULL;
  12.445 +	return NULL;
  12.446 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xenolinux-2.4.16-sparse/fs/partitions/msdos.c	Wed Feb 12 18:04:40 2003 +0000
    13.3 @@ -0,0 +1,642 @@
    13.4 +/*
    13.5 + *  fs/partitions/msdos.c
    13.6 + *
    13.7 + *  Code extracted from drivers/block/genhd.c
    13.8 + *  Copyright (C) 1991-1998  Linus Torvalds
    13.9 + *
   13.10 + *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
   13.11 + *  in the early extended-partition checks and added DM partitions
   13.12 + *
   13.13 + *  Support for DiskManager v6.0x added by Mark Lord,
   13.14 + *  with information provided by OnTrack.  This now works for linux fdisk
   13.15 + *  and LILO, as well as loadlin and bootln.  Note that disks other than
   13.16 + *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
   13.17 + *
   13.18 + *  More flexible handling of extended partitions - aeb, 950831
   13.19 + *
   13.20 + *  Check partition table on IDE disks for common CHS translations
   13.21 + *
   13.22 + *  Re-organised Feb 1998 Russell King
   13.23 + */
   13.24 +
   13.25 +#include <linux/config.h>
   13.26 +#include <linux/fs.h>
   13.27 +#include <linux/genhd.h>
   13.28 +#include <linux/kernel.h>
   13.29 +#include <linux/major.h>
   13.30 +#include <linux/string.h>
   13.31 +#include <linux/blk.h>
   13.32 +
   13.33 +#ifdef CONFIG_BLK_DEV_IDE
   13.34 +#include <linux/ide.h>	/* IDE xlate */
   13.35 +#endif /* CONFIG_BLK_DEV_IDE */
   13.36 +
   13.37 +#define MSDOS_DEBUG 0
   13.38 +
   13.39 +#include <asm/system.h>
   13.40 +
   13.41 +#include "check.h"
   13.42 +#include "msdos.h"
   13.43 +
   13.44 +#if CONFIG_BLK_DEV_MD
   13.45 +extern void md_autodetect_dev(kdev_t dev);
   13.46 +#endif
   13.47 +
   13.48 +/*
   13.49 + * Many architectures don't like unaligned accesses, which is
   13.50 + * frequently the case with the nr_sects and start_sect partition
   13.51 + * table entries.
   13.52 + */
   13.53 +#include <asm/unaligned.h>
   13.54 +
   13.55 +#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
   13.56 +#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
   13.57 +				get_unaligned(&p->nr_sects);	\
   13.58 +				le32_to_cpu(__a); \
   13.59 +			})
   13.60 +
   13.61 +#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
   13.62 +				get_unaligned(&p->start_sect);	\
   13.63 +				le32_to_cpu(__a); \
   13.64 +			})
   13.65 +
   13.66 +static inline int is_extended_partition(struct partition *p)
   13.67 +{
   13.68 +	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
   13.69 +		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
   13.70 +		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
   13.71 +}
   13.72 +
   13.73 +/*
   13.74 + * partition_name() formats the short partition name into the supplied
   13.75 + * buffer, and returns a pointer to that buffer.
   13.76 + * Used by several partition types which makes conditional inclusion messy,
   13.77 + * use __attribute__ ((unused)) instead.
   13.78 + */
   13.79 +static char __attribute__ ((unused))
   13.80 +	*partition_name (struct gendisk *hd, int minor, char *buf)
   13.81 +{
   13.82 +#ifdef CONFIG_DEVFS_FS
   13.83 +	sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
   13.84 +	return buf;
   13.85 +#else
   13.86 +	return disk_name(hd, minor, buf);
   13.87 +#endif
   13.88 +}
   13.89 +
   13.90 +#define MSDOS_LABEL_MAGIC1	0x55
   13.91 +#define MSDOS_LABEL_MAGIC2	0xAA
   13.92 +
   13.93 +static inline int
   13.94 +msdos_magic_present(unsigned char *p)
   13.95 +{
   13.96 +	return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
   13.97 +}
   13.98 +
   13.99 +/*
  13.100 + * Create devices for each logical partition in an extended partition.
  13.101 + * The logical partitions form a linked list, with each entry being
  13.102 + * a partition table with two entries.  The first entry
  13.103 + * is the real data partition (with a start relative to the partition
  13.104 + * table start).  The second is a pointer to the next logical partition
  13.105 + * (with a start relative to the entire extended partition).
  13.106 + * We do not create a Linux partition for the partition tables, but
  13.107 + * only for the actual data partitions.
  13.108 + */
  13.109 +
  13.110 +static void extended_partition(struct gendisk *hd, struct block_device *bdev,
  13.111 +			int minor, unsigned long first_size, int *current_minor)
  13.112 +{
  13.113 +	struct partition *p;
  13.114 +	Sector sect;
  13.115 +	unsigned char *data;
  13.116 +	unsigned long first_sector, this_sector, this_size;
  13.117 +	int mask = (1 << hd->minor_shift) - 1;
  13.118 +	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  13.119 +	int loopct = 0;		/* number of links followed
  13.120 +				   without finding a data partition */
  13.121 +	int i;
  13.122 +
  13.123 +	this_sector = first_sector = hd->part[minor].start_sect;
  13.124 +	this_size = first_size;
  13.125 +
  13.126 +	while (1) {
  13.127 +		if (++loopct > 100)
  13.128 +			return;
  13.129 +		if ((*current_minor & mask) == 0)
  13.130 +			return;
  13.131 +		data = read_dev_sector(bdev, this_sector, &sect);
  13.132 +		if (!data)
  13.133 +			return;
  13.134 +
  13.135 +		if (!msdos_magic_present(data + 510))
  13.136 +			goto done; 
  13.137 +
  13.138 +		p = (struct partition *) (data + 0x1be);
  13.139 +
  13.140 +		/*
  13.141 +		 * Usually, the first entry is the real data partition,
  13.142 +		 * the 2nd entry is the next extended partition, or empty,
  13.143 +		 * and the 3rd and 4th entries are unused.
  13.144 +		 * However, DRDOS sometimes has the extended partition as
  13.145 +		 * the first entry (when the data partition is empty),
  13.146 +		 * and OS/2 seems to use all four entries.
  13.147 +		 */
  13.148 +
  13.149 +		/* 
  13.150 +		 * First process the data partition(s)
  13.151 +		 */
  13.152 +		for (i=0; i<4; i++, p++) {
  13.153 +			unsigned long offs, size, next;
  13.154 +			if (!NR_SECTS(p) || is_extended_partition(p))
  13.155 +				continue;
  13.156 +
  13.157 +			/* Check the 3rd and 4th entries -
  13.158 +			   these sometimes contain random garbage */
  13.159 +			offs = START_SECT(p)*sector_size;
  13.160 +			size = NR_SECTS(p)*sector_size;
  13.161 +			next = this_sector + offs;
  13.162 +			if (i >= 2) {
  13.163 +				if (offs + size > this_size)
  13.164 +					continue;
  13.165 +				if (next < first_sector)
  13.166 +					continue;
  13.167 +				if (next + size > first_sector + first_size)
  13.168 +					continue;
  13.169 +			}
  13.170 +
  13.171 +			add_gd_partition(hd, *current_minor, next, size);
  13.172 +#if CONFIG_BLK_DEV_MD
  13.173 +			if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  13.174 +			    md_autodetect_dev(MKDEV(hd->major,*current_minor));
  13.175 +			}
  13.176 +#endif
  13.177 +
  13.178 +			(*current_minor)++;
  13.179 +			loopct = 0;
  13.180 +			if ((*current_minor & mask) == 0)
  13.181 +				goto done;
  13.182 +		}
  13.183 +		/*
  13.184 +		 * Next, process the (first) extended partition, if present.
  13.185 +		 * (So far, there seems to be no reason to make
  13.186 +		 *  extended_partition()  recursive and allow a tree
  13.187 +		 *  of extended partitions.)
  13.188 +		 * It should be a link to the next logical partition.
  13.189 +		 * Create a minor for this just long enough to get the next
  13.190 +		 * partition table.  The minor will be reused for the next
  13.191 +		 * data partition.
  13.192 +		 */
  13.193 +		p -= 4;
  13.194 +		for (i=0; i<4; i++, p++)
  13.195 +			if (NR_SECTS(p) && is_extended_partition(p))
  13.196 +				break;
  13.197 +		if (i == 4)
  13.198 +			goto done;	 /* nothing left to do */
  13.199 +
  13.200 +		this_sector = first_sector + START_SECT(p) * sector_size;
  13.201 +		this_size = NR_SECTS(p) * sector_size;
  13.202 +		minor = *current_minor;
  13.203 +		put_dev_sector(sect);
  13.204 +	}
  13.205 +done:
  13.206 +	put_dev_sector(sect);
  13.207 +}
  13.208 +
  13.209 +/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
  13.210 +   indicates linux swap.  Be careful before believing this is Solaris. */
  13.211 +
  13.212 +static void
  13.213 +solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
  13.214 +		int minor, int *current_minor)
  13.215 +{
  13.216 +
  13.217 +#ifdef CONFIG_SOLARIS_X86_PARTITION
  13.218 +	long offset = hd->part[minor].start_sect;
  13.219 +	Sector sect;
  13.220 +	struct solaris_x86_vtoc *v;
  13.221 +	struct solaris_x86_slice *s;
  13.222 +	int mask = (1 << hd->minor_shift) - 1;
  13.223 +	int i;
  13.224 +	char buf[40];
  13.225 +
  13.226 +	v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
  13.227 +	if (!v)
  13.228 +		return;
  13.229 +	if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
  13.230 +		put_dev_sector(sect);
  13.231 +		return;
  13.232 +	}
  13.233 +	printk(" %s: <solaris:", partition_name(hd, minor, buf));
  13.234 +	if (le32_to_cpu(v->v_version) != 1) {
  13.235 +		printk("  cannot handle version %d vtoc>\n",
  13.236 +			le32_to_cpu(v->v_version));
  13.237 +		put_dev_sector(sect);
  13.238 +		return;
  13.239 +	}
  13.240 +	for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
  13.241 +		if ((*current_minor & mask) == 0)
  13.242 +			break;
  13.243 +		s = &v->v_slice[i];
  13.244 +
  13.245 +		if (s->s_size == 0)
  13.246 +			continue;
  13.247 +		printk(" [s%d]", i);
  13.248 +		/* solaris partitions are relative to current MS-DOS
  13.249 +		 * one but add_gd_partition starts relative to sector
  13.250 +		 * zero of the disk.  Therefore, must add the offset
  13.251 +		 * of the current partition */
  13.252 +		add_gd_partition(hd, *current_minor,
  13.253 +				 le32_to_cpu(s->s_start)+offset,
  13.254 +				 le32_to_cpu(s->s_size));
  13.255 +		(*current_minor)++;
  13.256 +	}
  13.257 +	put_dev_sector(sect);
  13.258 +	printk(" >\n");
  13.259 +#endif
  13.260 +}
  13.261 +
  13.262 +#ifdef CONFIG_BSD_DISKLABEL
  13.263 +static void
  13.264 +check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
  13.265 +	int minor, int *current_minor)
  13.266 +{
  13.267 +	struct hd_struct *lin_p;
  13.268 +		/* check relative position of partitions.  */
  13.269 +	for (lin_p = hd->part + 1 + minor;
  13.270 +	     lin_p - hd->part - minor < *current_minor; lin_p++) {
  13.271 +			/* no relationship -> try again */
  13.272 +		if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
  13.273 +		    lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
  13.274 +			continue;	
  13.275 +			/* equal -> no need to add */
  13.276 +		if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) && 
  13.277 +			lin_p->nr_sects == le32_to_cpu(bsd_p->p_size)) 
  13.278 +			return;
  13.279 +			/* bsd living within dos partition */
  13.280 +		if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect 
  13.281 +			+ lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size)) {
  13.282 +#ifdef DEBUG_BSD_DISKLABEL
  13.283 +			printk("w: %d %ld+%ld,%d+%d", 
  13.284 +				lin_p - hd->part, 
  13.285 +				lin_p->start_sect, lin_p->nr_sects, 
  13.286 +				le32_to_cpu(bsd_p->p_offset),
  13.287 +				le32_to_cpu(bsd_p->p_size));
  13.288 +#endif
  13.289 +			break;
  13.290 +		}
  13.291 +	 /* ouch: bsd and linux overlap. Don't even try for that partition */
  13.292 +#ifdef DEBUG_BSD_DISKLABEL
  13.293 +		printk("???: %d %ld+%ld,%d+%d",
  13.294 +			lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
  13.295 +			le32_to_cpu(bsd_p->p_offset), le32_to_cpu(bsd_p->p_size));
  13.296 +#endif
  13.297 +		printk("???");
  13.298 +		return;
  13.299 +	} /* if the bsd partition is not currently known to linux, we end
  13.300 +	   * up here 
  13.301 +	   */
  13.302 +	add_gd_partition(hd, *current_minor, le32_to_cpu(bsd_p->p_offset),
  13.303 +			 le32_to_cpu(bsd_p->p_size));
  13.304 +	(*current_minor)++;
  13.305 +}
  13.306 +
  13.307 +/* 
  13.308 + * Create devices for BSD partitions listed in a disklabel, under a
  13.309 + * dos-like partition. See extended_partition() for more information.
  13.310 + */
  13.311 +static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
  13.312 +	int minor, int *current_minor, char *name, int max_partitions)
  13.313 +{
  13.314 +	long offset = hd->part[minor].start_sect;
  13.315 +	Sector sect;
  13.316 +	struct bsd_disklabel *l;
  13.317 +	struct bsd_partition *p;
  13.318 +	int mask = (1 << hd->minor_shift) - 1;
  13.319 +	char buf[40];
  13.320 +
  13.321 +	l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
  13.322 +	if (!l)
  13.323 +		return;
  13.324 +	if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
  13.325 +		put_dev_sector(sect);
  13.326 +		return;
  13.327 +	}
  13.328 +	printk(" %s: <%s", partition_name(hd, minor, buf), name);
  13.329 +
  13.330 +	if (le16_to_cpu(l->d_npartitions) < max_partitions)
  13.331 +		max_partitions = le16_to_cpu(l->d_npartitions);
  13.332 +	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
  13.333 +		if ((*current_minor & mask) == 0)
  13.334 +			break;
  13.335 +		if (p->p_fstype == BSD_FS_UNUSED) 
  13.336 +			continue;
  13.337 +		check_and_add_bsd_partition(hd, p, minor, current_minor);
  13.338 +	}
  13.339 +	put_dev_sector(sect);
  13.340 +	printk(" >\n");
  13.341 +}
  13.342 +#endif
  13.343 +
  13.344 +static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
  13.345 +	int minor, int *current_minor)
  13.346 +{
  13.347 +#ifdef CONFIG_BSD_DISKLABEL
  13.348 +	do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
  13.349 +		BSD_MAXPARTITIONS);
  13.350 +#endif
  13.351 +}
  13.352 +
  13.353 +static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
  13.354 +		int minor, int *current_minor)
  13.355 +{
  13.356 +#ifdef CONFIG_BSD_DISKLABEL
  13.357 +	do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
  13.358 +			BSD_MAXPARTITIONS);
  13.359 +#endif
  13.360 +}
  13.361 +
  13.362 +static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
  13.363 +		int minor, int *current_minor)
  13.364 +{
  13.365 +#ifdef CONFIG_BSD_DISKLABEL
  13.366 +	do_bsd_partition(hd, bdev, minor, current_minor,
  13.367 +			"openbsd", OPENBSD_MAXPARTITIONS);
  13.368 +#endif
  13.369 +}
  13.370 +
  13.371 +/*
  13.372 + * Create devices for Unixware partitions listed in a disklabel, under a
  13.373 + * dos-like partition. See extended_partition() for more information.
  13.374 + */
  13.375 +static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
  13.376 +		int minor, int *current_minor)
  13.377 +{
  13.378 +#ifdef CONFIG_UNIXWARE_DISKLABEL
  13.379 +	long offset = hd->part[minor].start_sect;
  13.380 +	Sector sect;
  13.381 +	struct unixware_disklabel *l;
  13.382 +	struct unixware_slice *p;
  13.383 +	int mask = (1 << hd->minor_shift) - 1;
  13.384 +	char buf[40];
  13.385 +
  13.386 +	l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
  13.387 +	if (!l)
  13.388 +		return;
  13.389 +	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
  13.390 +	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
  13.391 +		put_dev_sector(sect);
  13.392 +		return;
  13.393 +	}
  13.394 +	printk(" %s: <unixware:", partition_name(hd, minor, buf));
  13.395 +	p = &l->vtoc.v_slice[1];
  13.396 +	/* I omit the 0th slice as it is the same as whole disk. */
  13.397 +	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
  13.398 +		if ((*current_minor & mask) == 0)
  13.399 +			break;
  13.400 +
  13.401 +		if (p->s_label != UNIXWARE_FS_UNUSED) {
  13.402 +			add_gd_partition(hd, *current_minor, START_SECT(p),
  13.403 +					 NR_SECTS(p));
  13.404 +			(*current_minor)++;
  13.405 +		}
  13.406 +		p++;
  13.407 +	}
  13.408 +	put_dev_sector(sect);
  13.409 +	printk(" >\n");
  13.410 +#endif
  13.411 +}
  13.412 +
  13.413 +/*
  13.414 + * Minix 2.0.0/2.0.2 subpartition support.
  13.415 + * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
  13.416 + * Rajeev V. Pillai    <rajeevvp@yahoo.com>
  13.417 + */
  13.418 +static void minix_partition(struct gendisk *hd, struct block_device *bdev,
  13.419 +		int minor, int *current_minor)
  13.420 +{
  13.421 +#ifdef CONFIG_MINIX_SUBPARTITION
  13.422 +	long offset = hd->part[minor].start_sect;
  13.423 +	Sector sect;
  13.424 +	unsigned char *data;
  13.425 +	struct partition *p;
  13.426 +	int mask = (1 << hd->minor_shift) - 1;
  13.427 +	int i;
  13.428 +	char buf[40];
  13.429 +
  13.430 +	data = read_dev_sector(bdev, offset, &sect);
  13.431 +	if (!data)
  13.432 +		return;
  13.433 +
  13.434 +	p = (struct partition *)(data + 0x1be);
  13.435 +
  13.436 +	/* The first sector of a Minix partition can have either
  13.437 +	 * a secondary MBR describing its subpartitions, or
  13.438 +	 * the normal boot sector. */
  13.439 +	if (msdos_magic_present (data + 510) &&
  13.440 +	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
  13.441 +
  13.442 +		printk(" %s: <minix:", partition_name(hd, minor, buf));
  13.443 +		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
  13.444 +			if ((*current_minor & mask) == 0)
  13.445 +				break;
  13.446 +			/* add each partition in use */
  13.447 +			if (SYS_IND(p) == MINIX_PARTITION) {
  13.448 +				add_gd_partition(hd, *current_minor,
  13.449 +					      START_SECT(p), NR_SECTS(p));
  13.450 +				(*current_minor)++;
  13.451 +			}
  13.452 +		}
  13.453 +		printk(" >\n");
  13.454 +	}
  13.455 +	put_dev_sector(sect);
  13.456 +#endif /* CONFIG_MINIX_SUBPARTITION */
  13.457 +}
  13.458 +
  13.459 +static struct {
  13.460 +	unsigned char id;
  13.461 +	void (*parse)(struct gendisk *, struct block_device *, int, int *);
  13.462 +} subtypes[] = {
  13.463 +	{BSD_PARTITION, bsd_partition},
  13.464 +	{NETBSD_PARTITION, netbsd_partition},
  13.465 +	{OPENBSD_PARTITION, openbsd_partition},
  13.466 +	{MINIX_PARTITION, minix_partition},
  13.467 +	{UNIXWARE_PARTITION, unixware_partition},
  13.468 +	{SOLARIS_X86_PARTITION, solaris_x86_partition},
  13.469 +	{0, NULL},
  13.470 +};
  13.471 +/*
  13.472 + * Look for various forms of IDE disk geometry translation
  13.473 + */
  13.474 +static int handle_ide_mess(struct block_device *bdev)
  13.475 +{
  13.476 +#ifdef CONFIG_BLK_DEV_IDE
  13.477 +	Sector sect;
  13.478 +	unsigned char *data;
  13.479 +	kdev_t dev = to_kdev_t(bdev->bd_dev);
  13.480 +	unsigned int sig;
  13.481 +	int heads = 0;
  13.482 +	struct partition *p;
  13.483 +	int i;
  13.484 +
  13.485 +	if (MSDOS_DEBUG)
  13.486 +	  printk (KERN_ALERT "handle_ide_mess ------------\n");
  13.487 +
  13.488 +	/*
  13.489 +	 * The i386 partition handling programs very often
  13.490 +	 * make partitions end on cylinder boundaries.
  13.491 +	 * There is no need to do so, and Linux fdisk doesnt always
  13.492 +	 * do this, and Windows NT on Alpha doesnt do this either,
  13.493 +	 * but still, this helps to guess #heads.
  13.494 +	 */
  13.495 +	data = read_dev_sector(bdev, 0, &sect);
  13.496 +	if (!data)
  13.497 +		return -1;
  13.498 +	if (!msdos_magic_present(data + 510)) {
  13.499 +		put_dev_sector(sect);
  13.500 +		return 0;
  13.501 +	}
  13.502 +	sig = le16_to_cpu(*(unsigned short *)(data + 2));
  13.503 +	p = (struct partition *) (data + 0x1be);
  13.504 +	for (i = 0; i < 4; i++) {
  13.505 +		struct partition *q = &p[i];
  13.506 +		if (NR_SECTS(q)) {
  13.507 +			if ((q->sector & 63) == 1 &&
  13.508 +			    (q->end_sector & 63) == 63)
  13.509 +				heads = q->end_head + 1;
  13.510 +			break;
  13.511 +		}
  13.512 +	}
  13.513 +	if (SYS_IND(p) == EZD_PARTITION) {
  13.514 +		/*
  13.515 +		 * Accesses to sector 0 must go to sector 1 instead.
  13.516 +		 */
  13.517 +		if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
  13.518 +			goto reread;
  13.519 +	} else if (SYS_IND(p) == DM6_PARTITION) {
  13.520 +
  13.521 +		/*
  13.522 +		 * Everything on the disk is offset by 63 sectors,
  13.523 +		 * including a "new" MBR with its own partition table.
  13.524 +		 */
  13.525 +		if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
  13.526 +			goto reread;
  13.527 +	} else if (sig <= 0x1ae &&
  13.528 +		   data[sig] == 0xAA && data[sig+1] == 0x55 &&
  13.529 +		   (data[sig+2] & 1)) {
  13.530 +		/* DM6 signature in MBR, courtesy of OnTrack */
  13.531 +		(void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
  13.532 +	} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
  13.533 +		   SYS_IND(p) == DM6_AUX3PARTITION) {
  13.534 +		/*
  13.535 +		 * DM6 on other than the first (boot) drive
  13.536 +		 */
  13.537 +		(void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
  13.538 +	} else {
  13.539 +		(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
  13.540 +	}
  13.541 +	put_dev_sector(sect);
  13.542 +
  13.543 +	if (MSDOS_DEBUG)
  13.544 +	  printk (KERN_ALERT "handle_ide_mess -------- %d\n", heads);
  13.545 +	return 1;
  13.546 +
  13.547 +reread:
  13.548 +	put_dev_sector(sect);
  13.549 +	/* Flush the cache */
  13.550 +	invalidate_bdev(bdev, 1);
  13.551 +	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  13.552 +#endif /* CONFIG_BLK_DEV_IDE */
  13.553 +	return 1;
  13.554 +}
  13.555 + 
  13.556 +int msdos_partition(struct gendisk *hd, struct block_device *bdev,
  13.557 +		    unsigned long first_sector, int first_part_minor)
  13.558 +{
  13.559 +	int i, minor = first_part_minor;
  13.560 +	Sector sect;
  13.561 +	struct partition *p;
  13.562 +	unsigned char *data;
  13.563 +	int mask = (1 << hd->minor_shift) - 1;
  13.564 +	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  13.565 +	int current_minor = first_part_minor;
  13.566 +	int err;
  13.567 +
  13.568 +  if (MSDOS_DEBUG) printk (KERN_ALERT "msdos.c::msdos_partition\n");
  13.569 +	err = handle_ide_mess(bdev);
  13.570 +	if (err <= 0)
  13.571 +		return err;
  13.572 +	data = read_dev_sector(bdev, 0, &sect);
  13.573 +	if (!data)
  13.574 +		return -1;
  13.575 +	if (!msdos_magic_present(data + 510)) {
  13.576 +		put_dev_sector(sect);
  13.577 +		return 0;
  13.578 +	}
  13.579 +	p = (struct partition *) (data + 0x1be);
  13.580 +
  13.581 +	/*
  13.582 +	 * Look for partitions in two passes:
  13.583 +	 * First find the primary and DOS-type extended partitions.
  13.584 +	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
  13.585 +	 */
  13.586 +
  13.587 +	current_minor += 4;
  13.588 +	for (i=1 ; i<=4 ; minor++,i++,p++) {
  13.589 +		if (!NR_SECTS(p))
  13.590 +			continue;
  13.591 +		add_gd_partition(hd, minor,
  13.592 +				first_sector+START_SECT(p)*sector_size,
  13.593 +				NR_SECTS(p)*sector_size);
  13.594 +#if CONFIG_BLK_DEV_MD
  13.595 +		if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  13.596 +			md_autodetect_dev(MKDEV(hd->major,minor));
  13.597 +		}
  13.598 +#endif
  13.599 +		if (is_extended_partition(p)) {
  13.600 +			unsigned long size = hd->part[minor].nr_sects;
  13.601 +			printk(" <");
  13.602 +			/* prevent someone doing mkfs or mkswap on an
  13.603 +			   extended partition, but leave room for LILO */
  13.604 +			if (size > 2)
  13.605 +				hd->part[minor].nr_sects = 2;
  13.606 +			extended_partition(hd, bdev, minor, size, &current_minor);
  13.607 +			printk(" >");
  13.608 +		}
  13.609 +	}
  13.610 +
  13.611 +	/*
  13.612 +	 *  Check for old-style Disk Manager partition table
  13.613 +	 */
  13.614 +	if (msdos_magic_present(data + 0xfc)) {
  13.615 +		p = (struct partition *) (0x1be + data);
  13.616 +		for (i = 4 ; i < 16 ; i++, current_minor++) {
  13.617 +			p--;
  13.618 +			if ((current_minor & mask) == 0)
  13.619 +				break;
  13.620 +			if (!(START_SECT(p) && NR_SECTS(p)))
  13.621 +				continue;
  13.622 +			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
  13.623 +		}
  13.624 +	}
  13.625 +	printk("\n");
  13.626 +
  13.627 +	/* second pass - output for each on a separate line */
  13.628 +	minor -= 4;
  13.629 +	p = (struct partition *) (0x1be + data);
  13.630 +	for (i=1 ; i<=4 ; minor++,i++,p++) {
  13.631 +		unsigned char id = SYS_IND(p);
  13.632 +		int n;
  13.633 +
  13.634 +		if (!NR_SECTS(p))
  13.635 +			continue;
  13.636 +
  13.637 +		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
  13.638 +			;
  13.639 +
  13.640 +		if (subtypes[n].parse)
  13.641 +			subtypes[n].parse(hd, bdev, minor, &current_minor);
  13.642 +	}
  13.643 +	put_dev_sector(sect);
  13.644 +	return 1;
  13.645 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xenolinux-2.4.16-sparse/include/linux/blk.h	Wed Feb 12 18:04:40 2003 +0000
    14.3 @@ -0,0 +1,416 @@
    14.4 +#ifndef _BLK_H
    14.5 +#define _BLK_H
    14.6 +
    14.7 +#include <linux/blkdev.h>
    14.8 +#include <linux/locks.h>
    14.9 +#include <linux/config.h>
   14.10 +#include <linux/spinlock.h>
   14.11 +
   14.12 +/*
   14.13 + * Spinlock for protecting the request queue which
   14.14 + * is mucked around with in interrupts on potentially
   14.15 + * multiple CPU's..
   14.16 + */
   14.17 +extern spinlock_t io_request_lock;
   14.18 +
   14.19 +/*
   14.20 + * Initialization functions.
   14.21 + */
   14.22 +extern int isp16_init(void);
   14.23 +extern int cdu31a_init(void);
   14.24 +extern int acsi_init(void);
   14.25 +extern int mcd_init(void);
   14.26 +extern int mcdx_init(void);
   14.27 +extern int sbpcd_init(void);
   14.28 +extern int aztcd_init(void);
   14.29 +extern int sony535_init(void);
   14.30 +extern int gscd_init(void);
   14.31 +extern int cm206_init(void);
   14.32 +extern int optcd_init(void);
   14.33 +extern int sjcd_init(void);
   14.34 +extern int cdi_init(void);
   14.35 +extern int hd_init(void);
   14.36 +extern int ide_init(void);
   14.37 +extern int xd_init(void);
   14.38 +extern int mfm_init(void);
   14.39 +extern int loop_init(void);
   14.40 +extern int md_init(void);
   14.41 +extern int ap_init(void);
   14.42 +extern int ddv_init(void);
   14.43 +extern int z2_init(void);
   14.44 +extern int swim3_init(void);
   14.45 +extern int swimiop_init(void);
   14.46 +extern int amiga_floppy_init(void);
   14.47 +extern int atari_floppy_init(void);
   14.48 +extern int ez_init(void);
   14.49 +extern int bpcd_init(void);
   14.50 +extern int ps2esdi_init(void);
   14.51 +extern int jsfd_init(void);
   14.52 +extern int viodasd_init(void);
   14.53 +extern int viocd_init(void);
   14.54 +extern int xlblk_init(void);
   14.55 +
   14.56 +#if defined(CONFIG_ARCH_S390)
   14.57 +extern int dasd_init(void);
   14.58 +extern int xpram_init(void);
   14.59 +extern int tapeblock_init(void);
   14.60 +#endif /* CONFIG_ARCH_S390 */
   14.61 +
   14.62 +extern void set_device_ro(kdev_t dev,int flag);
   14.63 +void add_blkdev_randomness(int major);
   14.64 +
   14.65 +extern int floppy_init(void);
   14.66 +extern void rd_load(void);
   14.67 +extern int rd_init(void);
   14.68 +extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
   14.69 +extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
   14.70 +extern int rd_image_start;	/* starting block # of image */
   14.71 +
   14.72 +#ifdef CONFIG_BLK_DEV_INITRD
   14.73 +
   14.74 +#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
   14.75 +
   14.76 +extern unsigned long initrd_start,initrd_end;
   14.77 +extern int mount_initrd; /* zero if initrd should not be mounted */
   14.78 +extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
   14.79 +void initrd_init(void);
   14.80 +
   14.81 +#endif
   14.82 +
   14.83 +		 
   14.84 +/*
   14.85 + * end_request() and friends. Must be called with the request queue spinlock
   14.86 + * acquired. All functions called within end_request() _must_be_ atomic.
   14.87 + *
   14.88 + * Several drivers define their own end_request and call
   14.89 + * end_that_request_first() and end_that_request_last()
   14.90 + * for parts of the original function. This prevents
   14.91 + * code duplication in drivers.
   14.92 + */
   14.93 +
   14.94 +static inline void blkdev_dequeue_request(struct request * req)
   14.95 +{
   14.96 +	list_del(&req->queue);
   14.97 +}
   14.98 +
   14.99 +int end_that_request_first(struct request *req, int uptodate, char *name);
  14.100 +void end_that_request_last(struct request *req);
  14.101 +
  14.102 +#if defined(MAJOR_NR) || defined(IDE_DRIVER)
  14.103 +
  14.104 +#undef DEVICE_ON
  14.105 +#undef DEVICE_OFF
  14.106 +
  14.107 +/*
  14.108 + * Add entries as needed.
  14.109 + */
  14.110 +
  14.111 +#ifdef IDE_DRIVER
  14.112 +
  14.113 +#define DEVICE_NR(device)	(MINOR(device) >> PARTN_BITS)
  14.114 +#define DEVICE_NAME "ide"
  14.115 +
  14.116 +#elif (MAJOR_NR == RAMDISK_MAJOR)
  14.117 +
  14.118 +/* ram disk */
  14.119 +#define DEVICE_NAME "ramdisk"
  14.120 +#define DEVICE_NR(device) (MINOR(device))
  14.121 +#define DEVICE_NO_RANDOM
  14.122 +
  14.123 +#elif (MAJOR_NR == Z2RAM_MAJOR)
  14.124 +
  14.125 +/* Zorro II Ram */
  14.126 +#define DEVICE_NAME "Z2RAM"
  14.127 +#define DEVICE_REQUEST do_z2_request
  14.128 +#define DEVICE_NR(device) (MINOR(device))
  14.129 +
  14.130 +#elif (MAJOR_NR == FLOPPY_MAJOR)
  14.131 +
  14.132 +static void floppy_off(unsigned int nr);
  14.133 +
  14.134 +#define DEVICE_NAME "floppy"
  14.135 +#define DEVICE_INTR do_floppy
  14.136 +#define DEVICE_REQUEST do_fd_request
  14.137 +#define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 ))
  14.138 +#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
  14.139 +
  14.140 +#elif (MAJOR_NR == HD_MAJOR)
  14.141 +
  14.142 +/* Hard disk:  timeout is 6 seconds. */
  14.143 +#define DEVICE_NAME "hard disk"
  14.144 +#define DEVICE_INTR do_hd
  14.145 +#define TIMEOUT_VALUE (6*HZ)
  14.146 +#define DEVICE_REQUEST do_hd_request
  14.147 +#define DEVICE_NR(device) (MINOR(device)>>6)
  14.148 +
  14.149 +#elif (SCSI_DISK_MAJOR(MAJOR_NR))
  14.150 +
  14.151 +#define DEVICE_NAME "scsidisk"
  14.152 +#define TIMEOUT_VALUE (2*HZ)
  14.153 +#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
  14.154 +
  14.155 +/* Kludge to use the same number for both char and block major numbers */
  14.156 +#elif  (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)
  14.157 +
  14.158 +#define DEVICE_NAME "Multiple devices driver"
  14.159 +#define DEVICE_REQUEST do_md_request
  14.160 +#define DEVICE_NR(device) (MINOR(device))
  14.161 +
  14.162 +#elif (MAJOR_NR == SCSI_TAPE_MAJOR)
  14.163 +
  14.164 +#define DEVICE_NAME "scsitape"
  14.165 +#define DEVICE_INTR do_st  
  14.166 +#define DEVICE_NR(device) (MINOR(device) & 0x7f)
  14.167 +
  14.168 +#elif (MAJOR_NR == OSST_MAJOR)
  14.169 +
  14.170 +#define DEVICE_NAME "onstream" 
  14.171 +#define DEVICE_INTR do_osst
  14.172 +#define DEVICE_NR(device) (MINOR(device) & 0x7f) 
  14.173 +#define DEVICE_ON(device) 
  14.174 +#define DEVICE_OFF(device) 
  14.175 +
  14.176 +#elif (MAJOR_NR == SCSI_CDROM_MAJOR)
  14.177 +
  14.178 +#define DEVICE_NAME "CD-ROM"
  14.179 +#define DEVICE_NR(device) (MINOR(device))
  14.180 +
  14.181 +#elif (MAJOR_NR == XT_DISK_MAJOR)
  14.182 +
  14.183 +#define DEVICE_NAME "xt disk"
  14.184 +#define DEVICE_REQUEST do_xd_request
  14.185 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  14.186 +
  14.187 +#elif (MAJOR_NR == PS2ESDI_MAJOR)
  14.188 +
  14.189 +#define DEVICE_NAME "PS/2 ESDI"
  14.190 +#define DEVICE_REQUEST do_ps2esdi_request
  14.191 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  14.192 +
  14.193 +#elif (MAJOR_NR == CDU31A_CDROM_MAJOR)
  14.194 +
  14.195 +#define DEVICE_NAME "CDU31A"
  14.196 +#define DEVICE_REQUEST do_cdu31a_request
  14.197 +#define DEVICE_NR(device) (MINOR(device))
  14.198 +
  14.199 +#elif (MAJOR_NR == ACSI_MAJOR) && (defined(CONFIG_ATARI_ACSI) || defined(CONFIG_ATARI_ACSI_MODULE))
  14.200 +
  14.201 +#define DEVICE_NAME "ACSI"
  14.202 +#define DEVICE_INTR do_acsi
  14.203 +#define DEVICE_REQUEST do_acsi_request
  14.204 +#define DEVICE_NR(device) (MINOR(device) >> 4)
  14.205 +
  14.206 +#elif (MAJOR_NR == MITSUMI_CDROM_MAJOR)
  14.207 +
  14.208 +#define DEVICE_NAME "Mitsumi CD-ROM"
  14.209 +/* #define DEVICE_INTR do_mcd */
  14.210 +#define DEVICE_REQUEST do_mcd_request
  14.211 +#define DEVICE_NR(device) (MINOR(device))
  14.212 +
  14.213 +#elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR)
  14.214 +
  14.215 +#define DEVICE_NAME "Mitsumi CD-ROM"
  14.216 +/* #define DEVICE_INTR do_mcdx */
  14.217 +#define DEVICE_REQUEST do_mcdx_request
  14.218 +#define DEVICE_NR(device) (MINOR(device))
  14.219 +
  14.220 +#elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR)
  14.221 +
  14.222 +#define DEVICE_NAME "Matsushita CD-ROM controller #1"
  14.223 +#define DEVICE_REQUEST do_sbpcd_request
  14.224 +#define DEVICE_NR(device) (MINOR(device))
  14.225 +
  14.226 +#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR)
  14.227 +
  14.228 +#define DEVICE_NAME "Matsushita CD-ROM controller #2"
  14.229 +#define DEVICE_REQUEST do_sbpcd2_request
  14.230 +#define DEVICE_NR(device) (MINOR(device))
  14.231 +
  14.232 +#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR)
  14.233 +
  14.234 +#define DEVICE_NAME "Matsushita CD-ROM controller #3"
  14.235 +#define DEVICE_REQUEST do_sbpcd3_request
  14.236 +#define DEVICE_NR(device) (MINOR(device))
  14.237 +
  14.238 +#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR)
  14.239 +
  14.240 +#define DEVICE_NAME "Matsushita CD-ROM controller #4"
  14.241 +#define DEVICE_REQUEST do_sbpcd4_request
  14.242 +#define DEVICE_NR(device) (MINOR(device))
  14.243 +
  14.244 +#elif (MAJOR_NR == AZTECH_CDROM_MAJOR)
  14.245 +
  14.246 +#define DEVICE_NAME "Aztech CD-ROM"
  14.247 +#define DEVICE_REQUEST do_aztcd_request
  14.248 +#define DEVICE_NR(device) (MINOR(device))
  14.249 +
  14.250 +#elif (MAJOR_NR == CDU535_CDROM_MAJOR)
  14.251 +
  14.252 +#define DEVICE_NAME "SONY-CDU535"
  14.253 +#define DEVICE_INTR do_cdu535
  14.254 +#define DEVICE_REQUEST do_cdu535_request
  14.255 +#define DEVICE_NR(device) (MINOR(device))
  14.256 +
  14.257 +#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR)
  14.258 +
  14.259 +#define DEVICE_NAME "Goldstar R420"
  14.260 +#define DEVICE_REQUEST do_gscd_request
  14.261 +#define DEVICE_NR(device) (MINOR(device))
  14.262 +
  14.263 +#elif (MAJOR_NR == CM206_CDROM_MAJOR)
  14.264 +#define DEVICE_NAME "Philips/LMS CD-ROM cm206"
  14.265 +#define DEVICE_REQUEST do_cm206_request
  14.266 +#define DEVICE_NR(device) (MINOR(device))
  14.267 +
  14.268 +#elif (MAJOR_NR == OPTICS_CDROM_MAJOR)
  14.269 +
  14.270 +#define DEVICE_NAME "DOLPHIN 8000AT CD-ROM"
  14.271 +#define DEVICE_REQUEST do_optcd_request
  14.272 +#define DEVICE_NR(device) (MINOR(device))
  14.273 +
  14.274 +#elif (MAJOR_NR == SANYO_CDROM_MAJOR)
  14.275 +
  14.276 +#define DEVICE_NAME "Sanyo H94A CD-ROM"
  14.277 +#define DEVICE_REQUEST do_sjcd_request
  14.278 +#define DEVICE_NR(device) (MINOR(device))
  14.279 +
  14.280 +#elif (MAJOR_NR == APBLOCK_MAJOR)
  14.281 +
  14.282 +#define DEVICE_NAME "apblock"
  14.283 +#define DEVICE_REQUEST ap_request
  14.284 +#define DEVICE_NR(device) (MINOR(device))
  14.285 +
  14.286 +#elif (MAJOR_NR == DDV_MAJOR)
  14.287 +
  14.288 +#define DEVICE_NAME "ddv"
  14.289 +#define DEVICE_REQUEST ddv_request
  14.290 +#define DEVICE_NR(device) (MINOR(device)>>PARTN_BITS)
  14.291 +
  14.292 +#elif (MAJOR_NR == MFM_ACORN_MAJOR)
  14.293 +
  14.294 +#define DEVICE_NAME "mfm disk"
  14.295 +#define DEVICE_INTR do_mfm
  14.296 +#define DEVICE_REQUEST do_mfm_request
  14.297 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  14.298 +
  14.299 +#elif (MAJOR_NR == NBD_MAJOR)
  14.300 +
  14.301 +#define DEVICE_NAME "nbd"
  14.302 +#define DEVICE_REQUEST do_nbd_request
  14.303 +#define DEVICE_NR(device) (MINOR(device))
  14.304 +
  14.305 +#elif (MAJOR_NR == MDISK_MAJOR)
  14.306 +
  14.307 +#define DEVICE_NAME "mdisk"
  14.308 +#define DEVICE_REQUEST mdisk_request
  14.309 +#define DEVICE_NR(device) (MINOR(device))
  14.310 +
  14.311 +#elif (MAJOR_NR == DASD_MAJOR)
  14.312 +
  14.313 +#define DEVICE_NAME "dasd"
  14.314 +#define DEVICE_REQUEST do_dasd_request
  14.315 +#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
  14.316 +
  14.317 +#elif (MAJOR_NR == I2O_MAJOR)
  14.318 +
  14.319 +#define DEVICE_NAME "I2O block"
  14.320 +#define DEVICE_REQUEST i2ob_request
  14.321 +#define DEVICE_NR(device) (MINOR(device)>>4)
  14.322 +
  14.323 +#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
  14.324 +
  14.325 +#define DEVICE_NAME "ida"
  14.326 +#define TIMEOUT_VALUE (25*HZ)
  14.327 +#define DEVICE_REQUEST do_ida_request
  14.328 +#define DEVICE_NR(device) (MINOR(device) >> 4)
  14.329 +
  14.330 +#elif (MAJOR_NR == XLBLK_MAJOR)
  14.331 +
  14.332 +#define DEVICE_NAME "blk"
  14.333 +#define DEVICE_REQUEST do_xlblk_request
  14.334 +/* #define DEVICE_INTR */
  14.335 +#define DEVICE_NR(device) (MINOR(device))
  14.336 +
  14.337 +#endif /* MAJOR_NR == whatever */
  14.338 +
  14.339 +/* provide DEVICE_xxx defaults, if not explicitly defined
  14.340 + * above in the MAJOR_NR==xxx if-elif tree */
  14.341 +#ifndef DEVICE_ON
  14.342 +#define DEVICE_ON(device) do {} while (0)
  14.343 +#endif
  14.344 +#ifndef DEVICE_OFF
  14.345 +#define DEVICE_OFF(device) do {} while (0)
  14.346 +#endif
  14.347 +
  14.348 +#if (MAJOR_NR != SCSI_TAPE_MAJOR) && (MAJOR_NR != OSST_MAJOR)
  14.349 +#if !defined(IDE_DRIVER)
  14.350 +
  14.351 +#ifndef CURRENT
  14.352 +#define CURRENT blkdev_entry_next_request(&blk_dev[MAJOR_NR].request_queue.queue_head)
  14.353 +#endif
  14.354 +#ifndef QUEUE_EMPTY
  14.355 +#define QUEUE_EMPTY list_empty(&blk_dev[MAJOR_NR].request_queue.queue_head)
  14.356 +#endif
  14.357 +
  14.358 +#ifndef DEVICE_NAME
  14.359 +#define DEVICE_NAME "unknown"
  14.360 +#endif
  14.361 +
  14.362 +#define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev)
  14.363 +
  14.364 +#ifdef DEVICE_INTR
  14.365 +static void (*DEVICE_INTR)(void) = NULL;
  14.366 +#endif
  14.367 +
  14.368 +#define SET_INTR(x) (DEVICE_INTR = (x))
  14.369 +
  14.370 +#ifdef DEVICE_REQUEST
  14.371 +static void (DEVICE_REQUEST)(request_queue_t *);
  14.372 +#endif 
  14.373 +  
  14.374 +#ifdef DEVICE_INTR
  14.375 +#define CLEAR_INTR SET_INTR(NULL)
  14.376 +#else
  14.377 +#define CLEAR_INTR
  14.378 +#endif
  14.379 +
  14.380 +#define INIT_REQUEST \
  14.381 +	if (QUEUE_EMPTY) {\
  14.382 +		CLEAR_INTR; \
  14.383 +		return; \
  14.384 +	} \
  14.385 +	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
  14.386 +		panic(DEVICE_NAME ": request list destroyed"); \
  14.387 +	if (CURRENT->bh) { \
  14.388 +		if (!buffer_locked(CURRENT->bh)) \
  14.389 +			panic(DEVICE_NAME ": block not locked"); \
  14.390 +	}
  14.391 +
  14.392 +#endif /* !defined(IDE_DRIVER) */
  14.393 +
  14.394 +
  14.395 +#ifndef LOCAL_END_REQUEST	/* If we have our own end_request, we do not want to include this mess */
  14.396 +
  14.397 +#if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
  14.398 +
  14.399 +static inline void end_request(int uptodate) {
  14.400 +	struct request *req = CURRENT;
  14.401 +
  14.402 +	if (end_that_request_first(req, uptodate, DEVICE_NAME))
  14.403 +		return;
  14.404 +
  14.405 +#ifndef DEVICE_NO_RANDOM
  14.406 +	add_blkdev_randomness(MAJOR(req->rq_dev));
  14.407 +#endif
  14.408 +	DEVICE_OFF(req->rq_dev);
  14.409 +	blkdev_dequeue_request(req);
  14.410 +	end_that_request_last(req);
  14.411 +}
  14.412 +
  14.413 +#endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
  14.414 +#endif /* LOCAL_END_REQUEST */
  14.415 +
  14.416 +#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
  14.417 +#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
  14.418 +
  14.419 +#endif /* _BLK_H */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xenolinux-2.4.16-sparse/include/linux/major.h	Wed Feb 12 18:04:40 2003 +0000
    15.3 @@ -0,0 +1,199 @@
    15.4 +#ifndef _LINUX_MAJOR_H
    15.5 +#define _LINUX_MAJOR_H
    15.6 +
    15.7 +/*
    15.8 + * This file has definitions for major device numbers.
    15.9 + * For the device number assignments, see Documentation/devices.txt.
   15.10 + */
   15.11 +
   15.12 +/* limits */
   15.13 +
   15.14 +/*
   15.15 + * Important: Don't change this to 256.  Major number 255 is and must be
   15.16 + * reserved for future expansion into a larger dev_t space.
   15.17 + */
   15.18 +#define MAX_CHRDEV	255
   15.19 +#define MAX_BLKDEV	255
   15.20 +
   15.21 +#define UNNAMED_MAJOR	0
   15.22 +#define MEM_MAJOR	1
   15.23 +#define RAMDISK_MAJOR	1
   15.24 +#define FLOPPY_MAJOR	2
   15.25 +#define PTY_MASTER_MAJOR 2
   15.26 +#define IDE0_MAJOR	3
   15.27 +#define PTY_SLAVE_MAJOR 3
   15.28 +#define HD_MAJOR	IDE0_MAJOR
   15.29 +#define TTY_MAJOR	4
   15.30 +#define TTYAUX_MAJOR	5
   15.31 +#define LP_MAJOR	6
   15.32 +#define VCS_MAJOR	7
   15.33 +#define LOOP_MAJOR	7
   15.34 +#define SCSI_DISK0_MAJOR 8
   15.35 +#define SCSI_TAPE_MAJOR	9
   15.36 +#define MD_MAJOR        9
   15.37 +#define MISC_MAJOR	10
   15.38 +#define SCSI_CDROM_MAJOR 11
   15.39 +#define QIC02_TAPE_MAJOR 12
   15.40 +#define XT_DISK_MAJOR	13
   15.41 +#define SOUND_MAJOR	14
   15.42 +#define CDU31A_CDROM_MAJOR 15
   15.43 +#define JOYSTICK_MAJOR	15
   15.44 +#define GOLDSTAR_CDROM_MAJOR 16
   15.45 +#define OPTICS_CDROM_MAJOR 17
   15.46 +#define SANYO_CDROM_MAJOR 18
   15.47 +#define CYCLADES_MAJOR  19
   15.48 +#define CYCLADESAUX_MAJOR 20
   15.49 +#define MITSUMI_X_CDROM_MAJOR 20
   15.50 +#define MFM_ACORN_MAJOR 21	/* ARM Linux /dev/mfm */
   15.51 +#define SCSI_GENERIC_MAJOR 21
   15.52 +#define Z8530_MAJOR 34
   15.53 +#define DIGI_MAJOR 23
   15.54 +#define IDE1_MAJOR	22
   15.55 +#define DIGICU_MAJOR 22
   15.56 +#define MITSUMI_CDROM_MAJOR 23
   15.57 +#define CDU535_CDROM_MAJOR 24
   15.58 +#define STL_SERIALMAJOR 24
   15.59 +#define MATSUSHITA_CDROM_MAJOR 25
   15.60 +#define STL_CALLOUTMAJOR 25
   15.61 +#define MATSUSHITA_CDROM2_MAJOR 26
   15.62 +#define QIC117_TAPE_MAJOR 27
   15.63 +#define MATSUSHITA_CDROM3_MAJOR 27
   15.64 +#define MATSUSHITA_CDROM4_MAJOR 28
   15.65 +#define STL_SIOMEMMAJOR 28
   15.66 +#define ACSI_MAJOR	28
   15.67 +#define AZTECH_CDROM_MAJOR 29
   15.68 +#define GRAPHDEV_MAJOR	29	/* SparcLinux & Linux/68k /dev/fb */
   15.69 +#define SHMIQ_MAJOR	85	/* Linux/mips, SGI /dev/shmiq */
   15.70 +#define CM206_CDROM_MAJOR 32
   15.71 +#define IDE2_MAJOR	33
   15.72 +#define IDE3_MAJOR	34
   15.73 +#define XPRAM_MAJOR     35      /* expanded storage on S/390 = "slow ram" */
   15.74 +                                /* proposed by Peter                      */
   15.75 +#define NETLINK_MAJOR	36
   15.76 +#define PS2ESDI_MAJOR	36
   15.77 +#define IDETAPE_MAJOR	37
   15.78 +#define Z2RAM_MAJOR	37
   15.79 +#define APBLOCK_MAJOR   38   /* AP1000 Block device */
   15.80 +#define DDV_MAJOR       39   /* AP1000 DDV block device */
   15.81 +#define NBD_MAJOR	43   /* Network block device	*/
   15.82 +#define RISCOM8_NORMAL_MAJOR 48
   15.83 +#define DAC960_MAJOR	48	/* 48..55 */
   15.84 +#define RISCOM8_CALLOUT_MAJOR 49
   15.85 +#define MKISS_MAJOR	55
   15.86 +#define DSP56K_MAJOR    55   /* DSP56001 processor device */
   15.87 +
   15.88 +#define IDE4_MAJOR	56
   15.89 +#define IDE5_MAJOR	57
   15.90 +
   15.91 +#define LVM_BLK_MAJOR	58	/* Logical Volume Manager */
   15.92 +
   15.93 +#define SCSI_DISK1_MAJOR	65
   15.94 +#define SCSI_DISK2_MAJOR	66
   15.95 +#define SCSI_DISK3_MAJOR	67
   15.96 +#define SCSI_DISK4_MAJOR	68
   15.97 +#define SCSI_DISK5_MAJOR	69
   15.98 +#define SCSI_DISK6_MAJOR	70
   15.99 +#define SCSI_DISK7_MAJOR	71
  15.100 +
  15.101 +
  15.102 +#define COMPAQ_SMART2_MAJOR	72
  15.103 +#define COMPAQ_SMART2_MAJOR1	73
  15.104 +#define COMPAQ_SMART2_MAJOR2	74
  15.105 +#define COMPAQ_SMART2_MAJOR3	75
  15.106 +#define COMPAQ_SMART2_MAJOR4	76
  15.107 +#define COMPAQ_SMART2_MAJOR5	77
  15.108 +#define COMPAQ_SMART2_MAJOR6	78
  15.109 +#define COMPAQ_SMART2_MAJOR7	79
  15.110 +
  15.111 +#define SPECIALIX_NORMAL_MAJOR 75
  15.112 +#define SPECIALIX_CALLOUT_MAJOR 76
  15.113 +
  15.114 +#define COMPAQ_CISS_MAJOR 	104
  15.115 +#define COMPAQ_CISS_MAJOR1	105
  15.116 +#define COMPAQ_CISS_MAJOR2      106
  15.117 +#define COMPAQ_CISS_MAJOR3      107
  15.118 +#define COMPAQ_CISS_MAJOR4      108
  15.119 +#define COMPAQ_CISS_MAJOR5      109
  15.120 +#define COMPAQ_CISS_MAJOR6      110
  15.121 +#define COMPAQ_CISS_MAJOR7      111
  15.122 +
  15.123 +#define ATARAID_MAJOR		114
  15.124 +
  15.125 +#define DASD_MAJOR      94	/* Official assignations from Peter */
  15.126 +
  15.127 +#define MDISK_MAJOR     95	/* Official assignations from Peter */
  15.128 +
  15.129 +#define I2O_MAJOR		80	/* 80->87 */
  15.130 +
  15.131 +#define IDE6_MAJOR	88
  15.132 +#define IDE7_MAJOR	89
  15.133 +#define IDE8_MAJOR	90
  15.134 +#define IDE9_MAJOR	91
  15.135 +
  15.136 +#define UBD_MAJOR	98
  15.137 +
  15.138 +#define AURORA_MAJOR 79
  15.139 +
  15.140 +#define JSFD_MAJOR	99
  15.141 +
  15.142 +#define PHONE_MAJOR	100
  15.143 +
  15.144 +#define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
  15.145 +
  15.146 +#define	UMEM_MAJOR	116	/* http://www.umem.com/ Battery Backed RAM */
  15.147 +
  15.148 +#define XLBLK_MAJOR	123	/* XenoLinux Block Device */
  15.149 +
  15.150 +#define RTF_MAJOR	150
  15.151 +#define RAW_MAJOR	162
  15.152 +
  15.153 +#define USB_ACM_MAJOR		166
  15.154 +#define USB_ACM_AUX_MAJOR	167
  15.155 +#define USB_CHAR_MAJOR		180
  15.156 +
  15.157 +#define UNIX98_PTY_MASTER_MAJOR	128
  15.158 +#define UNIX98_PTY_MAJOR_COUNT	8
  15.159 +#define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
  15.160 +
  15.161 +#define VXVM_MAJOR		199	/* VERITAS volume i/o driver    */
  15.162 +#define VXSPEC_MAJOR		200	/* VERITAS volume config driver */
  15.163 +#define VXDMP_MAJOR		201	/* VERITAS volume multipath driver */
  15.164 +
  15.165 +#define MSR_MAJOR		202
  15.166 +#define CPUID_MAJOR		203
  15.167 +
  15.168 +#define OSST_MAJOR	206	/* OnStream-SCx0 SCSI tape */
  15.169 +
  15.170 +#define IBM_TTY3270_MAJOR       227	/* Official allocations now */
  15.171 +#define IBM_FS3270_MAJOR        228
  15.172 +
  15.173 +/*
  15.174 + * Tests for SCSI devices.
  15.175 + */
  15.176 +
  15.177 +#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
  15.178 +  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
  15.179 +  
  15.180 +#define SCSI_BLK_MAJOR(M) \
  15.181 +  (SCSI_DISK_MAJOR(M)	\
  15.182 +   || (M) == SCSI_CDROM_MAJOR)
  15.183 +
  15.184 +static __inline__ int scsi_blk_major(int m) {
  15.185 +	return SCSI_BLK_MAJOR(m);
  15.186 +}
  15.187 +
  15.188 +/*
  15.189 + * Tests for IDE devices
  15.190 + */
  15.191 +#define IDE_DISK_MAJOR(M)	((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
  15.192 +				(M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
  15.193 +				(M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
  15.194 +				(M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
  15.195 +				(M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
  15.196 +
  15.197 +static __inline__ int ide_blk_major(int m)
  15.198 +{
  15.199 +	return IDE_DISK_MAJOR(m);
  15.200 +}
  15.201 +
  15.202 +#endif
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xenolinux-2.4.16-sparse/init/main.c	Wed Feb 12 18:04:40 2003 +0000
    16.3 @@ -0,0 +1,871 @@
    16.4 +/*
    16.5 + *  linux/init/main.c
    16.6 + *
    16.7 + *  Copyright (C) 1991, 1992  Linus Torvalds
    16.8 + *
    16.9 + *  GK 2/5/95  -  Changed to support mounting root fs via NFS
   16.10 + *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
   16.11 + *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
   16.12 + *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
   16.13 + */
   16.14 +
   16.15 +#define __KERNEL_SYSCALLS__
   16.16 +
   16.17 +#include <linux/config.h>
   16.18 +#include <linux/proc_fs.h>
   16.19 +#include <linux/devfs_fs_kernel.h>
   16.20 +#include <linux/unistd.h>
   16.21 +#include <linux/string.h>
   16.22 +#include <linux/ctype.h>
   16.23 +#include <linux/delay.h>
   16.24 +#include <linux/utsname.h>
   16.25 +#include <linux/ioport.h>
   16.26 +#include <linux/init.h>
   16.27 +#include <linux/smp_lock.h>
   16.28 +#include <linux/blk.h>
   16.29 +#include <linux/hdreg.h>
   16.30 +#include <linux/iobuf.h>
   16.31 +#include <linux/bootmem.h>
   16.32 +#include <linux/tty.h>
   16.33 +
   16.34 +#include <asm/io.h>
   16.35 +#include <asm/bugs.h>
   16.36 +
   16.37 +#if defined(CONFIG_ARCH_S390)
   16.38 +#include <asm/s390mach.h>
   16.39 +#include <asm/ccwcache.h>
   16.40 +#endif
   16.41 +
   16.42 +#ifdef CONFIG_PCI
   16.43 +#include <linux/pci.h>
   16.44 +#endif
   16.45 +
   16.46 +#ifdef CONFIG_DIO
   16.47 +#include <linux/dio.h>
   16.48 +#endif
   16.49 +
   16.50 +#ifdef CONFIG_ZORRO
   16.51 +#include <linux/zorro.h>
   16.52 +#endif
   16.53 +
   16.54 +#ifdef CONFIG_MTRR
   16.55 +#  include <asm/mtrr.h>
   16.56 +#endif
   16.57 +
   16.58 +#ifdef CONFIG_NUBUS
   16.59 +#include <linux/nubus.h>
   16.60 +#endif
   16.61 +
   16.62 +#ifdef CONFIG_ISAPNP
   16.63 +#include <linux/isapnp.h>
   16.64 +#endif
   16.65 +
   16.66 +#ifdef CONFIG_IRDA
   16.67 +extern int irda_proto_init(void);
   16.68 +extern int irda_device_init(void);
   16.69 +#endif
   16.70 +
   16.71 +#ifdef CONFIG_X86_LOCAL_APIC
   16.72 +#include <asm/smp.h>
   16.73 +#endif
   16.74 +
   16.75 +#if defined(CONFIG_KDB)
   16.76 +#include <linux/kdb.h>
   16.77 +#endif
   16.78 +
   16.79 +/*
   16.80 + * Versions of gcc older than that listed below may actually compile
   16.81 + * and link okay, but the end product can have subtle run time bugs.
   16.82 + * To avoid associated bogus bug reports, we flatly refuse to compile
   16.83 + * with a gcc that is known to be too old from the very beginning.
   16.84 + */
   16.85 +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
   16.86 +#error Sorry, your GCC is too old. It builds incorrect kernels.
   16.87 +#endif
   16.88 +
   16.89 +extern char _stext, _etext;
   16.90 +extern char *linux_banner;
   16.91 +
   16.92 +static int init(void *);
   16.93 +
   16.94 +extern void init_IRQ(void);
   16.95 +extern void init_modules(void);
   16.96 +extern void sock_init(void);
   16.97 +extern void fork_init(unsigned long);
   16.98 +extern void mca_init(void);
   16.99 +extern void sbus_init(void);
  16.100 +extern void ppc_init(void);
  16.101 +extern void sysctl_init(void);
  16.102 +extern void signals_init(void);
  16.103 +extern int init_pcmcia_ds(void);
  16.104 +
  16.105 +extern void free_initmem(void);
  16.106 +
  16.107 +#ifdef CONFIG_TC
  16.108 +extern void tc_init(void);
  16.109 +#endif
  16.110 +
  16.111 +extern void ecard_init(void);
  16.112 +
  16.113 +#if defined(CONFIG_SYSVIPC)
  16.114 +extern void ipc_init(void);
  16.115 +#endif
  16.116 +
  16.117 +/*
  16.118 + * Boot command-line arguments
  16.119 + */
  16.120 +#define MAX_INIT_ARGS 8
  16.121 +#define MAX_INIT_ENVS 8
  16.122 +
  16.123 +extern void time_init(void);
  16.124 +extern void softirq_init(void);
  16.125 +
  16.126 +int rows, cols;
  16.127 +
  16.128 +#ifdef CONFIG_BLK_DEV_INITRD
  16.129 +unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
  16.130 +#endif
  16.131 +
  16.132 +int root_mountflags = MS_RDONLY;
  16.133 +char *execute_command;
  16.134 +char root_device_name[64];
  16.135 +
  16.136 +
  16.137 +static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
  16.138 +static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
  16.139 +
  16.140 +static int __init profile_setup(char *str)
  16.141 +{
  16.142 +    int par;
  16.143 +    if (get_option(&str,&par)) prof_shift = par;
  16.144 +	return 1;
  16.145 +}
  16.146 +
  16.147 +__setup("profile=", profile_setup);
  16.148 +
  16.149 +
  16.150 +static struct dev_name_struct {
  16.151 +	const char *name;
  16.152 +	const int num;
  16.153 +} root_dev_names[] __initdata = {
  16.154 +	{ "nfs",     0x00ff },
  16.155 +        { "blk",     0x7b00 },
  16.156 +	{ "hda",     0x0300 },
  16.157 +	{ "hdb",     0x0340 },
  16.158 +	{ "loop",    0x0700 },
  16.159 +	{ "hdc",     0x1600 },
  16.160 +	{ "hdd",     0x1640 },
  16.161 +	{ "hde",     0x2100 },
  16.162 +	{ "hdf",     0x2140 },
  16.163 +	{ "hdg",     0x2200 },
  16.164 +	{ "hdh",     0x2240 },
  16.165 +	{ "hdi",     0x3800 },
  16.166 +	{ "hdj",     0x3840 },
  16.167 +	{ "hdk",     0x3900 },
  16.168 +	{ "hdl",     0x3940 },
  16.169 +	{ "hdm",     0x5800 },
  16.170 +	{ "hdn",     0x5840 },
  16.171 +	{ "hdo",     0x5900 },
  16.172 +	{ "hdp",     0x5940 },
  16.173 +	{ "hdq",     0x5A00 },
  16.174 +	{ "hdr",     0x5A40 },
  16.175 +	{ "hds",     0x5B00 },
  16.176 +	{ "hdt",     0x5B40 },
  16.177 +	{ "sda",     0x0800 },
  16.178 +	{ "sdb",     0x0810 },
  16.179 +	{ "sdc",     0x0820 },
  16.180 +	{ "sdd",     0x0830 },
  16.181 +	{ "sde",     0x0840 },
  16.182 +	{ "sdf",     0x0850 },
  16.183 +	{ "sdg",     0x0860 },
  16.184 +	{ "sdh",     0x0870 },
  16.185 +	{ "sdi",     0x0880 },
  16.186 +	{ "sdj",     0x0890 },
  16.187 +	{ "sdk",     0x08a0 },
  16.188 +	{ "sdl",     0x08b0 },
  16.189 +	{ "sdm",     0x08c0 },
  16.190 +	{ "sdn",     0x08d0 },
  16.191 +	{ "sdo",     0x08e0 },
  16.192 +	{ "sdp",     0x08f0 },
  16.193 +	{ "ada",     0x1c00 },
  16.194 +	{ "adb",     0x1c10 },
  16.195 +	{ "adc",     0x1c20 },
  16.196 +	{ "add",     0x1c30 },
  16.197 +	{ "ade",     0x1c40 },
  16.198 +	{ "fd",      0x0200 },
  16.199 +	{ "md",      0x0900 },	     
  16.200 +	{ "xda",     0x0d00 },
  16.201 +	{ "xdb",     0x0d40 },
  16.202 +	{ "ram",     0x0100 },
  16.203 +	{ "scd",     0x0b00 },
  16.204 +	{ "mcd",     0x1700 },
  16.205 +	{ "cdu535",  0x1800 },
  16.206 +	{ "sonycd",  0x1800 },
  16.207 +	{ "aztcd",   0x1d00 },
  16.208 +	{ "cm206cd", 0x2000 },
  16.209 +	{ "gscd",    0x1000 },
  16.210 +	{ "sbpcd",   0x1900 },
  16.211 +	{ "eda",     0x2400 },
  16.212 +	{ "edb",     0x2440 },
  16.213 +	{ "pda",	0x2d00 },
  16.214 +	{ "pdb",	0x2d10 },
  16.215 +	{ "pdc",	0x2d20 },
  16.216 +	{ "pdd",	0x2d30 },
  16.217 +	{ "pcd",	0x2e00 },
  16.218 +	{ "pf",		0x2f00 },
  16.219 +	{ "apblock", APBLOCK_MAJOR << 8},
  16.220 +	{ "ddv", DDV_MAJOR << 8},
  16.221 +	{ "jsfd",    JSFD_MAJOR << 8},
  16.222 +#if defined(CONFIG_ARCH_S390)
  16.223 +	{ "dasda", (DASD_MAJOR << MINORBITS) },
  16.224 +	{ "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
  16.225 +	{ "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
  16.226 +	{ "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
  16.227 +	{ "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
  16.228 +	{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
  16.229 +	{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
  16.230 +	{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
  16.231 +#endif
  16.232 +#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
  16.233 +	{ "ida/c0d0p",0x4800 },
  16.234 +	{ "ida/c0d1p",0x4810 },
  16.235 +	{ "ida/c0d2p",0x4820 },
  16.236 +	{ "ida/c0d3p",0x4830 },
  16.237 +	{ "ida/c0d4p",0x4840 },
  16.238 +	{ "ida/c0d5p",0x4850 },
  16.239 +	{ "ida/c0d6p",0x4860 },
  16.240 +	{ "ida/c0d7p",0x4870 },
  16.241 +	{ "ida/c0d8p",0x4880 },
  16.242 +	{ "ida/c0d9p",0x4890 },
  16.243 +	{ "ida/c0d10p",0x48A0 },
  16.244 +	{ "ida/c0d11p",0x48B0 },
  16.245 +	{ "ida/c0d12p",0x48C0 },
  16.246 +	{ "ida/c0d13p",0x48D0 },
  16.247 +	{ "ida/c0d14p",0x48E0 },
  16.248 +	{ "ida/c0d15p",0x48F0 },
  16.249 +#endif
  16.250 +#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
  16.251 +	{ "cciss/c0d0p",0x6800 },
  16.252 +	{ "cciss/c0d1p",0x6810 },
  16.253 +	{ "cciss/c0d2p",0x6820 },
  16.254 +	{ "cciss/c0d3p",0x6830 },
  16.255 +	{ "cciss/c0d4p",0x6840 },
  16.256 +	{ "cciss/c0d5p",0x6850 },
  16.257 +	{ "cciss/c0d6p",0x6860 },
  16.258 +	{ "cciss/c0d7p",0x6870 },
  16.259 +	{ "cciss/c0d8p",0x6880 },
  16.260 +	{ "cciss/c0d9p",0x6890 },
  16.261 +	{ "cciss/c0d10p",0x68A0 },
  16.262 +	{ "cciss/c0d11p",0x68B0 },
  16.263 +	{ "cciss/c0d12p",0x68C0 },
  16.264 +	{ "cciss/c0d13p",0x68D0 },
  16.265 +	{ "cciss/c0d14p",0x68E0 },
  16.266 +	{ "cciss/c0d15p",0x68F0 },
  16.267 +#endif
  16.268 +	{ "nftla", 0x5d00 },
  16.269 +	{ "nftlb", 0x5d10 },
  16.270 +	{ "nftlc", 0x5d20 },
  16.271 +	{ "nftld", 0x5d30 },
  16.272 +	{ "ftla", 0x2c00 },
  16.273 +	{ "ftlb", 0x2c08 },
  16.274 +	{ "ftlc", 0x2c10 },
  16.275 +	{ "ftld", 0x2c18 },
  16.276 +	{ "mtdblock", 0x1f00 },
  16.277 +	{ NULL, 0 }
  16.278 +};
  16.279 +
  16.280 +kdev_t __init name_to_kdev_t(char *line)
  16.281 +{
  16.282 +	int base = 0;
  16.283 +
  16.284 +	if (strncmp(line,"/dev/",5) == 0) {
  16.285 +		struct dev_name_struct *dev = root_dev_names;
  16.286 +		line += 5;
  16.287 +		do {
  16.288 +			int len = strlen(dev->name);
  16.289 +			if (strncmp(line,dev->name,len) == 0) {
  16.290 +				line += len;
  16.291 +				base = dev->num;
  16.292 +				break;
  16.293 +			}
  16.294 +			dev++;
  16.295 +		} while (dev->name);
  16.296 +	}
  16.297 +	return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
  16.298 +}
  16.299 +
  16.300 +static int __init root_dev_setup(char *line)
  16.301 +{
  16.302 +	int i;
  16.303 +	char ch;
  16.304 +
  16.305 +	ROOT_DEV = name_to_kdev_t(line);
  16.306 +	memset (root_device_name, 0, sizeof root_device_name);
  16.307 +	if (strncmp (line, "/dev/", 5) == 0) line += 5;
  16.308 +	for (i = 0; i < sizeof root_device_name - 1; ++i)
  16.309 +	{
  16.310 +	    ch = line[i];
  16.311 +	    if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
  16.312 +	    root_device_name[i] = ch;
  16.313 +	}
  16.314 +	return 1;
  16.315 +}
  16.316 +
  16.317 +__setup("root=", root_dev_setup);
  16.318 +
  16.319 +static int __init checksetup(char *line)
  16.320 +{
  16.321 +	struct kernel_param *p;
  16.322 +
  16.323 +	p = &__setup_start;
  16.324 +	do {
  16.325 +		int n = strlen(p->str);
  16.326 +		if (!strncmp(line,p->str,n)) {
  16.327 +			if (p->setup_func(line+n))
  16.328 +				return 1;
  16.329 +		}
  16.330 +		p++;
  16.331 +	} while (p < &__setup_end);
  16.332 +	return 0;
  16.333 +}
  16.334 +
  16.335 +/* this should be approx 2 Bo*oMips to start (note initial shift), and will
  16.336 +   still work even if initially too large, it will just take slightly longer */
  16.337 +unsigned long loops_per_jiffy = (1<<12);
  16.338 +
  16.339 +/* This is the number of bits of precision for the loops_per_jiffy.  Each
  16.340 +   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
  16.341 +   better than 1% */
  16.342 +#define LPS_PREC 8
  16.343 +
  16.344 +void __init calibrate_delay(void)
  16.345 +{
  16.346 +	unsigned long ticks, loopbit;
  16.347 +	int lps_precision = LPS_PREC;
  16.348 +
  16.349 +	loops_per_jiffy = (1<<12);
  16.350 +
  16.351 +	printk("Calibrating delay loop... ");
  16.352 +	while (loops_per_jiffy <<= 1) {
  16.353 +		/* wait for "start of" clock tick */
  16.354 +		ticks = jiffies;
  16.355 +		while (ticks == jiffies)
  16.356 +			/* nothing */;
  16.357 +		/* Go .. */
  16.358 +		ticks = jiffies;
  16.359 +		__delay(loops_per_jiffy);
  16.360 +		ticks = jiffies - ticks;
  16.361 +		if (ticks)
  16.362 +			break;
  16.363 +	}
  16.364 +
  16.365 +/* Do a binary approximation to get loops_per_jiffy set to equal one clock
  16.366 +   (up to lps_precision bits) */
  16.367 +	loops_per_jiffy >>= 1;
  16.368 +	loopbit = loops_per_jiffy;
  16.369 +	while ( lps_precision-- && (loopbit >>= 1) ) {
  16.370 +		loops_per_jiffy |= loopbit;
  16.371 +		ticks = jiffies;
  16.372 +		while (ticks == jiffies);
  16.373 +		ticks = jiffies;
  16.374 +		__delay(loops_per_jiffy);
  16.375 +		if (jiffies != ticks)	/* longer than 1 tick */
  16.376 +			loops_per_jiffy &= ~loopbit;
  16.377 +	}
  16.378 +
  16.379 +/* Round the value and print it */	
  16.380 +	printk("%lu.%02lu BogoMIPS\n",
  16.381 +		loops_per_jiffy/(500000/HZ),
  16.382 +		(loops_per_jiffy/(5000/HZ)) % 100);
  16.383 +}
  16.384 +
  16.385 +static int __init readonly(char *str)
  16.386 +{
  16.387 +	if (*str)
  16.388 +		return 0;
  16.389 +	root_mountflags |= MS_RDONLY;
  16.390 +	return 1;
  16.391 +}
  16.392 +
  16.393 +static int __init readwrite(char *str)
  16.394 +{
  16.395 +	if (*str)
  16.396 +		return 0;
  16.397 +	root_mountflags &= ~MS_RDONLY;
  16.398 +	return 1;
  16.399 +}
  16.400 +
  16.401 +static int __init debug_kernel(char *str)
  16.402 +{
  16.403 +	if (*str)
  16.404 +		return 0;
  16.405 +	console_loglevel = 10;
  16.406 +	return 1;
  16.407 +}
  16.408 +
  16.409 +static int __init quiet_kernel(char *str)
  16.410 +{
  16.411 +	if (*str)
  16.412 +		return 0;
  16.413 +	console_loglevel = 4;
  16.414 +	return 1;
  16.415 +}
  16.416 +
  16.417 +__setup("ro", readonly);
  16.418 +__setup("rw", readwrite);
  16.419 +__setup("debug", debug_kernel);
  16.420 +__setup("quiet", quiet_kernel);
  16.421 +
  16.422 +/*
  16.423 + * This is a simple kernel command line parsing function: it parses
  16.424 + * the command line, and fills in the arguments/environment to init
  16.425 + * as appropriate. Any cmd-line option is taken to be an environment
  16.426 + * variable if it contains the character '='.
  16.427 + *
  16.428 + * This routine also checks for options meant for the kernel.
  16.429 + * These options are not given to init - they are for internal kernel use only.
  16.430 + */
  16.431 +static void __init parse_options(char *line)
  16.432 +{
  16.433 +	char *next,*quote;
  16.434 +	int args, envs;
  16.435 +
  16.436 +	if (!*line)
  16.437 +		return;
  16.438 +	args = 0;
  16.439 +	envs = 1;	/* TERM is set to 'linux' by default */
  16.440 +	next = line;
  16.441 +	while ((line = next) != NULL) {
  16.442 +                quote = strchr(line,'"');
  16.443 +                next = strchr(line, ' ');
  16.444 +                while (next != NULL && quote != NULL && quote < next) {
  16.445 +                        /* we found a left quote before the next blank
  16.446 +                         * now we have to find the matching right quote
  16.447 +                         */
  16.448 +                        next = strchr(quote+1, '"');
  16.449 +                        if (next != NULL) {
  16.450 +                                quote = strchr(next+1, '"');
  16.451 +                                next = strchr(next+1, ' ');
  16.452 +                        }
  16.453 +                }
  16.454 +                if (next != NULL)
  16.455 +                        *next++ = 0;
  16.456 +#if defined(CONFIG_KDB)
  16.457 +		/* kdb, kdb=on, kdb=off, kdb=early */
  16.458 +		if (strncmp(line, "kdb", 3) == 0) {
  16.459 +			if (line[3] == '\0') {
  16.460 +				/* Backward compatibility, kdb with no option means early activation */
  16.461 +				printk("Boot flag kdb with no options is obsolete, use kdb=early\n");
  16.462 +				kdb_on = 1;
  16.463 +				kdb_flags |= KDB_FLAG_EARLYKDB;
  16.464 +				continue;
  16.465 +			}
  16.466 +			if (line[3] == '=') {
  16.467 +				if (strcmp(line+4, "on") == 0) {
  16.468 +					kdb_on = 1;
  16.469 +					continue;
  16.470 +				}
  16.471 +				if (strcmp(line+4, "off") == 0) {
  16.472 +					kdb_on = 0;
  16.473 +					continue;
  16.474 +				}
  16.475 +				if (strcmp(line+4, "early") == 0) {
  16.476 +					kdb_on = 1;
  16.477 +					kdb_flags |= KDB_FLAG_EARLYKDB;
  16.478 +					continue;
  16.479 +				}
  16.480 +				printk("Boot flag %s not recognised, assumed to be environment variable\n", line);
  16.481 +			}
  16.482 +		}
  16.483 +#endif
  16.484 +		if (!strncmp(line,"init=",5)) {
  16.485 +			line += 5;
  16.486 +			execute_command = line;
  16.487 +			/* In case LILO is going to boot us with default command line,
  16.488 +			 * it prepends "auto" before the whole cmdline which makes
  16.489 +			 * the shell think it should execute a script with such name.
  16.490 +			 * So we ignore all arguments entered _before_ init=... [MJ]
  16.491 +			 */
  16.492 +			args = 0;
  16.493 +			continue;
  16.494 +		}
  16.495 +		if (checksetup(line))
  16.496 +			continue;
  16.497 +		
  16.498 +		/*
  16.499 +		 * Then check if it's an environment variable or
  16.500 +		 * an option.
  16.501 +		 */
  16.502 +		if (strchr(line,'=')) {
  16.503 +			if (envs >= MAX_INIT_ENVS)
  16.504 +				break;
  16.505 +			envp_init[++envs] = line;
  16.506 +		} else {
  16.507 +			if (args >= MAX_INIT_ARGS)
  16.508 +				break;
  16.509 +			if (*line)
  16.510 +				argv_init[++args] = line;
  16.511 +		}
  16.512 +	}
  16.513 +	argv_init[args+1] = NULL;
  16.514 +	envp_init[envs+1] = NULL;
  16.515 +}
  16.516 +
  16.517 +
  16.518 +extern void setup_arch(char **);
  16.519 +extern void cpu_idle(void);
  16.520 +
  16.521 +unsigned long wait_init_idle;
  16.522 +
  16.523 +#ifndef CONFIG_SMP
  16.524 +
  16.525 +#ifdef CONFIG_X86_LOCAL_APIC
  16.526 +static void __init smp_init(void)
  16.527 +{
  16.528 +	APIC_init_uniprocessor();
  16.529 +}
  16.530 +#else
  16.531 +#define smp_init()	do { } while (0)
  16.532 +#endif
  16.533 +
  16.534 +#else
  16.535 +
  16.536 +
  16.537 +/* Called by boot processor to activate the rest. */
  16.538 +static void __init smp_init(void)
  16.539 +{
  16.540 +	/* Get other processors into their bootup holding patterns. */
  16.541 +	smp_boot_cpus();
  16.542 +	wait_init_idle = cpu_online_map;
  16.543 +	clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */
  16.544 +
  16.545 +	smp_threads_ready=1;
  16.546 +	smp_commence();
  16.547 +
  16.548 +	/* Wait for the other cpus to set up their idle processes */
  16.549 +	printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle);
  16.550 +	while (wait_init_idle) {
  16.551 +		cpu_relax();
  16.552 +		barrier();
  16.553 +	}
  16.554 +	printk("All processors have done init_idle\n");
  16.555 +}
  16.556 +
  16.557 +#endif
  16.558 +
  16.559 +/*
  16.560 + * We need to finalize in a non-__init function or else race conditions
  16.561 + * between the root thread and the init thread may cause start_kernel to
  16.562 + * be reaped by free_initmem before the root thread has proceeded to
  16.563 + * cpu_idle.
  16.564 + */
  16.565 +
  16.566 +static void rest_init(void)
  16.567 +{
  16.568 +	kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
  16.569 +	unlock_kernel();
  16.570 +	current->need_resched = 1;
  16.571 + 	cpu_idle();
  16.572 +} 
  16.573 +
  16.574 +/*
  16.575 + *	Activate the first processor.
  16.576 + */
  16.577 +
  16.578 +asmlinkage void __init start_kernel(void)
  16.579 +{
  16.580 +	char * command_line;
  16.581 +	unsigned long mempages;
  16.582 +	extern char saved_command_line[];
  16.583 +/*
  16.584 + * Interrupts are still disabled. Do necessary setups, then
  16.585 + * enable them
  16.586 + */
  16.587 +	lock_kernel();
  16.588 +	printk(linux_banner);
  16.589 +	setup_arch(&command_line);
  16.590 +	printk("Kernel command line: %s\n", saved_command_line);
  16.591 +	parse_options(command_line);
  16.592 +	trap_init();
  16.593 +	init_IRQ();
  16.594 +	sched_init();
  16.595 +	softirq_init();
  16.596 +	time_init();
  16.597 +
  16.598 +	/*
  16.599 +	 * HACK ALERT! This is early. We're enabling the console before
  16.600 +	 * we've done PCI setups etc, and console_init() must be aware of
  16.601 +	 * this. But we do want output early, in case something goes wrong.
  16.602 +	 */
  16.603 +	console_init();
  16.604 +#ifdef CONFIG_MODULES
  16.605 +	init_modules();
  16.606 +#endif
  16.607 +	if (prof_shift) {
  16.608 +		unsigned int size;
  16.609 +		/* only text is profiled */
  16.610 +		prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
  16.611 +		prof_len >>= prof_shift;
  16.612 +		
  16.613 +		size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
  16.614 +		prof_buffer = (unsigned int *) alloc_bootmem(size);
  16.615 +	}
  16.616 +
  16.617 +	kmem_cache_init();
  16.618 +	sti();
  16.619 +	calibrate_delay();
  16.620 +#ifdef CONFIG_BLK_DEV_INITRD
  16.621 +	if (initrd_start && !initrd_below_start_ok &&
  16.622 +			initrd_start < min_low_pfn << PAGE_SHIFT) {
  16.623 +		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
  16.624 +		    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
  16.625 +		initrd_start = 0;
  16.626 +	}
  16.627 +#endif
  16.628 +	mem_init();
  16.629 +	kmem_cache_sizes_init();
  16.630 +#if defined(CONFIG_KDB)
  16.631 +	kdb_init();
  16.632 +	if (KDB_FLAG(EARLYKDB)) {
  16.633 +		KDB_ENTER();
  16.634 +	}
  16.635 +#endif
  16.636 +	mempages = num_physpages;
  16.637 +
  16.638 +	fork_init(mempages);
  16.639 +	proc_caches_init();
  16.640 +	vfs_caches_init(mempages);
  16.641 +	buffer_init(mempages);
  16.642 +	page_cache_init(mempages);
  16.643 +#if defined(CONFIG_ARCH_S390)
  16.644 +	ccwcache_init();
  16.645 +#endif
  16.646 +	signals_init();
  16.647 +#ifdef CONFIG_PROC_FS
  16.648 +	proc_root_init();
  16.649 +#endif
  16.650 +#if defined(CONFIG_SYSVIPC)
  16.651 +	ipc_init();
  16.652 +#endif
  16.653 +	check_bugs();
  16.654 +	printk("POSIX conformance testing by UNIFIX\n");
  16.655 +
  16.656 +	/* 
  16.657 +	 *	We count on the initial thread going ok 
  16.658 +	 *	Like idlers init is an unlocked kernel thread, which will
  16.659 +	 *	make syscalls (and thus be locked).
  16.660 +	 */
  16.661 +	smp_init();
  16.662 +	rest_init();
  16.663 +}
  16.664 +
  16.665 +#ifdef CONFIG_BLK_DEV_INITRD
  16.666 +static int do_linuxrc(void * shell)
  16.667 +{
  16.668 +	static char *argv[] = { "linuxrc", NULL, };
  16.669 +
  16.670 +	close(0);close(1);close(2);
  16.671 +	setsid();
  16.672 +	(void) open("/dev/console",O_RDWR,0);
  16.673 +	(void) dup(0);
  16.674 +	(void) dup(0);
  16.675 +	return execve(shell, argv, envp_init);
  16.676 +}
  16.677 +
  16.678 +#endif
  16.679 +
  16.680 +struct task_struct *child_reaper = &init_task;
  16.681 +
  16.682 +static void __init do_initcalls(void)
  16.683 +{
  16.684 +	initcall_t *call;
  16.685 +
  16.686 +	call = &__initcall_start;
  16.687 +	do {
  16.688 +		(*call)();
  16.689 +		call++;
  16.690 +	} while (call < &__initcall_end);
  16.691 +
  16.692 +	/* Make sure there is no pending stuff from the initcall sequence */
  16.693 +	flush_scheduled_tasks();
  16.694 +}
  16.695 +
  16.696 +/*
  16.697 + * Ok, the machine is now initialized. None of the devices
  16.698 + * have been touched yet, but the CPU subsystem is up and
  16.699 + * running, and memory and process management works.
  16.700 + *
  16.701 + * Now we can finally start doing some real work..
  16.702 + */
  16.703 +static void __init do_basic_setup(void)
  16.704 +{
  16.705 +
  16.706 +	/*
  16.707 +	 * Tell the world that we're going to be the grim
  16.708 +	 * reaper of innocent orphaned children.
  16.709 +	 *
  16.710 +	 * We don't want people to have to make incorrect
  16.711 +	 * assumptions about where in the task array this
  16.712 +	 * can be found.
  16.713 +	 */
  16.714 +	child_reaper = current;
  16.715 +
  16.716 +#if defined(CONFIG_MTRR)	/* Do this after SMP initialization */
  16.717 +/*
  16.718 + * We should probably create some architecture-dependent "fixup after
  16.719 + * everything is up" style function where this would belong better
  16.720 + * than in init/main.c..
  16.721 + */
  16.722 +	mtrr_init();
  16.723 +#endif
  16.724 +
  16.725 +#ifdef CONFIG_SYSCTL
  16.726 +	sysctl_init();
  16.727 +#endif
  16.728 +
  16.729 +	/*
  16.730 +	 * Ok, at this point all CPU's should be initialized, so
  16.731 +	 * we can start looking into devices..
  16.732 +	 */
  16.733 +#if defined(CONFIG_ARCH_S390)
  16.734 +	s390_init_machine_check();
  16.735 +#endif
  16.736 +
  16.737 +#ifdef CONFIG_PCI
  16.738 +	pci_init();
  16.739 +#endif
  16.740 +#ifdef CONFIG_SBUS
  16.741 +	sbus_init();
  16.742 +#endif
  16.743 +#if defined(CONFIG_PPC)
  16.744 +	ppc_init();
  16.745 +#endif
  16.746 +#ifdef CONFIG_MCA
  16.747 +	mca_init();
  16.748 +#endif
  16.749 +#ifdef CONFIG_ARCH_ACORN
  16.750 +	ecard_init();
  16.751 +#endif
  16.752 +#ifdef CONFIG_ZORRO
  16.753 +	zorro_init();
  16.754 +#endif
  16.755 +#ifdef CONFIG_DIO
  16.756 +	dio_init();
  16.757 +#endif
  16.758 +#ifdef CONFIG_NUBUS
  16.759 +	nubus_init();
  16.760 +#endif
  16.761 +#ifdef CONFIG_ISAPNP
  16.762 +	isapnp_init();
  16.763 +#endif
  16.764 +#ifdef CONFIG_TC
  16.765 +	tc_init();
  16.766 +#endif
  16.767 +
  16.768 +	/* Networking initialization needs a process context */ 
  16.769 +	sock_init();
  16.770 +
  16.771 +	start_context_thread();
  16.772 +	do_initcalls();
  16.773 +
  16.774 +#ifdef CONFIG_IRDA
  16.775 +	irda_proto_init();
  16.776 +	irda_device_init(); /* Must be done after protocol initialization */
  16.777 +#endif
  16.778 +#ifdef CONFIG_PCMCIA
  16.779 +	init_pcmcia_ds();		/* Do this last */
  16.780 +#endif
  16.781 +}
  16.782 +
  16.783 +extern void rd_load(void);
  16.784 +extern void initrd_load(void);
  16.785 +
  16.786 +/*
  16.787 + * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
  16.788 + */
  16.789 +static void prepare_namespace(void)
  16.790 +{
  16.791 +#ifdef CONFIG_BLK_DEV_INITRD
  16.792 +	int real_root_mountflags = root_mountflags;
  16.793 +	if (!initrd_start)
  16.794 +		mount_initrd = 0;
  16.795 +	if (mount_initrd)
  16.796 +		root_mountflags &= ~MS_RDONLY;
  16.797 +	real_root_dev = ROOT_DEV;
  16.798 +#endif
  16.799 +
  16.800 +#ifdef CONFIG_BLK_DEV_RAM
  16.801 +#ifdef CONFIG_BLK_DEV_INITRD
  16.802 +	if (mount_initrd)
  16.803 +		initrd_load();
  16.804 +	else
  16.805 +#endif
  16.806 +	rd_load();
  16.807 +#endif
  16.808 +
  16.809 +	/* Mount the root filesystem.. */
  16.810 +	mount_root();
  16.811 +
  16.812 +	mount_devfs_fs ();
  16.813 +
  16.814 +#ifdef CONFIG_BLK_DEV_INITRD
  16.815 +	root_mountflags = real_root_mountflags;
  16.816 +	if (mount_initrd && ROOT_DEV != real_root_dev
  16.817 +	    && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
  16.818 +		int error;
  16.819 +		int i, pid;
  16.820 +
  16.821 +		pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
  16.822 +		if (pid > 0) {
  16.823 +			while (pid != wait(&i)) {
  16.824 +				current->policy |= SCHED_YIELD;
  16.825 +				schedule();
  16.826 +			}
  16.827 +		}
  16.828 +		if (MAJOR(real_root_dev) != RAMDISK_MAJOR
  16.829 +		     || MINOR(real_root_dev) != 0) {
  16.830 +			error = change_root(real_root_dev,"/initrd");
  16.831 +			if (error)
  16.832 +				printk(KERN_ERR "Change root to /initrd: "
  16.833 +				    "error %d\n",error);
  16.834 +		}
  16.835 +	}
  16.836 +#endif
  16.837 +}
  16.838 +
  16.839 +static int init(void * unused)
  16.840 +{
  16.841 +	lock_kernel();
  16.842 +	do_basic_setup();
  16.843 +
  16.844 +	prepare_namespace();
  16.845 +
  16.846 +	/*
  16.847 +	 * Ok, we have completed the initial bootup, and
  16.848 +	 * we're essentially up and running. Get rid of the
  16.849 +	 * initmem segments and start the user-mode stuff..
  16.850 +	 */
  16.851 +	free_initmem();
  16.852 +	unlock_kernel();
  16.853 +
  16.854 +	if (open("/dev/console", O_RDWR, 0) < 0)
  16.855 +		printk("Warning: unable to open an initial console.\n");
  16.856 +
  16.857 +	(void) dup(0);
  16.858 +	(void) dup(0);
  16.859 +	
  16.860 +	/*
  16.861 +	 * We try each of these until one succeeds.
  16.862 +	 *
  16.863 +	 * The Bourne shell can be used instead of init if we are 
  16.864 +	 * trying to recover a really broken machine.
  16.865 +	 */
  16.866 +
  16.867 +	if (execute_command)
  16.868 +		execve(execute_command,argv_init,envp_init);
  16.869 +	execve("/sbin/init",argv_init,envp_init);
  16.870 +	execve("/etc/init",argv_init,envp_init);
  16.871 +	execve("/bin/init",argv_init,envp_init);
  16.872 +	execve("/bin/sh",argv_init,envp_init);
  16.873 +	panic("No init found.  Try passing init= option to kernel.");
  16.874 +}