ia64/xen-unstable

changeset 152:42a318e8648e

bitkeeper revision 1.27 (3e4bc0aaYLPRPEot-3f6sspi3HC6Xg)

Merge with recent checkins
author rn@wyvis.camb.intel-research.net
date Thu Feb 13 15:58:34 2003 +0000 (2003-02-13)
parents 4bd6c4bfc2b3 0834a70d2e19
children 5b394412fded
files .rootkeys BitKeeper/etc/ignore xen-2.4.16/Rules.mk xen-2.4.16/arch/i386/entry.S xen-2.4.16/arch/i386/io_apic.c xen-2.4.16/arch/i386/mpparse.c xen-2.4.16/arch/i386/process.c xen-2.4.16/arch/i386/setup.c xen-2.4.16/arch/i386/smpboot.c xen-2.4.16/arch/i386/traps.c xen-2.4.16/common/event.c xen-2.4.16/drivers/Makefile xen-2.4.16/drivers/block/ll_rw_blk.c 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 xen-2.4.16/drivers/ide/ide-disk.c.orig xen-2.4.16/drivers/ide/ide-probe.c xen-2.4.16/drivers/ide/ide-taskfile.c xen-2.4.16/drivers/ide/ide-xeno.c xen-2.4.16/drivers/ide/ide.c xen-2.4.16/drivers/ide/piix.c xen-2.4.16/drivers/net/Makefile xen-2.4.16/drivers/net/e1000/e1000.h xen-2.4.16/drivers/net/e1000/e1000_hw.c xen-2.4.16/drivers/net/e1000/e1000_main.c xen-2.4.16/drivers/net/e1000/e1000_osdep.h xen-2.4.16/include/asm-i386/apic.h xen-2.4.16/include/asm-i386/apicdef.h xen-2.4.16/include/asm-i386/io_apic.h xen-2.4.16/include/asm-i386/mpspec.h xen-2.4.16/include/asm-i386/processor.h xen-2.4.16/include/asm-i386/smpboot.h xen-2.4.16/include/hypervisor-ifs/block.h xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h xen-2.4.16/include/xeno/blkdev.h xen-2.4.16/include/xeno/config.h xen-2.4.16/include/xeno/sched.h xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile 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/drivers/block/ll_rw_blk.c xenolinux-2.4.16-sparse/fs/partitions/check.c xenolinux-2.4.16-sparse/fs/partitions/msdos.c xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h 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	Tue Feb 11 17:54:17 2003 +0000
     1.2 +++ b/.rootkeys	Thu Feb 13 15:58:34 2003 +0000
     1.3 @@ -59,16 +59,23 @@ 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  3ddb79bdYcxXT-2UEaDcG0Ic4MIK1g xen-2.4.16/drivers/ide/ide-pci.c
    1.18  3ddb79bdOXTbcImJo8DwmlNX88k78Q xen-2.4.16/drivers/ide/ide-probe.c
    1.19  3ddb79bdDWFwINnKn29RlFDwGJhjYg xen-2.4.16/drivers/ide/ide-taskfile.c
    1.20 +3e4a8d40XMqvT05EwZwJg1HMsFDUBA xen-2.4.16/drivers/ide/ide-xeno.c
    1.21  3ddb79bdkDY1bSOYkToP1Cc49VdBxg xen-2.4.16/drivers/ide/ide.c
    1.22  3ddb79bdPyAvT_WZTAFhaX0jp-yXSw xen-2.4.16/drivers/ide/ide_modes.h
    1.23 +3e4a8d401aSwOzCScQXR3lsmNlAwUQ xen-2.4.16/drivers/ide/piix.c
    1.24  3ddb79bfogeJNHTIepPjd8fy1TyoTw xen-2.4.16/drivers/net/3c509.c
    1.25  3ddb79bfMlOcWUwjtg6oMYhGySHDDw xen-2.4.16/drivers/net/3c59x.c
    1.26  3ddb79bfl_DWxZQFKiJ2BXrSedV4lg xen-2.4.16/drivers/net/8139cp.c
    1.27 @@ -271,9 +278,12 @@ 3ddb79b8L4xnwrcvWk6nAbgKVbNkSA xenolinux
    1.28  3ddb79b7v_Be34as7_mlzFlw65hOjQ xenolinux-2.4.16-sparse/arch/xeno/defconfig
    1.29  3ddb79b7KUvtx0knQJoRaBDZQeNidg xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile
    1.30  3ddb79b6Rc0uAOGFthIFxq1KGWZ_Iw xenolinux-2.4.16-sparse/arch/xeno/drivers/block/block.c
    1.31 +3e4a8cb7JECr--r1ipnrkd7NKdbUqQ xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c
    1.32 +3e4a8cb7SLWsLTXQjv7ng6-3hL4pCA xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c
    1.33  3ddb79b7LLVJBGynxHSOh9A9l97sug xenolinux-2.4.16-sparse/arch/xeno/drivers/console/Makefile
    1.34  3ddb79b7UG2QiRAU-Wvc1Y_BLigu1Q xenolinux-2.4.16-sparse/arch/xeno/drivers/console/console.c
    1.35  3ddb79b75eo4PRXkT6Th9popt_SJhg xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/Makefile
    1.36 +3e4a8cb79dT0F4q5T4GEqMj4CtAquQ xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_block.c
    1.37  3ddb79b7Xyaoep6U0kLvx6Kx7OauDw xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c
    1.38  3df9ce13K7qSLBtHV-01QHPW62649Q xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_memory.c
    1.39  3ddb79b7PulSkF9m3c7K5MkxHRf4hA xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_ops.h
    1.40 @@ -317,10 +327,13 @@ 3ddb79b85fpsKT8A9WYnuJg03b715g xenolinux
    1.41  3ddb79b83Zj7Xn2QVhU4HeMuAC9FjA xenolinux-2.4.16-sparse/arch/xeno/mm/init.c
    1.42  3df9ce13TRWIv0Mawm15zESP7jcT7A xenolinux-2.4.16-sparse/arch/xeno/mm/mmu_context.c
    1.43  3ddb79b7aKdTkbr3u6aze8tVwGh_TQ xenolinux-2.4.16-sparse/arch/xeno/vmlinux.lds
    1.44 +3e4a8cb7lpFFwT1Iu9zXWc8Ew4klFA xenolinux-2.4.16-sparse/drivers/block/Config.in
    1.45  3ddb79bbx682YH6vR2zbVOXwg73ULg xenolinux-2.4.16-sparse/drivers/block/ll_rw_blk.c
    1.46  3ddb79bcJfHdwrPsjqgI33_OsGdVCg xenolinux-2.4.16-sparse/drivers/block/rd.c
    1.47  3ddb79bcpVu-IbnqwQqpRqsEbLpsuw xenolinux-2.4.16-sparse/drivers/char/tty_io.c
    1.48  3e15d5273gfR2fbcYe05kqBSAvCX_w xenolinux-2.4.16-sparse/fs/exec.c
    1.49 +3e4a8cb7kqfJTMeOpPcYxqxv7N18DA xenolinux-2.4.16-sparse/fs/partitions/check.c
    1.50 +3e4a8cb7p079Xxly4uNcouacMSjJLw xenolinux-2.4.16-sparse/fs/partitions/msdos.c
    1.51  3ddb79b8VFtfWSCrXKPN2K21zd_vtw xenolinux-2.4.16-sparse/include/asm-xeno/a.out.h
    1.52  3ddb79b8Zzi13p3OAPV25QgiC3THAQ xenolinux-2.4.16-sparse/include/asm-xeno/apic.h
    1.53  3ddb79baZDlsdV_m6C5CXnWMl15p1g xenolinux-2.4.16-sparse/include/asm-xeno/apicdef.h
    1.54 @@ -426,7 +439,10 @@ 3ddb79bb3cMSs_k2X5Oq2hOIBvmPYA xenolinux
    1.55  3ddb79ba2qYtIQAT_-vCFkkZUXu_UQ xenolinux-2.4.16-sparse/include/asm-xeno/user.h
    1.56  3ddb79bbqhb9X9qWOz5Bv4wOzrkITg xenolinux-2.4.16-sparse/include/asm-xeno/vga.h
    1.57  3ddb79bbA52x94o6uwDYsbzrH2hjzA xenolinux-2.4.16-sparse/include/asm-xeno/xor.h
    1.58 +3e4a8cb7ON8EclY3NN3YPXyMT941hA xenolinux-2.4.16-sparse/include/linux/blk.h
    1.59 +3e4a8cb7GJrKD0z7EF0VZOhdEa01Mw xenolinux-2.4.16-sparse/include/linux/major.h
    1.60  3ddb79bb_7YG4U75ZmEic9YXWTW7Vw xenolinux-2.4.16-sparse/include/linux/sunrpc/debug.h
    1.61 +3e4a8cb7j05wwb1uPZgY16s68o7qAw xenolinux-2.4.16-sparse/init/main.c
    1.62  3ddb79bcxkVPfWlZ1PQKvDrfArzOVw xenolinux-2.4.16-sparse/kernel/panic.c
    1.63  3ddb79bbP31im-mx2NbfthSeqty1Dg xenolinux-2.4.16-sparse/mk
    1.64  3e15d52e0_j129JPvo7xfYGndVFpwQ xenolinux-2.4.16-sparse/mm/memory.c
     2.1 --- a/BitKeeper/etc/ignore	Tue Feb 11 17:54:17 2003 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Thu Feb 13 15:58:34 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 --- a/xen-2.4.16/Rules.mk	Tue Feb 11 17:54:17 2003 +0000
     3.2 +++ b/xen-2.4.16/Rules.mk	Thu Feb 13 15:58:34 2003 +0000
     3.3 @@ -15,6 +15,7 @@ OBJS    += $(patsubst %.c,%.o,$(C_SRCS))
     3.4  # Note that link order matters!
     3.5  ALL_OBJS := $(BASEDIR)/common/common.o
     3.6  ALL_OBJS += $(BASEDIR)/net/network.o
     3.7 +ALL_OBJS += $(BASEDIR)/drivers/char/driver.o
     3.8  ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o
     3.9  ALL_OBJS += $(BASEDIR)/drivers/net/driver.o
    3.10  ALL_OBJS += $(BASEDIR)/drivers/block/driver.o
     4.1 --- a/xen-2.4.16/arch/i386/entry.S	Tue Feb 11 17:54:17 2003 +0000
     4.2 +++ b/xen-2.4.16/arch/i386/entry.S	Thu Feb 13 15:58:34 2003 +0000
     4.3 @@ -524,6 +524,7 @@ ENTRY(hypervisor_call_table)
     4.4          .long SYMBOL_NAME(kill_domain)
     4.5          .long SYMBOL_NAME(do_dom0_op)
     4.6          .long SYMBOL_NAME(do_network_op)
     4.7 +        .long SYMBOL_NAME(do_block_io_op)
     4.8          .long SYMBOL_NAME(do_set_debugreg)
     4.9          .long SYMBOL_NAME(do_get_debugreg)
    4.10          .long SYMBOL_NAME(do_update_descriptor)
     5.1 --- a/xen-2.4.16/arch/i386/io_apic.c	Tue Feb 11 17:54:17 2003 +0000
     5.2 +++ b/xen-2.4.16/arch/i386/io_apic.c	Thu Feb 13 15:58:34 2003 +0000
     5.3 @@ -28,11 +28,23 @@
     5.4  #include <xeno/config.h>
     5.5  #include <asm/mc146818rtc.h>
     5.6  #include <asm/io.h>
     5.7 +#include <asm/smp.h>
     5.8  #include <asm/desc.h>
     5.9 -#include <asm/smp.h>
    5.10 +#include <asm/smpboot.h>
    5.11 +
    5.12 +
    5.13 +static unsigned int nmi_watchdog;  /* XXXX XEN */
    5.14 +
    5.15 +#undef APIC_LOCKUP_DEBUG
    5.16 +
    5.17 +#define APIC_LOCKUP_DEBUG
    5.18  
    5.19  static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
    5.20  
    5.21 +unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL;
    5.22 +unsigned char int_delivery_mode = dest_LowestPrio;
    5.23 +
    5.24 +
    5.25  /*
    5.26   * # of IRQ routing registers
    5.27   */
    5.28 @@ -47,6 +59,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
    5.29  
    5.30  /*
    5.31   * This is performance-critical, we want to do it O(1)
    5.32 + *
    5.33   * the indexing order of this array favors 1:1 mappings
    5.34   * between pins and IRQs.
    5.35   */
    5.36 @@ -60,7 +73,7 @@ static struct irq_pin_list {
    5.37   * shared ISA-space IRQs, so we have to support them. We are super
    5.38   * fast in the common case, and fast for shared ISA-space IRQs.
    5.39   */
    5.40 -static void add_pin_to_irq(unsigned int irq, int apic, int pin)
    5.41 +static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
    5.42  {
    5.43  	static int first_free_entry = NR_IRQS;
    5.44  	struct irq_pin_list *entry = irq_2_pin + irq;
    5.45 @@ -78,6 +91,26 @@ static void add_pin_to_irq(unsigned int 
    5.46  	entry->pin = pin;
    5.47  }
    5.48  
    5.49 +/*
    5.50 + * Reroute an IRQ to a different pin.
    5.51 + */
    5.52 +static void __init replace_pin_at_irq(unsigned int irq,
    5.53 +				      int oldapic, int oldpin,
    5.54 +				      int newapic, int newpin)
    5.55 +{
    5.56 +	struct irq_pin_list *entry = irq_2_pin + irq;
    5.57 +
    5.58 +	while (1) {
    5.59 +		if (entry->apic == oldapic && entry->pin == oldpin) {
    5.60 +			entry->apic = newapic;
    5.61 +			entry->pin = newpin;
    5.62 +		}
    5.63 +		if (!entry->next)
    5.64 +			break;
    5.65 +		entry = irq_2_pin + entry->next;
    5.66 +	}
    5.67 +}
    5.68 +
    5.69  #define __DO_ACTION(R, ACTION, FINAL)					\
    5.70  									\
    5.71  {									\
    5.72 @@ -157,6 +190,66 @@ static void clear_IO_APIC (void)
    5.73  }
    5.74  
    5.75  /*
    5.76 + * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
    5.77 + * specific CPU-side IRQs.
    5.78 + */
    5.79 +
    5.80 +#define MAX_PIRQS 8
    5.81 +int pirq_entries [MAX_PIRQS];
    5.82 +int pirqs_enabled;
    5.83 +
    5.84 +int skip_ioapic_setup;
    5.85 +#if 0
    5.86 +
    5.87 +static int __init noioapic_setup(char *str)
    5.88 +{
    5.89 +	skip_ioapic_setup = 1;
    5.90 +	return 1;
    5.91 +}
    5.92 +
    5.93 +__setup("noapic", noioapic_setup);
    5.94 +
    5.95 +static int __init ioapic_setup(char *str)
    5.96 +{
    5.97 +	skip_ioapic_setup = 0;
    5.98 +	return 1;
    5.99 +}
   5.100 +
   5.101 +__setup("apic", ioapic_setup);
   5.102 +
   5.103 +
   5.104 +
   5.105 +static int __init ioapic_pirq_setup(char *str)
   5.106 +{
   5.107 +	int i, max;
   5.108 +	int ints[MAX_PIRQS+1];
   5.109 +
   5.110 +	get_options(str, ARRAY_SIZE(ints), ints);
   5.111 +
   5.112 +	for (i = 0; i < MAX_PIRQS; i++)
   5.113 +		pirq_entries[i] = -1;
   5.114 +
   5.115 +	pirqs_enabled = 1;
   5.116 +	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
   5.117 +	max = MAX_PIRQS;
   5.118 +	if (ints[0] < MAX_PIRQS)
   5.119 +		max = ints[0];
   5.120 +
   5.121 +	for (i = 0; i < max; i++) {
   5.122 +		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
   5.123 +		/*
   5.124 +		 * PIRQs are mapped upside down, usually.
   5.125 +		 */
   5.126 +		pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
   5.127 +	}
   5.128 +	return 1;
   5.129 +}
   5.130 +
   5.131 +__setup("pirq=", ioapic_pirq_setup);
   5.132 +
   5.133 +#endif
   5.134 +
   5.135 +/*
   5.136   * Find the IRQ entry number of a certain pin.
   5.137   */
   5.138  static int __init find_irq_entry(int apic, int pin, int type)
   5.139 @@ -206,7 +299,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, 
   5.140  
   5.141  	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
   5.142  		bus, slot, pin);
   5.143 -	if (mp_bus_id_to_pci_bus[bus] == -1) {
   5.144 +	if ((mp_bus_id_to_pci_bus==NULL) || (mp_bus_id_to_pci_bus[bus] == -1)) {
   5.145  		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
   5.146  		return -1;
   5.147  	}
   5.148 @@ -466,6 +559,20 @@ static int pin_2_irq(int idx, int apic, 
   5.149  		}
   5.150  	}
   5.151  
   5.152 +	/*
   5.153 +	 * PCI IRQ command line redirection. Yes, limits are hardcoded.
   5.154 +	 */
   5.155 +	if ((pin >= 16) && (pin <= 23)) {
   5.156 +		if (pirq_entries[pin-16] != -1) {
   5.157 +			if (!pirq_entries[pin-16]) {
   5.158 +				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
   5.159 +			} else {
   5.160 +				irq = pirq_entries[pin-16];
   5.161 +				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
   5.162 +						pin-16, irq);
   5.163 +			}
   5.164 +		}
   5.165 +	}
   5.166  	return irq;
   5.167  }
   5.168  
   5.169 @@ -495,11 +602,17 @@ static int __init assign_irq_vector(int 
   5.170  		return IO_APIC_VECTOR(irq);
   5.171  next:
   5.172  	current_vector += 8;
   5.173 +
   5.174          /* XXX Skip the guestOS -> Xen syscall vector! XXX */
   5.175  	if (current_vector == HYPERVISOR_CALL_VECTOR) goto next;
   5.176          /* XXX Skip the Linux/BSD fast-trap vector! XXX */
   5.177          if (current_vector == 0x80) goto next;
   5.178  
   5.179 +#if 0
   5.180 +	if (current_vector == SYSCALL_VECTOR)
   5.181 +		goto next;
   5.182 +#endif
   5.183 +
   5.184  	if (current_vector > FIRST_SYSTEM_VECTOR) {
   5.185  		offset++;
   5.186  		current_vector = FIRST_DEVICE_VECTOR + offset;
   5.187 @@ -532,10 +645,10 @@ void __init setup_IO_APIC_irqs(void)
   5.188  		 */
   5.189  		memset(&entry,0,sizeof(entry));
   5.190  
   5.191 -		entry.delivery_mode = dest_LowestPrio;
   5.192 -		entry.dest_mode = INT_DELIVERY_MODE;
   5.193 +		entry.delivery_mode = INT_DELIVERY_MODE;
   5.194 +		entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
   5.195  		entry.mask = 0;				/* enable IRQ */
   5.196 -		entry.dest.logical.logical_dest = TARGET_CPUS;
   5.197 +		entry.dest.logical.logical_dest = target_cpus();
   5.198  
   5.199  		idx = find_irq_entry(apic,pin,mp_INT);
   5.200  		if (idx == -1) {
   5.201 @@ -553,11 +666,18 @@ void __init setup_IO_APIC_irqs(void)
   5.202  		if (irq_trigger(idx)) {
   5.203  			entry.trigger = 1;
   5.204  			entry.mask = 1;
   5.205 -			entry.dest.logical.logical_dest = TARGET_CPUS;
   5.206  		}
   5.207  
   5.208  		irq = pin_2_irq(idx, apic, pin);
   5.209 -		add_pin_to_irq(irq, apic, pin);
   5.210 +		/*
   5.211 +		 * skip adding the timer int on secondary nodes, which causes
   5.212 +		 * a small but painful rift in the time-space continuum
   5.213 +		 */
   5.214 +		if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) 
   5.215 +			&& (apic != 0) && (irq == 0))
   5.216 +			continue;
   5.217 +		else
   5.218 +			add_pin_to_irq(irq, apic, pin);
   5.219  
   5.220  		if (!apic && !IO_APIC_IRQ(irq))
   5.221  			continue;
   5.222 @@ -607,16 +727,16 @@ void __init setup_ExtINT_IRQ0_pin(unsign
   5.223  	 * We use logical delivery to get the timer IRQ
   5.224  	 * to the first CPU.
   5.225  	 */
   5.226 -	entry.dest_mode = INT_DELIVERY_MODE;
   5.227 +	entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
   5.228  	entry.mask = 0;					/* unmask IRQ now */
   5.229 -	entry.dest.logical.logical_dest = TARGET_CPUS;
   5.230 -	entry.delivery_mode = dest_LowestPrio;
   5.231 +	entry.dest.logical.logical_dest = target_cpus();
   5.232 +	entry.delivery_mode = INT_DELIVERY_MODE;
   5.233  	entry.polarity = 0;
   5.234  	entry.trigger = 0;
   5.235  	entry.vector = vector;
   5.236  
   5.237  	/*
   5.238 -	 * The timer IRQ doesnt have to know that behind the
   5.239 +	 * The timer IRQ doesn't have to know that behind the
   5.240  	 * scene we have a 8259A-master in AEOI mode ...
   5.241  	 */
   5.242  	irq_desc[0].handler = &ioapic_edge_irq_type;
   5.243 @@ -634,8 +754,9 @@ void __init setup_ExtINT_IRQ0_pin(unsign
   5.244  
   5.245  void __init UNEXPECTED_IO_APIC(void)
   5.246  {
   5.247 -	printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");
   5.248 -	printk(KERN_WARNING "          to linux-smp@vger.kernel.org\n");
   5.249 +	printk(KERN_WARNING 
   5.250 +		"An unexpected IO-APIC was found. If this kernel release is less than\n"
   5.251 +		"three months old please report this to linux-smp@vger.kernel.org\n");
   5.252  }
   5.253  
   5.254  void __init print_IO_APIC(void)
   5.255 @@ -667,7 +788,7 @@ void __init print_IO_APIC(void)
   5.256  	spin_unlock_irqrestore(&ioapic_lock, flags);
   5.257  
   5.258  	printk("\n");
   5.259 -	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
   5.260 +	printk(KERN_DEBUG "IO APIC #%d..XXXX....\n", mp_ioapics[apic].mpc_apicid);
   5.261  	printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);
   5.262  	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.ID);
   5.263  	if (reg_00.__reserved_1 || reg_00.__reserved_2)
   5.264 @@ -688,6 +809,7 @@ void __init print_IO_APIC(void)
   5.265  	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.PRQ);
   5.266  	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.version);
   5.267  	if (	(reg_01.version != 0x01) && /* 82489DX IO-APICs */
   5.268 +		(reg_01.version != 0x02) && /* VIA */
   5.269  		(reg_01.version != 0x10) && /* oldest IO-APICs */
   5.270  		(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
   5.271  		(reg_01.version != 0x13) && /* Xeon IO-APICs */
   5.272 @@ -898,6 +1020,9 @@ static void __init enable_IO_APIC(void)
   5.273  		irq_2_pin[i].pin = -1;
   5.274  		irq_2_pin[i].next = 0;
   5.275  	}
   5.276 +	if (!pirqs_enabled)
   5.277 +		for (i = 0; i < MAX_PIRQS; i++)
   5.278 +			pirq_entries[i] = -1;
   5.279  
   5.280  	/*
   5.281  	 * The number of IO-APIC IRQ registers (== #pins):
   5.282 @@ -944,6 +1069,9 @@ static void __init setup_ioapic_ids_from
   5.283  	unsigned char old_id;
   5.284  	unsigned long flags;
   5.285  
   5.286 +	if (clustered_apic_mode)
   5.287 +		/* We don't have a good way to do this yet - hack */
   5.288 +		phys_id_present_map = (u_long) 0xf;
   5.289  	/*
   5.290  	 * Set the IOAPIC ID to the value stored in the MPC table.
   5.291  	 */
   5.292 @@ -956,7 +1084,7 @@ static void __init setup_ioapic_ids_from
   5.293  		
   5.294  		old_id = mp_ioapics[apic].mpc_apicid;
   5.295  
   5.296 -		if (mp_ioapics[apic].mpc_apicid >= 0xf) {
   5.297 +		if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) {
   5.298  			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
   5.299  				apic, mp_ioapics[apic].mpc_apicid);
   5.300  			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
   5.301 @@ -968,14 +1096,16 @@ static void __init setup_ioapic_ids_from
   5.302  		 * Sanity check, is the ID really free? Every APIC in a
   5.303  		 * system must have a unique ID or we get lots of nice
   5.304  		 * 'stuck on smp_invalidate_needed IPI wait' messages.
   5.305 +		 * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs.
   5.306  		 */
   5.307 -		if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
   5.308 +		if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) &&
   5.309 +		    (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) {
   5.310  			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
   5.311  				apic, mp_ioapics[apic].mpc_apicid);
   5.312  			for (i = 0; i < 0xf; i++)
   5.313  				if (!(phys_id_present_map & (1 << i)))
   5.314  					break;
   5.315 -			if (i >= 0xf)
   5.316 +			if (i >= apic_broadcast_id)
   5.317  				panic("Max APIC ID exceeded!\n");
   5.318  			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
   5.319  				i);
   5.320 @@ -1170,6 +1300,10 @@ static void end_level_ioapic_irq (unsign
   5.321  #ifdef APIC_LOCKUP_DEBUG
   5.322  		struct irq_pin_list *entry;
   5.323  #endif
   5.324 +
   5.325 +#ifdef APIC_MISMATCH_DEBUG
   5.326 +		atomic_inc(&irq_mis_count);
   5.327 +#endif
   5.328  		spin_lock(&ioapic_lock);
   5.329  		__mask_and_edge_IO_APIC_irq(irq);
   5.330  #ifdef APIC_LOCKUP_DEBUG
   5.331 @@ -1302,6 +1436,36 @@ static struct hw_interrupt_type lapic_ir
   5.332  	end_lapic_irq
   5.333  };
   5.334  
   5.335 +static void enable_NMI_through_LVT0 (void * dummy)
   5.336 +{
   5.337 +	unsigned int v, ver;
   5.338 +
   5.339 +	ver = apic_read(APIC_LVR);
   5.340 +	ver = GET_APIC_VERSION(ver);
   5.341 +	v = APIC_DM_NMI;			/* unmask and set to NMI */
   5.342 +	if (!APIC_INTEGRATED(ver))		/* 82489DX */
   5.343 +		v |= APIC_LVT_LEVEL_TRIGGER;
   5.344 +	apic_write_around(APIC_LVT0, v);
   5.345 +}
   5.346 +
   5.347 +static void setup_nmi (void)
   5.348 +{
   5.349 +	/*
   5.350 + 	 * Dirty trick to enable the NMI watchdog ...
   5.351 +	 * We put the 8259A master into AEOI mode and
   5.352 +	 * unmask on all local APICs LVT0 as NMI.
   5.353 +	 *
   5.354 +	 * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
   5.355 +	 * is from Maciej W. Rozycki - so we do not have to EOI from
   5.356 +	 * the NMI handler or the timer interrupt.
   5.357 +	 */ 
   5.358 +	printk(KERN_INFO "activating NMI Watchdog ...");
   5.359 +
   5.360 +	smp_call_function(enable_NMI_through_LVT0, NULL, 1, 1);
   5.361 +	enable_NMI_through_LVT0(NULL);
   5.362 +
   5.363 +	printk(" done.\n");
   5.364 +}
   5.365  
   5.366  /*
   5.367   * This looks a bit hackish but it's about the only one way of sending
   5.368 @@ -1407,6 +1571,12 @@ static inline void check_timer(void)
   5.369  		 */
   5.370  		unmask_IO_APIC_irq(0);
   5.371  		if (timer_irq_works()) {
   5.372 +			if (nmi_watchdog == NMI_IO_APIC) {
   5.373 +				disable_8259A_irq(0);
   5.374 +				setup_nmi();
   5.375 +				enable_8259A_irq(0);
   5.376 +				// XXX Xen check_nmi_watchdog();
   5.377 +			}
   5.378  			return;
   5.379  		}
   5.380  		clear_IO_APIC_pin(0, pin1);
   5.381 @@ -1422,6 +1592,14 @@ static inline void check_timer(void)
   5.382  		setup_ExtINT_IRQ0_pin(pin2, vector);
   5.383  		if (timer_irq_works()) {
   5.384  			printk("works.\n");
   5.385 +			if (pin1 != -1)
   5.386 +				replace_pin_at_irq(0, 0, pin1, 0, pin2);
   5.387 +			else
   5.388 +				add_pin_to_irq(0, 0, pin2);
   5.389 +			if (nmi_watchdog == NMI_IO_APIC) {
   5.390 +				setup_nmi();
   5.391 +				// XXX Xen check_nmi_watchdog();
   5.392 +			}
   5.393  			return;
   5.394  		}
   5.395  		/*
   5.396 @@ -1431,6 +1609,11 @@ static inline void check_timer(void)
   5.397  	}
   5.398  	printk(" failed.\n");
   5.399  
   5.400 +	if (nmi_watchdog) {
   5.401 +		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
   5.402 +		nmi_watchdog = 0;
   5.403 +	}
   5.404 +
   5.405  	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
   5.406  
   5.407  	disable_8259A_irq(0);
   5.408 @@ -1462,10 +1645,19 @@ static inline void check_timer(void)
   5.409  }
   5.410  
   5.411  /*
   5.412 + *
   5.413   * IRQ's that are handled by the old PIC in all cases:
   5.414   * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
   5.415   *   Linux doesn't really care, as it's not actually used
   5.416   *   for any interrupt handling anyway.
   5.417 + * - There used to be IRQ13 here as well, but all
   5.418 + *   MPS-compliant must not use it for FPU coupling and we
   5.419 + *   want to use exception 16 anyway.  And there are
   5.420 + *   systems who connect it to an I/O APIC for other uses.
   5.421 + *   Thus we don't mark it special any longer.
   5.422 + *
   5.423 + * Additionally, something is definitely wrong with irq9
   5.424 + * on PIIX4 boards.
   5.425   */
   5.426  #define PIC_IRQS	(1<<2)
   5.427  
     6.1 --- a/xen-2.4.16/arch/i386/mpparse.c	Tue Feb 11 17:54:17 2003 +0000
     6.2 +++ b/xen-2.4.16/arch/i386/mpparse.c	Thu Feb 13 15:58:34 2003 +0000
     6.3 @@ -20,6 +20,10 @@
     6.4  #include <xeno/smp.h>
     6.5  #include <asm/mpspec.h>
     6.6  #include <asm/pgalloc.h>
     6.7 +#include <asm/smpboot.h>
     6.8 +#include <xeno/kernel.h>
     6.9 +
    6.10 +int numnodes = 1; /* XXX Xen */
    6.11  
    6.12  /* Have we found an MP table */
    6.13  int smp_found_config;
    6.14 @@ -29,16 +33,20 @@ int smp_found_config;
    6.15   * MP-table.
    6.16   */
    6.17  int apic_version [MAX_APICS];
    6.18 -int mp_bus_id_to_type [MAX_MP_BUSSES];
    6.19 -int mp_bus_id_to_node [MAX_MP_BUSSES];
    6.20 -int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
    6.21 +int quad_local_to_mp_bus_id [NR_CPUS/4][4];
    6.22  int mp_current_pci_id;
    6.23 +int *mp_bus_id_to_type;
    6.24 +int *mp_bus_id_to_node;
    6.25 +int *mp_bus_id_to_local;
    6.26 +int *mp_bus_id_to_pci_bus;
    6.27 +int max_mp_busses;
    6.28 +int max_irq_sources;
    6.29  
    6.30  /* I/O APIC entries */
    6.31  struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
    6.32  
    6.33  /* # of MP IRQ source entries */
    6.34 -struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
    6.35 +struct mpc_config_intsrc *mp_irqs;
    6.36  
    6.37  /* MP IRQ source entries */
    6.38  int mp_irq_entries;
    6.39 @@ -56,23 +64,32 @@ static unsigned int num_processors;
    6.40  
    6.41  /* Bitmask of physically existing CPUs */
    6.42  unsigned long phys_cpu_present_map;
    6.43 +unsigned long logical_cpu_present_map;
    6.44 +
    6.45 +#ifdef CONFIG_X86_CLUSTERED_APIC
    6.46 +unsigned char esr_disable = 0;
    6.47 +unsigned char clustered_apic_mode = CLUSTERED_APIC_NONE;
    6.48 +unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC;
    6.49 +#endif
    6.50 +unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    6.51  
    6.52  /*
    6.53   * Intel MP BIOS table parsing routines:
    6.54   */
    6.55  
    6.56 +#ifndef CONFIG_X86_VISWS_APIC
    6.57  /*
    6.58   * Checksum an MP configuration block.
    6.59   */
    6.60  
    6.61  static int __init mpf_checksum(unsigned char *mp, int len)
    6.62  {
    6.63 -    int sum = 0;
    6.64 +	int sum = 0;
    6.65  
    6.66 -    while (len--)
    6.67 -        sum += *mp++;
    6.68 +	while (len--)
    6.69 +		sum += *mp++;
    6.70  
    6.71 -    return sum & 0xFF;
    6.72 +	return sum & 0xFF;
    6.73  }
    6.74  
    6.75  /*
    6.76 @@ -81,38 +98,47 @@ static int __init mpf_checksum(unsigned 
    6.77  
    6.78  static char __init *mpc_family(int family,int model)
    6.79  {
    6.80 -    static char n[32];
    6.81 -    static char *model_defs[]=
    6.82 -    {
    6.83 -        "80486DX","80486DX",
    6.84 -        "80486SX","80486DX/2 or 80487",
    6.85 -        "80486SL","80486SX/2",
    6.86 -        "Unknown","80486DX/2-WB",
    6.87 -        "80486DX/4","80486DX/4-WB"
    6.88 -    };
    6.89 +	static char n[32];
    6.90 +	static char *model_defs[]=
    6.91 +	{
    6.92 +		"80486DX","80486DX",
    6.93 +		"80486SX","80486DX/2 or 80487",
    6.94 +		"80486SL","80486SX/2",
    6.95 +		"Unknown","80486DX/2-WB",
    6.96 +		"80486DX/4","80486DX/4-WB"
    6.97 +	};
    6.98  
    6.99 -    switch (family) {
   6.100 -    case 0x04:
   6.101 -        if (model < 10)
   6.102 -            return model_defs[model];
   6.103 -        break;
   6.104 +	switch (family) {
   6.105 +		case 0x04:
   6.106 +			if (model < 10)
   6.107 +				return model_defs[model];
   6.108 +			break;
   6.109 +
   6.110 +		case 0x05:
   6.111 +			return("Pentium(tm)");
   6.112  
   6.113 -    case 0x05:
   6.114 -        return("Pentium(tm)");
   6.115 -
   6.116 -    case 0x06:
   6.117 -        return("Pentium(tm) Pro");
   6.118 +		case 0x06:
   6.119 +			return("Pentium(tm) Pro");
   6.120  
   6.121 -    case 0x0F:
   6.122 -        if (model == 0x00)
   6.123 -            return("Pentium 4(tm)");
   6.124 -        if (model == 0x0F)
   6.125 -            return("Special controller");
   6.126 -    }
   6.127 -    sprintf(n,"Unknown CPU [%d:%d]",family, model);
   6.128 -    return n;
   6.129 +		case 0x0F:
   6.130 +			if (model == 0x00)
   6.131 +				return("Pentium 4(tm)");
   6.132 +			if (model == 0x02)
   6.133 +				return("Pentium 4(tm) XEON(tm)");
   6.134 +			if (model == 0x0F)
   6.135 +				return("Special controller");
   6.136 +	}
   6.137 +	sprintf(n,"Unknown CPU [%d:%d]",family, model);
   6.138 +	return n;
   6.139  }
   6.140  
   6.141 +#ifdef CONFIG_X86_IO_APIC
   6.142 +// XXX Xen extern int have_acpi_tables;	/* set by acpitable.c */
   6.143 +#define have_acpi_tables (0)
   6.144 +#else
   6.145 +#define have_acpi_tables (0)
   6.146 +#endif
   6.147 +
   6.148  /* 
   6.149   * Have to match translation table entries to main table entries by counter
   6.150   * hence the mpc_record variable .... can't see a less disgusting way of
   6.151 @@ -120,127 +146,256 @@ static char __init *mpc_family(int famil
   6.152   */
   6.153  
   6.154  static int mpc_record; 
   6.155 +static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
   6.156  
   6.157  void __init MP_processor_info (struct mpc_config_processor *m)
   6.158  {
   6.159 -    int ver, logical_apicid;
   6.160 + 	int ver, quad, logical_apicid;
   6.161   	
   6.162 -    if (!(m->mpc_cpuflag & CPU_ENABLED))
   6.163 -        return;
   6.164 +	if (!(m->mpc_cpuflag & CPU_ENABLED))
   6.165 +		return;
   6.166  
   6.167 -    logical_apicid = m->mpc_apicid;
   6.168 -    printk("Processor #%d %s APIC version %d\n",
   6.169 -           m->mpc_apicid,
   6.170 -           mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
   6.171 -                      (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
   6.172 -           m->mpc_apicver);
   6.173 -
   6.174 -    if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
   6.175 -        Dprintk("    Bootup CPU\n");
   6.176 -        boot_cpu_physical_apicid = m->mpc_apicid;
   6.177 -        boot_cpu_logical_apicid = logical_apicid;
   6.178 -    }
   6.179 +	logical_apicid = m->mpc_apicid;
   6.180 +	if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
   6.181 +		quad = translation_table[mpc_record]->trans_quad;
   6.182 +		logical_apicid = (quad << 4) + 
   6.183 +			(m->mpc_apicid ? m->mpc_apicid << 1 : 1);
   6.184 +		printk("Processor #%d %s APIC version %d (quad %d, apic %d)\n",
   6.185 +			m->mpc_apicid,
   6.186 +			mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
   6.187 +				   (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
   6.188 +			m->mpc_apicver, quad, logical_apicid);
   6.189 +	} else {
   6.190 +		printk("Processor #%d %s APIC version %d\n",
   6.191 +			m->mpc_apicid,
   6.192 +			mpc_family((m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
   6.193 +				   (m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
   6.194 +			m->mpc_apicver);
   6.195 +	}
   6.196  
   6.197 -    num_processors++;
   6.198 -
   6.199 -    if (m->mpc_apicid > MAX_APICS) {
   6.200 -        printk("Processor #%d INVALID. (Max ID: %d).\n",
   6.201 -               m->mpc_apicid, MAX_APICS);
   6.202 -        return;
   6.203 -    }
   6.204 -    ver = m->mpc_apicver;
   6.205 +	if (m->mpc_featureflag&(1<<0))
   6.206 +		Dprintk("    Floating point unit present.\n");
   6.207 +	if (m->mpc_featureflag&(1<<7))
   6.208 +		Dprintk("    Machine Exception supported.\n");
   6.209 +	if (m->mpc_featureflag&(1<<8))
   6.210 +		Dprintk("    64 bit compare & exchange supported.\n");
   6.211 +	if (m->mpc_featureflag&(1<<9))
   6.212 +		Dprintk("    Internal APIC present.\n");
   6.213 +	if (m->mpc_featureflag&(1<<11))
   6.214 +		Dprintk("    SEP present.\n");
   6.215 +	if (m->mpc_featureflag&(1<<12))
   6.216 +		Dprintk("    MTRR  present.\n");
   6.217 +	if (m->mpc_featureflag&(1<<13))
   6.218 +		Dprintk("    PGE  present.\n");
   6.219 +	if (m->mpc_featureflag&(1<<14))
   6.220 +		Dprintk("    MCA  present.\n");
   6.221 +	if (m->mpc_featureflag&(1<<15))
   6.222 +		Dprintk("    CMOV  present.\n");
   6.223 +	if (m->mpc_featureflag&(1<<16))
   6.224 +		Dprintk("    PAT  present.\n");
   6.225 +	if (m->mpc_featureflag&(1<<17))
   6.226 +		Dprintk("    PSE  present.\n");
   6.227 +	if (m->mpc_featureflag&(1<<18))
   6.228 +		Dprintk("    PSN  present.\n");
   6.229 +	if (m->mpc_featureflag&(1<<19))
   6.230 +		Dprintk("    Cache Line Flush Instruction present.\n");
   6.231 +	/* 20 Reserved */
   6.232 +	if (m->mpc_featureflag&(1<<21))
   6.233 +		Dprintk("    Debug Trace and EMON Store present.\n");
   6.234 +	if (m->mpc_featureflag&(1<<22))
   6.235 +		Dprintk("    ACPI Thermal Throttle Registers  present.\n");
   6.236 +	if (m->mpc_featureflag&(1<<23))
   6.237 +		Dprintk("    MMX  present.\n");
   6.238 +	if (m->mpc_featureflag&(1<<24))
   6.239 +		Dprintk("    FXSR  present.\n");
   6.240 +	if (m->mpc_featureflag&(1<<25))
   6.241 +		Dprintk("    XMM  present.\n");
   6.242 +	if (m->mpc_featureflag&(1<<26))
   6.243 +		Dprintk("    Willamette New Instructions  present.\n");
   6.244 +	if (m->mpc_featureflag&(1<<27))
   6.245 +		Dprintk("    Self Snoop  present.\n");
   6.246 +	if (m->mpc_featureflag&(1<<28))
   6.247 +		Dprintk("    HT  present.\n");
   6.248 +	if (m->mpc_featureflag&(1<<29))
   6.249 +		Dprintk("    Thermal Monitor present.\n");
   6.250 +	/* 30, 31 Reserved */
   6.251  
   6.252 -    phys_cpu_present_map |= 1 << m->mpc_apicid;
   6.253 +
   6.254 +	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
   6.255 +		Dprintk("    Bootup CPU\n");
   6.256 +		boot_cpu_physical_apicid = m->mpc_apicid;
   6.257 +		boot_cpu_logical_apicid = logical_apicid;
   6.258 +	}
   6.259 +
   6.260 +	num_processors++;
   6.261  
   6.262 -    /*
   6.263 -     * Validate version
   6.264 -     */
   6.265 -    if (ver == 0x0) {
   6.266 -        printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
   6.267 -        ver = 0x10;
   6.268 -    }
   6.269 -    apic_version[m->mpc_apicid] = ver;
   6.270 +	if (m->mpc_apicid > MAX_APICS) {
   6.271 +		printk("Processor #%d INVALID. (Max ID: %d).\n",
   6.272 +			m->mpc_apicid, MAX_APICS);
   6.273 +		--num_processors;
   6.274 +		return;
   6.275 +	}
   6.276 +	ver = m->mpc_apicver;
   6.277 +
   6.278 +	logical_cpu_present_map |= 1 << (num_processors-1);
   6.279 + 	phys_cpu_present_map |= apicid_to_phys_cpu_present(m->mpc_apicid);
   6.280 + 
   6.281 +	/*
   6.282 +	 * Validate version
   6.283 +	 */
   6.284 +	if (ver == 0x0) {
   6.285 +		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
   6.286 +		ver = 0x10;
   6.287 +	}
   6.288 +	apic_version[m->mpc_apicid] = ver;
   6.289 +	raw_phys_apicid[num_processors - 1] = m->mpc_apicid;
   6.290  }
   6.291  
   6.292  static void __init MP_bus_info (struct mpc_config_bus *m)
   6.293  {
   6.294 -    char str[7];
   6.295 -
   6.296 -    memcpy(str, m->mpc_bustype, 6);
   6.297 -    str[6] = 0;
   6.298 -	
   6.299 -    Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
   6.300 +	char str[7];
   6.301 +	int quad;
   6.302  
   6.303 -    if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
   6.304 -        mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
   6.305 -    } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
   6.306 -        mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
   6.307 -    } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
   6.308 -        mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
   6.309 -        mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
   6.310 -        mp_current_pci_id++;
   6.311 -    } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
   6.312 -        mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
   6.313 -    } else {
   6.314 -        printk("Unknown bustype %s - ignoring\n", str);
   6.315 -    }
   6.316 +	memcpy(str, m->mpc_bustype, 6);
   6.317 +	str[6] = 0;
   6.318 +	
   6.319 +	if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
   6.320 +		quad = translation_table[mpc_record]->trans_quad;
   6.321 +		mp_bus_id_to_node[m->mpc_busid] = quad;
   6.322 +		mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local;
   6.323 +		quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid;
   6.324 +		printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad);
   6.325 +	} else {
   6.326 +		Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
   6.327 +	}
   6.328 +
   6.329 +	if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
   6.330 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
   6.331 +	} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
   6.332 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
   6.333 +	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
   6.334 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
   6.335 +		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
   6.336 +		mp_current_pci_id++;
   6.337 +	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
   6.338 +		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
   6.339 +	} else {
   6.340 +		printk("Unknown bustype %s - ignoring\n", str);
   6.341 +	}
   6.342  }
   6.343  
   6.344  static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
   6.345  {
   6.346 -    if (!(m->mpc_flags & MPC_APIC_USABLE))
   6.347 -        return;
   6.348 +	if (!(m->mpc_flags & MPC_APIC_USABLE))
   6.349 +		return;
   6.350  
   6.351 -    printk("I/O APIC #%d Version %d at 0x%lX.\n",
   6.352 -           m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
   6.353 -    if (nr_ioapics >= MAX_IO_APICS) {
   6.354 -        printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
   6.355 -               MAX_IO_APICS, nr_ioapics);
   6.356 -        panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
   6.357 -    }
   6.358 -    if (!m->mpc_apicaddr) {
   6.359 -        printk("WARNING: bogus zero I/O APIC address"
   6.360 -               " found in MP table, skipping!\n");
   6.361 -        return;
   6.362 -    }
   6.363 -    mp_ioapics[nr_ioapics] = *m;
   6.364 -    nr_ioapics++;
   6.365 +	printk("I/O APIC #%d Version %d at 0x%lX.\n",
   6.366 +		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
   6.367 +	if (nr_ioapics >= MAX_IO_APICS) {
   6.368 +		printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
   6.369 +			MAX_IO_APICS, nr_ioapics);
   6.370 +		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
   6.371 +	}
   6.372 +	if (!m->mpc_apicaddr) {
   6.373 +		printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
   6.374 +			" found in MP table, skipping!\n");
   6.375 +		return;
   6.376 +	}
   6.377 +	mp_ioapics[nr_ioapics] = *m;
   6.378 +	nr_ioapics++;
   6.379  }
   6.380  
   6.381  static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
   6.382  {
   6.383 -    mp_irqs [mp_irq_entries] = *m;
   6.384 -    Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
   6.385 -            " IRQ %02x, APIC ID %x, APIC INT %02x\n",
   6.386 -            m->mpc_irqtype, m->mpc_irqflag & 3,
   6.387 -            (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
   6.388 -            m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
   6.389 -    if (++mp_irq_entries == MAX_IRQ_SOURCES)
   6.390 -        panic("Max # of irq sources exceeded!!\n");
   6.391 +	mp_irqs [mp_irq_entries] = *m;
   6.392 +	Dprintk("Int: type %d, pol %d, trig %d, bus %d,"
   6.393 +		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
   6.394 +			m->mpc_irqtype, m->mpc_irqflag & 3,
   6.395 +			(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
   6.396 +			m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
   6.397 +	if (++mp_irq_entries == max_irq_sources)
   6.398 +		panic("Max # of irq sources exceeded!!\n");
   6.399  }
   6.400  
   6.401  static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
   6.402  {
   6.403 -    Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
   6.404 -            " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
   6.405 -            m->mpc_irqtype, m->mpc_irqflag & 3,
   6.406 -            (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
   6.407 -            m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
   6.408 -    /*
   6.409 -     * Well it seems all SMP boards in existence
   6.410 -     * use ExtINT/LVT1 == LINT0 and
   6.411 -     * NMI/LVT2 == LINT1 - the following check
   6.412 -     * will show us if this assumptions is false.
   6.413 -     * Until then we do not have to add baggage.
   6.414 -     */
   6.415 -    if ((m->mpc_irqtype == mp_ExtINT) &&
   6.416 -        (m->mpc_destapiclint != 0))
   6.417 -        BUG();
   6.418 -    if ((m->mpc_irqtype == mp_NMI) &&
   6.419 -        (m->mpc_destapiclint != 1))
   6.420 -        BUG();
   6.421 +	Dprintk("Lint: type %d, pol %d, trig %d, bus %d,"
   6.422 +		" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
   6.423 +			m->mpc_irqtype, m->mpc_irqflag & 3,
   6.424 +			(m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
   6.425 +			m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
   6.426 +	/*
   6.427 +	 * Well it seems all SMP boards in existence
   6.428 +	 * use ExtINT/LVT1 == LINT0 and
   6.429 +	 * NMI/LVT2 == LINT1 - the following check
   6.430 +	 * will show us if this assumptions is false.
   6.431 +	 * Until then we do not have to add baggage.
   6.432 +	 */
   6.433 +	if ((m->mpc_irqtype == mp_ExtINT) &&
   6.434 +		(m->mpc_destapiclint != 0))
   6.435 +			BUG();
   6.436 +	if ((m->mpc_irqtype == mp_NMI) &&
   6.437 +		(m->mpc_destapiclint != 1))
   6.438 +			BUG();
   6.439 +}
   6.440 +
   6.441 +static void __init MP_translation_info (struct mpc_config_translation *m)
   6.442 +{
   6.443 +	printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
   6.444 +
   6.445 +	if (mpc_record >= MAX_MPC_ENTRY) 
   6.446 +		printk("MAX_MPC_ENTRY exceeded!\n");
   6.447 +	else
   6.448 +		translation_table[mpc_record] = m; /* stash this for later */
   6.449 +	if (m->trans_quad+1 > numnodes)
   6.450 +		numnodes = m->trans_quad+1;
   6.451  }
   6.452  
   6.453 +/*
   6.454 + * Read/parse the MPC oem tables
   6.455 + */
   6.456 +
   6.457 +static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
   6.458 +	unsigned short oemsize)
   6.459 +{
   6.460 +	int count = sizeof (*oemtable); /* the header size */
   6.461 +	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
   6.462 +	
   6.463 +	printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
   6.464 +	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
   6.465 +	{
   6.466 +		printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
   6.467 +			oemtable->oem_signature[0],
   6.468 +			oemtable->oem_signature[1],
   6.469 +			oemtable->oem_signature[2],
   6.470 +			oemtable->oem_signature[3]);
   6.471 +		return;
   6.472 +	}
   6.473 +	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
   6.474 +	{
   6.475 +		printk("SMP oem mptable: checksum error!\n");
   6.476 +		return;
   6.477 +	}
   6.478 +	while (count < oemtable->oem_length) {
   6.479 +		switch (*oemptr) {
   6.480 +			case MP_TRANSLATION:
   6.481 +			{
   6.482 +				struct mpc_config_translation *m=
   6.483 +					(struct mpc_config_translation *)oemptr;
   6.484 +				MP_translation_info(m);
   6.485 +				oemptr += sizeof(*m);
   6.486 +				count += sizeof(*m);
   6.487 +				++mpc_record;
   6.488 +				break;
   6.489 +			}
   6.490 +			default:
   6.491 +			{
   6.492 +				printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
   6.493 +				return;
   6.494 +			}
   6.495 +		}
   6.496 +       }
   6.497 +}
   6.498  
   6.499  /*
   6.500   * Read/parse the MPC
   6.501 @@ -248,383 +403,542 @@ static void __init MP_lintsrc_info (stru
   6.502  
   6.503  static int __init smp_read_mpc(struct mp_config_table *mpc)
   6.504  {
   6.505 -    char str[16];
   6.506 -    int count=sizeof(*mpc);
   6.507 -    unsigned char *mpt=((unsigned char *)mpc)+count;
   6.508 +	char oem[16], prod[14];
   6.509 +	int count=sizeof(*mpc);
   6.510 +	unsigned char *mpt=((unsigned char *)mpc)+count;
   6.511 +	int num_bus = 0;
   6.512 +	int num_irq = 0;
   6.513 +	unsigned char *bus_data;
   6.514  
   6.515 -    if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
   6.516 -        panic("SMP mptable: bad signature [%c%c%c%c]!\n",
   6.517 -              mpc->mpc_signature[0],
   6.518 -              mpc->mpc_signature[1],
   6.519 -              mpc->mpc_signature[2],
   6.520 -              mpc->mpc_signature[3]);
   6.521 -        return 0;
   6.522 -    }
   6.523 -    if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
   6.524 -        panic("SMP mptable: checksum error!\n");
   6.525 -        return 0;
   6.526 -    }
   6.527 -    if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
   6.528 -        printk("SMP mptable: bad table version (%d)!!\n",
   6.529 -               mpc->mpc_spec);
   6.530 -        return 0;
   6.531 -    }
   6.532 -    if (!mpc->mpc_lapic) {
   6.533 -        printk("SMP mptable: null local APIC address!\n");
   6.534 -        return 0;
   6.535 -    }
   6.536 -    memcpy(str,mpc->mpc_oem,8);
   6.537 -    str[8]=0;
   6.538 -    printk("OEM ID: %s ",str);
   6.539 +	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
   6.540 +		panic("SMP mptable: bad signature [%c%c%c%c]!\n",
   6.541 +			mpc->mpc_signature[0],
   6.542 +			mpc->mpc_signature[1],
   6.543 +			mpc->mpc_signature[2],
   6.544 +			mpc->mpc_signature[3]);
   6.545 +		return 0;
   6.546 +	}
   6.547 +	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
   6.548 +		panic("SMP mptable: checksum error!\n");
   6.549 +		return 0;
   6.550 +	}
   6.551 +	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
   6.552 +		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
   6.553 +			mpc->mpc_spec);
   6.554 +		return 0;
   6.555 +	}
   6.556 +	if (!mpc->mpc_lapic) {
   6.557 +		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
   6.558 +		return 0;
   6.559 +	}
   6.560 +	memcpy(oem,mpc->mpc_oem,8);
   6.561 +	oem[8]=0;
   6.562 +	printk("OEM ID: %s ",oem);
   6.563  
   6.564 -    memcpy(str,mpc->mpc_productid,12);
   6.565 -    str[12]=0;
   6.566 -    printk("Product ID: %s ",str);
   6.567 +	memcpy(prod,mpc->mpc_productid,12);
   6.568 +	prod[12]=0;
   6.569 +	printk("Product ID: %s ",prod);
   6.570  
   6.571 -    printk("APIC at: 0x%lX\n", mpc->mpc_lapic);
   6.572 -
   6.573 -    /* save the local APIC address, it might be non-default. */
   6.574 -    mp_lapic_addr = mpc->mpc_lapic;
   6.575 +	detect_clustered_apic(oem, prod);
   6.576 +	
   6.577 +	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
   6.578  
   6.579 -    /*
   6.580 -     *	Now process the configuration blocks.
   6.581 -     */
   6.582 -    while (count < mpc->mpc_length) {
   6.583 -        switch(*mpt) {
   6.584 -        case MP_PROCESSOR:
   6.585 -        {
   6.586 -            struct mpc_config_processor *m=
   6.587 -                (struct mpc_config_processor *)mpt;
   6.588 +	/* save the local APIC address, it might be non-default,
   6.589 +	 * but only if we're not using the ACPI tables
   6.590 +	 */
   6.591 +	if (!have_acpi_tables)
   6.592 +		mp_lapic_addr = mpc->mpc_lapic;
   6.593 +
   6.594 +	if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ) && mpc->mpc_oemptr) {
   6.595 +		/* We need to process the oem mpc tables to tell us which quad things are in ... */
   6.596 +		mpc_record = 0;
   6.597 +		smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, mpc->mpc_oemsize);
   6.598 +		mpc_record = 0;
   6.599 +	}
   6.600  
   6.601 -            MP_processor_info(m);
   6.602 -            mpt += sizeof(*m);
   6.603 -            count += sizeof(*m);
   6.604 -            break;
   6.605 -        }
   6.606 -        case MP_BUS:
   6.607 -        {
   6.608 -            struct mpc_config_bus *m=
   6.609 -                (struct mpc_config_bus *)mpt;
   6.610 -            MP_bus_info(m);
   6.611 -            mpt += sizeof(*m);
   6.612 -            count += sizeof(*m);
   6.613 -            break;
   6.614 -        }
   6.615 -        case MP_IOAPIC:
   6.616 -        {
   6.617 -            struct mpc_config_ioapic *m=
   6.618 -                (struct mpc_config_ioapic *)mpt;
   6.619 -            MP_ioapic_info(m);
   6.620 -            mpt+=sizeof(*m);
   6.621 -            count+=sizeof(*m);
   6.622 -            break;
   6.623 -        }
   6.624 -        case MP_INTSRC:
   6.625 -        {
   6.626 -            struct mpc_config_intsrc *m=
   6.627 -                (struct mpc_config_intsrc *)mpt;
   6.628 +	/* Pre-scan to determine the number of bus and 
   6.629 +	 * interrupts records we have
   6.630 +	 */
   6.631 +	while (count < mpc->mpc_length) {
   6.632 +		switch (*mpt) {
   6.633 +			case MP_PROCESSOR:
   6.634 +				mpt += sizeof(struct mpc_config_processor);
   6.635 +				count += sizeof(struct mpc_config_processor);
   6.636 +				break;
   6.637 +			case MP_BUS:
   6.638 +				++num_bus;
   6.639 +				mpt += sizeof(struct mpc_config_bus);
   6.640 +				count += sizeof(struct mpc_config_bus);
   6.641 +				break;
   6.642 +			case MP_INTSRC:
   6.643 +				++num_irq;
   6.644 +				mpt += sizeof(struct mpc_config_intsrc);
   6.645 +				count += sizeof(struct mpc_config_intsrc);
   6.646 +				break;
   6.647 +			case MP_IOAPIC:
   6.648 +				mpt += sizeof(struct mpc_config_ioapic);
   6.649 +				count += sizeof(struct mpc_config_ioapic);
   6.650 +				break;
   6.651 +			case MP_LINTSRC:
   6.652 +				mpt += sizeof(struct mpc_config_lintsrc);
   6.653 +				count += sizeof(struct mpc_config_lintsrc);
   6.654 +				break;
   6.655 +			default:
   6.656 +				count = mpc->mpc_length;
   6.657 +				break;
   6.658 +		}
   6.659 +	}
   6.660 +	/* 
   6.661 +	 * Paranoia: Allocate one extra of both the number of busses and number
   6.662 +	 * of irqs, and make sure that we have at least 4 interrupts per PCI
   6.663 +	 * slot.  But some machines do not report very many busses, so we need
   6.664 +	 * to fall back on the older defaults.
   6.665 +	 */
   6.666 +	++num_bus;
   6.667 +	max_mp_busses = max(num_bus, MAX_MP_BUSSES);
   6.668 +	if (num_irq < (4 * max_mp_busses))
   6.669 +		num_irq = 4 * num_bus;	/* 4 intr/PCI slot */
   6.670 +	++num_irq;
   6.671 +	max_irq_sources = max(num_irq, MAX_IRQ_SOURCES);
   6.672 +	
   6.673 +	count = (max_mp_busses * sizeof(int)) * 4;
   6.674 +	count += (max_irq_sources * sizeof(struct mpc_config_intsrc));
   6.675 +	
   6.676 +	{
   6.677 +	//bus_data = alloc_bootmem(count);  XXX Xen
   6.678 +	static char arr[4096];
   6.679 +	if(count > 4096) BUG();
   6.680 +	bus_data = (void*)arr;
   6.681 +	
   6.682 +	}
   6.683 +	if (!bus_data) {
   6.684 +		printk(KERN_ERR "SMP mptable: out of memory!\n");
   6.685 +		return 0;
   6.686 +	}
   6.687 +	mp_bus_id_to_type = (int *)&bus_data[0];
   6.688 +	mp_bus_id_to_node = (int *)&bus_data[(max_mp_busses * sizeof(int))];
   6.689 +	mp_bus_id_to_local = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 2];
   6.690 +	mp_bus_id_to_pci_bus = (int *)&bus_data[(max_mp_busses * sizeof(int)) * 3];
   6.691 +	mp_irqs = (struct mpc_config_intsrc *)&bus_data[(max_mp_busses * sizeof(int)) * 4];
   6.692 +	memset(mp_bus_id_to_pci_bus, -1, max_mp_busses);
   6.693  
   6.694 -            MP_intsrc_info(m);
   6.695 -            mpt+=sizeof(*m);
   6.696 -            count+=sizeof(*m);
   6.697 -            break;
   6.698 -        }
   6.699 -        case MP_LINTSRC:
   6.700 -        {
   6.701 -            struct mpc_config_lintsrc *m=
   6.702 -                (struct mpc_config_lintsrc *)mpt;
   6.703 -            MP_lintsrc_info(m);
   6.704 -            mpt+=sizeof(*m);
   6.705 -            count+=sizeof(*m);
   6.706 -            break;
   6.707 -        }
   6.708 -        default:
   6.709 -        {
   6.710 -            count = mpc->mpc_length;
   6.711 -            break;
   6.712 -        }
   6.713 -        }
   6.714 -        ++mpc_record;
   6.715 -    }
   6.716 +	/*
   6.717 +	 *	Now process the configuration blocks.
   6.718 +	 */
   6.719 +	count = sizeof(*mpc);
   6.720 +	mpt = ((unsigned char *)mpc)+count;
   6.721 +	while (count < mpc->mpc_length) {
   6.722 +		switch(*mpt) {
   6.723 +			case MP_PROCESSOR:
   6.724 +			{
   6.725 +				struct mpc_config_processor *m=
   6.726 +					(struct mpc_config_processor *)mpt;
   6.727  
   6.728 -    if (!num_processors)
   6.729 -        printk("SMP mptable: no processors registered!\n");
   6.730 -    return num_processors;
   6.731 +				/* ACPI may already have provided this one for us */
   6.732 +				if (!have_acpi_tables)
   6.733 +					MP_processor_info(m);
   6.734 +				mpt += sizeof(*m);
   6.735 +				count += sizeof(*m);
   6.736 +				break;
   6.737 +			}
   6.738 +			case MP_BUS:
   6.739 +			{
   6.740 +				struct mpc_config_bus *m=
   6.741 +					(struct mpc_config_bus *)mpt;
   6.742 +				MP_bus_info(m);
   6.743 +				mpt += sizeof(*m);
   6.744 +				count += sizeof(*m);
   6.745 +				break;
   6.746 +			}
   6.747 +			case MP_IOAPIC:
   6.748 +			{
   6.749 +				struct mpc_config_ioapic *m=
   6.750 +					(struct mpc_config_ioapic *)mpt;
   6.751 +				MP_ioapic_info(m);
   6.752 +				mpt+=sizeof(*m);
   6.753 +				count+=sizeof(*m);
   6.754 +				break;
   6.755 +			}
   6.756 +			case MP_INTSRC:
   6.757 +			{
   6.758 +				struct mpc_config_intsrc *m=
   6.759 +					(struct mpc_config_intsrc *)mpt;
   6.760 +
   6.761 +				MP_intsrc_info(m);
   6.762 +				mpt+=sizeof(*m);
   6.763 +				count+=sizeof(*m);
   6.764 +				break;
   6.765 +			}
   6.766 +			case MP_LINTSRC:
   6.767 +			{
   6.768 +				struct mpc_config_lintsrc *m=
   6.769 +					(struct mpc_config_lintsrc *)mpt;
   6.770 +				MP_lintsrc_info(m);
   6.771 +				mpt+=sizeof(*m);
   6.772 +				count+=sizeof(*m);
   6.773 +				break;
   6.774 +			}
   6.775 +			default:
   6.776 +			{
   6.777 +				count = mpc->mpc_length;
   6.778 +				break;
   6.779 +			}
   6.780 +		}
   6.781 +		++mpc_record;
   6.782 +	}
   6.783 +
   6.784 +	if (clustered_apic_mode){
   6.785 +		phys_cpu_present_map = logical_cpu_present_map;
   6.786 +	}
   6.787 +
   6.788 +
   6.789 +	printk("Enabling APIC mode: ");
   6.790 +	if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
   6.791 +		printk("Clustered Logical.	");
   6.792 +	else if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
   6.793 +		printk("Physical.	");
   6.794 +	else
   6.795 +		printk("Flat.	");
   6.796 +	printk("Using %d I/O APICs\n",nr_ioapics);
   6.797 +
   6.798 +	if (!num_processors)
   6.799 +		printk(KERN_ERR "SMP mptable: no processors registered!\n");
   6.800 +	return num_processors;
   6.801  }
   6.802  
   6.803  static int __init ELCR_trigger(unsigned int irq)
   6.804  {
   6.805 -    unsigned int port;
   6.806 +	unsigned int port;
   6.807  
   6.808 -    port = 0x4d0 + (irq >> 3);
   6.809 -    return (inb(port) >> (irq & 7)) & 1;
   6.810 +	port = 0x4d0 + (irq >> 3);
   6.811 +	return (inb(port) >> (irq & 7)) & 1;
   6.812  }
   6.813  
   6.814  static void __init construct_default_ioirq_mptable(int mpc_default_type)
   6.815  {
   6.816 -    struct mpc_config_intsrc intsrc;
   6.817 -    int i;
   6.818 -    int ELCR_fallback = 0;
   6.819 +	struct mpc_config_intsrc intsrc;
   6.820 +	int i;
   6.821 +	int ELCR_fallback = 0;
   6.822  
   6.823 -    intsrc.mpc_type = MP_INTSRC;
   6.824 -    intsrc.mpc_irqflag = 0;			/* conforming */
   6.825 -    intsrc.mpc_srcbus = 0;
   6.826 -    intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
   6.827 +	intsrc.mpc_type = MP_INTSRC;
   6.828 +	intsrc.mpc_irqflag = 0;			/* conforming */
   6.829 +	intsrc.mpc_srcbus = 0;
   6.830 +	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;
   6.831  
   6.832 -    intsrc.mpc_irqtype = mp_INT;
   6.833 +	intsrc.mpc_irqtype = mp_INT;
   6.834  
   6.835 -    /*
   6.836 -     *  If true, we have an ISA/PCI system with no IRQ entries
   6.837 -     *  in the MP table. To prevent the PCI interrupts from being set up
   6.838 -     *  incorrectly, we try to use the ELCR. The sanity check to see if
   6.839 -     *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
   6.840 -     *  never be level sensitive, so we simply see if the ELCR agrees.
   6.841 -     *  If it does, we assume it's valid.
   6.842 -     */
   6.843 -    if (mpc_default_type == 5) {
   6.844 -        printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
   6.845 +	/*
   6.846 +	 *  If true, we have an ISA/PCI system with no IRQ entries
   6.847 +	 *  in the MP table. To prevent the PCI interrupts from being set up
   6.848 +	 *  incorrectly, we try to use the ELCR. The sanity check to see if
   6.849 +	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can
   6.850 +	 *  never be level sensitive, so we simply see if the ELCR agrees.
   6.851 +	 *  If it does, we assume it's valid.
   6.852 +	 */
   6.853 +	if (mpc_default_type == 5) {
   6.854 +		printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
   6.855  
   6.856 -        if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
   6.857 -            printk("ELCR contains invalid data... not using ELCR\n");
   6.858 -        else {
   6.859 -            printk("Using ELCR to identify PCI interrupts\n");
   6.860 -            ELCR_fallback = 1;
   6.861 -        }
   6.862 -    }
   6.863 +		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
   6.864 +			printk("ELCR contains invalid data... not using ELCR\n");
   6.865 +		else {
   6.866 +			printk("Using ELCR to identify PCI interrupts\n");
   6.867 +			ELCR_fallback = 1;
   6.868 +		}
   6.869 +	}
   6.870  
   6.871 -    for (i = 0; i < 16; i++) {
   6.872 -        switch (mpc_default_type) {
   6.873 -        case 2:
   6.874 -            if (i == 0 || i == 13)
   6.875 -                continue;	/* IRQ0 & IRQ13 not connected */
   6.876 -            /* fall through */
   6.877 -        default:
   6.878 -            if (i == 2)
   6.879 -                continue;	/* IRQ2 is never connected */
   6.880 -        }
   6.881 +	for (i = 0; i < 16; i++) {
   6.882 +		switch (mpc_default_type) {
   6.883 +		case 2:
   6.884 +			if (i == 0 || i == 13)
   6.885 +				continue;	/* IRQ0 & IRQ13 not connected */
   6.886 +			/* fall through */
   6.887 +		default:
   6.888 +			if (i == 2)
   6.889 +				continue;	/* IRQ2 is never connected */
   6.890 +		}
   6.891  
   6.892 -        if (ELCR_fallback) {
   6.893 -            /*
   6.894 -             *  If the ELCR indicates a level-sensitive interrupt, we
   6.895 -             *  copy that information over to the MP table in the
   6.896 -             *  irqflag field (level sensitive, active high polarity).
   6.897 -             */
   6.898 -            if (ELCR_trigger(i))
   6.899 -                intsrc.mpc_irqflag = 13;
   6.900 -            else
   6.901 -                intsrc.mpc_irqflag = 0;
   6.902 -        }
   6.903 +		if (ELCR_fallback) {
   6.904 +			/*
   6.905 +			 *  If the ELCR indicates a level-sensitive interrupt, we
   6.906 +			 *  copy that information over to the MP table in the
   6.907 +			 *  irqflag field (level sensitive, active high polarity).
   6.908 +			 */
   6.909 +			if (ELCR_trigger(i))
   6.910 +				intsrc.mpc_irqflag = 13;
   6.911 +			else
   6.912 +				intsrc.mpc_irqflag = 0;
   6.913 +		}
   6.914  
   6.915 -        intsrc.mpc_srcbusirq = i;
   6.916 -        intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
   6.917 -        MP_intsrc_info(&intsrc);
   6.918 -    }
   6.919 +		intsrc.mpc_srcbusirq = i;
   6.920 +		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */
   6.921 +		MP_intsrc_info(&intsrc);
   6.922 +	}
   6.923  
   6.924 -    intsrc.mpc_irqtype = mp_ExtINT;
   6.925 -    intsrc.mpc_srcbusirq = 0;
   6.926 -    intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
   6.927 -    MP_intsrc_info(&intsrc);
   6.928 +	intsrc.mpc_irqtype = mp_ExtINT;
   6.929 +	intsrc.mpc_srcbusirq = 0;
   6.930 +	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */
   6.931 +	MP_intsrc_info(&intsrc);
   6.932  }
   6.933  
   6.934  static inline void __init construct_default_ISA_mptable(int mpc_default_type)
   6.935  {
   6.936 -    struct mpc_config_processor processor;
   6.937 -    struct mpc_config_bus bus;
   6.938 -    struct mpc_config_ioapic ioapic;
   6.939 -    struct mpc_config_lintsrc lintsrc;
   6.940 -    int linttypes[2] = { mp_ExtINT, mp_NMI };
   6.941 -    int i;
   6.942 +	struct mpc_config_processor processor;
   6.943 +	struct mpc_config_bus bus;
   6.944 +	struct mpc_config_ioapic ioapic;
   6.945 +	struct mpc_config_lintsrc lintsrc;
   6.946 +	int linttypes[2] = { mp_ExtINT, mp_NMI };
   6.947 +	int i;
   6.948  
   6.949 -    /*
   6.950 -     * local APIC has default address
   6.951 -     */
   6.952 -    mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
   6.953 +	/*
   6.954 +	 * local APIC has default address
   6.955 +	 */
   6.956 +	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
   6.957  
   6.958 -    /*
   6.959 -     * 2 CPUs, numbered 0 & 1.
   6.960 -     */
   6.961 -    processor.mpc_type = MP_PROCESSOR;
   6.962 -    /* Either an integrated APIC or a discrete 82489DX. */
   6.963 -    processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
   6.964 -    processor.mpc_cpuflag = CPU_ENABLED;
   6.965 -    processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
   6.966 -        (boot_cpu_data.x86_model << 4) |
   6.967 -        boot_cpu_data.x86_mask;
   6.968 -    processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
   6.969 -    processor.mpc_reserved[0] = 0;
   6.970 -    processor.mpc_reserved[1] = 0;
   6.971 -    for (i = 0; i < 2; i++) {
   6.972 -        processor.mpc_apicid = i;
   6.973 -        MP_processor_info(&processor);
   6.974 -    }
   6.975 +	/*
   6.976 +	 * 2 CPUs, numbered 0 & 1.
   6.977 +	 */
   6.978 +	processor.mpc_type = MP_PROCESSOR;
   6.979 +	/* Either an integrated APIC or a discrete 82489DX. */
   6.980 +	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
   6.981 +	processor.mpc_cpuflag = CPU_ENABLED;
   6.982 +	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
   6.983 +				   (boot_cpu_data.x86_model << 4) |
   6.984 +				   boot_cpu_data.x86_mask;
   6.985 +	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
   6.986 +	processor.mpc_reserved[0] = 0;
   6.987 +	processor.mpc_reserved[1] = 0;
   6.988 +	for (i = 0; i < 2; i++) {
   6.989 +		processor.mpc_apicid = i;
   6.990 +		MP_processor_info(&processor);
   6.991 +	}
   6.992  
   6.993 -    bus.mpc_type = MP_BUS;
   6.994 -    bus.mpc_busid = 0;
   6.995 -    switch (mpc_default_type) {
   6.996 -    default:
   6.997 -        printk("???\nUnknown standard configuration %d\n",
   6.998 -               mpc_default_type);
   6.999 -        /* fall through */
  6.1000 -    case 1:
  6.1001 -    case 5:
  6.1002 -        memcpy(bus.mpc_bustype, "ISA   ", 6);
  6.1003 -        break;
  6.1004 -    case 2:
  6.1005 -    case 6:
  6.1006 -    case 3:
  6.1007 -        memcpy(bus.mpc_bustype, "EISA  ", 6);
  6.1008 -        break;
  6.1009 -    case 4:
  6.1010 -    case 7:
  6.1011 -        memcpy(bus.mpc_bustype, "MCA   ", 6);
  6.1012 -    }
  6.1013 -    MP_bus_info(&bus);
  6.1014 -    if (mpc_default_type > 4) {
  6.1015 -        bus.mpc_busid = 1;
  6.1016 -        memcpy(bus.mpc_bustype, "PCI   ", 6);
  6.1017 -        MP_bus_info(&bus);
  6.1018 -    }
  6.1019 +	bus.mpc_type = MP_BUS;
  6.1020 +	bus.mpc_busid = 0;
  6.1021 +	switch (mpc_default_type) {
  6.1022 +		default:
  6.1023 +			printk("???\nUnknown standard configuration %d\n",
  6.1024 +				mpc_default_type);
  6.1025 +			/* fall through */
  6.1026 +		case 1:
  6.1027 +		case 5:
  6.1028 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
  6.1029 +			break;
  6.1030 +		case 2:
  6.1031 +		case 6:
  6.1032 +		case 3:
  6.1033 +			memcpy(bus.mpc_bustype, "EISA  ", 6);
  6.1034 +			break;
  6.1035 +		case 4:
  6.1036 +		case 7:
  6.1037 +			memcpy(bus.mpc_bustype, "MCA   ", 6);
  6.1038 +	}
  6.1039 +	MP_bus_info(&bus);
  6.1040 +	if (mpc_default_type > 4) {
  6.1041 +		bus.mpc_busid = 1;
  6.1042 +		memcpy(bus.mpc_bustype, "PCI   ", 6);
  6.1043 +		MP_bus_info(&bus);
  6.1044 +	}
  6.1045  
  6.1046 -    ioapic.mpc_type = MP_IOAPIC;
  6.1047 -    ioapic.mpc_apicid = 2;
  6.1048 -    ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
  6.1049 -    ioapic.mpc_flags = MPC_APIC_USABLE;
  6.1050 -    ioapic.mpc_apicaddr = 0xFEC00000;
  6.1051 -    MP_ioapic_info(&ioapic);
  6.1052 +	ioapic.mpc_type = MP_IOAPIC;
  6.1053 +	ioapic.mpc_apicid = 2;
  6.1054 +	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
  6.1055 +	ioapic.mpc_flags = MPC_APIC_USABLE;
  6.1056 +	ioapic.mpc_apicaddr = 0xFEC00000;
  6.1057 +	MP_ioapic_info(&ioapic);
  6.1058  
  6.1059 -    /*
  6.1060 -     * We set up most of the low 16 IO-APIC pins according to MPS rules.
  6.1061 -     */
  6.1062 -    construct_default_ioirq_mptable(mpc_default_type);
  6.1063 +	/*
  6.1064 +	 * We set up most of the low 16 IO-APIC pins according to MPS rules.
  6.1065 +	 */
  6.1066 +	construct_default_ioirq_mptable(mpc_default_type);
  6.1067  
  6.1068 -    lintsrc.mpc_type = MP_LINTSRC;
  6.1069 -    lintsrc.mpc_irqflag = 0;		/* conforming */
  6.1070 -    lintsrc.mpc_srcbusid = 0;
  6.1071 -    lintsrc.mpc_srcbusirq = 0;
  6.1072 -    lintsrc.mpc_destapic = MP_APIC_ALL;
  6.1073 -    for (i = 0; i < 2; i++) {
  6.1074 -        lintsrc.mpc_irqtype = linttypes[i];
  6.1075 -        lintsrc.mpc_destapiclint = i;
  6.1076 -        MP_lintsrc_info(&lintsrc);
  6.1077 -    }
  6.1078 +	lintsrc.mpc_type = MP_LINTSRC;
  6.1079 +	lintsrc.mpc_irqflag = 0;		/* conforming */
  6.1080 +	lintsrc.mpc_srcbusid = 0;
  6.1081 +	lintsrc.mpc_srcbusirq = 0;
  6.1082 +	lintsrc.mpc_destapic = MP_APIC_ALL;
  6.1083 +	for (i = 0; i < 2; i++) {
  6.1084 +		lintsrc.mpc_irqtype = linttypes[i];
  6.1085 +		lintsrc.mpc_destapiclint = i;
  6.1086 +		MP_lintsrc_info(&lintsrc);
  6.1087 +	}
  6.1088  }
  6.1089  
  6.1090  static struct intel_mp_floating *mpf_found;
  6.1091 +extern void 	config_acpi_tables(void);
  6.1092  
  6.1093  /*
  6.1094   * Scan the memory blocks for an SMP configuration block.
  6.1095   */
  6.1096  void __init get_smp_config (void)
  6.1097  {
  6.1098 -    struct intel_mp_floating *mpf = mpf_found;
  6.1099 +	struct intel_mp_floating *mpf = mpf_found;
  6.1100 +
  6.1101 +#ifdef CONFIG_X86_IO_APIC
  6.1102 +	/*
  6.1103 +	 * Check if the ACPI tables are provided. Use them only to get
  6.1104 +	 * the processor information, mainly because it provides
  6.1105 +	 * the info on the logical processor(s), rather than the physical
  6.1106 +	 * processor(s) that are provided by the MPS. We attempt to 
  6.1107 +	 * check only if the user provided a commandline override
  6.1108 +	 */
  6.1109 +	//XXX Xen config_acpi_tables();
  6.1110 +#endif
  6.1111  	
  6.1112 -    printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
  6.1113 -    if (mpf->mpf_feature2 & (1<<7)) {
  6.1114 -        printk("    IMCR and PIC compatibility mode.\n");
  6.1115 -        pic_mode = 1;
  6.1116 -    } else {
  6.1117 -        printk("    Virtual Wire compatibility mode.\n");
  6.1118 -        pic_mode = 0;
  6.1119 -    }
  6.1120 +	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
  6.1121 +	if (mpf->mpf_feature2 & (1<<7)) {
  6.1122 +		printk("    IMCR and PIC compatibility mode.\n");
  6.1123 +		pic_mode = 1;
  6.1124 +	} else {
  6.1125 +		printk("    Virtual Wire compatibility mode.\n");
  6.1126 +		pic_mode = 0;
  6.1127 +	}
  6.1128  
  6.1129 -    /*
  6.1130 -     * Now see if we need to read further.
  6.1131 -     */
  6.1132 -    if (mpf->mpf_feature1 != 0) {
  6.1133 +	/*
  6.1134 +	 * Now see if we need to read further.
  6.1135 +	 */
  6.1136 +	if (mpf->mpf_feature1 != 0) {
  6.1137  
  6.1138 -        printk("Default MP configuration #%d\n", mpf->mpf_feature1);
  6.1139 -        construct_default_ISA_mptable(mpf->mpf_feature1);
  6.1140 +		printk("Default MP configuration #%d\n", mpf->mpf_feature1);
  6.1141 +		construct_default_ISA_mptable(mpf->mpf_feature1);
  6.1142  
  6.1143 -    } else if (mpf->mpf_physptr) {
  6.1144 +	} else if (mpf->mpf_physptr) {
  6.1145  
  6.1146 -        /*
  6.1147 -         * Read the physical hardware table.  Anything here will
  6.1148 -         * override the defaults.
  6.1149 -         */
  6.1150 -        if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
  6.1151 -            smp_found_config = 0;
  6.1152 -            printk("BIOS bug, MP table errors detected!...\n");
  6.1153 -            printk("... disabling SMP support. (tell your hw vendor)\n");
  6.1154 -            return;
  6.1155 -        }
  6.1156 -        /*
  6.1157 -         * If there are no explicit MP IRQ entries, then we are
  6.1158 -         * broken.  We set up most of the low 16 IO-APIC pins to
  6.1159 -         * ISA defaults and hope it will work.
  6.1160 -         */
  6.1161 -        if (!mp_irq_entries) {
  6.1162 -            struct mpc_config_bus bus;
  6.1163 +		/*
  6.1164 +		 * Read the physical hardware table.  Anything here will
  6.1165 +		 * override the defaults.
  6.1166 +		 */
  6.1167 +		if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
  6.1168 +			smp_found_config = 0;
  6.1169 +			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
  6.1170 +			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
  6.1171 +			return;
  6.1172 +		}
  6.1173 +		/*
  6.1174 +		 * If there are no explicit MP IRQ entries, then we are
  6.1175 +		 * broken.  We set up most of the low 16 IO-APIC pins to
  6.1176 +		 * ISA defaults and hope it will work.
  6.1177 +		 */
  6.1178 +		if (!mp_irq_entries) {
  6.1179 +			struct mpc_config_bus bus;
  6.1180  
  6.1181 -            printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
  6.1182 +			printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
  6.1183  
  6.1184 -            bus.mpc_type = MP_BUS;
  6.1185 -            bus.mpc_busid = 0;
  6.1186 -            memcpy(bus.mpc_bustype, "ISA   ", 6);
  6.1187 -            MP_bus_info(&bus);
  6.1188 +			bus.mpc_type = MP_BUS;
  6.1189 +			bus.mpc_busid = 0;
  6.1190 +			memcpy(bus.mpc_bustype, "ISA   ", 6);
  6.1191 +			MP_bus_info(&bus);
  6.1192  
  6.1193 -            construct_default_ioirq_mptable(0);
  6.1194 -        }
  6.1195 +			construct_default_ioirq_mptable(0);
  6.1196 +		}
  6.1197  
  6.1198 -    } else
  6.1199 -        BUG();
  6.1200 +	} else
  6.1201 +		BUG();
  6.1202  
  6.1203 -    printk("Processors: %d\n", num_processors);
  6.1204 -    /*
  6.1205 -     * Only use the first configuration found.
  6.1206 -     */
  6.1207 +	printk("Processors: %d\n", num_processors);
  6.1208 +	/*
  6.1209 +	 * Only use the first configuration found.
  6.1210 +	 */
  6.1211  }
  6.1212  
  6.1213  static int __init smp_scan_config (unsigned long base, unsigned long length)
  6.1214  {
  6.1215 -    unsigned long *bp = phys_to_virt(base);
  6.1216 -    struct intel_mp_floating *mpf;
  6.1217 +	unsigned long *bp = phys_to_virt(base);
  6.1218 +	struct intel_mp_floating *mpf;
  6.1219  
  6.1220 -    Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
  6.1221 -    if (sizeof(*mpf) != 16)
  6.1222 -        printk("Error: MPF size\n");
  6.1223 +	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
  6.1224 +	if (sizeof(*mpf) != 16)
  6.1225 +		printk("Error: MPF size\n");
  6.1226  
  6.1227 -    while (length > 0) {
  6.1228 -        mpf = (struct intel_mp_floating *)bp;
  6.1229 -        if ((*bp == SMP_MAGIC_IDENT) &&
  6.1230 -            (mpf->mpf_length == 1) &&
  6.1231 -            !mpf_checksum((unsigned char *)bp, 16) &&
  6.1232 -            ((mpf->mpf_specification == 1)
  6.1233 -             || (mpf->mpf_specification == 4)) ) {
  6.1234 +	while (length > 0) {
  6.1235 +		mpf = (struct intel_mp_floating *)bp;
  6.1236 +		if ((*bp == SMP_MAGIC_IDENT) &&
  6.1237 +			(mpf->mpf_length == 1) &&
  6.1238 +			!mpf_checksum((unsigned char *)bp, 16) &&
  6.1239 +			((mpf->mpf_specification == 1)
  6.1240 +				|| (mpf->mpf_specification == 4)) ) {
  6.1241  
  6.1242 -            smp_found_config = 1;
  6.1243 -            printk("found SMP MP-table at %08lx\n",
  6.1244 -                   virt_to_phys(mpf));
  6.1245 -            reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
  6.1246 -            if (mpf->mpf_physptr)
  6.1247 -                reserve_bootmem(mpf->mpf_physptr, PAGE_SIZE);
  6.1248 -            mpf_found = mpf;
  6.1249 -            return 1;
  6.1250 -        }
  6.1251 -        bp += 4;
  6.1252 -        length -= 16;
  6.1253 -    }
  6.1254 -    return 0;
  6.1255 +			smp_found_config = 1;
  6.1256 +			printk("found SMP MP-table at %08lx\n",
  6.1257 +						virt_to_phys(mpf));
  6.1258 +			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
  6.1259 +			if (mpf->mpf_physptr)
  6.1260 +				reserve_bootmem(mpf->mpf_physptr, PAGE_SIZE);
  6.1261 +			mpf_found = mpf;
  6.1262 +			return 1;
  6.1263 +		}
  6.1264 +		bp += 4;
  6.1265 +		length -= 16;
  6.1266 +	}
  6.1267 +	return 0;
  6.1268  }
  6.1269  
  6.1270  void __init find_intel_smp (void)
  6.1271  {
  6.1272 -    /*
  6.1273 -     * 1) Scan the bottom 1K for a signature
  6.1274 -     * 2) Scan the top 1K of base RAM
  6.1275 -     * 3) Scan the 64K of bios
  6.1276 -     */
  6.1277 -    if (smp_scan_config(0x0,0x400) ||
  6.1278 -        smp_scan_config(639*0x400,0x400) ||
  6.1279 -        smp_scan_config(0xF0000,0x10000))
  6.1280 -        return;
  6.1281 +	unsigned int address;
  6.1282 +
  6.1283 +	/*
  6.1284 +	 * FIXME: Linux assumes you have 640K of base ram..
  6.1285 +	 * this continues the error...
  6.1286 +	 *
  6.1287 +	 * 1) Scan the bottom 1K for a signature
  6.1288 +	 * 2) Scan the top 1K of base RAM
  6.1289 +	 * 3) Scan the 64K of bios
  6.1290 +	 */
  6.1291 +	if (smp_scan_config(0x0,0x400) ||
  6.1292 +		smp_scan_config(639*0x400,0x400) ||
  6.1293 +			smp_scan_config(0xF0000,0x10000))
  6.1294 +		return;
  6.1295 +	/*
  6.1296 +	 * If it is an SMP machine we should know now, unless the
  6.1297 +	 * configuration is in an EISA/MCA bus machine with an
  6.1298 +	 * extended bios data area.
  6.1299 +	 *
  6.1300 +	 * there is a real-mode segmented pointer pointing to the
  6.1301 +	 * 4K EBDA area at 0x40E, calculate and scan it here.
  6.1302 +	 *
  6.1303 +	 * NOTE! There were Linux loaders that will corrupt the EBDA
  6.1304 +	 * area, and as such this kind of SMP config may be less
  6.1305 +	 * trustworthy, simply because the SMP table may have been
  6.1306 +	 * stomped on during early boot.  Thankfully the bootloaders
  6.1307 +	 * now honour the EBDA.
  6.1308 +	 */
  6.1309 +
  6.1310 +	address = *(unsigned short *)phys_to_virt(0x40E);
  6.1311 +	address <<= 4;
  6.1312 +	smp_scan_config(address, 0x1000);
  6.1313  }
  6.1314  
  6.1315 +#else
  6.1316 +
  6.1317 +/*
  6.1318 + * The Visual Workstation is Intel MP compliant in the hardware
  6.1319 + * sense, but it doesn't have a BIOS(-configuration table).
  6.1320 + * No problem for Linux.
  6.1321 + */
  6.1322 +void __init find_visws_smp(void)
  6.1323 +{
  6.1324 +	smp_found_config = 1;
  6.1325 +
  6.1326 +	phys_cpu_present_map |= 2; /* or in id 1 */
  6.1327 +	apic_version[1] |= 0x10; /* integrated APIC */
  6.1328 +	apic_version[0] |= 0x10;
  6.1329 +
  6.1330 +	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
  6.1331 +}
  6.1332 +
  6.1333 +#endif
  6.1334 +
  6.1335  /*
  6.1336   * - Intel MP Configuration Table
  6.1337   * - or SGI Visual Workstation configuration
  6.1338   */
  6.1339  void __init find_smp_config (void)
  6.1340  {
  6.1341 -    find_intel_smp();
  6.1342 +#ifdef CONFIG_X86_LOCAL_APIC
  6.1343 +	find_intel_smp();
  6.1344 +#endif
  6.1345 +#ifdef CONFIG_VISWS
  6.1346 +	find_visws_smp();
  6.1347 +#endif
  6.1348  }
  6.1349  
     7.1 --- a/xen-2.4.16/arch/i386/process.c	Tue Feb 11 17:54:17 2003 +0000
     7.2 +++ b/xen-2.4.16/arch/i386/process.c	Thu Feb 13 15:58:34 2003 +0000
     7.3 @@ -364,7 +364,6 @@ void new_thread(struct task_struct *p,
     7.4  /* NB. prev_p passed in %eax, next_p passed in %edx */
     7.5  void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
     7.6  {
     7.7 -    extern struct desc_struct idt_table[];
     7.8      struct thread_struct *prev = &prev_p->thread,
     7.9          *next = &next_p->thread;
    7.10      struct tss_struct *tss = init_tss + smp_processor_id();
     8.1 --- a/xen-2.4.16/arch/i386/setup.c	Tue Feb 11 17:54:17 2003 +0000
     8.2 +++ b/xen-2.4.16/arch/i386/setup.c	Thu Feb 13 15:58:34 2003 +0000
     8.3 @@ -283,6 +283,9 @@ void __init start_of_day(void)
     8.4  	extern void ac_timer_init(void);
     8.5      extern int  setup_network_devices(void);
     8.6      extern void net_init(void);
     8.7 +    extern void initialize_block_io(void);
     8.8 +    extern void initialize_serial(void);
     8.9 +    extern void initialize_keyboard(void);
    8.10  
    8.11      unsigned long low_mem_size;
    8.12      
    8.13 @@ -338,9 +341,15 @@ void __init start_of_day(void)
    8.14      pci_init();
    8.15  #endif
    8.16      do_initcalls();
    8.17 +
    8.18 +    initialize_serial();   /* setup serial 'driver' (for debugging) */
    8.19 +    initialize_keyboard(); /* setup keyboard (also for debugging) */
    8.20 +
    8.21      if ( !setup_network_devices() )
    8.22          panic("Must have a network device!\n");
    8.23 -    net_init(); /* initializes virtual network system. */
    8.24 +    net_init();            /* initializes virtual network system. */
    8.25 +    initialize_block_io(); /* setup block devices */
    8.26 +
    8.27  
    8.28  #ifdef CONFIG_SMP
    8.29      wait_init_idle = cpu_online_map;
     9.1 --- a/xen-2.4.16/arch/i386/smpboot.c	Tue Feb 11 17:54:17 2003 +0000
     9.2 +++ b/xen-2.4.16/arch/i386/smpboot.c	Thu Feb 13 15:58:34 2003 +0000
     9.3 @@ -395,6 +395,10 @@ int cpucount;
     9.4   */
     9.5  int __init start_secondary(void *unused)
     9.6  {
     9.7 +    unsigned int cpu = smp_processor_id();
     9.8 +    /* 6 bytes suitable for passing to LIDT instruction. */
     9.9 +    unsigned char idt_load[6];
    9.10 +
    9.11      extern void cpu_init(void);
    9.12  
    9.13      /*
    9.14 @@ -409,6 +413,16 @@ int __init start_secondary(void *unused)
    9.15          rep_nop();
    9.16  
    9.17      /*
    9.18 +     * At this point, boot CPU has fully initialised the IDT. It is
    9.19 +     * now safe to make ourselves a private copy.
    9.20 +     */
    9.21 +    idt_tables[cpu] = kmalloc(IDT_ENTRIES*8, GFP_KERNEL);
    9.22 +    memcpy(idt_tables[cpu], idt_table, IDT_ENTRIES*8);
    9.23 +    *(unsigned short *)(&idt_load[0]) = (IDT_ENTRIES*8)-1;
    9.24 +    *(unsigned long  *)(&idt_load[2]) = (unsigned long)idt_tables[cpu];
    9.25 +    __asm__ __volatile__ ( "lidt %0" : "=m" (idt_load) );
    9.26 +
    9.27 +    /*
    9.28       * low-memory mappings have been cleared, flush them from the local TLBs 
    9.29       * too.
    9.30       */
    10.1 --- a/xen-2.4.16/arch/i386/traps.c	Tue Feb 11 17:54:17 2003 +0000
    10.2 +++ b/xen-2.4.16/arch/i386/traps.c	Thu Feb 13 15:58:34 2003 +0000
    10.3 @@ -43,12 +43,10 @@ asmlinkage int hypervisor_call(void);
    10.4  asmlinkage void lcall7(void);
    10.5  asmlinkage void lcall27(void);
    10.6  
    10.7 -/*
    10.8 - * The IDT has to be page-aligned to simplify the Pentium
    10.9 - * F0 0F bug workaround.. We have a special link segment
   10.10 - * for this.
   10.11 - */
   10.12 -struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
   10.13 +/* Master table, and the one used by CPU0. */
   10.14 +struct desc_struct idt_table[256] = { {0, 0}, };
   10.15 +/* All other CPUs have their own copy. */
   10.16 +struct desc_struct *idt_tables[NR_CPUS] = { 0 };
   10.17  
   10.18  asmlinkage void divide_error(void);
   10.19  asmlinkage void debug(void);
   10.20 @@ -299,7 +297,12 @@ asmlinkage void do_general_protection(st
   10.21          ti = current->thread.traps + (error_code>>3);
   10.22          if ( ti->dpl >= (regs->xcs & 3) )
   10.23          {
   10.24 -            if ( (error_code>>3)==0x80 ) { printk("!!!\n"); BUG(); }
   10.25 +            /* XXX Kill next conditional soon :-) XXX */
   10.26 +            if ( (error_code>>3)==0x80 ) 
   10.27 +            { 
   10.28 +                printk("DIDN'T USE FAST-TRAP HANDLER FOR 0x80!!! :-(\n");
   10.29 +                BUG(); 
   10.30 +            }
   10.31              gtb->flags = GTBF_TRAP_NOCODE;
   10.32              gtb->cs    = ti->cs;
   10.33              gtb->eip   = ti->address;
   10.34 @@ -542,6 +545,9 @@ void __init trap_init(void)
   10.35      /* Only ring 1 can access monitor services. */
   10.36      _set_gate(idt_table+HYPERVISOR_CALL_VECTOR,15,1,&hypervisor_call);
   10.37  
   10.38 +    /* CPU0 uses the master IDT. */
   10.39 +    idt_tables[0] = idt_table;
   10.40 +
   10.41      /*
   10.42       * Should be a barrier for any external CPU state.
   10.43       */
    11.1 --- a/xen-2.4.16/common/event.c	Tue Feb 11 17:54:17 2003 +0000
    11.2 +++ b/xen-2.4.16/common/event.c	Thu Feb 13 15:58:34 2003 +0000
    11.3 @@ -15,13 +15,15 @@ typedef void (*hyp_event_callback_fn_t)(
    11.4  
    11.5  extern void schedule(void);
    11.6  extern void flush_rx_queue(void);
    11.7 +extern void flush_blk_queue(void);
    11.8  
    11.9  /* Ordering must match definitions of _HYP_EVENT_* in xeno/sched.h */
   11.10  static hyp_event_callback_fn_t event_call_fn[] = 
   11.11  {
   11.12      schedule,
   11.13      flush_rx_queue,
   11.14 -    kill_domain
   11.15 +    kill_domain, 
   11.16 +    flush_blk_queue
   11.17  };
   11.18  
   11.19  /* Handle outstanding events for the currently-executing domain. */
    12.1 --- a/xen-2.4.16/drivers/Makefile	Tue Feb 11 17:54:17 2003 +0000
    12.2 +++ b/xen-2.4.16/drivers/Makefile	Thu Feb 13 15:58:34 2003 +0000
    12.3 @@ -1,12 +1,16 @@
    12.4  
    12.5  default:
    12.6 +	$(MAKE) -C char
    12.7  	$(MAKE) -C pci
    12.8  	$(MAKE) -C net
    12.9  	$(MAKE) -C block
   12.10  	$(MAKE) -C ide
   12.11 +#	$(MAKE) -C scsi
   12.12  
   12.13  clean:
   12.14 +	$(MAKE) -C char clean
   12.15  	$(MAKE) -C pci clean
   12.16  	$(MAKE) -C net clean
   12.17  	$(MAKE) -C block clean
   12.18  	$(MAKE) -C ide clean
   12.19 +#	$(MAKE) -C scsi clean
    13.1 --- a/xen-2.4.16/drivers/block/ll_rw_blk.c	Tue Feb 11 17:54:17 2003 +0000
    13.2 +++ b/xen-2.4.16/drivers/block/ll_rw_blk.c	Thu Feb 13 15:58:34 2003 +0000
    13.3 @@ -31,8 +31,12 @@
    13.4  #include <xeno/slab.h>
    13.5  #include <xeno/module.h>
    13.6  
    13.7 +static void end_buffer_dummy(struct buffer_head *bh, int uptodate)
    13.8 +{
    13.9 +  /* do nothing */
   13.10 +}
   13.11 +
   13.12  /* This will die as all synchronous stuff is coming to an end */
   13.13 -#define end_buffer_io_sync NULL
   13.14  #define complete(_r) panic("completion.h stuff may be needed...")
   13.15  
   13.16  /*
   13.17 @@ -307,10 +311,14 @@ static void generic_plug_device(request_
   13.18   */
   13.19  static inline void __generic_unplug_device(request_queue_t *q)
   13.20  {
   13.21 +  /*	printk(KERN_ALERT "__generic_unplug_device %p %d\n", q, q->plugged); */
   13.22  	if (q->plugged) {
   13.23  		q->plugged = 0;
   13.24  		if (!list_empty(&q->queue_head))
   13.25 +		  {
   13.26 +		    /*		    printk(KERN_ALERT " calling %p\n", q->request_fn); */
   13.27  			q->request_fn(q);
   13.28 +		  }
   13.29  	}
   13.30  }
   13.31  
   13.32 @@ -319,6 +327,8 @@ void generic_unplug_device(void *data)
   13.33  	request_queue_t *q = (request_queue_t *) data;
   13.34  	unsigned long flags;
   13.35  
   13.36 +	/*	printk(KERN_ALERT "generic_unplug_device\n"); */
   13.37 +
   13.38  	spin_lock_irqsave(&io_request_lock, flags);
   13.39  	__generic_unplug_device(q);
   13.40  	spin_unlock_irqrestore(&io_request_lock, flags);
   13.41 @@ -856,6 +866,8 @@ static int __make_request(request_queue_
   13.42  	int latency;
   13.43  	elevator_t *elevator = &q->elevator;
   13.44  
   13.45 +	/* 	printk(KERN_ALERT "__make_request\n");*/
   13.46 +
   13.47  	count = bh->b_size >> 9;
   13.48  	sector = bh->b_rsector;
   13.49  
   13.50 @@ -1061,6 +1073,8 @@ void generic_make_request (int rw, struc
   13.51  	int minorsize = 0;
   13.52  	request_queue_t *q;
   13.53  
   13.54 +	/* 	printk(KERN_ALERT "generic_make_request\n"); */
   13.55 +
   13.56  	if (!bh->b_end_io)
   13.57  		BUG();
   13.58  
   13.59 @@ -1130,6 +1144,8 @@ void submit_bh(int rw, struct buffer_hea
   13.60  {
   13.61  	int count = bh->b_size >> 9;
   13.62  
   13.63 +	/* 	printk(KERN_ALERT "submit_bh\n"); */
   13.64 +
   13.65  	if (!test_bit(BH_Lock, &bh->b_state))
   13.66  		BUG();
   13.67  
   13.68 @@ -1141,7 +1157,7 @@ void submit_bh(int rw, struct buffer_hea
   13.69  	 * further remap this.
   13.70  	 */
   13.71  	bh->b_rdev = bh->b_dev;
   13.72 -	bh->b_rsector = bh->b_blocknr * count;
   13.73 +	/*	bh->b_rsector = bh->b_blocknr * count; */
   13.74  
   13.75  	generic_make_request(rw, bh);
   13.76  
   13.77 @@ -1194,6 +1210,8 @@ void ll_rw_block(int rw, int nr, struct 
   13.78  	int correct_size;
   13.79  	int i;
   13.80  
   13.81 +	/* 	printk(KERN_ALERT "ll_rw_block %d %d\n", rw, nr); */
   13.82 +
   13.83  	if (!nr)
   13.84  		return;
   13.85  
   13.86 @@ -1229,14 +1247,14 @@ void ll_rw_block(int rw, int nr, struct 
   13.87  
   13.88  		/* We have the buffer lock */
   13.89  		atomic_inc(&bh->b_count);
   13.90 -		bh->b_end_io = end_buffer_io_sync;
   13.91 +		bh->b_end_io = end_buffer_dummy;
   13.92  
   13.93  		switch(rw) {
   13.94  		case WRITE:
   13.95  			if (!atomic_set_buffer_clean(bh))
   13.96  				/* Hmmph! Nothing to write */
   13.97  				goto end_io;
   13.98 -			__mark_buffer_clean(bh);
   13.99 +			/* __mark_buffer_clean(bh); */
  13.100  			break;
  13.101  
  13.102  		case READA:
  13.103 @@ -1302,6 +1320,7 @@ int end_that_request_first (struct reque
  13.104  		req->bh = bh->b_reqnext;
  13.105  		bh->b_reqnext = NULL;
  13.106  		bh->b_end_io(bh, uptodate);
  13.107 +		end_block_io_op(bh);
  13.108  		if ((bh = req->bh) != NULL) {
  13.109  			req->hard_sector += nsect;
  13.110  			req->hard_nr_sectors -= nsect;
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen-2.4.16/drivers/block/xen_block.c	Thu Feb 13 15:58:34 2003 +0000
    14.3 @@ -0,0 +1,620 @@
    14.4 +/*
    14.5 + * xen-block.c
    14.6 + *
    14.7 + * process incoming block io requests from guestos's.
    14.8 + */
    14.9 +
   14.10 +#include <xeno/config.h>
   14.11 +#include <xeno/types.h>
   14.12 +#include <xeno/lib.h>
   14.13 +#include <xeno/sched.h>
   14.14 +#include <xeno/blkdev.h>
   14.15 +#include <xeno/event.h>                                    /* mark_hyp_event */
   14.16 +#include <hypervisor-ifs/block.h>
   14.17 +#include <hypervisor-ifs/hypervisor-if.h>
   14.18 +#include <asm-i386/io.h>
   14.19 +#include <asm/spinlock.h>
   14.20 +
   14.21 +#define XEN_BLK_DEBUG 0
   14.22 +#define XEN_BLK_DEBUG_LEVEL KERN_ALERT
   14.23 +
   14.24 +#define XEN_BLK_REQUEST_LIST_SIZE 256                      /* very arbitrary */
   14.25 +
   14.26 +typedef struct blk_request
   14.27 +{
   14.28 +  struct list_head queue;
   14.29 +  struct buffer_head *bh;
   14.30 +  blk_ring_entry_t request;
   14.31 +  struct task_struct *domain;                           /* requesting domain */
   14.32 +} blk_request_t;
   14.33 +
   14.34 +static int pending_work;                  /* which domains have work for us? */
   14.35 +blk_request_t blk_request_list[XEN_BLK_REQUEST_LIST_SIZE];
   14.36 +struct list_head free_queue;                              /* unused requests */
   14.37 +struct list_head pending_queue;                      /* waiting for hardware */
   14.38 +struct list_head io_done_queue;       /* request completed. send to guest os */
   14.39 +spinlock_t free_queue_lock;
   14.40 +spinlock_t pending_queue_lock;
   14.41 +spinlock_t io_done_queue_lock;
   14.42 +
   14.43 +/* some definitions */
   14.44 +void dumpx (char *buffer, int count);
   14.45 +void printx (char * string);
   14.46 +long do_block_io_op_domain (struct task_struct* task);
   14.47 +int dispatch_rw_block_io (int index);
   14.48 +int dispatch_probe_block_io (int index);
   14.49 +int dispatch_debug_block_io (int index);
   14.50 +
   14.51 +/*
   14.52 + * end_block_io_op
   14.53 + *
   14.54 + * IO has completed.  Need to notify the guest operating system.
   14.55 + * Called from hardware interrupt.
   14.56 + */
   14.57 +
   14.58 +void end_block_io_op(struct buffer_head * bh)
   14.59 +{
   14.60 +  unsigned long cpu_mask;
   14.61 +  /* struct list_head *list;*/
   14.62 +  blk_request_t *blk_request = NULL;
   14.63 +  unsigned long flags;                                           /* irq save */
   14.64 +
   14.65 +#if 0
   14.66 +  printk("{E}"); 
   14.67 +#endif
   14.68 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
   14.69 +			     "XEN end_block_io_op,  bh: %lx\n",
   14.70 +			     (unsigned long)bh);
   14.71 +
   14.72 +  {
   14.73 +    char temp[100];
   14.74 +    sprintf(temp, "endio  bh: 0x%p, blkno: 0x%lx",
   14.75 +	    bh, bh->b_blocknr);
   14.76 +    printx(temp);
   14.77 +  }
   14.78 +
   14.79 +  spin_lock_irqsave(&pending_queue_lock, flags);
   14.80 +  /*
   14.81 +  list_for_each (list, &pending_queue)
   14.82 +  {
   14.83 +    blk_request = list_entry(list, blk_request_t, queue);
   14.84 +    if (blk_request->bh == bh)      
   14.85 +    {
   14.86 +      break;
   14.87 +    }
   14.88 +  }
   14.89 +  */
   14.90 +  blk_request = (blk_request_t *)bh->b_xen_request;
   14.91 +  if (blk_request == NULL)
   14.92 +  {
   14.93 +    printk (KERN_ALERT
   14.94 +	    "   block io interrupt received for unknown buffer [0x%lx]\n",
   14.95 +	    (unsigned long) bh);
   14.96 +    spin_unlock_irqrestore(&pending_queue_lock, flags);
   14.97 +    return;
   14.98 +  }
   14.99 +  list_del(&blk_request->queue);
  14.100 +  spin_unlock_irqrestore(&pending_queue_lock, flags);
  14.101 +
  14.102 +  spin_lock_irqsave(&io_done_queue_lock, flags);
  14.103 +  list_add_tail(&blk_request->queue, &io_done_queue);
  14.104 +  spin_unlock_irqrestore(&io_done_queue_lock, flags);
  14.105 +
  14.106 +  /* enqueue work */
  14.107 +  cpu_mask = mark_hyp_event(blk_request->domain, _HYP_EVENT_BLK_RX);
  14.108 +
  14.109 +  return;
  14.110 +}
  14.111 +
  14.112 +/*
  14.113 + * flush_blk_queue
  14.114 + *
  14.115 + * Called by the hypervisor synchronously when there is something to do
  14.116 + * (block transfers have completed)
  14.117 + */
  14.118 +
  14.119 +void flush_blk_queue(void)
  14.120 +{
  14.121 +  blk_request_t *blk_request;
  14.122 +  int position = 0;
  14.123 +  blk_ring_t *blk_ring;
  14.124 +  unsigned long flags;
  14.125 +  int loop;
  14.126 +
  14.127 +#if 0
  14.128 +  printk("{F}"); 
  14.129 +#endif
  14.130 +  /*
  14.131 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
  14.132 +			     "XEN flush_blk_queue\n");
  14.133 +  */
  14.134 +
  14.135 +  clear_bit(_HYP_EVENT_BLK_RX, &current->hyp_events);
  14.136 +
  14.137 +  /* NEED LOCK? */
  14.138 +  spin_lock_irqsave(&io_done_queue_lock, flags);
  14.139 +  while (!list_empty(&io_done_queue))
  14.140 +  {
  14.141 +    blk_request = list_entry(io_done_queue.next, blk_request_t, queue);
  14.142 +    list_del (&blk_request->queue);
  14.143 +    spin_unlock_irqrestore(&io_done_queue_lock, flags);
  14.144 +
  14.145 +    /* place on ring for guest os */ 
  14.146 +    blk_ring = blk_request->domain->blk_ring_base;
  14.147 +    position = blk_ring->rx_prod;
  14.148 +
  14.149 +    if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
  14.150 +			       "XEN flush_blk_queue [%d]\n", position);
  14.151 +
  14.152 +    memcpy(&blk_ring->rx_ring[position], &blk_request->request,
  14.153 +	   sizeof(blk_ring_entry_t));
  14.154 +    blk_ring->rx_prod = BLK_RX_RING_INC(blk_ring->rx_prod);
  14.155 +
  14.156 +    /* notify appropriate guest os */
  14.157 +    set_bit(_EVENT_BLK_RX,
  14.158 +	    &blk_request->domain->shared_info->events);
  14.159 +
  14.160 +    if (0)
  14.161 +    {
  14.162 +      int temp;
  14.163 +      struct buffer_head *bh = blk_request->bh;
  14.164 +      char * vbuffer = bh->b_data;
  14.165 +
  14.166 +      printk (KERN_ALERT "XEN return block 0x%lx\n", bh->b_blocknr);
  14.167 +
  14.168 +      for (temp = 0; temp < bh->b_size; temp++)
  14.169 +      {
  14.170 +	if (temp % 16 == 0)       printk ("[%04x]  ", temp);
  14.171 +	else if (temp % 4 == 0)   printk (" ");
  14.172 +	                          printk ("%02x",
  14.173 +					  vbuffer[temp] & 255);
  14.174 +	if ((temp + 1) % 16 == 0) printk ("\n");
  14.175 +      }
  14.176 +      printk ("\n\n");
  14.177 +    }
  14.178 +
  14.179 +    /* free the buffer header allocated in do_block_io_op */
  14.180 +    if (blk_request->bh)
  14.181 +    {
  14.182 +      kfree(blk_request->bh);                     /* alloc in do_block_io_op */
  14.183 +    }
  14.184 +
  14.185 +    spin_lock_irqsave(&free_queue_lock, flags);
  14.186 +    list_add_tail(&blk_request->queue, &free_queue);
  14.187 +    spin_unlock_irqrestore(&free_queue_lock, flags);
  14.188 +
  14.189 +    spin_lock_irqsave(&io_done_queue_lock, flags);
  14.190 +  }
  14.191 +  spin_unlock_irqrestore(&io_done_queue_lock, flags);
  14.192 +
  14.193 +  /*
  14.194 +   * now check if there is any pending work from any domain
  14.195 +   * that we were previously unable to process.
  14.196 +   *
  14.197 +   * NOTE: the current algorithm will check _every_ domain
  14.198 +   * and wake up _every_ domain that has pending work.
  14.199 +   * In the future, we should stop waking up domains once
  14.200 +   * there isn't any space for their requests any more
  14.201 +   * ALSO, we need to maintain a counter of the last domain
  14.202 +   * that we woke up for fairness... we shouldn't restart
  14.203 +   * at domain 0 every time (although we might want to special
  14.204 +   * case domain 0);
  14.205 +   */
  14.206 +  for (loop = 0; loop < XEN_BLOCK_MAX_DOMAINS; loop++)
  14.207 +  {
  14.208 +    int domain = pending_work & (1 << loop);
  14.209 +
  14.210 +    if (domain)
  14.211 +    {
  14.212 +      struct task_struct *mytask = current;
  14.213 +
  14.214 +      /*
  14.215 +      printk (KERN_ALERT 
  14.216 +	      "flush_blk_queue  pending_work: %x  domain: %d  loop: %d\n",
  14.217 +	      pending_work, domain, loop);
  14.218 +      */
  14.219 +      /* IS THERE A BETTER WAY OF FINDING THE TASK STRUCT FOR A 
  14.220 +       * PARTICULAR DOMAIN? 
  14.221 +       *
  14.222 +       * WHAT IF THE TASK GOES AWAY BEFORE WE HAVE A CHANCE TO
  14.223 +       * FINISH PROCESSING ALL OF ITS REQUESTS?
  14.224 +       */
  14.225 +      while (mytask->domain != loop)
  14.226 +      {
  14.227 +	mytask = mytask->next_task;
  14.228 +      }
  14.229 +      do_block_io_op_domain(mytask);
  14.230 +
  14.231 +      pending_work = pending_work & !(1 << loop);
  14.232 +      /*
  14.233 +      printk (KERN_ALERT 
  14.234 +	      "                 pending_work: %x  domain: %d  loop: %d\n",
  14.235 +	      pending_work, domain, loop);
  14.236 +      */
  14.237 +    }
  14.238 +  }
  14.239 +}
  14.240 +
  14.241 +/*
  14.242 + * do_block_io_op
  14.243 + *
  14.244 + * Accept a block io request from a guest operating system.
  14.245 + * There is an entry in the hypervisor_call_table (xen/arch/i386/entry.S).
  14.246 + */
  14.247 +
  14.248 +long do_block_io_op (void)
  14.249 +{
  14.250 +  return do_block_io_op_domain(current);
  14.251 +}
  14.252 +
  14.253 +/*
  14.254 + * do_block_io_op
  14.255 + *
  14.256 + * handle the requests for a particular domain
  14.257 + */
  14.258 +
  14.259 +long do_block_io_op_domain (struct task_struct* task)
  14.260 +{
  14.261 +  blk_ring_t *blk_ring = task->blk_ring_base;
  14.262 +  int loop;
  14.263 +
  14.264 +#if 0
  14.265 +  printk("{%d}", current->domain); 
  14.266 +#endif
  14.267 +  if (XEN_BLK_DEBUG)  printk(XEN_BLK_DEBUG_LEVEL
  14.268 +			     "XEN do_block_io_op %d %d\n",
  14.269 +			     blk_ring->tx_cons, blk_ring->tx_prod);
  14.270 +
  14.271 +  for (loop = blk_ring->tx_cons;
  14.272 +       loop != blk_ring->tx_prod;
  14.273 +       loop = BLK_TX_RING_INC(loop))
  14.274 +  {
  14.275 +    int status = 1;
  14.276 +
  14.277 +    switch (blk_ring->tx_ring[loop].operation)
  14.278 +    {
  14.279 +      case XEN_BLOCK_READ :
  14.280 +      case XEN_BLOCK_WRITE :
  14.281 +      {
  14.282 +	status = dispatch_rw_block_io(loop);
  14.283 +	break;
  14.284 +      }
  14.285 +      case XEN_BLOCK_PROBE :
  14.286 +      {
  14.287 +	status = dispatch_probe_block_io(loop);
  14.288 +	break;
  14.289 +      }
  14.290 +      case XEN_BLOCK_DEBUG :
  14.291 +      {
  14.292 +	status = dispatch_debug_block_io(loop);
  14.293 +	break;
  14.294 +      }
  14.295 +      default :
  14.296 +      {
  14.297 +	printk (KERN_ALERT "error: unknown block io operation [%d]\n",
  14.298 +		blk_ring->tx_ring[loop].operation);
  14.299 +	BUG();
  14.300 +      }
  14.301 +    }
  14.302 +
  14.303 +    if (status)
  14.304 +    {
  14.305 +      /* unable to successfully issue / complete command, maybe because
  14.306 +       * another resource (e.g. disk request buffers) is unavailable.
  14.307 +       * stop removing items from the communications ring and try 
  14.308 +       * again later 
  14.309 +       */
  14.310 +
  14.311 +      /*
  14.312 +      printk ("do_block_io_op_domain  domain:%d, pending_work: %x\n",
  14.313 +	      task->domain, pending_work);
  14.314 +      */
  14.315 +      pending_work = pending_work | (1 << task->domain);
  14.316 +      /*
  14.317 +      printk ("do_block_io_op_domain  domain:%d, pending_work: %x\n",
  14.318 +	      task->domain, pending_work);
  14.319 +      */
  14.320 +      break;
  14.321 +    }
  14.322 +  }
  14.323 +
  14.324 +  blk_ring->tx_cons = loop;
  14.325 +
  14.326 +  return 0L;
  14.327 +}
  14.328 +
  14.329 +int dispatch_debug_block_io (int index)
  14.330 +{
  14.331 +  struct task_struct *task;
  14.332 +  blk_ring_t *blk_ring = current->blk_ring_base;
  14.333 +  char * buffer;
  14.334 +  char output[1000];
  14.335 +
  14.336 +  int foobar = (unsigned long)blk_ring->tx_ring[index].block_number;
  14.337 +
  14.338 +  printk (KERN_ALERT "dispatch_debug_block_io %d\n", foobar);
  14.339 +
  14.340 +  buffer = phys_to_virt(blk_ring->tx_ring[index].buffer);
  14.341 +  strcpy (buffer, "DEBUG\n");
  14.342 +
  14.343 +  task = current;
  14.344 +  sprintf (buffer, "current %d\n", current->domain);
  14.345 +  sprintf (buffer, "%s  tx: prod: %d, cons: %d, size: %d\n", buffer,
  14.346 +	   blk_ring->tx_prod, blk_ring->tx_cons, blk_ring->tx_ring_size);
  14.347 +  sprintf (buffer, "%s  rx: prod: %d, cons: %d, size: %d\n", buffer,
  14.348 +	   blk_ring->rx_prod, blk_ring->rx_cons, blk_ring->rx_ring_size);
  14.349 +
  14.350 +  task = task->next_task;
  14.351 +  while (task != current)
  14.352 +  {
  14.353 +    blk_ring = task->blk_ring_base;
  14.354 +    sprintf (buffer, "%stask %d\n", buffer, task->domain);
  14.355 +    if (blk_ring != NULL)
  14.356 +    {
  14.357 +      sprintf (buffer, "%s  tx: prod: %d, cons: %d, size: %d\n",
  14.358 +	       buffer, blk_ring->tx_prod, blk_ring->tx_cons, 
  14.359 +	       blk_ring->tx_ring_size);
  14.360 +      sprintf (buffer, "%s  rx: prod: %d, cons: %d, size: %d\n",
  14.361 +	       buffer, blk_ring->rx_prod, blk_ring->rx_cons, 
  14.362 +	       blk_ring->rx_ring_size);
  14.363 +    }
  14.364 +    task = task->next_task;
  14.365 +  }
  14.366 +  dumpx(output, foobar);
  14.367 +  sprintf (buffer, "%s%s\n", buffer, output);
  14.368 +
  14.369 +  return 0;
  14.370 +}
  14.371 +
  14.372 +int dispatch_probe_block_io (int index)
  14.373 +{
  14.374 +  blk_ring_t *blk_ring = current->blk_ring_base;
  14.375 +  xen_disk_info_t *xdi;
  14.376 +
  14.377 +  xdi = phys_to_virt(blk_ring->tx_ring[index].buffer);
  14.378 +
  14.379 +  ide_probe_devices(xdi);
  14.380 +
  14.381 +  return 0;
  14.382 +}
  14.383 +
  14.384 +int dispatch_rw_block_io (int index)
  14.385 +{
  14.386 +  blk_ring_t *blk_ring = current->blk_ring_base;
  14.387 +  struct buffer_head *bh;
  14.388 +  struct request_queue *rq;
  14.389 +  int operation;
  14.390 +  blk_request_t *blk_request;
  14.391 +  unsigned long flags;
  14.392 +
  14.393 +    /*
  14.394 +     * check to make sure that the block request seems at least
  14.395 +     * a bit legitimate
  14.396 +     */
  14.397 +    if ((blk_ring->tx_ring[index].block_size & (0x200 - 1)) != 0)
  14.398 +    {
  14.399 +      printk(KERN_ALERT
  14.400 +	     "    error: dodgy block size: %d\n", 
  14.401 +	     blk_ring->tx_ring[index].block_size);
  14.402 +      BUG();
  14.403 +    }
  14.404 +
  14.405 +    if (XEN_BLK_DEBUG) 
  14.406 +    {
  14.407 +    printk(XEN_BLK_DEBUG_LEVEL
  14.408 +	   "    tx_cons: %d  tx_prod %d  index: %d     op: %s, pri: %s\n",
  14.409 +	   blk_ring->tx_cons, blk_ring->tx_prod, index,
  14.410 +	   (blk_ring->tx_ring[index].operation == XEN_BLOCK_READ ? "read" : "write"),
  14.411 +	   (blk_ring->tx_ring[index].priority == XEN_BLOCK_SYNC ? "sync" : "async"));
  14.412 +    }
  14.413 +
  14.414 +    {
  14.415 +      char temp[100];
  14.416 +      sprintf(temp, "issue  buf: 0x%p, bh: 0x%p, blkno: 0x%lx",
  14.417 +	      blk_ring->tx_ring[index].buffer, bh,
  14.418 +	      (unsigned long)blk_ring->tx_ring[index].block_number);
  14.419 +      printx(temp);
  14.420 +    }
  14.421 +
  14.422 +    /* find an empty request slot */
  14.423 +    spin_lock_irqsave(&free_queue_lock, flags);
  14.424 +    if (list_empty(&free_queue))
  14.425 +    {
  14.426 +      /*      printk (KERN_ALERT "dispatch_rw_block_io EMPTY FREE LIST!! %d\n", index); */
  14.427 +      spin_unlock_irqrestore(&free_queue_lock, flags);
  14.428 +      return 1;
  14.429 +    }
  14.430 +    blk_request = list_entry(free_queue.next, blk_request_t, queue);
  14.431 +    list_del(&blk_request->queue);
  14.432 +    spin_unlock_irqrestore(&free_queue_lock, flags);
  14.433 +
  14.434 +    /* place request on pending list */
  14.435 +    spin_lock_irqsave(&pending_queue_lock, flags);
  14.436 +    list_add_tail(&blk_request->queue, &pending_queue);
  14.437 +    spin_unlock_irqrestore(&pending_queue_lock, flags);
  14.438 +
  14.439 +    /* we'll be doing this frequently, would a cache be appropriate? */
  14.440 +    /* free in flush_blk_queue */
  14.441 +    bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head), 
  14.442 +					GFP_KERNEL);
  14.443 +    if (!bh)
  14.444 +    {
  14.445 +      printk(KERN_ALERT "ERROR: bh is null\n");
  14.446 +      BUG();
  14.447 +    }
  14.448 +
  14.449 +    /* set just the important bits of the buffer header */
  14.450 +    memset (bh, 0, sizeof (struct buffer_head));
  14.451 +
  14.452 +    bh->b_blocknr = blk_ring->tx_ring[index].block_number;   /* block number */
  14.453 +    bh->b_size = blk_ring->tx_ring[index].block_size;          /* block size */
  14.454 +    bh->b_dev = blk_ring->tx_ring[index].device;   /* device (B_FREE = free) */
  14.455 +    bh->b_rsector = blk_ring->tx_ring[index].sector_number; /* sector number */
  14.456 +                                                    
  14.457 +    bh->b_data = phys_to_virt(blk_ring->tx_ring[index].buffer);
  14.458 +                                                          /* ptr to data blk */
  14.459 +    bh->b_count.counter = 1;                       /* users using this block */
  14.460 +    bh->b_xen_request = (void *)blk_request;           /* save block request */
  14.461 +    
  14.462 +
  14.463 +    if (blk_ring->tx_ring[index].operation == XEN_BLOCK_WRITE)
  14.464 +    {
  14.465 +      bh->b_state = ((1 << BH_JBD) |                  /* buffer state bitmap */
  14.466 +		     (1 << BH_Mapped) |
  14.467 +		     (1 << BH_Req) |
  14.468 +		     (1 << BH_Dirty) |
  14.469 +		     (1 << BH_Uptodate));
  14.470 +      operation = WRITE;
  14.471 +    }
  14.472 +    else
  14.473 +    {
  14.474 +      bh->b_state = (1 << BH_Mapped);                 /* buffer state bitmap */
  14.475 +      operation = READ;
  14.476 +    }
  14.477 +
  14.478 +    /* save meta data about request */
  14.479 +    memcpy(&blk_request->request,                    /* NEED COPY_FROM_USER? */
  14.480 +	   &blk_ring->tx_ring[index], sizeof(blk_ring_entry_t));
  14.481 +    blk_request->bh = bh;
  14.482 +    blk_request->domain = current;                    /* save current domain */
  14.483 +
  14.484 +    /* dispatch single block request */
  14.485 +    ll_rw_block(operation, 1, &bh);                        /* linux top half */
  14.486 +    rq = blk_get_queue(bh->b_rdev);                         
  14.487 +    generic_unplug_device(rq);                          /* linux bottom half */
  14.488 +
  14.489 +    return 0;
  14.490 +}
  14.491 +
  14.492 +/*
  14.493 + * initialize_block_io
  14.494 + *
  14.495 + * initialize everything for block io 
  14.496 + * called from arch/i386/setup.c::start_of_day
  14.497 + */
  14.498 +
  14.499 +void initialize_block_io ()
  14.500 +{
  14.501 +  int loop;
  14.502 +
  14.503 +  INIT_LIST_HEAD(&free_queue);
  14.504 +  INIT_LIST_HEAD(&pending_queue);
  14.505 +  INIT_LIST_HEAD(&io_done_queue);
  14.506 +  
  14.507 +  spin_lock_init(&free_queue_lock);
  14.508 +  spin_lock_init(&pending_queue_lock);
  14.509 +  spin_lock_init(&io_done_queue_lock);
  14.510 +
  14.511 +  for (loop = 0; loop < XEN_BLK_REQUEST_LIST_SIZE; loop++)
  14.512 +  {
  14.513 +    list_add_tail(&blk_request_list[loop].queue, &free_queue);
  14.514 +  }
  14.515 +
  14.516 +  /*
  14.517 +   * if bit i is true then domain i has work for us to do.
  14.518 +   */
  14.519 +  pending_work = 0;
  14.520 +
  14.521 +  return;
  14.522 +}
  14.523 +
  14.524 +
  14.525 +#ifdef DEBUG
  14.526 +
  14.527 +/*
  14.528 + * debug dump_queue
  14.529 + * arguments: queue head, name of queue
  14.530 + */
  14.531 +void dump_queue(struct list_head *queue, char *name)
  14.532 +{
  14.533 +  struct list_head *list;
  14.534 +  int loop = 0;
  14.535 +
  14.536 +  printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
  14.537 +	  (unsigned long) queue->next, (unsigned long) queue->prev);
  14.538 +  list_for_each (list, queue)
  14.539 +  {
  14.540 +    printk ("  %s %d : %lx   n: %lx, p: %lx\n", name, loop++, 
  14.541 +	    (unsigned long)list,
  14.542 +	    (unsigned long)list->next, (unsigned long)list->prev);
  14.543 +  }
  14.544 +}
  14.545 +
  14.546 +void dump_queue_head(struct list_head *queue, char *name)
  14.547 +{
  14.548 +  struct list_head *list;
  14.549 +  int loop = 0;
  14.550 +
  14.551 +  printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
  14.552 +	  (unsigned long) queue->next, (unsigned long) queue->prev);
  14.553 +  list_for_each (list, queue)
  14.554 +  {
  14.555 +    printk ("      %d : %lx   n: %lx, p: %lx\n", loop++, 
  14.556 +	    (unsigned long)list,
  14.557 +	    (unsigned long)list->next, (unsigned long)list->prev);
  14.558 +    if (loop >= 5) return;
  14.559 +  }
  14.560 +}
  14.561 +
  14.562 +#endif /* DEBUG */
  14.563 +
  14.564 +
  14.565 +#define debug_block_size 200000
  14.566 +#define debug_output_size 10
  14.567 +
  14.568 +static int    countx = 0;
  14.569 +static char * arrayx[debug_block_size];
  14.570 +static int    outputx = 0;
  14.571 +
  14.572 +void
  14.573 +printx (char * string)
  14.574 +{
  14.575 +  char * s;
  14.576 +
  14.577 +  s = (char *) kmalloc(strlen(string), GFP_KERNEL);
  14.578 +  strcpy (s, string);
  14.579 +  arrayx[countx++] = s;
  14.580 +
  14.581 +  if (countx >= debug_block_size)
  14.582 +  {
  14.583 +    countx = 0;
  14.584 +    printk (KERN_ALERT "printx wrap\n");
  14.585 +  }
  14.586 +
  14.587 +}
  14.588 +
  14.589 +void
  14.590 +dumpx (char *buffer, int count)
  14.591 +{
  14.592 +  int loop;
  14.593 +  int start;
  14.594 +
  14.595 +  sprintf (buffer, "debug dump\n");
  14.596 +
  14.597 +  /*
  14.598 +  for (loop = outputx;
  14.599 +       loop < outputx + debug_output_size && loop < countx; 
  14.600 +       loop ++)
  14.601 +  {
  14.602 +    sprintf (buffer, "%s%02d:%s\n", buffer, loop, arrayx[loop]);
  14.603 +  }
  14.604 +  outputx = loop;
  14.605 +  */
  14.606 +  
  14.607 +  if (count == 0 || count > countx)
  14.608 +  {
  14.609 +    start = 0;
  14.610 +  }
  14.611 +  else
  14.612 +  {
  14.613 +    start = countx - count;
  14.614 +  }
  14.615 +
  14.616 +  printk (KERN_ALERT "DUMPX BUFFER\n");
  14.617 +  for (loop = start; loop < countx; loop++)
  14.618 +  {
  14.619 +    printk (KERN_ALERT "%4d %s\n", loop, arrayx[loop]);
  14.620 +  }
  14.621 +  printk (KERN_ALERT "DUMPX bye bye\n");
  14.622 +}
  14.623 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen-2.4.16/drivers/char/Makefile	Thu Feb 13 15:58:34 2003 +0000
    15.3 @@ -0,0 +1,8 @@
    15.4 +
    15.5 +include $(BASEDIR)/Rules.mk
    15.6 +
    15.7 +default: $(OBJS)
    15.8 +	$(LD) -r -o driver.o $(OBJS)
    15.9 +
   15.10 +clean:
   15.11 +	rm -f *.o *~ core
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xen-2.4.16/drivers/char/xen_kbd.c	Thu Feb 13 15:58:34 2003 +0000
    16.3 @@ -0,0 +1,111 @@
    16.4 +#include <asm-i386/io.h>
    16.5 +#include <xeno/sched.h>    /* this has request_irq() proto for some reason */
    16.6 +
    16.7 +#define KEYBOARD_IRQ 1
    16.8 +
    16.9 +#define KBD_STATUS_REG	     0x64 /* Status register (R) */
   16.10 +#define KBD_CNTL_REG	     0x64 /* Controller command register (W) */
   16.11 +#define KBD_DATA_REG	     0x60 /* Keyboard data register (R/W) */
   16.12 +
   16.13 +/* register status bits */
   16.14 +#define KBD_STAT_OBF 	     0x01 /* Keyboard output buffer full */
   16.15 +#define KBD_STAT_IBF 	     0x02 /* Keyboard input buffer full */
   16.16 +#define KBD_STAT_SELFTEST    0x04 /* Self test successful */
   16.17 +#define KBD_STAT_CMD	     0x08 /* Last write was a command write (0=data) */
   16.18 +
   16.19 +#define KBD_STAT_UNLOCKED    0x10 /* Zero if keyboard locked */
   16.20 +#define KBD_STAT_MOUSE_OBF   0x20 /* Mouse output buffer full */
   16.21 +#define KBD_STAT_GTO 	     0x40 /* General receive/xmit timeout */
   16.22 +#define KBD_STAT_PERR 	     0x80 /* Parity error */
   16.23 +
   16.24 +#define kbd_read_input() inb(KBD_DATA_REG)
   16.25 +#define kbd_read_status() inb(KBD_STATUS_REG)
   16.26 +
   16.27 +
   16.28 +
   16.29 +static void
   16.30 +dispatch_scancode (unsigned char scancode)
   16.31 +{
   16.32 +
   16.33 +    /*
   16.34 +     * we could be a bit more clever here, but why?
   16.35 +     * just add a jump to your debug routine for the appropriate character.
   16.36 +     */
   16.37 +    switch (scancode)
   16.38 +    {
   16.39 +    case 0x01 :                                                       /* esc */
   16.40 +	printk ("<esc>");
   16.41 +	break;
   16.42 +    case 0x9e :                                                         /* a */
   16.43 +	printk ("a");
   16.44 +	break;
   16.45 +    case 0x9f :                                                         /* s */
   16.46 +	printk ("s");
   16.47 +	break;
   16.48 +    case 0xae :                                                         /* c */
   16.49 +	printk ("c");
   16.50 +	break;
   16.51 +    case 0xb0 :                                                         /* b */
   16.52 +	printk ("b");
   16.53 +	break;
   16.54 +    case 0xbb :                                                        /* f1 */
   16.55 +	printk ("<f1>");
   16.56 +	break;
   16.57 +    case 0xbc :                                                        /* f2 */
   16.58 +	printk ("<f2>");
   16.59 +	break;
   16.60 +    case 0xbd :                                                        /* f3 */
   16.61 +	printk ("<f3>");
   16.62 +	break;
   16.63 +    case 0xbe :                                                        /* f4 */
   16.64 +	printk ("<f4>");
   16.65 +	break;
   16.66 +    case 0xbf :                                                        /* f5 */
   16.67 +	/* xen_block_dump_state(); */
   16.68 +	break;
   16.69 +    default :
   16.70 +	/* printk ("%x ", scancode); */
   16.71 +    }
   16.72 +
   16.73 +    return; 
   16.74 +}
   16.75 +
   16.76 +
   16.77 +/* regs should be struct pt_regs */
   16.78 +
   16.79 +static void keyboard_interrupt(int irq, void *dev_id, void *regs)
   16.80 +{
   16.81 +    unsigned char status = kbd_read_status();
   16.82 +    unsigned int work = 10000;
   16.83 +    
   16.84 +    while ((--work > 0) && (status & KBD_STAT_OBF))
   16.85 +    {
   16.86 +	unsigned char scancode;
   16.87 +	
   16.88 +	scancode = kbd_read_input();
   16.89 +	
   16.90 +	if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
   16.91 +	{
   16.92 +	    if (status & KBD_STAT_MOUSE_OBF)
   16.93 +		/* mouse event, ignore */;
   16.94 +	    else
   16.95 +		dispatch_scancode (scancode);
   16.96 +	}
   16.97 +	status = kbd_read_status();
   16.98 +    }
   16.99 +    
  16.100 +    if (!work)
  16.101 +	printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n", status);
  16.102 +    
  16.103 +    return;
  16.104 +}
  16.105 +
  16.106 +
  16.107 +void initialize_keyboard()
  16.108 +{
  16.109 +    if(request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL))
  16.110 +	printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); 
  16.111 +
  16.112 +    return; 
  16.113 +}
  16.114 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xen-2.4.16/drivers/char/xen_serial.c	Thu Feb 13 15:58:34 2003 +0000
    17.3 @@ -0,0 +1,140 @@
    17.4 +#include <asm-i386/io.h>
    17.5 +#include <xeno/sched.h>    /* this has request_irq() proto for some reason */
    17.6 +
    17.7 +
    17.8 +/* Register offsets */
    17.9 +#define NS16550_RBR	0x00	/* receive buffer	*/
   17.10 +#define NS16550_THR	0x00	/* transmit holding	*/
   17.11 +#define NS16550_IER	0x01	/* interrupt enable	*/
   17.12 +#define NS16550_IIR	0x02	/* interrupt identity	*/
   17.13 +#define NS16550_FCR     0x02    /* FIFO control         */
   17.14 +#define NS16550_LCR	0x03	/* line control		*/
   17.15 +#define NS16550_MCR	0x04	/* MODEM control	*/
   17.16 +#define NS16550_LSR	0x05	/* line status		*/
   17.17 +#define NS16550_MSR	0x06	/* MODEM status		*/
   17.18 +#define NS16550_SCR	0x07	/* scratch		*/
   17.19 +#define NS16550_DDL	0x00	/* divisor latch (ls) ( DLAB=1)	*/
   17.20 +#define NS16550_DLM	0x01	/* divisor latch (ms) ( DLAB=1)	*/
   17.21 +
   17.22 +/* Interrupt enable register */
   17.23 +#define NS16550_IER_ERDAI	0x01	/* rx data recv'd	*/
   17.24 +#define NS16550_IER_ETHREI	0x02	/* tx reg. empty	*/
   17.25 +#define NS16550_IER_ELSI	0x04	/* rx line status	*/
   17.26 +#define NS16550_IER_EMSI	0x08	/* MODEM status		*/
   17.27 +
   17.28 +/* FIFO control register */
   17.29 +#define NS16550_FCR_ENABLE      0x01    /* enable FIFO          */
   17.30 +#define NS16550_FCR_CLRX        0x02    /* clear Rx FIFO        */
   17.31 +#define NS16550_FCR_CLTX        0x04    /* clear Tx FIFO        */
   17.32 +#define NS16550_FCR_DMA         0x10    /* enter DMA mode       */
   17.33 +#define NS16550_FCR_TRG1        0x00    /* Rx FIFO trig lev 1   */
   17.34 +#define NS16550_FCR_TRG4        0x40    /* Rx FIFO trig lev 4   */
   17.35 +#define NS16550_FCR_TRG8        0x80    /* Rx FIFO trig lev 8   */
   17.36 +#define NS16550_FCR_TRG14       0xc0    /* Rx FIFO trig lev 14  */
   17.37 +
   17.38 +/* MODEM control register */
   17.39 +#define NS16550_MCR_DTR 	0x01	/* Data Terminal Ready	*/
   17.40 +#define NS16550_MCR_RTS 	0x02	/* Request to Send	*/
   17.41 +#define NS16550_MCR_OUT1        0x04    /* OUT1: unused         */
   17.42 +#define NS16550_MCR_OUT2        0x08    /* OUT2: interrupt mask */
   17.43 +#define NS16550_MCR_LOOP	0x10	/* Loop			*/
   17.44 +
   17.45 +#define SERIAL_BASE 0x3f8  /* XXX SMH: horrible hardwired COM1   */
   17.46 +
   17.47 +
   17.48 +
   17.49 +/* 
   17.50 +** We keep an array of 'handlers' for each key code between 0 and 255; 
   17.51 +** this is intended to allow very simple debugging routines (toggle 
   17.52 +** debug flag, dump registers, reboot, etc) to be hooked in in a slightly
   17.53 +** nicer fashion than just editing this file :-) 
   17.54 +*/
   17.55 +
   17.56 +#define KEY_MAX 256
   17.57 +typedef void key_handler(u_char key); 
   17.58 +
   17.59 +static key_handler *key_table[KEY_MAX]; 
   17.60 +    
   17.61 +void add_key_handler(u_char key, key_handler *handler) 
   17.62 +{
   17.63 +    if(key_table[key] != NULL) 
   17.64 +	printk("Warning: overwriting handler for key 0x%x\n", key); 
   17.65 +
   17.66 +    key_table[key] = handler; 
   17.67 +    return; 
   17.68 +}
   17.69 +
   17.70 +
   17.71 +
   17.72 +static int serial_echo = 0;   /* default is not to echo; change with 'e' */
   17.73 +
   17.74 +void toggle_echo(u_char key) 
   17.75 +{
   17.76 +    serial_echo = !serial_echo; 
   17.77 +    return; 
   17.78 +}
   17.79 +
   17.80 +
   17.81 +void halt_machine(u_char key) 
   17.82 +{
   17.83 +    /* This is 'debug me please' => just dump info and halt machine */
   17.84 +    printk("serial_rx_int: got EOT => halting machine.\n"); 
   17.85 +    printk("<not actually halting for now>\n"); 
   17.86 +    return; 
   17.87 +}
   17.88 +
   17.89 +
   17.90 +
   17.91 +static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs)
   17.92 +{
   17.93 +    u_char c; 
   17.94 +
   17.95 +    /* XXX SMH: should probably check this is an RX interrupt :-) */
   17.96 +
   17.97 +    /* clear the interrupt by reading the character */
   17.98 +    c = inb(SERIAL_BASE + NS16550_RBR );
   17.99 +
  17.100 +    /* if there's a handler, call it: we trust it won't screw us too badly */
  17.101 +    if(key_table[c]) 
  17.102 +	(*key_table[c])(c); 
  17.103 +
  17.104 +    if(serial_echo) 
  17.105 +	printk("%c", c); 
  17.106 +
  17.107 +    return; 
  17.108 +}
  17.109 +
  17.110 +
  17.111 +void initialize_serial() 
  17.112 +{
  17.113 +    int i, fifo, rc; 
  17.114 +
  17.115 +    /* first initialize key handler table */
  17.116 +    for(i = 0; i < KEY_MAX; i++) 
  17.117 +	key_table[i] = (key_handler *)NULL; 
  17.118 +
  17.119 +    /* setup own handlers */
  17.120 +    add_key_handler(0x01, toggle_echo);    /* <esc> to toggle echo */
  17.121 +    add_key_handler(0x04, halt_machine);   /* CTRL-D to 'halt' */
  17.122 +
  17.123 +    
  17.124 +    /* Should detect this, but must be a ns16550a at least, surely? */
  17.125 +    fifo = 1;  
  17.126 +    if(fifo) {
  17.127 +	/* Clear FIFOs, enable, trigger at 1 byte */
  17.128 +	outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE |
  17.129 +	     NS16550_FCR_CLRX  | NS16550_FCR_CLTX, SERIAL_BASE+NS16550_FCR);
  17.130 +    }
  17.131 +
  17.132 +    outb(NS16550_MCR_OUT2, SERIAL_BASE + NS16550_MCR);   /* Modem control */
  17.133 +    outb(NS16550_IER_ERDAI, SERIAL_BASE + NS16550_IER ); /* Setup interrupts */
  17.134 +
  17.135 +    /* XXX SMH: this is a hack; probably is IRQ4 but grab both anyway */
  17.136 +    if((rc = request_irq(4, serial_rx_int, 0, "serial", (void *)0x1234)))
  17.137 +	printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc); 
  17.138 +
  17.139 +    if((rc = request_irq(3, serial_rx_int, 0, "serial", (void *)0x1234)))
  17.140 +	printk("initialize_serial: failed to get IRQ3, rc=%d\n", rc); 
  17.141 +    
  17.142 +    return; 
  17.143 +}
    18.1 --- a/xen-2.4.16/drivers/ide/ide-disk.c	Tue Feb 11 17:54:17 2003 +0000
    18.2 +++ b/xen-2.4.16/drivers/ide/ide-disk.c	Thu Feb 13 15:58:34 2003 +0000
    18.3 @@ -420,13 +420,13 @@ static ide_startstop_t chs_rw_disk (ide_
    18.4  	taskfile.device_head	|= drive->select.all;
    18.5  	taskfile.command	= command;
    18.6  
    18.7 -#ifdef DEBUG
    18.8 +	/* #ifdef DEBUG */
    18.9  	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
   18.10  	if (lba)	printk("LBAsect=%lld, ", block);
   18.11  	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
   18.12  	printk("sectors=%ld, ", rq->nr_sectors);
   18.13  	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
   18.14 -#endif
   18.15 +	/* #endif*/
   18.16  
   18.17  	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
   18.18  	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
   18.19 @@ -578,7 +578,8 @@ static ide_startstop_t do_rw_disk (ide_d
   18.20  			tasklets[9] = (task_ioreg_t) 0;
   18.21  //			tasklets[8] = (task_ioreg_t) (block>>32);
   18.22  //			tasklets[9] = (task_ioreg_t) (block>>40);
   18.23 -#ifdef DEBUG
   18.24 +			/*#ifdef DEBUG */
   18.25 +			printk("[A]\n");
   18.26  			printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n",
   18.27  				drive->name,
   18.28  				(rq->cmd==READ)?"read":"writ",
   18.29 @@ -590,7 +591,7 @@ static ide_startstop_t do_rw_disk (ide_d
   18.30  				drive->name, tasklets[3], tasklets[2],
   18.31  				tasklets[9], tasklets[8], tasklets[7],
   18.32  				tasklets[6], tasklets[5], tasklets[4]);
   18.33 -#endif
   18.34 +			/* #endif */
   18.35  			OUT_BYTE(tasklets[1], IDE_FEATURE_REG);
   18.36  			OUT_BYTE(tasklets[3], IDE_NSECTOR_REG);
   18.37  			OUT_BYTE(tasklets[7], IDE_SECTOR_REG);
   18.38 @@ -1320,6 +1321,10 @@ static void idedisk_setup (ide_drive_t *
   18.39  	
   18.40  	struct hd_driveid *id = drive->id;
   18.41  	unsigned long capacity;
   18.42 +
   18.43 +	printk (KERN_ALERT
   18.44 +		"ide-disk.c::idedisk_setup: chs %d %d %d\n",
   18.45 +		drive->cyl, drive->head, drive->sect);
   18.46  	
   18.47  	idedisk_add_settings(drive);
   18.48  
   18.49 @@ -1383,7 +1388,7 @@ static void idedisk_setup (ide_drive_t *
   18.50  	if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
   18.51  	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head)
   18.52  		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
   18.53 -	printk (KERN_INFO "XEN %s: %ld sectors", drive->name, capacity);
   18.54 +	printk (KERN_INFO "[XEN] %s: %ld sectors", drive->name, capacity);
   18.55  
   18.56  	/* Give size in megabytes (MB), not mebibytes (MiB). */
   18.57  	/* We compute the exact rounded value, avoiding overflow. */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xen-2.4.16/drivers/ide/ide-disk.c.orig	Thu Feb 13 15:58:34 2003 +0000
    19.3 @@ -0,0 +1,1550 @@
    19.4 +/*
    19.5 + *  linux/drivers/ide/ide-disk.c	Version 1.10	June 9, 2000
    19.6 + *
    19.7 + *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
    19.8 + */
    19.9 +
   19.10 +/*
   19.11 + *  Mostly written by Mark Lord <mlord@pobox.com>
   19.12 + *                and Gadi Oxman <gadio@netvision.net.il>
   19.13 + *                and Andre Hedrick <andre@linux-ide.org>
   19.14 + *
   19.15 + * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
   19.16 + *
   19.17 + * Version 1.00		move disk only code from ide.c to ide-disk.c
   19.18 + *			support optional byte-swapping of all data
   19.19 + * Version 1.01		fix previous byte-swapping code
   19.20 + * Version 1.02		remove ", LBA" from drive identification msgs
   19.21 + * Version 1.03		fix display of id->buf_size for big-endian
   19.22 + * Version 1.04		add /proc configurable settings and S.M.A.R.T support
   19.23 + * Version 1.05		add capacity support for ATA3 >= 8GB
   19.24 + * Version 1.06		get boot-up messages to show full cyl count
   19.25 + * Version 1.07		disable door-locking if it fails
   19.26 + * Version 1.08		fixed CHS/LBA translations for ATA4 > 8GB,
   19.27 + *			process of adding new ATA4 compliance.
   19.28 + *			fixed problems in allowing fdisk to see
   19.29 + *			the entire disk.
   19.30 + * Version 1.09		added increment of rq->sector in ide_multwrite
   19.31 + *			added UDMA 3/4 reporting
   19.32 + * Version 1.10		request queue changes, Ultra DMA 100
   19.33 + * Version 1.11		added 48-bit lba
   19.34 + * Version 1.12		adding taskfile io access method
   19.35 + */
   19.36 +
   19.37 +#define IDEDISK_VERSION	"1.12"
   19.38 +
   19.39 +#undef REALLY_SLOW_IO		/* most systems can safely undef this */
   19.40 +
   19.41 +#include <xeno/config.h>
   19.42 +#include <xeno/module.h>
   19.43 +#include <xeno/types.h>
   19.44 +#include <xeno/lib.h>
   19.45 +#include <xeno/timer.h>
   19.46 +#include <xeno/mm.h>
   19.47 +#include <xeno/interrupt.h>
   19.48 +#include <xeno/major.h>
   19.49 +#include <xeno/errno.h>
   19.50 +#include <xeno/genhd.h>
   19.51 +#include <xeno/slab.h>
   19.52 +#include <xeno/delay.h>
   19.53 +#include <xeno/ide.h>
   19.54 +
   19.55 +#include <asm/byteorder.h>
   19.56 +#include <asm/irq.h>
   19.57 +#include <asm/uaccess.h>
   19.58 +#include <asm/io.h>
   19.59 +
   19.60 +#ifdef CONFIG_BLK_DEV_PDC4030
   19.61 +#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
   19.62 +#else
   19.63 +#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
   19.64 +#endif
   19.65 +
   19.66 +#ifdef CONFIG_IDE_TASKFILE_IO
   19.67 +#  undef __TASKFILE__IO /* define __TASKFILE__IO */
   19.68 +#else /* CONFIG_IDE_TASKFILE_IO */
   19.69 +#  undef __TASKFILE__IO
   19.70 +#endif /* CONFIG_IDE_TASKFILE_IO */
   19.71 +
   19.72 +#ifndef __TASKFILE__IO
   19.73 +
   19.74 +static void idedisk_bswap_data (void *buffer, int wcount)
   19.75 +{
   19.76 +	u16 *p = buffer;
   19.77 +
   19.78 +	while (wcount--) {
   19.79 +		*p = *p << 8 | *p >> 8; p++;
   19.80 +		*p = *p << 8 | *p >> 8; p++;
   19.81 +	}
   19.82 +}
   19.83 +
   19.84 +static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
   19.85 +{
   19.86 +	ide_input_data(drive, buffer, wcount);
   19.87 +	if (drive->bswap)
   19.88 +		idedisk_bswap_data(buffer, wcount);
   19.89 +}
   19.90 +
   19.91 +static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
   19.92 +{
   19.93 +	if (drive->bswap) {
   19.94 +		idedisk_bswap_data(buffer, wcount);
   19.95 +		ide_output_data(drive, buffer, wcount);
   19.96 +		idedisk_bswap_data(buffer, wcount);
   19.97 +	} else
   19.98 +		ide_output_data(drive, buffer, wcount);
   19.99 +}
  19.100 +
  19.101 +#endif /* __TASKFILE__IO */
  19.102 +
  19.103 +/*
  19.104 + * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
  19.105 + * value for this drive (from its reported identification information).
  19.106 + *
  19.107 + * Returns:	1 if lba_capacity looks sensible
  19.108 + *		0 otherwise
  19.109 + *
  19.110 + * It is called only once for each drive.
  19.111 + */
  19.112 +static int lba_capacity_is_ok (struct hd_driveid *id)
  19.113 +{
  19.114 +	unsigned long lba_sects, chs_sects, head, tail;
  19.115 +
  19.116 +	if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
  19.117 +		printk("48-bit Drive: %llu \n", id->lba_capacity_2);
  19.118 +		return 1;
  19.119 +	}
  19.120 +
  19.121 +	/*
  19.122 +	 * The ATA spec tells large drives to return
  19.123 +	 * C/H/S = 16383/16/63 independent of their size.
  19.124 +	 * Some drives can be jumpered to use 15 heads instead of 16.
  19.125 +	 * Some drives can be jumpered to use 4092 cyls instead of 16383.
  19.126 +	 */
  19.127 +	if ((id->cyls == 16383
  19.128 +	     || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
  19.129 +	    id->sectors == 63 &&
  19.130 +	    (id->heads == 15 || id->heads == 16) &&
  19.131 +	    id->lba_capacity >= 16383*63*id->heads)
  19.132 +		return 1;
  19.133 +
  19.134 +	lba_sects   = id->lba_capacity;
  19.135 +	chs_sects   = id->cyls * id->heads * id->sectors;
  19.136 +
  19.137 +	/* perform a rough sanity check on lba_sects:  within 10% is OK */
  19.138 +	if ((lba_sects - chs_sects) < chs_sects/10)
  19.139 +		return 1;
  19.140 +
  19.141 +	/* some drives have the word order reversed */
  19.142 +	head = ((lba_sects >> 16) & 0xffff);
  19.143 +	tail = (lba_sects & 0xffff);
  19.144 +	lba_sects = (head | (tail << 16));
  19.145 +	if ((lba_sects - chs_sects) < chs_sects/10) {
  19.146 +		id->lba_capacity = lba_sects;
  19.147 +		return 1;	/* lba_capacity is (now) good */
  19.148 +	}
  19.149 +
  19.150 +	return 0;	/* lba_capacity value may be bad */
  19.151 +}
  19.152 +
  19.153 +#ifndef __TASKFILE__IO
  19.154 +
  19.155 +/*
  19.156 + * read_intr() is the handler for disk read/multread interrupts
  19.157 + */
  19.158 +static ide_startstop_t read_intr (ide_drive_t *drive)
  19.159 +{
  19.160 +	byte stat;
  19.161 +	int i;
  19.162 +	unsigned int msect, nsect;
  19.163 +	struct request *rq;
  19.164 +
  19.165 +	/* new way for dealing with premature shared PCI interrupts */
  19.166 +	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
  19.167 +		if (stat & (ERR_STAT|DRQ_STAT)) {
  19.168 +			return ide_error(drive, "read_intr", stat);
  19.169 +		}
  19.170 +		/* no data yet, so wait for another interrupt */
  19.171 +		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
  19.172 +		return ide_started;
  19.173 +	}
  19.174 +	msect = drive->mult_count;
  19.175 +	
  19.176 +read_next:
  19.177 +	rq = HWGROUP(drive)->rq;
  19.178 +	if (msect) {
  19.179 +		if ((nsect = rq->current_nr_sectors) > msect)
  19.180 +			nsect = msect;
  19.181 +		msect -= nsect;
  19.182 +	} else
  19.183 +		nsect = 1;
  19.184 +	idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
  19.185 +#ifdef DEBUG
  19.186 +	printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
  19.187 +		drive->name, rq->sector, rq->sector+nsect-1,
  19.188 +		(unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
  19.189 +#endif
  19.190 +	rq->sector += nsect;
  19.191 +	rq->buffer += nsect<<9;
  19.192 +	rq->errors = 0;
  19.193 +	i = (rq->nr_sectors -= nsect);
  19.194 +	if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
  19.195 +		ide_end_request(1, HWGROUP(drive));
  19.196 +	if (i > 0) {
  19.197 +		if (msect)
  19.198 +			goto read_next;
  19.199 +		ide_set_handler (drive, &read_intr, WAIT_CMD, NULL);
  19.200 +                return ide_started;
  19.201 +	}
  19.202 +        return ide_stopped;
  19.203 +}
  19.204 +
  19.205 +/*
  19.206 + * write_intr() is the handler for disk write interrupts
  19.207 + */
  19.208 +static ide_startstop_t write_intr (ide_drive_t *drive)
  19.209 +{
  19.210 +	byte stat;
  19.211 +	int i;
  19.212 +	ide_hwgroup_t *hwgroup = HWGROUP(drive);
  19.213 +	struct request *rq = hwgroup->rq;
  19.214 +
  19.215 +	if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
  19.216 +		printk("%s: write_intr error1: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
  19.217 +        } else {
  19.218 +#ifdef DEBUG
  19.219 +		printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
  19.220 +			drive->name, rq->sector, (unsigned long) rq->buffer,
  19.221 +			rq->nr_sectors-1);
  19.222 +#endif
  19.223 +		if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
  19.224 +			rq->sector++;
  19.225 +			rq->buffer += 512;
  19.226 +			rq->errors = 0;
  19.227 +			i = --rq->nr_sectors;
  19.228 +			--rq->current_nr_sectors;
  19.229 +			if (((long)rq->current_nr_sectors) <= 0)
  19.230 +				ide_end_request(1, hwgroup);
  19.231 +			if (i > 0) {
  19.232 +				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
  19.233 +				ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
  19.234 +                                return ide_started;
  19.235 +			}
  19.236 +                        return ide_stopped;
  19.237 +		}
  19.238 +		return ide_stopped;	/* the original code did this here (?) */
  19.239 +	}
  19.240 +	return ide_error(drive, "write_intr", stat);
  19.241 +}
  19.242 +
  19.243 +/*
  19.244 + * ide_multwrite() transfers a block of up to mcount sectors of data
  19.245 + * to a drive as part of a disk multiple-sector write operation.
  19.246 + *
  19.247 + * Returns 0 on success.
  19.248 + *
  19.249 + * Note that we may be called from two contexts - the do_rw_disk context
  19.250 + * and IRQ context. The IRQ can happen any time after we've output the
  19.251 + * full "mcount" number of sectors, so we must make sure we update the
  19.252 + * state _before_ we output the final part of the data!
  19.253 + */
  19.254 +int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
  19.255 +{
  19.256 + 	ide_hwgroup_t	*hwgroup= HWGROUP(drive);
  19.257 + 	struct request	*rq = &hwgroup->wrq;
  19.258 + 
  19.259 +  	do {
  19.260 +  		char *buffer;
  19.261 +  		int nsect = rq->current_nr_sectors;
  19.262 + 
  19.263 +		if (nsect > mcount)
  19.264 +			nsect = mcount;
  19.265 +		mcount -= nsect;
  19.266 +		buffer = rq->buffer;
  19.267 +
  19.268 +		rq->sector += nsect;
  19.269 +		rq->buffer += nsect << 9;
  19.270 +		rq->nr_sectors -= nsect;
  19.271 +		rq->current_nr_sectors -= nsect;
  19.272 +
  19.273 +		/* Do we move to the next bh after this? */
  19.274 +		if (!rq->current_nr_sectors) {
  19.275 +			struct buffer_head *bh = rq->bh->b_reqnext;
  19.276 +
  19.277 +			/* end early early we ran out of requests */
  19.278 +			if (!bh) {
  19.279 +				mcount = 0;
  19.280 +			} else {
  19.281 +				rq->bh = bh;
  19.282 +				rq->current_nr_sectors = bh->b_size >> 9;
  19.283 +				rq->buffer             = bh->b_data;
  19.284 +			}
  19.285 +		}
  19.286 +
  19.287 +		/*
  19.288 +		 * Ok, we're all setup for the interrupt
  19.289 +		 * re-entering us on the last transfer.
  19.290 +		 */
  19.291 +		idedisk_output_data(drive, buffer, nsect<<7);
  19.292 +	} while (mcount);
  19.293 +
  19.294 +        return 0;
  19.295 +}
  19.296 +
  19.297 +/*
  19.298 + * multwrite_intr() is the handler for disk multwrite interrupts
  19.299 + */
  19.300 +static ide_startstop_t multwrite_intr (ide_drive_t *drive)
  19.301 +{
  19.302 +	byte stat;
  19.303 +	int i;
  19.304 +	ide_hwgroup_t *hwgroup = HWGROUP(drive);
  19.305 +	struct request *rq = &hwgroup->wrq;
  19.306 +
  19.307 +	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
  19.308 +		if (stat & DRQ_STAT) {
  19.309 +			/*
  19.310 +			 *	The drive wants data. Remember rq is the copy
  19.311 +			 *	of the request
  19.312 +			 */
  19.313 +			if (rq->nr_sectors) {
  19.314 +				if (ide_multwrite(drive, drive->mult_count))
  19.315 +					return ide_stopped;
  19.316 +				ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
  19.317 +				return ide_started;
  19.318 +			}
  19.319 +		} else {
  19.320 +			/*
  19.321 +			 *	If the copy has all the blocks completed then
  19.322 +			 *	we can end the original request.
  19.323 +			 */
  19.324 +			if (!rq->nr_sectors) {	/* all done? */
  19.325 +				rq = hwgroup->rq;
  19.326 +				for (i = rq->nr_sectors; i > 0;){
  19.327 +					i -= rq->current_nr_sectors;
  19.328 +					ide_end_request(1, hwgroup);
  19.329 +				}
  19.330 +				return ide_stopped;
  19.331 +			}
  19.332 +		}
  19.333 +		return ide_stopped;	/* the original code did this here (?) */
  19.334 +	}
  19.335 +	return ide_error(drive, "multwrite_intr", stat);
  19.336 +}
  19.337 +#endif /* __TASKFILE__IO */
  19.338 +
  19.339 +#ifdef __TASKFILE__IO
  19.340 +
  19.341 +static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
  19.342 +static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block);
  19.343 +static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block);
  19.344 +
  19.345 +/*
  19.346 + * do_rw_disk() issues READ and WRITE commands to a disk,
  19.347 + * using LBA if supported, or CHS otherwise, to address sectors.
  19.348 + * It also takes care of issuing special DRIVE_CMDs.
  19.349 + */
  19.350 +static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
  19.351 +{
  19.352 +	if (rq->cmd == READ)
  19.353 +		goto good_command;
  19.354 +	if (rq->cmd == WRITE)
  19.355 +		goto good_command;
  19.356 +
  19.357 +	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
  19.358 +	ide_end_request(0, HWGROUP(drive));
  19.359 +	return ide_stopped;
  19.360 +
  19.361 +good_command:
  19.362 +
  19.363 +#ifdef CONFIG_BLK_DEV_PDC4030
  19.364 +	if (IS_PDC4030_DRIVE) {
  19.365 +		extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
  19.366 +		return promise_rw_disk(drive, rq, block);
  19.367 +	}
  19.368 +#endif /* CONFIG_BLK_DEV_PDC4030 */
  19.369 +
  19.370 +	if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))	/* 48-bit LBA */
  19.371 +		return lba_48_rw_disk(drive, rq, (unsigned long long) block);
  19.372 +	if (drive->select.b.lba)		/* 28-bit LBA */
  19.373 +		return lba_28_rw_disk(drive, rq, (unsigned long) block);
  19.374 +
  19.375 +	/* 28-bit CHS : DIE DIE DIE piece of legacy crap!!! */
  19.376 +	return chs_rw_disk(drive, rq, (unsigned long) block);
  19.377 +}
  19.378 +
  19.379 +static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
  19.380 +{
  19.381 +	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
  19.382 +
  19.383 +#if 1
  19.384 +	lba48bit = drive->addressing;
  19.385 +#endif
  19.386 +
  19.387 +	if ((cmd == READ) && (drive->using_dma))
  19.388 +		return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
  19.389 +	else if ((cmd == READ) && (drive->mult_count))
  19.390 +		return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
  19.391 +	else if (cmd == READ)
  19.392 +		return (lba48bit) ? WIN_READ_EXT : WIN_READ;
  19.393 +	else if ((cmd == WRITE) && (drive->using_dma))
  19.394 +		return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
  19.395 +	else if ((cmd == WRITE) && (drive->mult_count))
  19.396 +		return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
  19.397 +	else if (cmd == WRITE)
  19.398 +		return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
  19.399 +	else
  19.400 +		return WIN_NOP;
  19.401 +}
  19.402 +
  19.403 +static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
  19.404 +{
  19.405 +	struct hd_drive_task_hdr	taskfile;
  19.406 +	struct hd_drive_hob_hdr		hobfile;
  19.407 +	ide_task_t			args;
  19.408 +
  19.409 +	task_ioreg_t command	= get_command(drive, rq->cmd);
  19.410 +	unsigned int track	= (block / drive->sect);
  19.411 +	unsigned int sect	= (block % drive->sect) + 1;
  19.412 +	unsigned int head	= (track % drive->head);
  19.413 +	unsigned int cyl	= (track / drive->head);
  19.414 +
  19.415 +	memset(&taskfile, 0, sizeof(task_struct_t));
  19.416 +	memset(&hobfile, 0, sizeof(hob_struct_t));
  19.417 +
  19.418 +	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;
  19.419 +	taskfile.sector_number	= sect;
  19.420 +	taskfile.low_cylinder	= cyl;
  19.421 +	taskfile.high_cylinder	= (cyl>>8);
  19.422 +	taskfile.device_head	= head;
  19.423 +	taskfile.device_head	|= drive->select.all;
  19.424 +	taskfile.command	= command;
  19.425 +
  19.426 +#ifdef DEBUG
  19.427 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
  19.428 +	if (lba)	printk("LBAsect=%lld, ", block);
  19.429 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
  19.430 +	printk("sectors=%ld, ", rq->nr_sectors);
  19.431 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
  19.432 +#endif
  19.433 +
  19.434 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
  19.435 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
  19.436 +	args.command_type	= ide_cmd_type_parser(&args);
  19.437 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
  19.438 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
  19.439 +	args.posthandler	= NULL;
  19.440 +	args.rq			= (struct request *) rq;
  19.441 +	args.block		= block;
  19.442 +	rq->special		= NULL;
  19.443 +	rq->special		= (ide_task_t *)&args;
  19.444 +
  19.445 +	return do_rw_taskfile(drive, &args);
  19.446 +}
  19.447 +
  19.448 +static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
  19.449 +{
  19.450 +	struct hd_drive_task_hdr	taskfile;
  19.451 +	struct hd_drive_hob_hdr		hobfile;
  19.452 +	ide_task_t			args;
  19.453 +
  19.454 +	task_ioreg_t command	= get_command(drive, rq->cmd);
  19.455 +
  19.456 +	memset(&taskfile, 0, sizeof(task_struct_t));
  19.457 +	memset(&hobfile, 0, sizeof(hob_struct_t));
  19.458 +
  19.459 +	taskfile.sector_count	= (rq->nr_sectors==256)?0x00:rq->nr_sectors;
  19.460 +	taskfile.sector_number	= block;
  19.461 +	taskfile.low_cylinder	= (block>>=8);
  19.462 +	taskfile.high_cylinder	= (block>>=8);
  19.463 +	taskfile.device_head	= ((block>>8)&0x0f);
  19.464 +	taskfile.device_head	|= drive->select.all;
  19.465 +	taskfile.command	= command;
  19.466 +
  19.467 +
  19.468 +#ifdef DEBUG
  19.469 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
  19.470 +	if (lba)	printk("LBAsect=%lld, ", block);
  19.471 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
  19.472 +	printk("sectors=%ld, ", rq->nr_sectors);
  19.473 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
  19.474 +#endif
  19.475 +
  19.476 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
  19.477 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
  19.478 +	args.command_type	= ide_cmd_type_parser(&args);
  19.479 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
  19.480 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
  19.481 +	args.posthandler	= NULL;
  19.482 +	args.rq			= (struct request *) rq;
  19.483 +	args.block		= block;
  19.484 +	rq->special		= NULL;
  19.485 +	rq->special		= (ide_task_t *)&args;
  19.486 +
  19.487 +	return do_rw_taskfile(drive, &args);
  19.488 +}
  19.489 +
  19.490 +/*
  19.491 + * 268435455  == 137439 MB or 28bit limit
  19.492 + * 320173056  == 163929 MB or 48bit addressing
  19.493 + * 1073741822 == 549756 MB or 48bit addressing fake drive
  19.494 + */
  19.495 +
  19.496 +static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block)
  19.497 +{
  19.498 +	struct hd_drive_task_hdr	taskfile;
  19.499 +	struct hd_drive_hob_hdr		hobfile;
  19.500 +	ide_task_t			args;
  19.501 +
  19.502 +	task_ioreg_t command	= get_command(drive, rq->cmd);
  19.503 +
  19.504 +	memset(&taskfile, 0, sizeof(task_struct_t));
  19.505 +	memset(&hobfile, 0, sizeof(hob_struct_t));
  19.506 +
  19.507 +	taskfile.sector_count	= rq->nr_sectors;
  19.508 +	hobfile.sector_count	= (rq->nr_sectors>>8);
  19.509 +
  19.510 +	if (rq->nr_sectors == 65536) {
  19.511 +		taskfile.sector_count	= 0x00;
  19.512 +		hobfile.sector_count	= 0x00;
  19.513 +	}
  19.514 +
  19.515 +	taskfile.sector_number	= block;	/* low lba */
  19.516 +	taskfile.low_cylinder	= (block>>=8);	/* mid lba */
  19.517 +	taskfile.high_cylinder	= (block>>=8);	/* hi  lba */
  19.518 +	hobfile.sector_number	= (block>>=8);	/* low lba */
  19.519 +	hobfile.low_cylinder	= (block>>=8);	/* mid lba */
  19.520 +	hobfile.high_cylinder	= (block>>=8);	/* hi  lba */
  19.521 +	taskfile.device_head	= drive->select.all;
  19.522 +	hobfile.device_head	= taskfile.device_head;
  19.523 +	hobfile.control		= (drive->ctl|0x80);
  19.524 +	taskfile.command	= command;
  19.525 +
  19.526 +#ifdef DEBUG
  19.527 +	printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ");
  19.528 +	if (lba)	printk("LBAsect=%lld, ", block);
  19.529 +	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
  19.530 +	printk("sectors=%ld, ", rq->nr_sectors);
  19.531 +	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
  19.532 +#endif
  19.533 +
  19.534 +	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
  19.535 +	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
  19.536 +	args.command_type	= ide_cmd_type_parser(&args);
  19.537 +	args.prehandler		= ide_pre_handler_parser(&taskfile, &hobfile);
  19.538 +	args.handler		= ide_handler_parser(&taskfile, &hobfile);
  19.539 +	args.posthandler	= NULL;
  19.540 +	args.rq			= (struct request *) rq;
  19.541 +	args.block		= block;
  19.542 +	rq->special		= NULL;
  19.543 +	rq->special		= (ide_task_t *)&args;
  19.544 +
  19.545 +	return do_rw_taskfile(drive, &args);
  19.546 +}
  19.547 +
  19.548 +#else /* !__TASKFILE__IO */
  19.549 +/*
  19.550 + * do_rw_disk() issues READ and WRITE commands to a disk,
  19.551 + * using LBA if supported, or CHS otherwise, to address sectors.
  19.552 + * It also takes care of issuing special DRIVE_CMDs.
  19.553 + */
  19.554 +static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
  19.555 +{
  19.556 +	if (IDE_CONTROL_REG)
  19.557 +		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
  19.558 +
  19.559 +#ifdef CONFIG_BLK_DEV_PDC4030
  19.560 +	if (drive->select.b.lba || IS_PDC4030_DRIVE) {
  19.561 +#else /* !CONFIG_BLK_DEV_PDC4030 */
  19.562 +	if (drive->select.b.lba) {
  19.563 +#endif /* CONFIG_BLK_DEV_PDC4030 */
  19.564 +
  19.565 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
  19.566 +			task_ioreg_t tasklets[10];
  19.567 +
  19.568 +			tasklets[0] = 0;
  19.569 +			tasklets[1] = 0;
  19.570 +			tasklets[2] = rq->nr_sectors;
  19.571 +			tasklets[3] = (rq->nr_sectors>>8);
  19.572 +			if (rq->nr_sectors == 65536) {
  19.573 +				tasklets[2] = 0x00;
  19.574 +				tasklets[3] = 0x00;
  19.575 +			}
  19.576 +			tasklets[4] = (task_ioreg_t) block;
  19.577 +			tasklets[5] = (task_ioreg_t) (block>>8);
  19.578 +			tasklets[6] = (task_ioreg_t) (block>>16);
  19.579 +			tasklets[7] = (task_ioreg_t) (block>>24);
  19.580 +			tasklets[8] = (task_ioreg_t) 0;
  19.581 +			tasklets[9] = (task_ioreg_t) 0;
  19.582 +//			tasklets[8] = (task_ioreg_t) (block>>32);
  19.583 +//			tasklets[9] = (task_ioreg_t) (block>>40);
  19.584 +#ifdef DEBUG
  19.585 +			printk("%s: %sing: LBAsect=%lu, sectors=%ld, buffer=0x%08lx, LBAsect=0x%012lx\n",
  19.586 +				drive->name,
  19.587 +				(rq->cmd==READ)?"read":"writ",
  19.588 +				block,
  19.589 +				rq->nr_sectors,
  19.590 +				(unsigned long) rq->buffer,
  19.591 +				block);
  19.592 +			printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
  19.593 +				drive->name, tasklets[3], tasklets[2],
  19.594 +				tasklets[9], tasklets[8], tasklets[7],
  19.595 +				tasklets[6], tasklets[5], tasklets[4]);
  19.596 +#endif
  19.597 +			OUT_BYTE(tasklets[1], IDE_FEATURE_REG);
  19.598 +			OUT_BYTE(tasklets[3], IDE_NSECTOR_REG);
  19.599 +			OUT_BYTE(tasklets[7], IDE_SECTOR_REG);
  19.600 +			OUT_BYTE(tasklets[8], IDE_LCYL_REG);
  19.601 +			OUT_BYTE(tasklets[9], IDE_HCYL_REG);
  19.602 +
  19.603 +			OUT_BYTE(tasklets[0], IDE_FEATURE_REG);
  19.604 +			OUT_BYTE(tasklets[2], IDE_NSECTOR_REG);
  19.605 +			OUT_BYTE(tasklets[4], IDE_SECTOR_REG);
  19.606 +			OUT_BYTE(tasklets[5], IDE_LCYL_REG);
  19.607 +			OUT_BYTE(tasklets[6], IDE_HCYL_REG);
  19.608 +			OUT_BYTE(0x00|drive->select.all,IDE_SELECT_REG);
  19.609 +		} else {
  19.610 +#ifdef DEBUG
  19.611 +			printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
  19.612 +				drive->name, (rq->cmd==READ)?"read":"writ",
  19.613 +				block, rq->nr_sectors, (unsigned long) rq->buffer);
  19.614 +#endif
  19.615 +			OUT_BYTE(0x00, IDE_FEATURE_REG);
  19.616 +			OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
  19.617 +			OUT_BYTE(block,IDE_SECTOR_REG);
  19.618 +			OUT_BYTE(block>>=8,IDE_LCYL_REG);
  19.619 +			OUT_BYTE(block>>=8,IDE_HCYL_REG);
  19.620 +			OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
  19.621 +		}
  19.622 +	} else {
  19.623 +		unsigned int sect,head,cyl,track;
  19.624 +		track = block / drive->sect;
  19.625 +		sect  = block % drive->sect + 1;
  19.626 +		OUT_BYTE(sect,IDE_SECTOR_REG);
  19.627 +		head  = track % drive->head;
  19.628 +		cyl   = track / drive->head;
  19.629 +
  19.630 +		OUT_BYTE(0x00, IDE_FEATURE_REG);
  19.631 +		OUT_BYTE((rq->nr_sectors==256)?0x00:rq->nr_sectors,IDE_NSECTOR_REG);
  19.632 +		OUT_BYTE(cyl,IDE_LCYL_REG);
  19.633 +		OUT_BYTE(cyl>>8,IDE_HCYL_REG);
  19.634 +		OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
  19.635 +#ifdef DEBUG
  19.636 +		printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
  19.637 +			drive->name, (rq->cmd==READ)?"read":"writ", cyl,
  19.638 +			head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
  19.639 +#endif
  19.640 +	}
  19.641 +#ifdef CONFIG_BLK_DEV_PDC4030
  19.642 +	if (IS_PDC4030_DRIVE) {
  19.643 +		extern ide_startstop_t do_pdc4030_io(ide_drive_t *, struct request *);
  19.644 +		return do_pdc4030_io (drive, rq);
  19.645 +	}
  19.646 +#endif /* CONFIG_BLK_DEV_PDC4030 */
  19.647 +	if (rq->cmd == READ) {
  19.648 +#ifdef CONFIG_BLK_DEV_IDEDMA
  19.649 +		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
  19.650 +			return ide_started;
  19.651 +#endif /* CONFIG_BLK_DEV_IDEDMA */
  19.652 +		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
  19.653 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
  19.654 +			OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG);
  19.655 +		} else {
  19.656 +			OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
  19.657 +		}
  19.658 +		return ide_started;
  19.659 +	}
  19.660 +	if (rq->cmd == WRITE) {
  19.661 +		ide_startstop_t startstop;
  19.662 +#ifdef CONFIG_BLK_DEV_IDEDMA
  19.663 +		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
  19.664 +			return ide_started;
  19.665 +#endif /* CONFIG_BLK_DEV_IDEDMA */
  19.666 +		if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
  19.667 +			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE_EXT : WIN_WRITE_EXT, IDE_COMMAND_REG);
  19.668 +		} else {
  19.669 +			OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
  19.670 +		}
  19.671 +		if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
  19.672 +			printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name,
  19.673 +				drive->mult_count ? "MULTWRITE" : "WRITE");
  19.674 +			return startstop;
  19.675 +		}
  19.676 +		if (!drive->unmask)
  19.677 +			__cli();	/* local CPU only */
  19.678 +		if (drive->mult_count) {
  19.679 +			ide_hwgroup_t *hwgroup = HWGROUP(drive);
  19.680 +	/*
  19.681 +	 * Ugh.. this part looks ugly because we MUST set up
  19.682 +	 * the interrupt handler before outputting the first block
  19.683 +	 * of data to be written.  If we hit an error (corrupted buffer list)
  19.684 +	 * in ide_multwrite(), then we need to remove the handler/timer
  19.685 +	 * before returning.  Fortunately, this NEVER happens (right?).
  19.686 +	 *
  19.687 +	 * Except when you get an error it seems...
  19.688 +	 */
  19.689 +			hwgroup->wrq = *rq; /* scratchpad */
  19.690 +			ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL);
  19.691 +			if (ide_multwrite(drive, drive->mult_count)) {
  19.692 +				unsigned long flags;
  19.693 +				spin_lock_irqsave(&io_request_lock, flags);
  19.694 +				hwgroup->handler = NULL;
  19.695 +				del_timer(&hwgroup->timer);
  19.696 +				spin_unlock_irqrestore(&io_request_lock, flags);
  19.697 +				return ide_stopped;
  19.698 +			}
  19.699 +		} else {
  19.700 +			ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
  19.701 +			idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);
  19.702 +		}
  19.703 +		return ide_started;
  19.704 +	}
  19.705 +	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
  19.706 +	ide_end_request(0, HWGROUP(drive));
  19.707 +	return ide_stopped;
  19.708 +}
  19.709 +
  19.710 +#endif /* __TASKFILE__IO */
  19.711 +
  19.712 +static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
  19.713 +{
  19.714 +	MOD_INC_USE_COUNT;
  19.715 +	if (drive->removable && drive->usage == 1) {
  19.716 +		struct hd_drive_task_hdr taskfile;
  19.717 +		struct hd_drive_hob_hdr hobfile;
  19.718 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  19.719 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  19.720 +		taskfile.command = WIN_DOORLOCK;
  19.721 +		check_disk_change(inode->i_rdev);
  19.722 +		/*
  19.723 +		 * Ignore the return code from door_lock,
  19.724 +		 * since the open() has already succeeded,
  19.725 +		 * and the door_lock is irrelevant at this point.
  19.726 +		 */
  19.727 +		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
  19.728 +			drive->doorlocking = 0;
  19.729 +	}
  19.730 +	return 0;
  19.731 +}
  19.732 +
  19.733 +static int do_idedisk_flushcache(ide_drive_t *drive);
  19.734 +
  19.735 +static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
  19.736 +{
  19.737 +	if (drive->removable && !drive->usage) {
  19.738 +		struct hd_drive_task_hdr taskfile;
  19.739 +		struct hd_drive_hob_hdr hobfile;
  19.740 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
  19.741 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
  19.742 +		taskfile.command = WIN_DOORUNLOCK;
  19.743 +		invalidate_bdev(inode->i_bdev, 0);
  19.744 +		if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
  19.745 +			drive->doorlocking = 0;
  19.746 +	}
  19.747 +	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
  19.748 +		if (do_idedisk_flushcache(drive))
  19.749 +			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
  19.750 +				drive->name);
  19.751 +	MOD_DEC_USE_COUNT;
  19.752 +}
  19.753 +
  19.754 +static int idedisk_media_change (ide_drive_t *drive)
  19.755 +{
  19.756 +	return drive->removable;	/* if removable, always assume it was changed */
  19.757 +}
  19.758 +
  19.759 +static void idedisk_revalidate (ide_drive_t *drive)
  19.760 +{
  19.761 +	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
  19.762 +			1<<PARTN_BITS,
  19.763 +			current_capacity(drive));
  19.764 +}
  19.765 +
  19.766 +/*
  19.767 + * Queries for true maximum capacity of the drive.
  19.768 + * Returns maximum LBA address (> 0) of the drive, 0 if failed.
  19.769 + */
  19.770 +static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
  19.771 +{
  19.772 +	ide_task_t args;
  19.773 +	unsigned long addr = 0;
  19.774 +
  19.775 +	if (!(drive->id->command_set_1 & 0x0400) &&
  19.776 +	    !(drive->id->cfs_enable_2 & 0x0100))
  19.777 +		return addr;
  19.778 +
  19.779 +	/* Create IDE/ATA command request structure */
  19.780 +	memset(&args, 0, sizeof(ide_task_t));
  19.781 +	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
  19.782 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
  19.783 +	args.handler				= task_no_data_intr;
  19.784 +
  19.785 +	/* submit command request */
  19.786 +	ide_raw_taskfile(drive, &args, NULL);
  19.787 +
  19.788 +	/* if OK, compute maximum address value */
  19.789 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
  19.790 +		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
  19.791 +		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
  19.792 +		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
  19.793 +		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
  19.794 +	}
  19.795 +	addr++;	/* since the return value is (maxlba - 1), we add 1 */
  19.796 +	return addr;
  19.797 +}
  19.798 +
  19.799 +static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
  19.800 +{
  19.801 +	ide_task_t args;
  19.802 +	unsigned long long addr = 0;
  19.803 +
  19.804 +	/* Create IDE/ATA command request structure */
  19.805 +	memset(&args, 0, sizeof(ide_task_t));
  19.806 +
  19.807 +	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
  19.808 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
  19.809 +	args.handler				= task_no_data_intr;
  19.810 +
  19.811 +        /* submit command request */
  19.812 +        ide_raw_taskfile(drive, &args, NULL);
  19.813 +
  19.814 +	/* if OK, compute maximum address value */
  19.815 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
  19.816 +		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
  19.817 +			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
  19.818 +  			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]); 
  19.819 +		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
  19.820 +			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
  19.821 +			    (args.tfRegister[IDE_SECTOR_OFFSET]);
  19.822 +		addr = ((__u64)high << 24) | low;
  19.823 +	}
  19.824 +	addr++;	/* since the return value is (maxlba - 1), we add 1 */
  19.825 +	return addr;
  19.826 +}
  19.827 +
  19.828 +#ifdef CONFIG_IDEDISK_STROKE
  19.829 +/*
  19.830 + * Sets maximum virtual LBA address of the drive.
  19.831 + * Returns new maximum virtual LBA address (> 0) or 0 on failure.
  19.832 + */
  19.833 +static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
  19.834 +{
  19.835 +	ide_task_t args;
  19.836 +	unsigned long addr_set = 0;
  19.837 +	
  19.838 +	addr_req--;
  19.839 +	/* Create IDE/ATA command request structure */
  19.840 +	memset(&args, 0, sizeof(ide_task_t));
  19.841 +	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
  19.842 +	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
  19.843 +	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
  19.844 +	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
  19.845 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
  19.846 +	args.handler				= task_no_data_intr;
  19.847 +	/* submit command request */
  19.848 +	ide_raw_taskfile(drive, &args, NULL);
  19.849 +	/* if OK, read new maximum address value */
  19.850 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
  19.851 +		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
  19.852 +			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
  19.853 +			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
  19.854 +			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
  19.855 +	}
  19.856 +	addr_set++;
  19.857 +	return addr_set;
  19.858 +}
  19.859 +
  19.860 +static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
  19.861 +{
  19.862 +	ide_task_t args;
  19.863 +	unsigned long long addr_set = 0;
  19.864 +
  19.865 +	addr_req--;
  19.866 +	/* Create IDE/ATA command request structure */
  19.867 +	memset(&args, 0, sizeof(ide_task_t));
  19.868 +	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
  19.869 +	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
  19.870 +	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
  19.871 +	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
  19.872 +	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
  19.873 +	args.hobRegister[IDE_SECTOR_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
  19.874 +	args.hobRegister[IDE_LCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
  19.875 +	args.hobRegister[IDE_HCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
  19.876 +	args.hobRegister[IDE_SELECT_OFFSET_HOB]	= 0x40;
  19.877 +	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
  19.878 +        args.handler				= task_no_data_intr;
  19.879 +	/* submit command request */
  19.880 +	ide_raw_taskfile(drive, &args, NULL);
  19.881 +	/* if OK, compute maximum address value */
  19.882 +	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
  19.883 +		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
  19.884 +			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
  19.885 +			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
  19.886 +		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
  19.887 +			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
  19.888 +			    (args.tfRegister[IDE_SECTOR_OFFSET]);
  19.889 +		addr_set = ((__u64)high << 24) | low;
  19.890 +	}
  19.891 +	return addr_set;
  19.892 +}
  19.893 +
  19.894 +/*
  19.895 + * Tests if the drive supports Host Protected Area feature.
  19.896 + * Returns true if supported, false otherwise.
  19.897 + */
  19.898 +static inline int idedisk_supports_host_protected_area(ide_drive_t *drive)
  19.899 +{
  19.900 +	int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0;
  19.901 +	printk("%s: host protected area => %d\n", drive->name, flag);
  19.902 +	return flag;
  19.903 +}
  19.904 +
  19.905 +#endif /* CONFIG_IDEDISK_STROKE */
  19.906 +
  19.907 +/*
  19.908 + * Compute drive->capacity, the full capacity of the drive
  19.909 + * Called with drive->id != NULL.
  19.910 + *
  19.911 + * To compute capacity, this uses either of
  19.912 + *
  19.913 + *    1. CHS value set by user       (whatever user sets will be trusted)
  19.914 + *    2. LBA value from target drive (require new ATA feature)
  19.915 + *    3. LBA value from system BIOS  (new one is OK, old one may break)
  19.916 + *    4. CHS value from system BIOS  (traditional style)
  19.917 + *
  19.918 + * in above order (i.e., if value of higher priority is available,
  19.919 + * reset will be ignored).
  19.920 + */
  19.921 +static void init_idedisk_capacity (ide_drive_t  *drive)
  19.922 +{
  19.923 +	struct hd_driveid *id = drive->id;
  19.924 +	unsigned long capacity = drive->cyl * drive->head * drive->sect;
  19.925 +	unsigned long set_max = idedisk_read_native_max_address(drive);
  19.926 +	unsigned long long capacity_2 = capacity;
  19.927 +	unsigned long long set_max_ext;
  19.928 +
  19.929 +	drive->capacity48 = 0;
  19.930 +	drive->select.b.lba = 0;
  19.931 +
  19.932 +	if (id->cfs_enable_2 & 0x0400) {
  19.933 +		capacity_2 = id->lba_capacity_2;
  19.934 +		drive->head		= drive->bios_head = 255;
  19.935 +		drive->sect		= drive->bios_sect = 63;
  19.936 +		drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect);
  19.937 +		drive->select.b.lba	= 1;
  19.938 +		set_max_ext = idedisk_read_native_max_address_ext(drive);
  19.939 +		if (set_max_ext > capacity_2) {
  19.940 +#ifdef CONFIG_IDEDISK_STROKE
  19.941 +			set_max_ext = idedisk_read_native_max_address_ext(drive);
  19.942 +			set_max_ext = idedisk_set_max_address_ext(drive, set_max_ext);
  19.943 +			if (set_max_ext) {
  19.944 +				drive->capacity48 = capacity_2 = set_max_ext;
  19.945 +				drive->cyl = (unsigned int) set_max_ext / (drive->head * drive->sect);
  19.946 +				drive->select.b.lba = 1;
  19.947 +				drive->id->lba_capacity_2 = capacity_2;
  19.948 +                        }
  19.949 +#else /* !CONFIG_IDEDISK_STROKE */
  19.950 +			printk("%s: setmax_ext LBA %llu, native  %llu\n",
  19.951 +				drive->name, set_max_ext, capacity_2);
  19.952 +#endif /* CONFIG_IDEDISK_STROKE */
  19.953 +		}
  19.954 +		drive->bios_cyl		= drive->cyl;
  19.955 +		drive->capacity48	= capacity_2;
  19.956 +		drive->capacity		= (unsigned long) capacity_2;
  19.957 +		return;
  19.958 +	/* Determine capacity, and use LBA if the drive properly supports it */
  19.959 +	} else if ((id->capability & 2) && lba_capacity_is_ok(id)) {
  19.960 +		capacity = id->lba_capacity;
  19.961 +		drive->cyl = capacity / (drive->head * drive->sect);
  19.962 +		drive->select.b.lba = 1;
  19.963 +	}
  19.964 +
  19.965 +	if (set_max > capacity) {
  19.966 +#ifdef CONFIG_IDEDISK_STROKE
  19.967 +		set_max = idedisk_read_native_max_address(drive);
  19.968 +		set_max = idedisk_set_max_address(drive, set_max);
  19.969 +		if (set_max) {
  19.970 +			drive->capacity = capacity = set_max;
  19.971 +			drive->cyl = set_max / (drive->head * drive->sect);
  19.972 +			drive->select.b.lba = 1;
  19.973 +			drive->id->lba_capacity = capacity;
  19.974 +		}
  19.975 +#else /* !CONFIG_IDEDISK_STROKE */
  19.976 +		printk("%s: setmax LBA %lu, native  %lu\n",
  19.977 +			drive->name, set_max, capacity);
  19.978 +#endif /* CONFIG_IDEDISK_STROKE */
  19.979 +	}
  19.980 +
  19.981 +	drive->capacity = capacity;
  19.982 +
  19.983 +	if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) {
  19.984 +                drive->capacity48 = id->lba_capacity_2;
  19.985 +		drive->head = 255;
  19.986 +		drive->sect = 63;
  19.987 +		drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect);
  19.988 +	}
  19.989 +}
  19.990 +
  19.991 +static unsigned long idedisk_capacity (ide_drive_t *drive)
  19.992 +{
  19.993 +	if (drive->id->cfs_enable_2 & 0x0400)
  19.994 +		return (drive->capacity48 - drive->sect0);
  19.995 +	return (drive->capacity - drive->sect0);
  19.996 +}
  19.997 +
  19.998 +static ide_startstop_t idedisk_special (ide_drive_t *drive)
  19.999 +{
 19.1000 +	special_t *s = &drive->special;
 19.1001 +
 19.1002 +	if (s->b.set_geometry) {
 19.1003 +		struct hd_drive_task_hdr taskfile;
 19.1004 +		struct hd_drive_hob_hdr hobfile;
 19.1005 +		ide_handler_t *handler = NULL;
 19.1006 +
 19.1007 +		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1008 +		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1009 +
 19.1010 +		s->b.set_geometry	= 0;
 19.1011 +		taskfile.sector_number	= drive->sect;
 19.1012 +		taskfile.low_cylinder	= drive->cyl;
 19.1013 +		taskfile.high_cylinder	= drive->cyl>>8;
 19.1014 +		taskfile.device_head	= ((drive->head-1)|drive->select.all)&0xBF;
 19.1015 +		if (!IS_PDC4030_DRIVE) {
 19.1016 +			taskfile.sector_count	= drive->sect;
 19.1017 +			taskfile.command	= WIN_SPECIFY;
 19.1018 +			handler			= ide_handler_parser(&taskfile, &hobfile);
 19.1019 +		}
 19.1020 +		do_taskfile(drive, &taskfile, &hobfile, handler);
 19.1021 +	} else if (s->b.recalibrate) {
 19.1022 +		s->b.recalibrate = 0;
 19.1023 +		if (!IS_PDC4030_DRIVE) {
 19.1024 +			struct hd_drive_task_hdr taskfile;
 19.1025 +			struct hd_drive_hob_hdr hobfile;
 19.1026 +			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1027 +			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1028 +			taskfile.sector_count	= drive->sect;
 19.1029 +			taskfile.command	= WIN_RESTORE;
 19.1030 +			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
 19.1031 +		}
 19.1032 +	} else if (s->b.set_multmode) {
 19.1033 +		s->b.set_multmode = 0;
 19.1034 +		if (drive->id && drive->mult_req > drive->id->max_multsect)
 19.1035 +			drive->mult_req = drive->id->max_multsect;
 19.1036 +		if (!IS_PDC4030_DRIVE) {
 19.1037 +			struct hd_drive_task_hdr taskfile;
 19.1038 +			struct hd_drive_hob_hdr hobfile;
 19.1039 +			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1040 +			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1041 +			taskfile.sector_count	= drive->mult_req;
 19.1042 +			taskfile.command	= WIN_SETMULT;
 19.1043 +			do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile));
 19.1044 +		}
 19.1045 +	} else if (s->all) {
 19.1046 +		int special = s->all;
 19.1047 +		s->all = 0;
 19.1048 +		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
 19.1049 +		return ide_stopped;
 19.1050 +	}
 19.1051 +	return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
 19.1052 +}
 19.1053 +
 19.1054 +static void idedisk_pre_reset (ide_drive_t *drive)
 19.1055 +{
 19.1056 +	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
 19.1057 +
 19.1058 +	drive->special.all = 0;
 19.1059 +	drive->special.b.set_geometry = legacy;
 19.1060 +	drive->special.b.recalibrate  = legacy;
 19.1061 +	if (OK_TO_RESET_CONTROLLER)
 19.1062 +		drive->mult_count = 0;
 19.1063 +	if (!drive->keep_settings && !drive->using_dma)
 19.1064 +		drive->mult_req = 0;
 19.1065 +	if (drive->mult_req != drive->mult_count)
 19.1066 +		drive->special.b.set_multmode = 1;
 19.1067 +}
 19.1068 +
 19.1069 +#ifdef CONFIG_PROC_FS
 19.1070 +
 19.1071 +static int smart_enable(ide_drive_t *drive)
 19.1072 +{
 19.1073 +	struct hd_drive_task_hdr taskfile;
 19.1074 +	struct hd_drive_hob_hdr hobfile;
 19.1075 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1076 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1077 +	taskfile.feature	= SMART_ENABLE;
 19.1078 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
 19.1079 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
 19.1080 +	taskfile.command	= WIN_SMART;
 19.1081 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1082 +}
 19.1083 +
 19.1084 +static int get_smart_values(ide_drive_t *drive, byte *buf)
 19.1085 +{
 19.1086 +	struct hd_drive_task_hdr taskfile;
 19.1087 +	struct hd_drive_hob_hdr hobfile;
 19.1088 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1089 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1090 +	taskfile.feature	= SMART_READ_VALUES;
 19.1091 +	taskfile.sector_count	= 0x01;
 19.1092 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
 19.1093 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
 19.1094 +	taskfile.command	= WIN_SMART;
 19.1095 +	(void) smart_enable(drive);
 19.1096 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
 19.1097 +}
 19.1098 +
 19.1099 +static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
 19.1100 +{
 19.1101 +	struct hd_drive_task_hdr taskfile;
 19.1102 +	struct hd_drive_hob_hdr hobfile;
 19.1103 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1104 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1105 +	taskfile.feature	= SMART_READ_THRESHOLDS;
 19.1106 +	taskfile.sector_count	= 0x01;
 19.1107 +	taskfile.low_cylinder	= SMART_LCYL_PASS;
 19.1108 +	taskfile.high_cylinder	= SMART_HCYL_PASS;
 19.1109 +	taskfile.command	= WIN_SMART;
 19.1110 +	(void) smart_enable(drive);
 19.1111 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
 19.1112 +}
 19.1113 +
 19.1114 +static int proc_idedisk_read_cache
 19.1115 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
 19.1116 +{
 19.1117 +	ide_drive_t	*drive = (ide_drive_t *) data;
 19.1118 +	char		*out = page;
 19.1119 +	int		len;
 19.1120 +
 19.1121 +	if (drive->id)
 19.1122 +		len = sprintf(out,"%i\n", drive->id->buf_size / 2);
 19.1123 +	else
 19.1124 +		len = sprintf(out,"(none)\n");
 19.1125 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 19.1126 +}
 19.1127 +
 19.1128 +static int proc_idedisk_read_smart_thresholds
 19.1129 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
 19.1130 +{
 19.1131 +	ide_drive_t	*drive = (ide_drive_t *)data;
 19.1132 +	int		len = 0, i = 0;
 19.1133 +
 19.1134 +	if (!get_smart_thresholds(drive, page)) {
 19.1135 +		unsigned short *val = (unsigned short *) page;
 19.1136 +		char *out = ((char *)val) + (SECTOR_WORDS * 4);
 19.1137 +		page = out;
 19.1138 +		do {
 19.1139 +			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
 19.1140 +			val += 1;
 19.1141 +		} while (i < (SECTOR_WORDS * 2));
 19.1142 +		len = out - page;
 19.1143 +	}
 19.1144 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 19.1145 +}
 19.1146 +
 19.1147 +static int proc_idedisk_read_smart_values
 19.1148 +	(char *page, char **start, off_t off, int count, int *eof, void *data)
 19.1149 +{
 19.1150 +	ide_drive_t	*drive = (ide_drive_t *)data;
 19.1151 +	int		len = 0, i = 0;
 19.1152 +
 19.1153 +	if (!get_smart_values(drive, page)) {
 19.1154 +		unsigned short *val = (unsigned short *) page;
 19.1155 +		char *out = ((char *)val) + (SECTOR_WORDS * 4);
 19.1156 +		page = out;
 19.1157 +		do {
 19.1158 +			out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
 19.1159 +			val += 1;
 19.1160 +		} while (i < (SECTOR_WORDS * 2));
 19.1161 +		len = out - page;
 19.1162 +	}
 19.1163 +	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 19.1164 +}
 19.1165 +
 19.1166 +static ide_proc_entry_t idedisk_proc[] = {
 19.1167 +	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },
 19.1168 +	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },
 19.1169 +	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },
 19.1170 +	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },
 19.1171 +	{ NULL, 0, NULL, NULL }
 19.1172 +};
 19.1173 +
 19.1174 +#else
 19.1175 +
 19.1176 +#define	idedisk_proc	NULL
 19.1177 +
 19.1178 +#endif	/* CONFIG_PROC_FS */
 19.1179 +
 19.1180 +static int set_multcount(ide_drive_t *drive, int arg)
 19.1181 +{
 19.1182 +#ifdef __TASKFILE__IO
 19.1183 +	struct hd_drive_task_hdr taskfile;
 19.1184 +	struct hd_drive_hob_hdr hobfile;
 19.1185 +
 19.1186 +	if (drive->special.b.set_multmode)
 19.1187 +		return -EBUSY;
 19.1188 +
 19.1189 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1190 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1191 +	taskfile.sector_count	= drive->mult_req;
 19.1192 +	taskfile.command	= WIN_SETMULT;
 19.1193 +	drive->mult_req		= arg;
 19.1194 +	drive->special.b.set_multmode = 1;
 19.1195 +	ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1196 +#else /* !__TASKFILE__IO */
 19.1197 +	struct request rq;
 19.1198 +
 19.1199 +	if (drive->special.b.set_multmode)
 19.1200 +		return -EBUSY;
 19.1201 +	ide_init_drive_cmd (&rq);
 19.1202 +	rq.cmd = IDE_DRIVE_CMD;
 19.1203 +	drive->mult_req = arg;
 19.1204 +	drive->special.b.set_multmode = 1;
 19.1205 +	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
 19.1206 +#endif /* __TASKFILE__IO */
 19.1207 +	return (drive->mult_count == arg) ? 0 : -EIO;
 19.1208 +}
 19.1209 +
 19.1210 +static int set_nowerr(ide_drive_t *drive, int arg)
 19.1211 +{
 19.1212 +	if (ide_spin_wait_hwgroup(drive))
 19.1213 +		return -EBUSY;
 19.1214 +	drive->nowerr = arg;
 19.1215 +	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
 19.1216 +	spin_unlock_irq(&io_request_lock);
 19.1217 +	return 0;
 19.1218 +}
 19.1219 +
 19.1220 +static int write_cache (ide_drive_t *drive, int arg)
 19.1221 +{
 19.1222 +	struct hd_drive_task_hdr taskfile;
 19.1223 +	struct hd_drive_hob_hdr hobfile;
 19.1224 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1225 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1226 +	taskfile.feature	= (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
 19.1227 +	taskfile.command	= WIN_SETFEATURES;
 19.1228 +
 19.1229 +	if (!(drive->id->cfs_enable_2 & 0x3000))
 19.1230 +		return 1;
 19.1231 +
 19.1232 +	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1233 +	drive->wcache = arg;
 19.1234 +	return 0;
 19.1235 +}
 19.1236 +
 19.1237 +static int do_idedisk_standby (ide_drive_t *drive)
 19.1238 +{
 19.1239 +	struct hd_drive_task_hdr taskfile;
 19.1240 +	struct hd_drive_hob_hdr hobfile;
 19.1241 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1242 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1243 +	taskfile.command	= WIN_STANDBYNOW1;
 19.1244 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1245 +}
 19.1246 +
 19.1247 +static int do_idedisk_flushcache (ide_drive_t *drive)
 19.1248 +{
 19.1249 +	struct hd_drive_task_hdr taskfile;
 19.1250 +	struct hd_drive_hob_hdr hobfile;
 19.1251 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1252 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1253 +	if (drive->id->cfs_enable_2 & 0x2400) {
 19.1254 +		taskfile.command	= WIN_FLUSH_CACHE_EXT;
 19.1255 +	} else {
 19.1256 +		taskfile.command	= WIN_FLUSH_CACHE;
 19.1257 +	}
 19.1258 +	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1259 +}
 19.1260 +
 19.1261 +static int set_acoustic (ide_drive_t *drive, int arg)
 19.1262 +{
 19.1263 +	struct hd_drive_task_hdr taskfile;
 19.1264 +	struct hd_drive_hob_hdr hobfile;
 19.1265 +	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 19.1266 +	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 19.1267 +
 19.1268 +	taskfile.feature	= (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
 19.1269 +	taskfile.sector_count	= arg;
 19.1270 +
 19.1271 +	taskfile.command	= WIN_SETFEATURES;
 19.1272 +	(void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 19.1273 +	drive->acoustic = arg;
 19.1274 +	return 0;
 19.1275 +}
 19.1276 +
 19.1277 +static int probe_lba_addressing (ide_drive_t *drive, int arg)
 19.1278 +{
 19.1279 +	drive->addressing =  0;
 19.1280 +
 19.1281 +	if (!(drive->id->cfs_enable_2 & 0x0400))
 19.1282 +                return -EIO;
 19.1283 +
 19.1284 +	drive->addressing = arg;
 19.1285 +	return 0;
 19.1286 +}
 19.1287 +
 19.1288 +static int set_lba_addressing (ide_drive_t *drive, int arg)
 19.1289 +{
 19.1290 +	return (probe_lba_addressing(drive, arg));
 19.1291 +}
 19.1292 +
 19.1293 +static void idedisk_add_settings(ide_drive_t *drive)
 19.1294 +{
 19.1295 +	struct hd_driveid *id = drive->id;
 19.1296 +#if 0
 19.1297 +	int major = HWIF(drive)->major;
 19.1298 +	int minor = drive->select.b.unit << PARTN_BITS;
 19.1299 +#endif
 19.1300 +
 19.1301 +	ide_add_setting(drive,	"bios_cyl",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->bios_cyl,		NULL);
 19.1302 +	ide_add_setting(drive,	"bios_head",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	255,				1,	1,	&drive->bios_head,		NULL);
 19.1303 +	ide_add_setting(drive,	"bios_sect",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	63,				1,	1,	&drive->bios_sect,		NULL);
 19.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);
 19.1305 +	ide_add_setting(drive,	"bswap",		SETTING_READ,					-1,			-1,			TYPE_BYTE,	0,	1,				1,	1,	&drive->bswap,			NULL);
 19.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);
 19.1307 +	ide_add_setting(drive,	"nowerr",		SETTING_RW,					HDIO_GET_NOWERR,	HDIO_SET_NOWERR,	TYPE_BYTE,	0,	1,				1,	1,	&drive->nowerr,			set_nowerr);
 19.1308 +#if 0
 19.1309 +	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	1,	&read_ahead[major],		NULL);
 19.1310 +	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	4096,			PAGE_SIZE,	1024,	&max_readahead[major][minor],	NULL);
 19.1311 +	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	1,	&max_sectors[major][minor],	NULL);
 19.1312 +#endif
 19.1313 +	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);
 19.1314 +	ide_add_setting(drive,	"wcache",		SETTING_RW,					HDIO_GET_WCACHE,	HDIO_SET_WCACHE,	TYPE_BYTE,	0,	1,				1,	1,	&drive->wcache,			write_cache);
 19.1315 +	ide_add_setting(drive,	"acoustic",		SETTING_RW,					HDIO_GET_ACOUSTIC,	HDIO_SET_ACOUSTIC,	TYPE_BYTE,	0,	254,				1,	1,	&drive->acoustic,		set_acoustic);
 19.1316 + 	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL);
 19.1317 + 	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
 19.1318 +}
 19.1319 +
 19.1320 +static void idedisk_setup (ide_drive_t *drive)
 19.1321 +{
 19.1322 +	int i;
 19.1323 +	
 19.1324 +	struct hd_driveid *id = drive->id;
 19.1325 +	unsigned long capacity;
 19.1326 +	
 19.1327 +	idedisk_add_settings(drive);
 19.1328 +
 19.1329 +	if (id == NULL)
 19.1330 +		return;
 19.1331 +
 19.1332 +	/*
 19.1333 +	 * CompactFlash cards and their brethern look just like hard drives
 19.1334 +	 * to us, but they are removable and don't have a doorlock mechanism.
 19.1335 +	 */
 19.1336 +	if (drive->removable && !drive_is_flashcard(drive)) {
 19.1337 +		/*
 19.1338 +		 * Removable disks (eg. SYQUEST); ignore 'WD' drives 
 19.1339 +		 */
 19.1340 +		if (id->model[0] != 'W' || id->model[1] != 'D') {
 19.1341 +			drive->doorlocking = 1;
 19.1342 +		}
 19.1343 +	}
 19.1344 +	for (i = 0; i < MAX_DRIVES; ++i) {
 19.1345 +		ide_hwif_t *hwif = HWIF(drive);
 19.1346 +
 19.1347 +		if (drive != &hwif->drives[i]) continue;
 19.1348 +#ifdef DEVFS_MUST_DIE
 19.1349 +		hwif->gd->de_arr[i] = drive->de;
 19.1350 +#endif
 19.1351 +		if (drive->removable)
 19.1352 +			hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
 19.1353 +		break;
 19.1354 +	}
 19.1355 +
 19.1356 +	/* Extract geometry if we did not already have one for the drive */
 19.1357 +	if (!drive->cyl || !drive->head || !drive->sect) {
 19.1358 +		drive->cyl     = drive->bios_cyl  = id->cyls;
 19.1359 +		drive->head    = drive->bios_head = id->heads;
 19.1360 +		drive->sect    = drive->bios_sect = id->sectors;
 19.1361 +	}
 19.1362 +
 19.1363 +	/* Handle logical geometry translation by the drive */
 19.1364 +	if ((id->field_valid & 1) && id->cur_cyls &&
 19.1365 +	    id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
 19.1366 +		drive->cyl  = id->cur_cyls;
 19.1367 +		drive->head = id->cur_heads;
 19.1368 +		drive->sect = id->cur_sectors;
 19.1369 +	}
 19.1370 +
 19.1371 +	/* Use physical geometry if what we have still makes no sense */
 19.1372 +	if (drive->head > 16 && id->heads && id->heads <= 16) {
 19.1373 +		drive->cyl  = id->cyls;
 19.1374 +		drive->head = id->heads;
 19.1375 +		drive->sect = id->sectors;
 19.1376 +	}
 19.1377 +
 19.1378 +	/* calculate drive capacity, and select LBA if possible */
 19.1379 +	init_idedisk_capacity (drive);
 19.1380 +
 19.1381 +	/*
 19.1382 +	 * if possible, give fdisk access to more of the drive,
 19.1383 +	 * by correcting bios_cyls:
 19.1384 +	 */
 19.1385 +	capacity = idedisk_capacity (drive);
 19.1386 +	if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
 19.1387 +	    (!drive->forced_geom) && drive->bios_sect && drive->bios_head)
 19.1388 +		drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
 19.1389 +	printk (KERN_INFO "XEN %s: %ld sectors", drive->name, capacity);
 19.1390 +
 19.1391 +	/* Give size in megabytes (MB), not mebibytes (MiB). */
 19.1392 +	/* We compute the exact rounded value, avoiding overflow. */
 19.1393 +	printk (" (%ld MB)", (capacity - capacity/625 + 974)/1950);
 19.1394 +
 19.1395 +	/* Only print cache size when it was specified */
 19.1396 +	if (id->buf_size)
 19.1397 +		printk (" w/%dKiB Cache", id->buf_size/2);
 19.1398 +
 19.1399 +	printk(", CHS=%d/%d/%d", 
 19.1400 +	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 19.1401 +#ifdef CONFIG_BLK_DEV_IDEDMA
 19.1402 +	if (drive->using_dma)
 19.1403 +		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
 19.1404 +#endif /* CONFIG_BLK_DEV_IDEDMA */
 19.1405 +	printk("\n");
 19.1406 +
 19.1407 +	drive->mult_count = 0;
 19.1408 +	if (id->max_multsect) {
 19.1409 +#ifdef CONFIG_IDEDISK_MULTI_MODE
 19.1410 +		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
 19.1411 +		id->multsect_valid = id->multsect ? 1 : 0;
 19.1412 +		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
 19.1413 +		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
 19.1414 +#else	/* original, pre IDE-NFG, per request of AC */
 19.1415 +		drive->mult_req = INITIAL_MULT_COUNT;
 19.1416 +		if (drive->mult_req > id->max_multsect)
 19.1417 +			drive->mult_req = id->max_multsect;
 19.1418 +		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
 19.1419 +			drive->special.b.set_multmode = 1;
 19.1420 +#endif	/* CONFIG_IDEDISK_MULTI_MODE */
 19.1421 +	}
 19.1422 +	drive->no_io_32bit = id->dword_io ? 1 : 0;
 19.1423 +	if (drive->id->cfs_enable_2 & 0x3000)
 19.1424 +		write_cache(drive, (id->cfs_enable_2 & 0x3000));
 19.1425 +	(void) probe_lba_addressing(drive, 1);
 19.1426 +}
 19.1427 +
 19.1428 +static int idedisk_cleanup (ide_drive_t *drive)
 19.1429 +{
 19.1430 +	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
 19.1431 +		if (do_idedisk_flushcache(drive))
 19.1432 +			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
 19.1433 +				drive->name);
 19.1434 +	return ide_unregister_subdriver(drive);
 19.1435 +}
 19.1436 +
 19.1437 +int idedisk_reinit(ide_drive_t *drive);
 19.1438 +
 19.1439 +/*
 19.1440 + *      IDE subdriver functions, registered with ide.c
 19.1441 + */
 19.1442 +static ide_driver_t idedisk_driver = {
 19.1443 +	name:			"ide-disk",
 19.1444 +	version:		IDEDISK_VERSION,
 19.1445 +	media:			ide_disk,
 19.1446 +	busy:			0,
 19.1447 +	supports_dma:		1,
 19.1448 +	supports_dsc_overlap:	0,
 19.1449 +	cleanup:		idedisk_cleanup,
 19.1450 +	standby:		do_idedisk_standby,
 19.1451 +	flushcache:		do_idedisk_flushcache,
 19.1452 +	do_request:		do_rw_disk,
 19.1453 +	end_request:		NULL,
 19.1454 +	ioctl:			NULL,
 19.1455 +	open:			idedisk_open,
 19.1456 +	release:		idedisk_release,
 19.1457 +	media_change:		idedisk_media_change,
 19.1458 +	revalidate:		idedisk_revalidate,
 19.1459 +	pre_reset:		idedisk_pre_reset,
 19.1460 +	capacity:		idedisk_capacity,
 19.1461 +	special:		idedisk_special,
 19.1462 +	/*proc:			idedisk_proc,*/
 19.1463 +	reinit:			idedisk_reinit,
 19.1464 +	ata_prebuilder:		NULL,
 19.1465 +	atapi_prebuilder:	NULL,
 19.1466 +};
 19.1467 +
 19.1468 +int idedisk_init (void);
 19.1469 +static ide_module_t idedisk_module = {
 19.1470 +	IDE_DRIVER_MODULE,
 19.1471 +	idedisk_init,
 19.1472 +	&idedisk_driver,
 19.1473 +	NULL
 19.1474 +};
 19.1475 +
 19.1476 +MODULE_DESCRIPTION("ATA DISK Driver");
 19.1477 +
 19.1478 +int idedisk_reinit (ide_drive_t *drive)
 19.1479 +{
 19.1480 +	int failed = 0;
 19.1481 +
 19.1482 +	MOD_INC_USE_COUNT;
 19.1483 +
 19.1484 +	if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
 19.1485 +		printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
 19.1486 +		return 1;
 19.1487 +	}
 19.1488 +	DRIVER(drive)->busy++;
 19.1489 +	idedisk_setup(drive);
 19.1490 +	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
 19.1491 +		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
 19.1492 +		(void) idedisk_cleanup(drive);
 19.1493 +		DRIVER(drive)->busy--;
 19.1494 +		return 1;
 19.1495 +	}
 19.1496 +	DRIVER(drive)->busy--;
 19.1497 +	failed--;
 19.1498 +
 19.1499 +	ide_register_module(&idedisk_module);
 19.1500 +	MOD_DEC_USE_COUNT;
 19.1501 +	return 0;
 19.1502 +}
 19.1503 +
 19.1504 +static void __exit idedisk_exit (void)
 19.1505 +{
 19.1506 +	ide_drive_t *drive;
 19.1507 +	int failed = 0;
 19.1508 +
 19.1509 +	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) {
 19.1510 +		if (idedisk_cleanup (drive)) {
 19.1511 +			printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
 19.1512 +			failed++;
 19.1513 +		}
 19.1514 +		/* We must remove proc entries defined in this module.
 19.1515 +		   Otherwise we oops while accessing these entries */
 19.1516 +#ifdef CONFIG_PROC_FS
 19.1517 +		if (drive->proc)
 19.1518 +			ide_remove_proc_entries(drive->proc, idedisk_proc);
 19.1519 +#endif
 19.1520 +	}
 19.1521 +	ide_unregister_module(&idedisk_module);
 19.1522 +}
 19.1523 +
 19.1524 +int idedisk_init (void)
 19.1525 +{
 19.1526 +	ide_drive_t *drive;
 19.1527 +	int failed = 0;
 19.1528 +	
 19.1529 +	MOD_INC_USE_COUNT;
 19.1530 +	while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
 19.1531 +		if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) {
 19.1532 +			printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
 19.1533 +			continue;
 19.1534 +		}
 19.1535 +		DRIVER(drive)->busy++;
 19.1536 +		idedisk_setup(drive);
 19.1537 +		if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
 19.1538 +			printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head);
 19.1539 +			(void) idedisk_cleanup(drive);
 19.1540 +			DRIVER(drive)->busy--;
 19.1541 +			continue;
 19.1542 +		}
 19.1543 +		DRIVER(drive)->busy--;
 19.1544 +		failed--;
 19.1545 +	}
 19.1546 +	ide_register_module(&idedisk_module);
 19.1547 +	MOD_DEC_USE_COUNT;
 19.1548 +	return 0;
 19.1549 +}
 19.1550 +
 19.1551 +module_init(idedisk_init);
 19.1552 +module_exit(idedisk_exit);
 19.1553 +MODULE_LICENSE("GPL");
    20.1 --- a/xen-2.4.16/drivers/ide/ide-probe.c	Tue Feb 11 17:54:17 2003 +0000
    20.2 +++ b/xen-2.4.16/drivers/ide/ide-probe.c	Thu Feb 13 15:58:34 2003 +0000
    20.3 @@ -51,11 +51,18 @@
    20.4  #include <asm/uaccess.h>
    20.5  #include <asm/io.h>
    20.6  
    20.7 +#define IDE_PROBE_TRACE 0
    20.8 +
    20.9  static inline void do_identify (ide_drive_t *drive, byte cmd)
   20.10  {
   20.11  	int bswap = 1;
   20.12  	struct hd_driveid *id;
   20.13  
   20.14 +	if (IDE_PROBE_TRACE)
   20.15 +	{
   20.16 +	  printk (KERN_ALERT "ide-probe::do_identify\n");
   20.17 +	}
   20.18 +
   20.19  	id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC);	/* called with interrupts disabled! */
   20.20  	if (!id) {
   20.21  		printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n");
   20.22 @@ -201,6 +208,11 @@ static int actual_try_to_identify (ide_d
   20.23  	unsigned long timeout;
   20.24  	byte s, a;
   20.25  
   20.26 +	if (IDE_PROBE_TRACE)
   20.27 +	{
   20.28 +	  printk (KERN_ALERT "ide-probe::actual_try_to_identify\n");
   20.29 +	}
   20.30 +
   20.31  	if (IDE_CONTROL_REG) {
   20.32  		/* take a deep breath */
   20.33  		ide_delay_50ms();
   20.34 @@ -260,6 +272,11 @@ static int try_to_identify (ide_drive_t 
   20.35  	int autoprobe = 0;
   20.36  	unsigned long cookie = 0;
   20.37  
   20.38 +	if (IDE_PROBE_TRACE)
   20.39 +	{
   20.40 +	  printk (KERN_ALERT "ide-probe::try_to_identify\n");
   20.41 +	}
   20.42 +
   20.43  	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
   20.44  		autoprobe = 1;
   20.45  		cookie = probe_irq_on();
   20.46 @@ -314,6 +331,12 @@ static int do_probe (ide_drive_t *drive,
   20.47  {
   20.48  	int rc;
   20.49  	ide_hwif_t *hwif = HWIF(drive);
   20.50 +
   20.51 +	if (IDE_PROBE_TRACE)
   20.52 +	{
   20.53 +	  printk (KERN_ALERT "ide-probe::do_probe\n");
   20.54 +	}
   20.55 +
   20.56  	if (drive->present) {	/* avoid waiting for inappropriate probes */
   20.57  		if ((drive->media != ide_disk) && (cmd == WIN_IDENTIFY))
   20.58  			return 4;
   20.59 @@ -372,6 +395,11 @@ static void enable_nest (ide_drive_t *dr
   20.60  {
   20.61  	unsigned long timeout;
   20.62  
   20.63 +	if (IDE_PROBE_TRACE)
   20.64 +	{
   20.65 +	  printk (KERN_ALERT "ide-probe::enable_nest\n");
   20.66 +	}
   20.67 +
   20.68  	printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
   20.69  	SELECT_DRIVE(HWIF(drive), drive);
   20.70  	ide_delay_50ms();
   20.71 @@ -402,6 +430,11 @@ static void enable_nest (ide_drive_t *dr
   20.72   */
   20.73  static inline byte probe_for_drive (ide_drive_t *drive)
   20.74  {
   20.75 +  if (IDE_PROBE_TRACE)
   20.76 +  {
   20.77 +    printk (KERN_ALERT "ide-probe::probe_for_drive\n");
   20.78 +  }
   20.79 +
   20.80  	if (drive->noprobe)			/* skip probing? */
   20.81  		return drive->present;
   20.82  	if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */
   20.83 @@ -500,6 +533,11 @@ static void probe_hwif (ide_hwif_t *hwif
   20.84  	unsigned int unit;
   20.85  	unsigned long flags;
   20.86  
   20.87 +  if (IDE_PROBE_TRACE)
   20.88 +  {
   20.89 +    printk (KERN_ALERT "ide-probe::probe_hwif\n");
   20.90 +  }
   20.91 +
   20.92  	if (hwif->noprobe)
   20.93  		return;
   20.94  #ifdef CONFIG_BLK_DEV_IDE
   20.95 @@ -978,6 +1016,11 @@ int ideprobe_init (void)
   20.96  {
   20.97  	unsigned int index;
   20.98  	int probe[MAX_HWIFS];
   20.99 +
  20.100 +  if (IDE_PROBE_TRACE)
  20.101 +  {
  20.102 +    printk (KERN_ALERT "ide-probe::ideprobe_init\n");
  20.103 +  }
  20.104  	
  20.105  	MOD_INC_USE_COUNT;
  20.106  	memset(probe, 0, MAX_HWIFS * sizeof(int));
    21.1 --- a/xen-2.4.16/drivers/ide/ide-taskfile.c	Tue Feb 11 17:54:17 2003 +0000
    21.2 +++ b/xen-2.4.16/drivers/ide/ide-taskfile.c	Thu Feb 13 15:58:34 2003 +0000
    21.3 @@ -171,6 +171,8 @@ ide_startstop_t do_rw_taskfile (ide_driv
    21.4  	struct hd_driveid *id = drive->id;
    21.5  	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
    21.6  
    21.7 +	printk(KERN_ALERT "do_rw_taskfile\n");
    21.8 +
    21.9  	/* (ks/hs): Moved to start, do not use for multiple out commands */
   21.10  	if (task->handler != task_mulout_intr) {
   21.11  		if (IDE_CONTROL_REG)
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xen-2.4.16/drivers/ide/ide-xeno.c	Thu Feb 13 15:58:34 2003 +0000
    22.3 @@ -0,0 +1,46 @@
    22.4 +#include <xeno/config.h>
    22.5 +#include <xeno/types.h>
    22.6 +#include <xeno/lib.h>
    22.7 +#include <xeno/ide.h>
    22.8 +#include <hypervisor-ifs/block.h>
    22.9 +
   22.10 +
   22.11 +void
   22.12 +ide_probe_devices (xen_disk_info_t* xdi)
   22.13 +{
   22.14 +  int loop;
   22.15 +
   22.16 +  for (loop = 0; loop < MAX_HWIFS; ++loop)
   22.17 +  {
   22.18 +    ide_hwif_t *hwif = &ide_hwifs[loop];
   22.19 +    if (hwif->present)
   22.20 +    {
   22.21 +      struct gendisk *gd = hwif->gd;
   22.22 +      unsigned int unit;
   22.23 +
   22.24 +      for (unit = 0; unit < MAX_DRIVES; ++unit)
   22.25 +      {
   22.26 +	unsigned long capacity;
   22.27 +
   22.28 +	ide_drive_t *drive = &hwif->drives[unit];
   22.29 +
   22.30 +	if (drive->present)
   22.31 +	{
   22.32 +	  capacity = current_capacity (drive);
   22.33 +
   22.34 +	  xdi->disks[xdi->count].type = XEN_DISK_IDE;
   22.35 +	  xdi->disks[xdi->count].capacity = capacity;
   22.36 +	  xdi->count++;
   22.37 +
   22.38 +	  printk (KERN_ALERT "IDE-XENO %d\n", xdi->count);
   22.39 +	  printk (KERN_ALERT "  capacity  0x%x\n", capacity);
   22.40 +	  printk (KERN_ALERT "  head      0x%x\n", drive->bios_head);
   22.41 +	  printk (KERN_ALERT "  sector    0x%x\n", drive->bios_sect);
   22.42 +	  printk (KERN_ALERT "  cylinder  0x%x\n", drive->bios_cyl);
   22.43 +	}
   22.44 +      }
   22.45 +    }
   22.46 +  }
   22.47 +
   22.48 +  return;
   22.49 +}
    23.1 --- a/xen-2.4.16/drivers/ide/ide.c	Tue Feb 11 17:54:17 2003 +0000
    23.2 +++ b/xen-2.4.16/drivers/ide/ide.c	Thu Feb 13 15:58:34 2003 +0000
    23.3 @@ -1391,6 +1391,8 @@ static ide_startstop_t start_request (id
    23.4  	block    = rq->sector;
    23.5  	blockend = block + rq->nr_sectors;
    23.6  
    23.7 +
    23.8 +#ifdef NEVER
    23.9  	if ((rq->cmd == READ || rq->cmd == WRITE) &&
   23.10  	    (drive->media == ide_disk || drive->media == ide_floppy)) {
   23.11  		if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
   23.12 @@ -1404,6 +1406,15 @@ static ide_startstop_t start_request (id
   23.13  	   possibly killing some innocent following sector */
   23.14  	if (block == 0 && drive->remap_0_to_1 == 1)
   23.15  		block = 1;  /* redirect MBR access to EZ-Drive partn table */
   23.16 +#endif
   23.17 +
   23.18 +#ifdef NEVER_DEBUG
   23.19 +	{
   23.20 +	  printk("    ide::start_request  %lx %lx  %lx  %lx %lx\n", 
   23.21 +		 rq->sector, rq->nr_sectors, block,
   23.22 +		 drive->part[minor&PARTN_MASK].start_sect, drive->sect0);
   23.23 +	}
   23.24 +#endif
   23.25  
   23.26  #if (DISK_RECOVERY_TIME > 0)
   23.27  	while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
   23.28 @@ -1414,6 +1425,7 @@ static ide_startstop_t start_request (id
   23.29  		printk("%s: drive not ready for command\n", drive->name);
   23.30  		return startstop;
   23.31  	}
   23.32 +	drive->special.all = 0;
   23.33  	if (!drive->special.all) {
   23.34  		switch(rq->cmd) {
   23.35  			case IDE_DRIVE_CMD:
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/xen-2.4.16/drivers/ide/piix.c	Thu Feb 13 15:58:34 2003 +0000
    24.3 @@ -0,0 +1,536 @@
    24.4 +/*
    24.5 + *  linux/drivers/ide/piix.c		Version 0.32	June 9, 2000
    24.6 + *
    24.7 + *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
    24.8 + *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
    24.9 + *  May be copied or modified under the terms of the GNU General Public License
   24.10 + *
   24.11 + *  PIO mode setting function for Intel chipsets.  
   24.12 + *  For use instead of BIOS settings.
   24.13 + *
   24.14 + * 40-41
   24.15 + * 42-43
   24.16 + * 
   24.17 + *                 41
   24.18 + *                 43
   24.19 + *
   24.20 + * | PIO 0       | c0 | 80 | 0 | 	piix_tune_drive(drive, 0);
   24.21 + * | PIO 2 | SW2 | d0 | 90 | 4 | 	piix_tune_drive(drive, 2);
   24.22 + * | PIO 3 | MW1 | e1 | a1 | 9 | 	piix_tune_drive(drive, 3);
   24.23 + * | PIO 4 | MW2 | e3 | a3 | b | 	piix_tune_drive(drive, 4);
   24.24 + * 
   24.25 + * sitre = word40 & 0x4000; primary
   24.26 + * sitre = word42 & 0x4000; secondary
   24.27 + *
   24.28 + * 44 8421|8421    hdd|hdb
   24.29 + * 
   24.30 + * 48 8421         hdd|hdc|hdb|hda udma enabled
   24.31 + *
   24.32 + *    0001         hda
   24.33 + *    0010         hdb
   24.34 + *    0100         hdc
   24.35 + *    1000         hdd
   24.36 + *
   24.37 + * 4a 84|21        hdb|hda
   24.38 + * 4b 84|21        hdd|hdc
   24.39 + *
   24.40 + *    ata-33/82371AB
   24.41 + *    ata-33/82371EB
   24.42 + *    ata-33/82801AB            ata-66/82801AA
   24.43 + *    00|00 udma 0              00|00 reserved
   24.44 + *    01|01 udma 1              01|01 udma 3
   24.45 + *    10|10 udma 2              10|10 udma 4
   24.46 + *    11|11 reserved            11|11 reserved
   24.47 + *
   24.48 + * 54 8421|8421    ata66 drive|ata66 enable
   24.49 + *
   24.50 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
   24.51 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
   24.52 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
   24.53 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
   24.54 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
   24.55 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
   24.56 + *
   24.57 + */
   24.58 +
   24.59 +#include <linux/config.h>
   24.60 +#include <linux/types.h>
   24.61 +#include <linux/kernel.h>
   24.62 +#include <linux/ioport.h>
   24.63 +#include <linux/pci.h>
   24.64 +#include <linux/hdreg.h>
   24.65 +#include <linux/ide.h>
   24.66 +#include <linux/delay.h>
   24.67 +#include <linux/init.h>
   24.68 +
   24.69 +#include <asm/io.h>
   24.70 +
   24.71 +#include "ide_modes.h"
   24.72 +
   24.73 +#define PIIX_DEBUG_DRIVE_INFO		0
   24.74 +
   24.75 +#define DISPLAY_PIIX_TIMINGS
   24.76 +
   24.77 +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
   24.78 +#include <linux/stat.h>
   24.79 +#include <linux/proc_fs.h>
   24.80 +
   24.81 +static int piix_get_info(char *, char **, off_t, int);
   24.82 +extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */
   24.83 +extern char *ide_media_verbose(ide_drive_t *);
   24.84 +static struct pci_dev *bmide_dev;
   24.85 +
   24.86 +static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
   24.87 +{
   24.88 +	char *p = buffer;
   24.89 +	u32 bibma = pci_resource_start(bmide_dev, 4);
   24.90 +        u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
   24.91 +	u8  c0 = 0, c1 = 0;
   24.92 +	u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
   24.93 +
   24.94 +	switch(bmide_dev->device) {
   24.95 +		case PCI_DEVICE_ID_INTEL_82801BA_8:
   24.96 +		case PCI_DEVICE_ID_INTEL_82801BA_9:
   24.97 +	        case PCI_DEVICE_ID_INTEL_82801CA_10:
   24.98 +			p += sprintf(p, "\n                                Intel PIIX4 Ultra 100 Chipset.\n");
   24.99 +			break;
  24.100 +		case PCI_DEVICE_ID_INTEL_82372FB_1:
  24.101 +		case PCI_DEVICE_ID_INTEL_82801AA_1:
  24.102 +			p += sprintf(p, "\n                                Intel PIIX4 Ultra 66 Chipset.\n");
  24.103 +			break;
  24.104 +		case PCI_DEVICE_ID_INTEL_82451NX:
  24.105 +		case PCI_DEVICE_ID_INTEL_82801AB_1:
  24.106 +		case PCI_DEVICE_ID_INTEL_82443MX_1:
  24.107 +		case PCI_DEVICE_ID_INTEL_82371AB:
  24.108 +			p += sprintf(p, "\n                                Intel PIIX4 Ultra 33 Chipset.\n");
  24.109 +			break;
  24.110 +		case PCI_DEVICE_ID_INTEL_82371SB_1:
  24.111 +			p += sprintf(p, "\n                                Intel PIIX3 Chipset.\n");
  24.112 +			break;
  24.113 +		case PCI_DEVICE_ID_INTEL_82371MX:
  24.114 +			p += sprintf(p, "\n                                Intel MPIIX Chipset.\n");
  24.115 +			return p-buffer;	/* => must be less than 4k! */
  24.116 +		case PCI_DEVICE_ID_INTEL_82371FB_1:
  24.117 +		case PCI_DEVICE_ID_INTEL_82371FB_0:
  24.118 +		default:
  24.119 +			p += sprintf(p, "\n                                Intel PIIX Chipset.\n");
  24.120 +			break;
  24.121 +	}
  24.122 +
  24.123 +	pci_read_config_word(bmide_dev, 0x40, &reg40);
  24.124 +	pci_read_config_word(bmide_dev, 0x42, &reg42);
  24.125 +	pci_read_config_byte(bmide_dev, 0x44, &reg44);
  24.126 +	pci_read_config_byte(bmide_dev, 0x48, &reg48);
  24.127 +	pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
  24.128 +	pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
  24.129 +	pci_read_config_byte(bmide_dev, 0x54, &reg54);
  24.130 +	pci_read_config_byte(bmide_dev, 0x55, &reg55);
  24.131 +
  24.132 +	psitre = (reg40 & 0x4000) ? 1 : 0;
  24.133 +	ssitre = (reg42 & 0x4000) ? 1 : 0;
  24.134 +
  24.135 +	/*
  24.136 +	 * at that point bibma+0x2 et bibma+0xa are byte registers
  24.137 +	 * to investigate:
  24.138 +	 */
  24.139 +	c0 = inb_p((unsigned short)bibma + 0x02);
  24.140 +	c1 = inb_p((unsigned short)bibma + 0x0a);
  24.141 +
  24.142 +	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
  24.143 +	p += sprintf(p, "                %sabled                         %sabled\n",
  24.144 +			(c0&0x80) ? "dis" : " en",
  24.145 +			(c1&0x80) ? "dis" : " en");
  24.146 +	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
  24.147 +	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
  24.148 +			(c0&0x20) ? "yes" : "no ",
  24.149 +			(c0&0x40) ? "yes" : "no ",
  24.150 +			(c1&0x20) ? "yes" : "no ",
  24.151 +			(c1&0x40) ? "yes" : "no " );
  24.152 +	p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
  24.153 +			(reg48&0x01) ? "yes" : "no ",
  24.154 +			(reg48&0x02) ? "yes" : "no ",
  24.155 +			(reg48&0x04) ? "yes" : "no ",
  24.156 +			(reg48&0x08) ? "yes" : "no " );
  24.157 +	p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
  24.158 +			((reg54&0x11) && (reg55&0x10) && (reg4a&0x01)) ? "5" :
  24.159 +			((reg54&0x11) && (reg4a&0x02)) ? "4" :
  24.160 +			((reg54&0x11) && (reg4a&0x01)) ? "3" :
  24.161 +			(reg4a&0x02) ? "2" :
  24.162 +			(reg4a&0x01) ? "1" :
  24.163 +			(reg4a&0x00) ? "0" : "X",
  24.164 +			((reg54&0x22) && (reg55&0x20) && (reg4a&0x10)) ? "5" :
  24.165 +			((reg54&0x22) && (reg4a&0x20)) ? "4" :
  24.166 +			((reg54&0x22) && (reg4a&0x10)) ? "3" :
  24.167 +			(reg4a&0x20) ? "2" :
  24.168 +			(reg4a&0x10) ? "1" :
  24.169 +			(reg4a&0x00) ? "0" : "X",
  24.170 +			((reg54&0x44) && (reg55&0x40) && (reg4b&0x03)) ? "5" :
  24.171 +			((reg54&0x44) && (reg4b&0x02)) ? "4" :
  24.172 +			((reg54&0x44) && (reg4b&0x01)) ? "3" :
  24.173 +			(reg4b&0x02) ? "2" :
  24.174 +			(reg4b&0x01) ? "1" :
  24.175 +			(reg4b&0x00) ? "0" : "X",
  24.176 +			((reg54&0x88) && (reg55&0x80) && (reg4b&0x30)) ? "5" :
  24.177 +			((reg54&0x88) && (reg4b&0x20)) ? "4" :
  24.178 +			((reg54&0x88) && (reg4b&0x10)) ? "3" :
  24.179 +			(reg4b&0x20) ? "2" :
  24.180 +			(reg4b&0x10) ? "1" :
  24.181 +			(reg4b&0x00) ? "0" : "X");
  24.182 +
  24.183 +	p += sprintf(p, "UDMA\n");
  24.184 +	p += sprintf(p, "DMA\n");
  24.185 +	p += sprintf(p, "PIO\n");
  24.186 +
  24.187 +/*
  24.188 + *	FIXME.... Add configuration junk data....blah blah......
  24.189 + */
  24.190 +
  24.191 +	return p-buffer;	 /* => must be less than 4k! */
  24.192 +}
  24.193 +#endif  /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
  24.194 +
  24.195 +/*
  24.196 + *  Used to set Fifo configuration via kernel command line:
  24.197 + */
  24.198 +
  24.199 +byte piix_proc = 0;
  24.200 +
  24.201 +extern char *ide_xfer_verbose (byte xfer_rate);
  24.202 +
  24.203 +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
  24.204 +/*
  24.205 + *
  24.206 + */
  24.207 +static byte piix_dma_2_pio (byte xfer_rate) {
  24.208 +	switch(xfer_rate) {
  24.209 +		case XFER_UDMA_5:
  24.210 +		case XFER_UDMA_4:
  24.211 +		case XFER_UDMA_3:
  24.212 +		case XFER_UDMA_2:
  24.213 +		case XFER_UDMA_1:
  24.214 +		case XFER_UDMA_0:
  24.215 +		case XFER_MW_DMA_2:
  24.216 +		case XFER_PIO_4:
  24.217 +			return 4;
  24.218 +		case XFER_MW_DMA_1:
  24.219 +		case XFER_PIO_3:
  24.220 +			return 3;
  24.221 +		case XFER_SW_DMA_2:
  24.222 +		case XFER_PIO_2:
  24.223 +			return 2;
  24.224 +		case XFER_MW_DMA_0:
  24.225 +		case XFER_SW_DMA_1:
  24.226 +		case XFER_SW_DMA_0:
  24.227 +		case XFER_PIO_1:
  24.228 +		case XFER_PIO_0:
  24.229 +		case XFER_PIO_SLOW:
  24.230 +		default:
  24.231 +			return 0;
  24.232 +	}
  24.233 +}
  24.234 +#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
  24.235 +
  24.236 +/*
  24.237 + *  Based on settings done by AMI BIOS
  24.238 + *  (might be useful if drive is not registered in CMOS for any reason).
  24.239 + */
  24.240 +static void piix_tune_drive (ide_drive_t *drive, byte pio)
  24.241 +{
  24.242 +	unsigned long flags;
  24.243 +	u16 master_data;
  24.244 +	byte slave_data;
  24.245 +	int is_slave		= (&HWIF(drive)->drives[1] == drive);
  24.246 +	int master_port		= HWIF(drive)->index ? 0x42 : 0x40;
  24.247 +	int slave_port		= 0x44;
  24.248 +				 /* ISP  RTC */
  24.249 +	byte timings[][2]	= { { 0, 0 },
  24.250 +				    { 0, 0 },
  24.251 +				    { 1, 0 },
  24.252 +				    { 2, 1 },
  24.253 +				    { 2, 3 }, };
  24.254 +
  24.255 +	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
  24.256 +	pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
  24.257 +	if (is_slave) {
  24.258 +		master_data = master_data | 0x4000;
  24.259 +		if (pio > 1)
  24.260 +			/* enable PPE, IE and TIME */
  24.261 +			master_data = master_data | 0x0070;
  24.262 +		pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
  24.263 +		slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
  24.264 +		slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1]
  24.265 +					   << (HWIF(drive)->index ? 4 : 0)));
  24.266 +	} else {
  24.267 +		master_data = master_data & 0xccf8;
  24.268 +		if (pio > 1)
  24.269 +			/* enable PPE, IE and TIME */
  24.270 +			master_data = master_data | 0x0007;
  24.271 +		master_data = master_data | (timings[pio][0] << 12) |
  24.272 +			      (timings[pio][1] << 8);
  24.273 +	}
  24.274 +	save_flags(flags);
  24.275 +	cli();
  24.276 +	pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
  24.277 +	if (is_slave)
  24.278 +		pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
  24.279 +	restore_flags(flags);
  24.280 +}
  24.281 +
  24.282 +#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
  24.283 +static int piix_tune_chipset (ide_drive_t *drive, byte speed)
  24.284 +{
  24.285 +	ide_hwif_t *hwif	= HWIF(drive);
  24.286 +	struct pci_dev *dev	= hwif->pci_dev;
  24.287 +	byte maslave		= hwif->channel ? 0x42 : 0x40;
  24.288 +	int a_speed		= 3 << (drive->dn * 4);
  24.289 +	int u_flag		= 1 << drive->dn;
  24.290 +	int v_flag		= 0x01 << drive->dn;
  24.291 +	int w_flag		= 0x10 << drive->dn;
  24.292 +	int u_speed		= 0;
  24.293 +	int err			= 0;
  24.294 +	int			sitre;
  24.295 +	short			reg4042, reg44, reg48, reg4a, reg54;
  24.296 +	byte			reg55;
  24.297 +
  24.298 +	pci_read_config_word(dev, maslave, &reg4042);
  24.299 +	sitre = (reg4042 & 0x4000) ? 1 : 0;
  24.300 +	pci_read_config_word(dev, 0x44, &reg44);
  24.301 +	pci_read_config_word(dev, 0x48, &reg48);
  24.302 +	pci_read_config_word(dev, 0x4a, &reg4a);
  24.303 +	pci_read_config_word(dev, 0x54, &reg54);
  24.304 +	pci_read_config_byte(dev, 0x55, &reg55);
  24.305 +
  24.306 +	switch(speed) {
  24.307 +		case XFER_UDMA_4:
  24.308 +		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
  24.309 +		case XFER_UDMA_5:
  24.310 +		case XFER_UDMA_3:
  24.311 +		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
  24.312 +		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
  24.313 +		case XFER_MW_DMA_2:
  24.314 +		case XFER_MW_DMA_1:
  24.315 +		case XFER_SW_DMA_2:	break;
  24.316 +		default:		return -1;
  24.317 +	}
  24.318 +
  24.319 +	if (speed >= XFER_UDMA_0) {
  24.320 +		if (!(reg48 & u_flag))
  24.321 +			pci_write_config_word(dev, 0x48, reg48|u_flag);
  24.322 +		if (speed == XFER_UDMA_5) {
  24.323 +			pci_write_config_byte(dev, 0x55, (byte) reg55|w_flag);
  24.324 +		} else {
  24.325 +			pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
  24.326 +		}
  24.327 +		if (!(reg4a & u_speed)) {
  24.328 +			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
  24.329 +			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
  24.330 +		}
  24.331 +		if (speed > XFER_UDMA_2) {
  24.332 +			if (!(reg54 & v_flag)) {
  24.333 +				pci_write_config_word(dev, 0x54, reg54|v_flag);
  24.334 +			}
  24.335 +		} else {
  24.336 +			pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
  24.337 +		}
  24.338 +	}
  24.339 +	if (speed < XFER_UDMA_0) {
  24.340 +		if (reg48 & u_flag)
  24.341 +			pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
  24.342 +		if (reg4a & a_speed)
  24.343 +			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
  24.344 +		if (reg54 & v_flag)
  24.345 +			pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
  24.346 +		if (reg55 & w_flag)
  24.347 +			pci_write_config_byte(dev, 0x55, (byte) reg55 & ~w_flag);
  24.348 +	}
  24.349 +
  24.350 +	piix_tune_drive(drive, piix_dma_2_pio(speed));
  24.351 +
  24.352 +#if PIIX_DEBUG_DRIVE_INFO
  24.353 +	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
  24.354 +#endif /* PIIX_DEBUG_DRIVE_INFO */
  24.355 +	if (!drive->init_speed)
  24.356 +		drive->init_speed = speed;
  24.357 +	err = ide_config_drive_speed(drive, speed);
  24.358 +	drive->current_speed = speed;
  24.359 +	return err;
  24.360 +}
  24.361 +
  24.362 +static int piix_config_drive_for_dma (ide_drive_t *drive)
  24.363 +{
  24.364 +	struct hd_driveid *id	= drive->id;
  24.365 +	ide_hwif_t *hwif	= HWIF(drive);
  24.366 +	struct pci_dev *dev	= hwif->pci_dev;
  24.367 +	byte			speed;
  24.368 +
  24.369 +	byte udma_66		= eighty_ninty_three(drive);
  24.370 +	int ultra100		= ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) ||
  24.371 +				   (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) ||
  24.372 +				   (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10)) ? 1 : 0;
  24.373 +	int ultra66		= ((ultra100) ||
  24.374 +				   (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
  24.375 +				   (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
  24.376 +	int ultra		= ((ultra66) ||
  24.377 +				   (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
  24.378 +				   (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) ||
  24.379 +				   (dev->device == PCI_DEVICE_ID_INTEL_82451NX) ||
  24.380 +				   (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
  24.381 +
  24.382 +	if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) {
  24.383 +		speed = XFER_UDMA_5;
  24.384 +	} else if ((id->dma_ultra & 0x0010) && (ultra)) {
  24.385 +		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
  24.386 +	} else if ((id->dma_ultra & 0x0008) && (ultra)) {
  24.387 +		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
  24.388 +	} else if ((id->dma_ultra & 0x0004) && (ultra)) {
  24.389 +		speed = XFER_UDMA_2;
  24.390 +	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
  24.391 +		speed = XFER_UDMA_1;
  24.392 +	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
  24.393 +		speed = XFER_UDMA_0;
  24.394 +	} else if (id->dma_mword & 0x0004) {
  24.395 +		speed = XFER_MW_DMA_2;
  24.396 +	} else if (id->dma_mword & 0x0002) {
  24.397 +		speed = XFER_MW_DMA_1;
  24.398 +	} else if (id->dma_1word & 0x0004) {
  24.399 +		speed = XFER_SW_DMA_2;
  24.400 +        } else {
  24.401 +		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
  24.402 +	}
  24.403 +
  24.404 +	(void) piix_tune_chipset(drive, speed);
  24.405 +
  24.406 +	return ((int)	((id->dma_ultra >> 11) & 7) ? ide_dma_on :
  24.407 +			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
  24.408 +			((id->dma_mword >> 8) & 7) ? ide_dma_on :
  24.409 +			((id->dma_1word >> 8) & 7) ? ide_dma_on :
  24.410 +						     ide_dma_off_quietly);
  24.411 +}
  24.412 +
  24.413 +static void config_chipset_for_pio (ide_drive_t *drive)
  24.414 +{
  24.415 +	piix_tune_drive(drive, ide_get_best_pio_mode(drive, 255, 5, NULL));
  24.416 +}
  24.417 +
  24.418 +static int config_drive_xfer_rate (ide_drive_t *drive)
  24.419 +{
  24.420 +	struct hd_driveid *id = drive->id;
  24.421 +	ide_dma_action_t dma_func = ide_dma_on;
  24.422 +
  24.423 +	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
  24.424 +		/* Consult the list of known "bad" drives */
  24.425 +		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
  24.426 +			dma_func = ide_dma_off;
  24.427 +			goto fast_ata_pio;
  24.428 +		}
  24.429 +		dma_func = ide_dma_off_quietly;
  24.430 +		if (id->field_valid & 4) {
  24.431 +			if (id->dma_ultra & 0x002F) {
  24.432 +				/* Force if Capable UltraDMA */
  24.433 +				dma_func = piix_config_drive_for_dma(drive);
  24.434 +				if ((id->field_valid & 2) &&
  24.435 +				    (dma_func != ide_dma_on))
  24.436 +					goto try_dma_modes;
  24.437 +			}
  24.438 +		} else if (id->field_valid & 2) {
  24.439 +try_dma_modes:
  24.440 +			if ((id->dma_mword & 0x0007) ||
  24.441 +			    (id->dma_1word & 0x007)) {
  24.442 +				/* Force if Capable regular DMA modes */
  24.443 +				dma_func = piix_config_drive_for_dma(drive);
  24.444 +				if (dma_func != ide_dma_on)
  24.445 +					goto no_dma_set;
  24.446 +			}
  24.447 +		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
  24.448 +			if (id->eide_dma_time > 150) {
  24.449 +				goto no_dma_set;
  24.450 +			}
  24.451 +			/* Consult the list of known "good" drives */
  24.452 +			dma_func = piix_config_drive_for_dma(drive);
  24.453 +			if (dma_func != ide_dma_on)
  24.454 +				goto no_dma_set;
  24.455 +		} else {
  24.456 +			goto fast_ata_pio;
  24.457 +		}
  24.458 +	} else if ((id->capability & 8) || (id->field_valid & 2)) {
  24.459 +fast_ata_pio:
  24.460 +		dma_func = ide_dma_off_quietly;
  24.461 +no_dma_set:
  24.462 +		config_chipset_for_pio(drive);
  24.463 +	}
  24.464 +	return HWIF(drive)->dmaproc(dma_func, drive);
  24.465 +}
  24.466 +
  24.467 +static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
  24.468 +{
  24.469 +	switch (func) {
  24.470 +		case ide_dma_check:
  24.471 +			return config_drive_xfer_rate(drive);
  24.472 +		default :
  24.473 +			break;
  24.474 +	}
  24.475 +	/* Other cases are done by generic IDE-DMA code. */
  24.476 +	return ide_dmaproc(func, drive);
  24.477 +}
  24.478 +#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_PIIX_TUNING) */
  24.479 +
  24.480 +unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name)
  24.481 +{
  24.482 +#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
  24.483 +	if (!piix_proc) {
  24.484 +		piix_proc = 1;
  24.485 +		bmide_dev = dev;
  24.486 +		piix_display_info = &piix_get_info;
  24.487 +	}
  24.488 +#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
  24.489 +	return 0;
  24.490 +}
  24.491 +
  24.492 +/*
  24.493 + * Sheesh, someone at Intel needs to go read the ATA-4/5 T13 standards.
  24.494 + * It does not specify device detection, but channel!!!
  24.495 + * You determine later if bit 13 of word93 is set...
  24.496 + */
  24.497 +unsigned int __init ata66_piix (ide_hwif_t *hwif)
  24.498 +{
  24.499 +	byte reg54h = 0, reg55h = 0, ata66 = 0;
  24.500 +	byte mask = hwif->channel ? 0xc0 : 0x30;
  24.501 +
  24.502 +	pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
  24.503 +	pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
  24.504 +
  24.505 +	ata66 = (reg54h & mask) ? 1 : 0;
  24.506 +
  24.507 +	return ata66;
  24.508 +}
  24.509 +
  24.510 +void __init ide_init_piix (ide_hwif_t *hwif)
  24.511 +{
  24.512 +#ifndef CONFIG_IA64
  24.513 +	if (!hwif->irq)
  24.514 +		hwif->irq = hwif->channel ? 15 : 14;
  24.515 +#endif /* CONFIG_IA64 */
  24.516 +
  24.517 +	if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
  24.518 +		/* This is a painful system best to let it self tune for now */
  24.519 +		return;
  24.520 +	}
  24.521 +
  24.522 +	hwif->tuneproc = &piix_tune_drive;
  24.523 +	hwif->drives[0].autotune = 1;
  24.524 +	hwif->drives[1].autotune = 1;
  24.525 +
  24.526 +	if (!hwif->dma_base)
  24.527 +		return;
  24.528 +
  24.529 +#ifndef CONFIG_BLK_DEV_IDEDMA
  24.530 +	hwif->autodma = 0;
  24.531 +#else /* CONFIG_BLK_DEV_IDEDMA */
  24.532 +#ifdef CONFIG_PIIX_TUNING
  24.533 +	if (!noautodma)
  24.534 +		hwif->autodma = 1;
  24.535 +	hwif->dmaproc = &piix_dmaproc;
  24.536 +	hwif->speedproc = &piix_tune_chipset;
  24.537 +#endif /* CONFIG_PIIX_TUNING */
  24.538 +#endif /* !CONFIG_BLK_DEV_IDEDMA */
  24.539 +}
    25.1 --- a/xen-2.4.16/drivers/net/Makefile	Tue Feb 11 17:54:17 2003 +0000
    25.2 +++ b/xen-2.4.16/drivers/net/Makefile	Thu Feb 13 15:58:34 2003 +0000
    25.3 @@ -5,12 +5,11 @@ default: $(OBJS)
    25.4  	$(MAKE) -C ne
    25.5  	$(MAKE) -C tulip
    25.6  	$(MAKE) -C e1000
    25.7 -	$(LD) -r -o driver.o $(OBJS) tulip/tulip.o e1000/e1000.o ne/ne_drv.o
    25.8 +	$(LD) -r -o driver.o e1000/e1000.o $(OBJS) tulip/tulip.o ne/ne_drv.o
    25.9  
   25.10  clean:
   25.11  	$(MAKE) -C ne clean
   25.12  	$(MAKE) -C tulip clean
   25.13 -	$(MAKE) -C e1000 clean
   25.14  	rm -f *.o *~ core
   25.15  
   25.16  .PHONY: default clean
    26.1 --- a/xen-2.4.16/drivers/net/e1000/e1000.h	Tue Feb 11 17:54:17 2003 +0000
    26.2 +++ b/xen-2.4.16/drivers/net/e1000/e1000.h	Thu Feb 13 15:58:34 2003 +0000
    26.3 @@ -77,14 +77,13 @@
    26.4  struct e1000_adapter;
    26.5  
    26.6  // XEN XXX
    26.7 -#define DBG 1
    26.8 +// #define DBG 1
    26.9  
   26.10  #include "e1000_hw.h"
   26.11  
   26.12  #if DBG
   26.13  #define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
   26.14  #else
   26.15 -XXX
   26.16  #define E1000_DBG(args...)
   26.17  #endif
   26.18  
    27.1 --- a/xen-2.4.16/drivers/net/e1000/e1000_hw.c	Tue Feb 11 17:54:17 2003 +0000
    27.2 +++ b/xen-2.4.16/drivers/net/e1000/e1000_hw.c	Thu Feb 13 15:58:34 2003 +0000
    27.3 @@ -1879,7 +1879,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
    27.4      uint32_t mdic = 0;
    27.5      const uint32_t phy_addr = 1;
    27.6  
    27.7 -    DEBUGFUNC("e1000_read_phy_reg");
    27.8 +    DEBUGFUNC("XXXXe1000_read_phy_reg");
    27.9  
   27.10      if(reg_addr > MAX_PHY_REG_ADDRESS) {
   27.11          DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
    28.1 --- a/xen-2.4.16/drivers/net/e1000/e1000_main.c	Tue Feb 11 17:54:17 2003 +0000
    28.2 +++ b/xen-2.4.16/drivers/net/e1000/e1000_main.c	Thu Feb 13 15:58:34 2003 +0000
    28.3 @@ -301,11 +301,9 @@ e1000_reset(struct e1000_adapter *adapte
    28.4  
    28.5  	adapter->hw.fc = adapter->hw.original_fc;
    28.6  	e1000_reset_hw(&adapter->hw);
    28.7 -printk("RESET_H/W\n");
    28.8  	if(adapter->hw.mac_type >= e1000_82544)
    28.9  		E1000_WRITE_REG(&adapter->hw, WUC, 0);
   28.10  	e1000_init_hw(&adapter->hw);
   28.11 -printk("INIT H/W\n");
   28.12  	e1000_reset_adaptive(&adapter->hw);
   28.13  	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
   28.14  }
   28.15 @@ -470,14 +468,12 @@ e1000_probe(struct pci_dev *pdev,
   28.16  
   28.17  	printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
   28.18  	e1000_check_options(adapter);
   28.19 -printk("OPTIONS OVER\n");
   28.20  	/* Initial Wake on LAN setting
   28.21  	 * If APM wake is enabled in the EEPROM,
   28.22  	 * enable the ACPI Magic Packet filter
   28.23  	 */
   28.24  
   28.25  	e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data);
   28.26 -printk("EPROM OVER\n");
   28.27  	if((adapter->hw.mac_type >= e1000_82544) &&
   28.28  	   (eeprom_data & E1000_EEPROM_APME))
   28.29  		adapter->wol |= E1000_WUFC_MAG;
   28.30 @@ -485,7 +481,6 @@ printk("EPROM OVER\n");
   28.31  	/* reset the hardware with the new settings */
   28.32  
   28.33  	e1000_reset(adapter);
   28.34 -printk("PROBE OVER\n");
   28.35  	cards_found++;
   28.36  	return 0;
   28.37  
    29.1 --- a/xen-2.4.16/drivers/net/e1000/e1000_osdep.h	Tue Feb 11 17:54:17 2003 +0000
    29.2 +++ b/xen-2.4.16/drivers/net/e1000/e1000_osdep.h	Thu Feb 13 15:58:34 2003 +0000
    29.3 @@ -45,7 +45,7 @@
    29.4  #define msec_delay(x) {\
    29.5   	int s=jiffies+1+((x*HZ)/1000); \
    29.6  	printk("mdelay(%d) called -- spin\n",x); \
    29.7 -	while(jiffies<s); printk("mdelay over\n");}
    29.8 +	while(jiffies<s); }
    29.9  
   29.10  #if 0
   29.11  /********************  NOT in XEN ! *******/
   29.12 @@ -73,7 +73,7 @@ typedef enum {
   29.13  #define ASSERT(x)	if(!(x)) BUG()
   29.14  #define MSGOUT(S, A, B)	printk(KERN_DEBUG S "\n", A, B)
   29.15  
   29.16 -#define DBG 1
   29.17 +//#define DBG 1
   29.18  
   29.19  #if DBG
   29.20  #define DEBUGOUT(S)		printk(KERN_DEBUG S "\n")
    30.1 --- a/xen-2.4.16/include/asm-i386/apic.h	Tue Feb 11 17:54:17 2003 +0000
    30.2 +++ b/xen-2.4.16/include/asm-i386/apic.h	Thu Feb 13 15:58:34 2003 +0000
    30.3 @@ -1,9 +1,12 @@
    30.4  #ifndef __ASM_APIC_H
    30.5  #define __ASM_APIC_H
    30.6  
    30.7 +//#include <linux/config.h>
    30.8 +//#include <linux/pm.h>
    30.9 +#include <asm/apicdef.h>
   30.10  #include <asm/system.h>
   30.11 -#include <asm/ptrace.h>
   30.12 -#include <asm/apicdef.h>
   30.13 +
   30.14 +#ifdef CONFIG_X86_LOCAL_APIC
   30.15  
   30.16  #define APIC_DEBUG 0
   30.17  
   30.18 @@ -37,9 +40,15 @@ static __inline__ void apic_wait_icr_idl
   30.19  	do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
   30.20  }
   30.21  
   30.22 -#define FORCE_READ_AROUND_WRITE 0
   30.23 -#define apic_read_around(x)
   30.24 -#define apic_write_around(x,y) apic_write((x),(y))
   30.25 +#ifdef CONFIG_X86_GOOD_APIC
   30.26 +# define FORCE_READ_AROUND_WRITE 0
   30.27 +# define apic_read_around(x)
   30.28 +# define apic_write_around(x,y) apic_write((x),(y))
   30.29 +#else
   30.30 +# define FORCE_READ_AROUND_WRITE 1
   30.31 +# define apic_read_around(x) apic_read(x)
   30.32 +# define apic_write_around(x,y) apic_write_atomic((x),(y))
   30.33 +#endif
   30.34  
   30.35  static inline void ack_APIC_irq(void)
   30.36  {
   30.37 @@ -64,8 +73,24 @@ extern void init_bsp_APIC (void);
   30.38  extern void setup_local_APIC (void);
   30.39  extern void init_apic_mappings (void);
   30.40  extern void setup_APIC_clocks (void);
   30.41 +extern void setup_apic_nmi_watchdog (void);
   30.42 +extern inline void nmi_watchdog_tick (struct pt_regs * regs);
   30.43  extern int APIC_init_uniprocessor (void);
   30.44 +extern void disable_APIC_timer(void);
   30.45 +extern void enable_APIC_timer(void);
   30.46 +
   30.47 +//extern struct pm_dev *apic_pm_register(pm_dev_t, unsigned long, pm_callback);
   30.48 +//extern void apic_pm_unregister(struct pm_dev*);
   30.49  
   30.50  extern unsigned int apic_timer_irqs [NR_CPUS];
   30.51 +extern int check_nmi_watchdog (void);
   30.52 +
   30.53 +extern unsigned int nmi_watchdog;
   30.54 +#define NMI_NONE	0
   30.55 +#define NMI_IO_APIC	1
   30.56 +#define NMI_LOCAL_APIC	2
   30.57 +#define NMI_INVALID	3
   30.58 +
   30.59 +#endif /* CONFIG_X86_LOCAL_APIC */
   30.60  
   30.61  #endif /* __ASM_APIC_H */
    31.1 --- a/xen-2.4.16/include/asm-i386/apicdef.h	Tue Feb 11 17:54:17 2003 +0000
    31.2 +++ b/xen-2.4.16/include/asm-i386/apicdef.h	Thu Feb 13 15:58:34 2003 +0000
    31.3 @@ -32,6 +32,8 @@
    31.4  #define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
    31.5  #define			APIC_ALL_CPUS		0xFF
    31.6  #define		APIC_DFR	0xE0
    31.7 +#define			APIC_DFR_CLUSTER	0x0FFFFFFFul	/* Clustered */
    31.8 +#define			APIC_DFR_FLAT		0xFFFFFFFFul	/* Flat mode */
    31.9  #define		APIC_SPIV	0xF0
   31.10  #define			APIC_SPIV_FOCUS_DISABLED	(1<<9)
   31.11  #define			APIC_SPIV_APIC_ENABLED		(1<<8)
   31.12 @@ -57,6 +59,7 @@
   31.13  #define			APIC_INT_LEVELTRIG	0x08000
   31.14  #define			APIC_INT_ASSERT		0x04000
   31.15  #define			APIC_ICR_BUSY		0x01000
   31.16 +#define			APIC_DEST_PHYSICAL	0x00000
   31.17  #define			APIC_DEST_LOGICAL	0x00800
   31.18  #define			APIC_DM_FIXED		0x00000
   31.19  #define			APIC_DM_LOWEST		0x00100
   31.20 @@ -107,7 +110,19 @@
   31.21  
   31.22  #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
   31.23  
   31.24 +#ifdef CONFIG_X86_CLUSTERED_APIC
   31.25 +#define MAX_IO_APICS 32
   31.26 +#else
   31.27  #define MAX_IO_APICS 8
   31.28 +#endif
   31.29 +
   31.30 +
   31.31 +/*
   31.32 + * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs.  SAPICs
   31.33 + * don't broadcast (yet?), but if they did, they might use 0xFFFF.
   31.34 + */
   31.35 +#define APIC_BROADCAST_ID_XAPIC (0xFF)
   31.36 +#define APIC_BROADCAST_ID_APIC  (0x0F)
   31.37  
   31.38  /*
   31.39   * the local APIC register structure, memory mapped. Not terribly well
    32.1 --- a/xen-2.4.16/include/asm-i386/io_apic.h	Tue Feb 11 17:54:17 2003 +0000
    32.2 +++ b/xen-2.4.16/include/asm-i386/io_apic.h	Thu Feb 13 15:58:34 2003 +0000
    32.3 @@ -15,7 +15,8 @@
    32.4  #define APIC_MISMATCH_DEBUG
    32.5  
    32.6  #define IO_APIC_BASE(idx) \
    32.7 -		((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
    32.8 +		((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
    32.9 +		+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
   32.10  
   32.11  /*
   32.12   * The structure of the IO-APIC:
   32.13 @@ -96,7 +97,7 @@ extern struct mpc_config_ioapic mp_ioapi
   32.14  extern int mp_irq_entries;
   32.15  
   32.16  /* MP IRQ source entries */
   32.17 -extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
   32.18 +extern struct mpc_config_intsrc *mp_irqs;
   32.19  
   32.20  /* non-0 if default (table-less) MP configuration */
   32.21  extern int mpc_default_type;
   32.22 @@ -132,8 +133,7 @@ static inline void io_apic_sync(unsigned
   32.23  }
   32.24  
   32.25  /* 1 if "noapic" boot option passed */
   32.26 -//extern int skip_ioapic_setup;
   32.27 -#define skip_ioapic_setup 0
   32.28 +extern int skip_ioapic_setup;
   32.29  
   32.30  /*
   32.31   * If we use the IO-APIC for IRQ routing, disable automatic
    33.1 --- a/xen-2.4.16/include/asm-i386/mpspec.h	Tue Feb 11 17:54:17 2003 +0000
    33.2 +++ b/xen-2.4.16/include/asm-i386/mpspec.h	Thu Feb 13 15:58:34 2003 +0000
    33.3 @@ -1,6 +1,7 @@
    33.4  #ifndef __ASM_MPSPEC_H
    33.5  #define __ASM_MPSPEC_H
    33.6  
    33.7 +
    33.8  /*
    33.9   * Structure definitions for SMP machines following the
   33.10   * Intel Multiprocessing Specification 1.1 and 1.4.
   33.11 @@ -13,8 +14,15 @@
   33.12   
   33.13  #define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
   33.14  
   33.15 -/* Maximum of 16 APICs with the current APIC ID architecture. */
   33.16 +/*
   33.17 + * a maximum of 16 APICs with the current APIC ID architecture.
   33.18 + * xAPICs can have up to 256.  SAPICs have 16 ID bits.
   33.19 + */
   33.20 +#ifdef CONFIG_X86_CLUSTERED_APIC
   33.21 +#define MAX_APICS 256
   33.22 +#else
   33.23  #define MAX_APICS 16
   33.24 +#endif
   33.25  
   33.26  #define MAX_MPC_ENTRY 1024
   33.27  
   33.28 @@ -178,7 +186,11 @@ struct mpc_config_translation
   33.29   *	7	2 CPU MCA+PCI
   33.30   */
   33.31  
   33.32 +#ifdef CONFIG_MULTIQUAD
   33.33 +#define MAX_IRQ_SOURCES 512
   33.34 +#else /* !CONFIG_MULTIQUAD */
   33.35  #define MAX_IRQ_SOURCES 256
   33.36 +#endif /* CONFIG_MULTIQUAD */
   33.37  
   33.38  #define MAX_MP_BUSSES 32
   33.39  enum mp_bustype {
   33.40 @@ -187,8 +199,11 @@ enum mp_bustype {
   33.41  	MP_BUS_PCI,
   33.42  	MP_BUS_MCA
   33.43  };
   33.44 -extern int mp_bus_id_to_type [MAX_MP_BUSSES];
   33.45 -extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
   33.46 +extern int *mp_bus_id_to_type;
   33.47 +extern int *mp_bus_id_to_node;
   33.48 +extern int *mp_bus_id_to_local;
   33.49 +extern int *mp_bus_id_to_pci_bus;
   33.50 +extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
   33.51  
   33.52  extern unsigned int boot_cpu_physical_apicid;
   33.53  extern unsigned long phys_cpu_present_map;
   33.54 @@ -197,11 +212,9 @@ extern void find_smp_config (void);
   33.55  extern void get_smp_config (void);
   33.56  extern int nr_ioapics;
   33.57  extern int apic_version [MAX_APICS];
   33.58 -extern int mp_bus_id_to_type [MAX_MP_BUSSES];
   33.59  extern int mp_irq_entries;
   33.60 -extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
   33.61 +extern struct mpc_config_intsrc *mp_irqs;
   33.62  extern int mpc_default_type;
   33.63 -extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
   33.64  extern int mp_current_pci_id;
   33.65  extern unsigned long mp_lapic_addr;
   33.66  extern int pic_mode;
    34.1 --- a/xen-2.4.16/include/asm-i386/processor.h	Tue Feb 11 17:54:17 2003 +0000
    34.2 +++ b/xen-2.4.16/include/asm-i386/processor.h	Thu Feb 13 15:58:34 2003 +0000
    34.3 @@ -358,16 +358,22 @@ struct thread_struct {
    34.4      trap_info_t         traps[256];
    34.5  };
    34.6  
    34.7 +#define IDT_ENTRIES 256
    34.8 +extern struct desc_struct idt_table[];
    34.9 +extern struct desc_struct *idt_tables[];
   34.10 +
   34.11  #define SET_DEFAULT_FAST_TRAP(_p) \
   34.12      (_p)->fast_trap_idx = 0x20;   \
   34.13      (_p)->fast_trap_desc.a = 0;   \
   34.14      (_p)->fast_trap_desc.b = 0;
   34.15  
   34.16  #define CLEAR_FAST_TRAP(_p) \
   34.17 -    (memset(idt_table + (_p)->fast_trap_idx, 0, 8))
   34.18 +    (memset(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
   34.19 +     0, 8))
   34.20  
   34.21  #define SET_FAST_TRAP(_p)   \
   34.22 -    (memcpy(idt_table + (_p)->fast_trap_idx, &((_p)->fast_trap_desc), 8))
   34.23 +    (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
   34.24 +     &((_p)->fast_trap_desc), 8))
   34.25  
   34.26  #define INIT_THREAD  {						\
   34.27  	sizeof(idle0_stack) + (long) &idle0_stack, /* esp0 */   \
    35.1 --- a/xen-2.4.16/include/asm-i386/smpboot.h	Tue Feb 11 17:54:17 2003 +0000
    35.2 +++ b/xen-2.4.16/include/asm-i386/smpboot.h	Thu Feb 13 15:58:34 2003 +0000
    35.3 @@ -1,13 +1,82 @@
    35.4  #ifndef __ASM_SMPBOOT_H
    35.5  #define __ASM_SMPBOOT_H
    35.6  
    35.7 -#define TRAMPOLINE_LOW phys_to_virt(0x467)
    35.8 -#define TRAMPOLINE_HIGH phys_to_virt(0x469)
    35.9 +/*emum for clustered_apic_mode values*/
   35.10 +enum{
   35.11 +	CLUSTERED_APIC_NONE = 0,
   35.12 +	CLUSTERED_APIC_XAPIC,
   35.13 +	CLUSTERED_APIC_NUMAQ
   35.14 +};
   35.15 +
   35.16 +#ifdef CONFIG_X86_CLUSTERED_APIC
   35.17 +extern unsigned int apic_broadcast_id;
   35.18 +extern unsigned char clustered_apic_mode;
   35.19 +extern unsigned char esr_disable;
   35.20 +extern unsigned char int_delivery_mode;
   35.21 +extern unsigned int int_dest_addr_mode;
   35.22 +extern int cyclone_setup(char*);
   35.23  
   35.24 -#define boot_cpu_apicid boot_cpu_physical_apicid
   35.25 +static inline void detect_clustered_apic(char* oem, char* prod)
   35.26 +{
   35.27 +	/*
   35.28 +	 * Can't recognize Summit xAPICs at present, so use the OEM ID.
   35.29 +	 */
   35.30 +	if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){
   35.31 +		clustered_apic_mode = CLUSTERED_APIC_XAPIC;
   35.32 +		apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
   35.33 +		int_dest_addr_mode = APIC_DEST_PHYSICAL;
   35.34 +		int_delivery_mode = dest_Fixed;
   35.35 +		esr_disable = 1;
   35.36 +		/*Start cyclone clock*/
   35.37 +		cyclone_setup(0);
   35.38 +	}
   35.39 +	else if (!strncmp(oem, "IBM NUMA", 8)){
   35.40 +		clustered_apic_mode = CLUSTERED_APIC_NUMAQ;
   35.41 +		apic_broadcast_id = APIC_BROADCAST_ID_APIC;
   35.42 +		int_dest_addr_mode = APIC_DEST_LOGICAL;
   35.43 +		int_delivery_mode = dest_LowestPrio;
   35.44 +		esr_disable = 1;
   35.45 +	}
   35.46 +}
   35.47 +#define	INT_DEST_ADDR_MODE (int_dest_addr_mode)
   35.48 +#define	INT_DELIVERY_MODE (int_delivery_mode)
   35.49 +#else /* CONFIG_X86_CLUSTERED_APIC */
   35.50 +#define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
   35.51 +#define clustered_apic_mode (CLUSTERED_APIC_NONE)
   35.52 +#define esr_disable (0)
   35.53 +#define detect_clustered_apic(x,y)
   35.54 +#define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL)	/* logical delivery */
   35.55 +#define INT_DELIVERY_MODE (dest_LowestPrio)
   35.56 +#endif /* CONFIG_X86_CLUSTERED_APIC */
   35.57 +#define BAD_APICID 0xFFu
   35.58  
   35.59 -/* How to map from the cpu_present_map. */
   35.60 -#define cpu_present_to_apicid(apicid) (apicid)
   35.61 +#define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
   35.62 +#define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
   35.63 +
   35.64 +#define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid)
   35.65 +
   35.66 +extern unsigned char raw_phys_apicid[NR_CPUS];
   35.67 +
   35.68 +/*
   35.69 + * How to map from the cpu_present_map
   35.70 + */
   35.71 +static inline int cpu_present_to_apicid(int mps_cpu)
   35.72 +{
   35.73 +	if (clustered_apic_mode == CLUSTERED_APIC_XAPIC)
   35.74 +		return raw_phys_apicid[mps_cpu];
   35.75 +	if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
   35.76 +		return (mps_cpu/4)*16 + (1<<(mps_cpu%4));
   35.77 +	return mps_cpu;
   35.78 +}
   35.79 +
   35.80 +static inline unsigned long apicid_to_phys_cpu_present(int apicid)
   35.81 +{
   35.82 +	if(clustered_apic_mode)
   35.83 +		return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3));
   35.84 +	return 1UL << apicid;
   35.85 +}
   35.86 +
   35.87 +#define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) )
   35.88  
   35.89  /*
   35.90   * Mappings between logical cpu number and logical / physical apicid
   35.91 @@ -22,7 +91,31 @@ extern volatile int cpu_2_physical_apici
   35.92  #define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu]
   35.93  #define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
   35.94  #define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu]
   35.95 +#ifdef CONFIG_MULTIQUAD			/* use logical IDs to bootstrap */
   35.96 +#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
   35.97 +#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu]
   35.98 +#else /* !CONFIG_MULTIQUAD */		/* use physical IDs to bootstrap */
   35.99  #define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
  35.100  #define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu]
  35.101 +#endif /* CONFIG_MULTIQUAD */
  35.102  
  35.103 +#ifdef CONFIG_X86_CLUSTERED_APIC
  35.104 +static inline int target_cpus(void)
  35.105 +{
  35.106 +	static int cpu;
  35.107 +	switch(clustered_apic_mode){
  35.108 +		case CLUSTERED_APIC_NUMAQ:
  35.109 +			/* Broadcast intrs to local quad only. */
  35.110 +			return APIC_BROADCAST_ID_APIC;
  35.111 +		case CLUSTERED_APIC_XAPIC:
  35.112 +			/*round robin the interrupts*/
  35.113 +			cpu = (cpu+1)%smp_num_cpus;
  35.114 +			return cpu_to_physical_apicid(cpu);
  35.115 +		default:
  35.116 +	}
  35.117 +	return cpu_online_map;
  35.118 +}
  35.119 +#else
  35.120 +#define target_cpus() (0x01)
  35.121  #endif
  35.122 +#endif
    36.1 --- a/xen-2.4.16/include/hypervisor-ifs/block.h	Tue Feb 11 17:54:17 2003 +0000
    36.2 +++ b/xen-2.4.16/include/hypervisor-ifs/block.h	Thu Feb 13 15:58:34 2003 +0000
    36.3 @@ -6,35 +6,80 @@
    36.4   * These are the ring data structures for buffering messages between 
    36.5   * the hypervisor and guestos's.  
    36.6   *
    36.7 - * For now we'll start with our own rings for the block IO code instead
    36.8 - * of using the network rings.  Hopefully, this will give us additional
    36.9 - * flexibility in the future should we choose to move away from a 
   36.10 - * ring producer consumer communication model.
   36.11   */
   36.12  
   36.13  #ifndef __BLOCK_H__
   36.14  #define __BLOCK_H__
   36.15  
   36.16 -typedef struct blk_tx_entry_st {
   36.17 -	unsigned long addr; /* virtual address */
   36.18 -	unsigned long size; /* in bytes */
   36.19 -} blk_tx_entry_t;
   36.20 +#include <linux/kdev_t.h>
   36.21 +
   36.22 +/* the first four definitions match fs.h */
   36.23 +#define XEN_BLOCK_READ  0
   36.24 +#define XEN_BLOCK_WRITE 1
   36.25 +#define XEN_BLOCK_READA 2                                /* currently unused */
   36.26 +#define XEN_BLOCK_SPECIAL 4                              /* currently unused */
   36.27 +#define XEN_BLOCK_PROBE 8      /* determine io configuration from hypervisor */
   36.28 +#define XEN_BLOCK_DEBUG 16                                          /* debug */
   36.29 +
   36.30 +#define XEN_BLOCK_SYNC  2
   36.31 +#define XEN_BLOCK_ASYNC 3
   36.32 +
   36.33 +#define XEN_BLOCK_MAX_DOMAINS 32  /* NOTE: FIX THIS. VALUE SHOULD COME FROM? */
   36.34 +
   36.35 +#define BLK_TX_RING_SIZE 256
   36.36 +#define BLK_RX_RING_SIZE 256
   36.37 +
   36.38 +#define BLK_TX_RING_MAX_ENTRIES (BLK_TX_RING_SIZE - 2)
   36.39 +#define BLK_RX_RING_MAX_ENTRIES (BLK_RX_RING_SIZE - 2)
   36.40  
   36.41 -typedef struct blk_rx_entry_st {
   36.42 -	unsigned long addr; /* virtual address */
   36.43 -	unsigned long size; /* in bytes */
   36.44 -} blk_rx_entry_t;
   36.45 +#define BLK_TX_RING_INC(_i)    (((_i)+1) & (BLK_TX_RING_SIZE-1))
   36.46 +#define BLK_RX_RING_INC(_i)    (((_i)+1) & (BLK_RX_RING_SIZE-1))
   36.47 +#define BLK_TX_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_TX_RING_SIZE-1))
   36.48 +#define BLK_RX_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_RX_RING_SIZE-1))
   36.49  
   36.50 -typedef struct blk_ring_st {
   36.51 -	blk_tx_entry_t	*tx_ring;
   36.52 -	unsigned int	tx_prod, tx_cons, tx_event;
   36.53 -	unsigned int 	tx_ring_size;
   36.54 +typedef struct blk_ring_entry 
   36.55 +{
   36.56 +  void *          id;                   /* for guest os use; used for the bh */
   36.57 +  int             priority;         /* orig sched pri, SYNC or ASYNC for now */
   36.58 +  int             operation;            /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
   36.59 +  char *          buffer;
   36.60 +  unsigned long   block_number;                              /* block number */
   36.61 +  unsigned short  block_size;                                  /* block size */
   36.62 +  kdev_t          device;
   36.63 +  unsigned long   sector_number;             /* real buffer location on disk */
   36.64 +} blk_ring_entry_t;
   36.65  
   36.66 -	blk_rx_entry_t	*rx_ring;
   36.67 -	unsigned int	rx_prod, rx_cons, rx_event;
   36.68 -	unsigned int	rx_ring_size;
   36.69 +typedef struct blk_ring_st 
   36.70 +{
   36.71 +  blk_ring_entry_t *tx_ring;
   36.72 +  unsigned int      tx_prod, tx_cons;
   36.73 +  unsigned int 	    tx_ring_size;
   36.74 +
   36.75 +  blk_ring_entry_t *rx_ring;
   36.76 +  unsigned int      rx_prod, rx_cons;
   36.77 +  unsigned int	    rx_ring_size;
   36.78  } blk_ring_t;
   36.79  
   36.80 -int blk_create_ring(int domain, unsigned long ptr);
   36.81 +#define MAX_XEN_DISK_COUNT 100
   36.82 +
   36.83 +#define XEN_DISK_IDE  1
   36.84 +#define XEN_DISK_SCSI 2
   36.85 +
   36.86 +typedef struct xen_disk                                     /* physical disk */
   36.87 +{
   36.88 +  int           type;                                           /* disk type */
   36.89 +  unsigned long capacity;
   36.90 +  unsigned char heads;                               /* hdreg.h::hd_geometry */
   36.91 +  unsigned char sectors;                             /* hdreg.h::hd_geometry */
   36.92 +  unsigned int  cylinders;                       /* hdreg.h::hd_big_geometry */
   36.93 +  unsigned long start;                               /* hdreg.h::hd_geometry */
   36.94 +  void *        gendisk;                               /* struct gendisk ptr */
   36.95 +} xen_disk_t;
   36.96 +
   36.97 +typedef struct xen_disk_info
   36.98 +{
   36.99 +  int         count; /* number of subsequent xen_disk_t structures to follow */
  36.100 +  xen_disk_t  disks[100];
  36.101 +} xen_disk_info_t;
  36.102  
  36.103  #endif
    37.1 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Tue Feb 11 17:54:17 2003 +0000
    37.2 +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Thu Feb 13 15:58:34 2003 +0000
    37.3 @@ -85,10 +85,11 @@ typedef struct
    37.4  #define __HYPERVISOR_exit                  8
    37.5  #define __HYPERVISOR_dom0_op               9
    37.6  #define __HYPERVISOR_network_op           10
    37.7 -#define __HYPERVISOR_set_debugreg         11
    37.8 -#define __HYPERVISOR_get_debugreg         12
    37.9 -#define __HYPERVISOR_update_descriptor    13
   37.10 -#define __HYPERVISOR_set_fast_trap        14
   37.11 +#define __HYPERVISOR_block_io_op          11
   37.12 +#define __HYPERVISOR_set_debugreg         12
   37.13 +#define __HYPERVISOR_get_debugreg         13
   37.14 +#define __HYPERVISOR_update_descriptor    14
   37.15 +#define __HYPERVISOR_set_fast_trap        15
   37.16  
   37.17  #define TRAP_INSTR "int $0x82"
   37.18  
    38.1 --- a/xen-2.4.16/include/xeno/blkdev.h	Tue Feb 11 17:54:17 2003 +0000
    38.2 +++ b/xen-2.4.16/include/xeno/blkdev.h	Thu Feb 13 15:58:34 2003 +0000
    38.3 @@ -85,6 +85,7 @@ struct buffer_head {
    38.4  
    38.5          struct inode *       b_inode;
    38.6          struct list_head     b_inode_buffers;   /* doubly linked list of inode dirty buffers */
    38.7 +        void *b_xen_request;                        /* xen request structure */
    38.8  };
    38.9  
   38.10  typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
    39.1 --- a/xen-2.4.16/include/xeno/config.h	Tue Feb 11 17:54:17 2003 +0000
    39.2 +++ b/xen-2.4.16/include/xeno/config.h	Thu Feb 13 15:58:34 2003 +0000
    39.3 @@ -29,6 +29,7 @@
    39.4  #define CONFIG_IDEDMA_PCI_AUTO 1
    39.5  #define CONFIG_IDEDMA_AUTO 1
    39.6  #define CONFIG_BLK_DEV_IDE_MODES 1
    39.7 +#define CONFIG_BLK_DEV_PIIX 1
    39.8  
    39.9  #define CONFIG_SCSI 1
   39.10  #define CONFIG_BLK_DEV_SD 1
    40.1 --- a/xen-2.4.16/include/xeno/sched.h	Tue Feb 11 17:54:17 2003 +0000
    40.2 +++ b/xen-2.4.16/include/xeno/sched.h	Thu Feb 13 15:58:34 2003 +0000
    40.3 @@ -1,4 +1,3 @@
    40.4 -
    40.5  #ifndef _LINUX_SCHED_H
    40.6  #define _LINUX_SCHED_H
    40.7  
    40.8 @@ -49,6 +48,7 @@ extern struct mm_struct init_mm;
    40.9  #define _HYP_EVENT_NEED_RESCHED 0
   40.10  #define _HYP_EVENT_NET_RX       1
   40.11  #define _HYP_EVENT_DIE          2
   40.12 +#define _HYP_EVENT_BLK_RX       3
   40.13  
   40.14  #define PF_DONEFPUINIT  0x1  /* Has the FPU been initialised for this task? */
   40.15  #define PF_USEDFPU      0x2  /* Has this task used the FPU since last save? */
    41.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile	Tue Feb 11 17:54:17 2003 +0000
    41.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/Makefile	Thu Feb 13 15:58:34 2003 +0000
    41.3 @@ -1,3 +1,3 @@
    41.4  O_TARGET := blk.o
    41.5 -obj-y := block.o
    41.6 +obj-y := xl_block.o xl_block_test.o
    41.7  include $(TOPDIR)/Rules.make
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block.c	Thu Feb 13 15:58:34 2003 +0000
    42.3 @@ -0,0 +1,827 @@
    42.4 +#include <linux/config.h>
    42.5 +#include <linux/module.h>
    42.6 +
    42.7 +#include <linux/kernel.h>
    42.8 +#include <linux/sched.h>
    42.9 +#include <linux/slab.h>
   42.10 +#include <linux/string.h>
   42.11 +#include <linux/errno.h>
   42.12 +
   42.13 +#include <linux/fs.h>
   42.14 +#include <linux/hdreg.h>                               /* HDIO_GETGEO, et al */
   42.15 +#include <linux/blkdev.h>
   42.16 +#include <linux/major.h>
   42.17 +
   42.18 +/* NOTE: this is drive independent, so no inclusion of ide.h */
   42.19 +
   42.20 +#include <asm/hypervisor-ifs/block.h>
   42.21 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   42.22 +#include <asm/io.h>
   42.23 +#include <asm/uaccess.h>                                       /* put_user() */
   42.24 +
   42.25 +#define MAJOR_NR XLBLK_MAJOR   /* force defns in blk.h, must preceed include */
   42.26 +static int xlblk_major = XLBLK_MAJOR;
   42.27 +
   42.28 +#include <linux/blk.h>           /* must come after definition of MAJOR_NR!! */
   42.29 +
   42.30 +/* instead of including linux/ide.h to pick up the definitiong of byte
   42.31 + * (and consequently screwing up blk.h, we'll just copy the definition */
   42.32 +typedef unsigned char	byte; 
   42.33 +
   42.34 +void xlblk_ide_register_disk(int, unsigned long);
   42.35 +
   42.36 +#define XLBLK_MAX 2                                        /* very arbitrary */
   42.37 +#define XLBLK_MAJOR_NAME "blk"
   42.38 +#define IDE_PARTN_BITS 6                           /* from ide.h::PARTN_BITS */
   42.39 +#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1)     /* from ide.h::PARTN_MASK */
   42.40 +static int xlblk_blk_size[XLBLK_MAX];
   42.41 +static int xlblk_blksize_size[XLBLK_MAX];
   42.42 +static int xlblk_hardsect_size[XLBLK_MAX];
   42.43 +static int xlblk_read_ahead[XLBLK_MAX];
   42.44 +static int xlblk_max_sectors[XLBLK_MAX];
   42.45 +
   42.46 +#define XLBLK_RX_IRQ _EVENT_BLK_RX
   42.47 +#define XLBLK_TX_IRQ _EVENT_BLK_TX
   42.48 +
   42.49 +typedef struct xlblk_device
   42.50 +{
   42.51 +  struct buffer_head *bh;
   42.52 +  unsigned int tx_count;                  /* number of used slots in tx ring */
   42.53 +} xlblk_device_t;
   42.54 +
   42.55 +xlblk_device_t xlblk_device;
   42.56 +
   42.57 +/* USE_REQUEST_QUEUE = 1  use (multiple) request queues
   42.58 + *                   = 0  don't use IO request queue 
   42.59 + */
   42.60 +#define USE_REQUEST_QUEUE 1
   42.61 +
   42.62 +#define XLBLK_DEBUG       0
   42.63 +#define XLBLK_DEBUG_IOCTL 0
   42.64 +
   42.65 +/* 
   42.66 + * disk management
   42.67 + */
   42.68 +
   42.69 +xen_disk_info_t xen_disk_info;
   42.70 +
   42.71 +/* some declarations */
   42.72 +void hypervisor_request(void *         id,
   42.73 +			int            operation,
   42.74 +			char *         buffer,
   42.75 +			unsigned long  block_number,
   42.76 +			unsigned short block_size,
   42.77 +			kdev_t         device,
   42.78 +			int            mode);
   42.79 +
   42.80 +
   42.81 +/* ------------------------------------------------------------------------
   42.82 + */
   42.83 +
   42.84 +static int xenolinux_block_open(struct inode *inode, struct file *filep)
   42.85 +{
   42.86 +  if (XLBLK_DEBUG) {
   42.87 +    printk (KERN_ALERT "xenolinux_block_open\n"); }
   42.88 +  return 0;
   42.89 +}
   42.90 +
   42.91 +static int xenolinux_block_release(struct inode *inode, struct file *filep)
   42.92 +{
   42.93 +  if (XLBLK_DEBUG) {
   42.94 +    printk (KERN_ALERT "xenolinux_block_release\n"); }
   42.95 +  return 0;
   42.96 +}
   42.97 +
   42.98 +static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
   42.99 +			  unsigned command, unsigned long argument)
  42.100 +{
  42.101 +  int minor_dev;
  42.102 +
  42.103 +  if (XLBLK_DEBUG_IOCTL)
  42.104 +  {
  42.105 +    printk (KERN_ALERT "xenolinux_block_ioctl\n"); 
  42.106 +  }
  42.107 +
  42.108 +  /* check permissions */
  42.109 +  if (!capable(CAP_SYS_ADMIN)) return -EPERM;
  42.110 +  if (!inode)                  return -EINVAL;
  42.111 +  minor_dev = MINOR(inode->i_rdev);
  42.112 +  if (minor_dev >= XLBLK_MAX)  return -ENODEV;
  42.113 +
  42.114 +  if (XLBLK_DEBUG_IOCTL)
  42.115 +  {
  42.116 +    printk (KERN_ALERT  
  42.117 +	    "   command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
  42.118 +	    command, (long) argument, minor_dev); 
  42.119 +  }
  42.120 +  
  42.121 +  switch (command)
  42.122 +  {
  42.123 +    case BLKGETSIZE :
  42.124 +    {
  42.125 +      if (XLBLK_DEBUG_IOCTL)
  42.126 +      {
  42.127 +	printk (KERN_ALERT
  42.128 +		"   BLKGETSIZE: %x %lx\n", BLKGETSIZE, 
  42.129 +		(long) xen_disk_info.disks[0].capacity); 
  42.130 +      }
  42.131 +      return put_user(xen_disk_info.disks[0].capacity, 
  42.132 +		      (unsigned long *) argument);
  42.133 +    }
  42.134 +    case BLKRRPART :
  42.135 +    {
  42.136 +      if (XLBLK_DEBUG_IOCTL) {
  42.137 +	printk (KERN_ALERT "   BLKRRPART: %x\n", BLKRRPART); }
  42.138 +      break;
  42.139 +    }
  42.140 +    case BLKSSZGET :
  42.141 +    {
  42.142 +      if (XLBLK_DEBUG_IOCTL) {
  42.143 +	printk (KERN_ALERT "   BLKSSZGET: %x 0x%x\n", BLKSSZGET,
  42.144 +		xlblk_hardsect_size[minor_dev]); }
  42.145 +      return xlblk_hardsect_size[minor_dev]; 
  42.146 +    }
  42.147 +    case HDIO_GETGEO :
  42.148 +    {
  42.149 +      struct hd_geometry *geo = (struct hd_geometry *)argument;
  42.150 +
  42.151 +      if (XLBLK_DEBUG_IOCTL) {
  42.152 +	printk (KERN_ALERT "   HDIO_GETGEO: %x\n", HDIO_GETGEO); }
  42.153 +
  42.154 +      if (!argument) return -EINVAL;
  42.155 +      /*
  42.156 +      if (put_user(0x80,  (byte *)&geo->heads)) return -EFAULT;
  42.157 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  42.158 +      if (put_user(0x20b, (unsigned short *) &geo->cylinders)) return -EFAULT;
  42.159 +      */
  42.160 +      if (put_user(0x00,  (unsigned long *) &geo->start)) return -EFAULT;
  42.161 +      if (put_user(0xff,  (byte *)&geo->heads)) return -EFAULT;
  42.162 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  42.163 +      if (put_user(0x106, (unsigned short *) &geo->cylinders)) return -EFAULT;
  42.164 +
  42.165 +      return 0;
  42.166 +    }
  42.167 +    case HDIO_GETGEO_BIG :
  42.168 +    {
  42.169 +      struct hd_big_geometry *geo = (struct hd_big_geometry *) argument;
  42.170 +
  42.171 +      if (XLBLK_DEBUG_IOCTL) {
  42.172 +	printk (KERN_ALERT "   HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); }
  42.173 +
  42.174 +      if (!argument) return -EINVAL;
  42.175 +      /*
  42.176 +      if (put_user(0x80,  (byte *)&geo->heads))   return -EFAULT;
  42.177 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  42.178 +      if (put_user(0x20b, (unsigned int *) &geo->cylinders)) return -EFAULT;
  42.179 +      */
  42.180 +      if (put_user(0x00,  (unsigned long *) &geo->start))  return -EFAULT;
  42.181 +      if (put_user(0xff,  (byte *)&geo->heads))   return -EFAULT;
  42.182 +      if (put_user(0x3f,  (byte *)&geo->sectors)) return -EFAULT;
  42.183 +      if (put_user(0x106, (unsigned int *) &geo->cylinders)) return -EFAULT;
  42.184 +
  42.185 +      return 0;
  42.186 +    }
  42.187 +    default :
  42.188 +    {
  42.189 +      if (XLBLK_DEBUG_IOCTL) {
  42.190 +	printk (KERN_ALERT "   eh? unknown ioctl\n"); }
  42.191 +      break;
  42.192 +    }
  42.193 +  }
  42.194 +
  42.195 +  return 0;
  42.196 +}
  42.197 +
  42.198 +static int xenolinux_block_check(kdev_t dev)
  42.199 +{
  42.200 +  if (XLBLK_DEBUG) {
  42.201 +    printk (KERN_ALERT "xenolinux_block_check\n"); }
  42.202 +  return 0;
  42.203 +}
  42.204 +
  42.205 +static int xenolinux_block_revalidate(kdev_t dev)
  42.206 +{
  42.207 +  if (XLBLK_DEBUG) {
  42.208 +    printk (KERN_ALERT "xenolinux_block_revalidate\n"); }
  42.209 +  return 0;
  42.210 +}
  42.211 +
  42.212 +/*
  42.213 + * hypervisor_request
  42.214 + *
  42.215 + * request block io 
  42.216 + * 
  42.217 + * id: for guest use only.
  42.218 + * operation: XEN_BLOCK_READ, XEN_BLOCK_WRITE or XEN_BLOCK_PROBE
  42.219 + * buffer: buffer to read/write into. this should be a
  42.220 + *   virtual address in the guest os.
  42.221 + * block_number:  block to read
  42.222 + * block_size:  size of each block
  42.223 + * device:  ide/hda is 768 or 0x300
  42.224 + * mode: XEN_BLOCK_SYNC or XEN_BLOCK_ASYNC.  async requests
  42.225 + *   will queue until a sync request is issued.
  42.226 + */
  42.227 +
  42.228 +void hypervisor_request(void *         id,
  42.229 +			int            operation,
  42.230 +			char *         buffer,
  42.231 +			unsigned long  block_number,
  42.232 +			unsigned short block_size,
  42.233 +			kdev_t         device,
  42.234 +			int            mode)
  42.235 +{
  42.236 +  blk_ring_t *blk_ring = start_info.blk_ring;
  42.237 +  int position;
  42.238 +  void *buffer_pa, *buffer_ma; 
  42.239 +  kdev_t phys_device = (kdev_t) 0;
  42.240 +  unsigned long sector_number = 0;
  42.241 +
  42.242 +#if 0
  42.243 +  printk(KERN_ALERT "[%x]", id); 
  42.244 +  printk (KERN_ALERT
  42.245 +	  "xlblk_req: id:%p op:%d, bf:%p, blk:%lu, sz:%u, dev:%x\n",
  42.246 +	  id, operation, buffer, block_number, block_size, device);
  42.247 +#endif
  42.248 +
  42.249 +  /* XXX SMH: now need to convert guest virtual address to machine address */
  42.250 +  buffer_pa = (void *)virt_to_phys((unsigned long)buffer); 
  42.251 +  buffer_ma = (void *)phys_to_machine((unsigned long)buffer_pa); 
  42.252 +
  42.253 +#if 0
  42.254 +  printk(KERN_ALERT "va %p => pa %p => ma %p\n", buffer, buffer_pa, buffer_ma);
  42.255 +#endif
  42.256 +
  42.257 +  if (operation == XEN_BLOCK_PROBE)
  42.258 +  {
  42.259 +    phys_device = (kdev_t) 0;
  42.260 +    sector_number = 0;
  42.261 +  }
  42.262 +  else if (operation == XEN_BLOCK_READ || operation == XEN_BLOCK_WRITE)
  42.263 +  {
  42.264 +    /*
  42.265 +     * map logial major device to the physical device number 
  42.266 +     *
  42.267 +     *           XLBLK_MAJOR -> IDE0_MAJOR  (123 -> 3)
  42.268 +     */
  42.269 +    if (MAJOR(device) == XLBLK_MAJOR)
  42.270 +    {
  42.271 +      phys_device = MKDEV(IDE0_MAJOR, 0);
  42.272 +    }
  42.273 +    else
  42.274 +    {
  42.275 +      printk (KERN_ALERT
  42.276 +	      "error: xl_block::hypervisor_request: unknown device [0x%x]\n", 
  42.277 +	      device);
  42.278 +      BUG();
  42.279 +    }
  42.280 +  
  42.281 +    /*
  42.282 +     * compute real buffer location on disk
  42.283 +     * (from ll_rw_block.c::submit_bh)
  42.284 +     */
  42.285 +    {
  42.286 +      int idx = 0;
  42.287 +
  42.288 +      struct gendisk *gd = (struct gendisk *) xen_disk_info.disks[idx].gendisk;
  42.289 +      unsigned int minor = MINOR(device);
  42.290 +
  42.291 +      sector_number = block_number /* * block_size >> 9 */;
  42.292 +
  42.293 +      if (gd != NULL)                     /* if we have a partition table... */
  42.294 +      {
  42.295 +	sector_number += gd->part[minor & IDE_PARTN_MASK].start_sect;
  42.296 +      }
  42.297 +    }
  42.298 +  }
  42.299 +
  42.300 +  /*
  42.301 +   * CHECK TO SEE IF THERE IS SPACE IN THE RING
  42.302 +   */
  42.303 +  if (BLK_TX_RING_INC(blk_ring->tx_prod) == blk_ring->tx_cons)
  42.304 +  {
  42.305 +    printk (KERN_ALERT "hypervisor_request: tx_cons: %d, tx_prod:%d",
  42.306 +	    blk_ring->tx_cons, blk_ring->tx_prod);
  42.307 +  }
  42.308 +
  42.309 +  /* fill out a communications ring structure 
  42.310 +     and then trap into the hypervisor */
  42.311 +  position = blk_ring->tx_prod;
  42.312 +  blk_ring->tx_ring[position].id            = id;
  42.313 +  blk_ring->tx_ring[position].priority      = mode;
  42.314 +  blk_ring->tx_ring[position].operation     = operation;
  42.315 +  blk_ring->tx_ring[position].buffer        = buffer_ma;
  42.316 +  blk_ring->tx_ring[position].block_number  = block_number;
  42.317 +  blk_ring->tx_ring[position].block_size    = block_size;
  42.318 +  blk_ring->tx_ring[position].device        = phys_device;
  42.319 +  blk_ring->tx_ring[position].sector_number = sector_number;
  42.320 +
  42.321 +  blk_ring->tx_prod = BLK_TX_RING_INC(blk_ring->tx_prod);
  42.322 +
  42.323 +  if (mode == XEN_BLOCK_SYNC)
  42.324 +  {
  42.325 +    /* trap into hypervisor */
  42.326 +    HYPERVISOR_block_io_op();
  42.327 +  }
  42.328 +  else if (mode == XEN_BLOCK_ASYNC)
  42.329 +  {
  42.330 +    /* for now, do nothing.  the request will go in the ring and
  42.331 +       the next sync request will trigger the hypervisor to act */
  42.332 +  }
  42.333 +  else
  42.334 +  {
  42.335 +    /* ummm, unknown mode. */
  42.336 +    BUG();
  42.337 +  }
  42.338 +
  42.339 +  return;
  42.340 +}
  42.341 +
  42.342 +
  42.343 +/*
  42.344 + * do_xlblk_request
  42.345 + *
  42.346 + * read a block; request is in a request queue
  42.347 + *
  42.348 + * TO DO: should probably release the io_request_lock and then re-acquire
  42.349 + *        (see LDD p. 338)
  42.350 + */
  42.351 +
  42.352 +static void do_xlblk_request (request_queue_t *rq)
  42.353 +{
  42.354 +  struct request *req;
  42.355 +
  42.356 +  if (XLBLK_DEBUG)
  42.357 +  {
  42.358 +    printk (KERN_ALERT "xlblk.c::do_xlblk_request for '%s'\n", DEVICE_NAME); 
  42.359 +  }
  42.360 +
  42.361 +  while (!QUEUE_EMPTY)
  42.362 +  {
  42.363 +    struct buffer_head *bh;
  42.364 +    unsigned long offset;
  42.365 +    unsigned long length;
  42.366 +    int rw;
  42.367 +
  42.368 +    req = CURRENT;
  42.369 +
  42.370 +    if (XLBLK_DEBUG)
  42.371 +    {
  42.372 +      printk (KERN_ALERT
  42.373 +	      "do_xlblk_request %p: cmd %i, sec %lx, (%li) bh:%p\n",
  42.374 +	      req, req->cmd, req->sector,
  42.375 +	      req->current_nr_sectors, req->bh);
  42.376 +    }
  42.377 +
  42.378 +    /* is there space in the tx ring for this request?
  42.379 +     * if the ring is full, then leave the request in the queue
  42.380 +     *
  42.381 +     * THIS IS A BIT BOGUS SINCE XEN COULD BE UPDATING TX_CONS
  42.382 +     * AT THE SAME TIME
  42.383 +     */
  42.384 +    {
  42.385 +      blk_ring_t *blk_ring = start_info.blk_ring;
  42.386 +      
  42.387 +      if (BLK_RX_RING_INC(blk_ring->tx_prod) == blk_ring->tx_cons)
  42.388 +      {
  42.389 +	printk (KERN_ALERT "OOPS, TX LOOKS FULL  cons: %d  prod: %d\n",
  42.390 +		blk_ring->tx_cons, blk_ring->tx_prod);
  42.391 +	break;
  42.392 +      }
  42.393 +    }
  42.394 +
  42.395 +    req->errors = 0;
  42.396 +    blkdev_dequeue_request(req);
  42.397 +
  42.398 +    bh = req->bh;
  42.399 +
  42.400 +    while (bh)
  42.401 +    {
  42.402 +
  42.403 +    offset = bh->b_rsector << 9;
  42.404 +    length = bh->b_size;
  42.405 +    
  42.406 +    rw = req->cmd;
  42.407 +    if (rw == READA)  rw= READ;
  42.408 +    if ((rw != READ) && (rw != WRITE))
  42.409 +    {
  42.410 +      printk (KERN_ALERT
  42.411 +	      "XenoLinux Virtual Block Device: bad command: %d\n", rw);
  42.412 +      BUG();
  42.413 +    }
  42.414 +
  42.415 +    /*
  42.416 +    if (XLBLK_DEBUG)
  42.417 +    {
  42.418 +      printk (KERN_ALERT "xlblk.c::do_xlblk_request\n");
  42.419 +      printk (KERN_ALERT "  b_blocknr: 0x%lx %ld\n", 
  42.420 +                         bh->b_blocknr, bh->b_blocknr);
  42.421 +      printk (KERN_ALERT "  b_size:    0x%x  %d\n", bh->b_size, bh->b_size);
  42.422 +      printk (KERN_ALERT "  b_dev:     0x%x  %d\n", bh->b_dev, bh->b_dev);
  42.423 +      printk (KERN_ALERT "  b_rsector: 0x%lx %ld\n", 
  42.424 +                         bh->b_rsector, bh->b_rsector);
  42.425 +    }
  42.426 +    */
  42.427 +
  42.428 +    hypervisor_request (req, rw == READ ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
  42.429 +			bh->b_data, bh->b_rsector, bh->b_size, 
  42.430 +			bh->b_dev, XEN_BLOCK_SYNC);
  42.431 +
  42.432 +      bh = bh->b_reqnext;
  42.433 +    }
  42.434 +  }
  42.435 +
  42.436 +  return;
  42.437 +}
  42.438 +
  42.439 +/*
  42.440 + * xenolinux_block_request
  42.441 + *
  42.442 + * read a block without using a request queue
  42.443 + */
  42.444 +
  42.445 +static int xenolinux_block_request(request_queue_t *rq,
  42.446 +				   int rw,
  42.447 +				   struct buffer_head *bh)
  42.448 +{
  42.449 +  unsigned int minor;
  42.450 +  unsigned long offset;
  42.451 +  unsigned long length;
  42.452 +
  42.453 +  if (XLBLK_DEBUG) {
  42.454 +    printk (KERN_ALERT "xlblk.c::xenolinux_block_request: %lx %d %lx\n",
  42.455 +	    (unsigned long) rq, rw, (unsigned long) bh); }
  42.456 +  /*
  42.457 +  printk (KERN_ALERT "xlblk.c::xlblk_request: op:%d bh:%p sect:%lu sz:%u\n",
  42.458 +	  rw,  bh, bh->b_rsector, bh->b_size);
  42.459 +  */
  42.460 +
  42.461 +  minor = MINOR(bh->b_rdev);
  42.462 +
  42.463 +  offset = bh->b_rsector << 9;
  42.464 +  length = bh->b_size;
  42.465 +
  42.466 +  if (rw == READA)  rw= READ;
  42.467 +  if ((rw != READ) && (rw != WRITE))
  42.468 +  {
  42.469 +    printk (KERN_ALERT 
  42.470 +	    "XenoLinux Virtual Block Device: bad command: %d\n", rw);
  42.471 +    goto fail;
  42.472 +  }
  42.473 +
  42.474 +  hypervisor_request (bh, rw == READ ? XEN_BLOCK_READ : XEN_BLOCK_WRITE, 
  42.475 +		      bh->b_data, bh->b_rsector, bh->b_size, 
  42.476 +		      bh->b_dev, XEN_BLOCK_SYNC);
  42.477 +
  42.478 +  return 0;
  42.479 +
  42.480 + fail:
  42.481 +  return 0;
  42.482 +}
  42.483 +
  42.484 +static struct block_device_operations xenolinux_block_fops = 
  42.485 +{
  42.486 +    open:               xenolinux_block_open,
  42.487 +    release:            xenolinux_block_release,
  42.488 +    ioctl:              xenolinux_block_ioctl,
  42.489 +    check_media_change: xenolinux_block_check,
  42.490 +    revalidate:         xenolinux_block_revalidate,
  42.491 +};
  42.492 +
  42.493 +static void xlblk_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
  42.494 +{
  42.495 +  xlblk_device_t *dev = (xlblk_device_t *)dev_id;
  42.496 +  blk_ring_t *blk_ring = start_info.blk_ring;
  42.497 +  struct buffer_head *bh;
  42.498 +  struct request *req;
  42.499 +  int loop;
  42.500 +
  42.501 +  for (loop = blk_ring->rx_cons;
  42.502 +       loop != blk_ring->rx_prod;
  42.503 +       loop = BLK_RX_RING_INC(loop))
  42.504 +  {
  42.505 +    blk_ring_entry_t *bret = &blk_ring->rx_ring[loop];
  42.506 +    void *buffer_pa, *buffer_va; 
  42.507 +
  42.508 +    buffer_pa = machine_to_phys((unsigned long)bret->buffer); 
  42.509 +    buffer_va = phys_to_virt((unsigned long)buffer_pa); 
  42.510 +    
  42.511 +#if 0
  42.512 +    printk(KERN_ALERT "xlblk_rx_int: buffer ma %p => pa %p => va %p\n", 
  42.513 +	   bret->buffer, buffer_pa, buffer_va); 
  42.514 +
  42.515 +
  42.516 +    if (XLBLK_DEBUG)
  42.517 +    {
  42.518 +      printk (KERN_ALERT 
  42.519 +	      "xlblock::xlblk_rx_int [%s]\n",
  42.520 +	      (bret->operation == XEN_BLOCK_READ) ? "read" : "write");
  42.521 +      printk (KERN_ALERT 
  42.522 +	      "   vbuf: %lx, pbuf: %lx, blockno: %lx, size: %x, device %x\n",
  42.523 +	      (unsigned long) buffer_va, (unsigned long) bret->buffer,
  42.524 +	      bret->block_number, bret->block_size, bret->device);
  42.525 +      printk (KERN_ALERT "   bret: %p  bh: %p\n", bret, bret->id); 
  42.526 +    }
  42.527 +
  42.528 +    /*
  42.529 +    printk (KERN_ALERT
  42.530 +	    "xlblk_rx: id:%p op:%d, bf:%p, blk:%lu, sz:%u, dev:%x\n",
  42.531 +	    bret->id, bret->operation, bret->buffer, bret->block_number,
  42.532 +	    bret->block_size, bret->device);
  42.533 +    */
  42.534 +#endif
  42.535 +
  42.536 +    if (USE_REQUEST_QUEUE)
  42.537 +    {
  42.538 +      req = (struct request *)bret->id;
  42.539 +      printk(KERN_ALERT "|%x|", req); 
  42.540 +
  42.541 +      if (!end_that_request_first(req, 1, "NAME"))
  42.542 +      {
  42.543 +	blkdev_dequeue_request(req);
  42.544 +
  42.545 +	/* should be end_that_request_last(req)
  42.546 +	   to wake up waiting processes (with complete) */
  42.547 +	blkdev_release_request(req);
  42.548 +      }
  42.549 +
  42.550 +      /*
  42.551 +	if (XLBLK_DEBUG)
  42.552 +	{
  42.553 +	  int temp;
  42.554 +	  printk(KERN_ALERT 
  42.555 +		 "buff: 0x%p, blkno: 0x%lx, size: 0x%x, device 0x%x [%p]\n",
  42.556 +		 vbuffer, bret->block_number, bret->block_size, bret->device,
  42.557 +		 bh->b_end_io); 
  42.558 +
  42.559 +	  for (temp = 0; temp < bret->block_size; temp++)
  42.560 +	  {
  42.561 +	    if (temp % 16 == 0)       printk ("[%4x]  ", temp);
  42.562 +	    else if (temp % 4 == 0)   printk (" ");
  42.563 +	                              printk ("%02x",
  42.564 +					      vbuffer[temp] & 255);
  42.565 +            if ((temp + 1) % 16 == 0) printk ("\n");
  42.566 +	  }
  42.567 +	  printk ("\n\n");
  42.568 +	}
  42.569 +      */
  42.570 +
  42.571 +#ifdef BOGUS
  42.572 +      req = (struct request *)bret->id;
  42.573 +      while ((bh = req->bh) != NULL)
  42.574 +      {
  42.575 +	req->bh = bh->b_reqnext;
  42.576 +	bh->b_reqnext = NULL;
  42.577 +	bh->b_end_io(bh,1);
  42.578 +      }
  42.579 +      blkdev_release_request(req);
  42.580 +#endif /* BOGUS  */
  42.581 +    }
  42.582 +    else
  42.583 +    {
  42.584 +      bh = (struct buffer_head *)bret->id;
  42.585 +      bh->b_end_io(bh,1);
  42.586 +
  42.587 +      /*
  42.588 +	if (XLBLK_DEBUG)
  42.589 +	{
  42.590 +	  int temp;
  42.591 +#if 0
  42.592 +	  printk(KERN_ALERT 
  42.593 +		 "buff: 0x%p, blkno: 0x%lx, size: 0x%x, device 0x%x [%p]\n",
  42.594 +		 vbuffer, bret->block_number, bret->block_size, bret->device,
  42.595 +		 bh->b_end_io); 
  42.596 +#endif
  42.597 +
  42.598 +	  for (temp = 0; temp < bret->block_size; temp++)
  42.599 +	  {
  42.600 +	    if (temp % 16 == 0)       printk ("[%4x]  ", temp);
  42.601 +	    else if (temp % 4 == 0)   printk (" ");
  42.602 +	                              printk ("%02x",
  42.603 +					      vbuffer[temp] & 255);
  42.604 +            if ((temp + 1) % 16 == 0) printk ("\n");
  42.605 +	  }
  42.606 +	  printk ("\n\n");
  42.607 +	}
  42.608 +      */    
  42.609 +    }
  42.610 +  }
  42.611 +
  42.612 +  blk_ring->rx_cons = loop;
  42.613 +}
  42.614 +
  42.615 +static void xlblk_tx_int(int irq, void *dev_id, struct pt_regs *ptregs)
  42.616 +{
  42.617 +  if (XLBLK_DEBUG) {
  42.618 +    printk (KERN_ALERT "--- xlblock::xlblk_tx_int\n"); }
  42.619 +}
  42.620 +
  42.621 +int __init xlblk_init(void)
  42.622 +{
  42.623 +  blk_ring_t *blk_ring = start_info.blk_ring;
  42.624 +  int loop, error, result;
  42.625 +
  42.626 +  /*
  42.627 +   * initialize memory rings to communicate with hypervisor 
  42.628 +   */
  42.629 +
  42.630 +  if ( blk_ring == NULL ) return -ENOMEM;
  42.631 +
  42.632 +  blk_ring->tx_prod = blk_ring->tx_cons = 0;
  42.633 +  blk_ring->rx_prod = blk_ring->rx_cons = 0;
  42.634 +  blk_ring->tx_ring = NULL;
  42.635 +  blk_ring->rx_ring = NULL;
  42.636 +
  42.637 +  blk_ring->tx_ring = kmalloc(BLK_TX_RING_SIZE * sizeof(blk_ring_entry_t),
  42.638 +			      GFP_KERNEL);
  42.639 +  blk_ring->rx_ring = kmalloc(BLK_RX_RING_SIZE * sizeof(blk_ring_entry_t),
  42.640 +			      GFP_KERNEL);
  42.641 +
  42.642 +  if ((blk_ring->tx_ring == NULL) ||
  42.643 +      (blk_ring->rx_ring == NULL))
  42.644 +  {
  42.645 +    printk (KERN_ALERT 
  42.646 +	    "error, could not allocate ring memory for block device\n");
  42.647 +    error = -ENOBUFS;
  42.648 +    goto fail;
  42.649 +  }
  42.650 +
  42.651 +  /*
  42.652 +   * setup soft interrupts to communicate with hypervisor
  42.653 +   */
  42.654 +
  42.655 +  error = request_irq(XLBLK_RX_IRQ, xlblk_rx_int, 0, "xlblk-rx", 
  42.656 +		      &xlblk_device);
  42.657 +  if (error)
  42.658 +  {
  42.659 +    printk(KERN_ALERT "Could not allocate receive interrupt\n");
  42.660 +    goto fail;
  42.661 +  }
  42.662 +
  42.663 +  error = request_irq(XLBLK_TX_IRQ, xlblk_tx_int, 0, "xlblk-tx", 
  42.664 +		      &xlblk_device);
  42.665 +  if (error)
  42.666 +  {
  42.667 +    printk(KERN_ALERT "Could not allocate transmit interrupt\n");
  42.668 +    free_irq(XLBLK_RX_IRQ, &xlblk_device);
  42.669 +    goto fail;
  42.670 +  }
  42.671 +
  42.672 +  /*
  42.673 +   * get information about physical drives
  42.674 +   *
  42.675 +   */
  42.676 +  {
  42.677 +    /* NOTE: this should only occur in domain 0 */
  42.678 +    memset (&xen_disk_info, 0, sizeof(xen_disk_info));
  42.679 +    xen_disk_info.count = 0;
  42.680 +
  42.681 +    hypervisor_request(NULL, XEN_BLOCK_PROBE, (char *) &xen_disk_info,
  42.682 +		       0, 0, (kdev_t) 0, XEN_BLOCK_SYNC);
  42.683 +
  42.684 +    {
  42.685 +      int loop;
  42.686 +      for (loop = 0; loop < xen_disk_info.count; loop++)
  42.687 +      {
  42.688 +	printk (KERN_ALERT "  %2d: type: %d, capacity: %ld\n",
  42.689 +		loop, xen_disk_info.disks[loop].type, 
  42.690 +		xen_disk_info.disks[loop].capacity);
  42.691 +      }
  42.692 +    }
  42.693 +  }
  42.694 +
  42.695 +  /*
  42.696 +   * initialize device driver
  42.697 +   */
  42.698 +
  42.699 +  SET_MODULE_OWNER(&xenolinux_block_fops);
  42.700 +
  42.701 +  result = register_blkdev(xlblk_major, "block", &xenolinux_block_fops);
  42.702 +  if (result < 0)
  42.703 +  {
  42.704 +    printk (KERN_ALERT "xenolinux block: can't get major %d\n", xlblk_major);
  42.705 +    return result;
  42.706 +  }
  42.707 +
  42.708 +  /* initialize global arrays in drivers/block/ll_rw_block.c */
  42.709 +  blk_size[xlblk_major] = xlblk_blk_size;
  42.710 +  blksize_size[xlblk_major] = xlblk_blksize_size;
  42.711 +  hardsect_size[xlblk_major] = xlblk_hardsect_size;
  42.712 +  read_ahead[xlblk_major] = xlblk_read_ahead;
  42.713 +  max_sectors[xlblk_major] = xlblk_max_sectors;
  42.714 +  for (loop = 0; loop < XLBLK_MAX; loop++)
  42.715 +  {
  42.716 +    xlblk_blk_size[loop] = xen_disk_info.disks[0].capacity;
  42.717 +    xlblk_blksize_size[loop] = 512;
  42.718 +    xlblk_hardsect_size[loop] = 512;
  42.719 +    xlblk_read_ahead[loop] = 8; 
  42.720 +    xlblk_max_sectors[loop] = 128;
  42.721 +  }
  42.722 +
  42.723 +  if (USE_REQUEST_QUEUE)
  42.724 +  {
  42.725 +    /* NEED TO MODIFY THIS TO HANDLE MULTIPLE QUEUES
  42.726 +     * also, should replace do_xlblk_request with blk.h::DEVICE_REQUEST
  42.727 +     */
  42.728 +    blk_init_queue(BLK_DEFAULT_QUEUE(xlblk_major), do_xlblk_request);
  42.729 +    blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
  42.730 +  }
  42.731 +  else
  42.732 +  {
  42.733 +    /* we don't use __make_request in ll_rw_blk */
  42.734 +    blk_queue_make_request(BLK_DEFAULT_QUEUE(xlblk_major), 
  42.735 +			   xenolinux_block_request);
  42.736 +  }
  42.737 +  xlblk_ide_register_disk(0, xen_disk_info.disks[0].capacity);
  42.738 +
  42.739 +  /*
  42.740 +   * completion 
  42.741 +   */
  42.742 +  printk(KERN_ALERT 
  42.743 +	 "XenoLinux Virtual Block Device Driver installed [device: %d]\n",
  42.744 +	 xlblk_major);
  42.745 +  return 0;
  42.746 +
  42.747 + fail:
  42.748 +  if (blk_ring->tx_ring) kfree(blk_ring->tx_ring);
  42.749 +  if (blk_ring->rx_ring) kfree(blk_ring->rx_ring);
  42.750 +  return error;
  42.751 +}
  42.752 +
  42.753 +void xlblk_ide_register_disk(int idx, unsigned long capacity)
  42.754 +{
  42.755 +  int units;
  42.756 +  int minors;
  42.757 +  struct gendisk *gd;
  42.758 +
  42.759 +  /* plagarized from ide-probe.c::init_gendisk */
  42.760 +
  42.761 +  units = 2;                                       /* from ide.h::MAX_DRIVES */
  42.762 +
  42.763 +  minors    = units * (1<<IDE_PARTN_BITS);
  42.764 +  gd        = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
  42.765 +  gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
  42.766 +  gd->part  = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
  42.767 +  memset(gd->part, 0, minors * sizeof(struct hd_struct));
  42.768 +
  42.769 +  gd->major       = xlblk_major;                  /* our major device number */
  42.770 +  gd->major_name  = XLBLK_MAJOR_NAME;          /* treated special in genhd.c */
  42.771 +  gd->minor_shift = IDE_PARTN_BITS;               /* num bits for partitions */
  42.772 +  gd->max_p	  = 1<<IDE_PARTN_BITS;         /* 1 + max partitions / drive */
  42.773 +  gd->nr_real	  = units;                        /* current num real drives */
  42.774 +  gd->real_devices= NULL;                /* ptr to internal data (was: hwif) */
  42.775 +  gd->next	  = NULL;                       /* linked list of major devs */
  42.776 +  gd->fops        = &xenolinux_block_fops;                /* file operations */
  42.777 +  gd->de_arr      = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
  42.778 +  gd->flags	  = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
  42.779 +  if (gd->de_arr)   memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
  42.780 +  if (gd->flags)    memset (gd->flags, 0, sizeof *gd->flags * units);
  42.781 +  add_gendisk(gd);
  42.782 +
  42.783 +  xen_disk_info.disks[idx].gendisk = gd;
  42.784 +
  42.785 +  /* default disk size is just a big number.  in the future, we
  42.786 +     need a message to probe the devices to determine the actual size */
  42.787 +  register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
  42.788 +		&xenolinux_block_fops, capacity);
  42.789 +
  42.790 +  return;
  42.791 +}
  42.792 +
  42.793 +static void __exit xlblk_cleanup(void)
  42.794 +{
  42.795 +  /* CHANGE FOR MULTIQUEUE */
  42.796 +  blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major));
  42.797 +
  42.798 +  /* clean up global arrays */
  42.799 +  read_ahead[xlblk_major] = 0;
  42.800 +  if (blk_size[xlblk_major]) kfree(blk_size[xlblk_major]);
  42.801 +  blk_size[xlblk_major] = NULL;
  42.802 +  if (blksize_size[xlblk_major]) kfree(blksize_size[xlblk_major]);
  42.803 +  blksize_size[xlblk_major] = NULL;
  42.804 +  if (hardsect_size[xlblk_major]) kfree(hardsect_size[xlblk_major]);
  42.805 +  hardsect_size[xlblk_major] = NULL;
  42.806 +
  42.807 +  /*
  42.808 +   *
  42.809 +   * TODO: FOR EACH GENDISK, FREE 
  42.810 +   *
  42.811 +   */
  42.812 +
  42.813 +  if (unregister_blkdev(xlblk_major, "block"))
  42.814 +  {
  42.815 +    printk(KERN_ALERT
  42.816 +	   "XenoLinux Virtual Block Device Driver uninstalled with errors\n");
  42.817 +  }
  42.818 +  else
  42.819 +  {
  42.820 +    printk(KERN_ALERT "XenoLinux Virtual Block Device Driver uninstalled\n");
  42.821 +  }
  42.822 +
  42.823 +  return;
  42.824 +}
  42.825 +
  42.826 +
  42.827 +#ifdef MODULE
  42.828 +module_init(xlblk_init);
  42.829 +module_exit(xlblk_cleanup);
  42.830 +#endif
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/block/xl_block_test.c	Thu Feb 13 15:58:34 2003 +0000
    43.3 @@ -0,0 +1,233 @@
    43.4 +/******************************************************************************
    43.5 + * xenolinux_block_test.c
    43.6 + * 
    43.7 + */
    43.8 +#define EXPORT_SYMTAB
    43.9 +
   43.10 +#include <linux/config.h>
   43.11 +#include <linux/module.h>
   43.12 +
   43.13 +#include <linux/kernel.h>
   43.14 +#include <linux/init.h>
   43.15 +#include <linux/proc_fs.h>
   43.16 +#include <linux/sched.h>
   43.17 +#include <asm/uaccess.h>
   43.18 +#include <linux/slab.h>
   43.19 +#include <linux/string.h>
   43.20 +#include <linux/errno.h>
   43.21 +
   43.22 +#include <asm/hypervisor-ifs/block.h>
   43.23 +#include <asm/hypervisor-ifs/hypervisor-if.h>
   43.24 +
   43.25 +/******************************************************************/
   43.26 +
   43.27 +static struct proc_dir_entry *bdt;
   43.28 +static blk_ring_entry_t meta;
   43.29 +static char * data;
   43.30 +
   43.31 +static int proc_read_bdt(char *page, char **start, off_t off,
   43.32 +			 int count, int *eof, void *data)
   43.33 +{
   43.34 +  switch (meta.operation)
   43.35 +  {
   43.36 +    case XEN_BLOCK_READ :
   43.37 +    case XEN_BLOCK_WRITE :
   43.38 +    {
   43.39 +      return proc_dump_block(page, start, off, count, eof, data);
   43.40 +    }
   43.41 +    case XEN_BLOCK_DEBUG :
   43.42 +    {
   43.43 +      return proc_dump_debug(page, start, off, count, eof, data);
   43.44 +    }
   43.45 +    default :
   43.46 +    {
   43.47 +      printk(KERN_ALERT 
   43.48 +	     "block device test error: unknown operation [%c]\n",
   43.49 +	     meta.operation);
   43.50 +      return -EINVAL;
   43.51 +    }
   43.52 +  }
   43.53 +}
   43.54 +
   43.55 +int proc_dump_debug(char *page, char **start, off_t off,
   43.56 +		    int count, int *eof, void *data)
   43.57 +{
   43.58 +  char header[100];
   43.59 +  char dump[1024];
   43.60 +
   43.61 +  sprintf (header, "Block Device Test: Debug Dump\n\n");
   43.62 +  
   43.63 +  sprintf (dump, "%s\n", meta.buffer);
   43.64 +  
   43.65 +  if (data)
   43.66 +  {
   43.67 +    kfree(data);
   43.68 +  }
   43.69 +
   43.70 +  strncpy (page, dump, count);
   43.71 +  return strlen(page);
   43.72 +}
   43.73 +
   43.74 +int proc_dump_block(char *page, char **start, off_t off,
   43.75 +		    int count, int *eof, void *data)
   43.76 +{
   43.77 +  char header[100];
   43.78 +  char dump[1024];
   43.79 +  char temp[100];
   43.80 +  int loop;
   43.81 +
   43.82 +  sprintf (header, "Block Device Test\n\n%s  blk num: %ld 0x%lx;  size: %d 0x%x;  device: 0x%x\n",
   43.83 +	   meta.operation == XEN_BLOCK_WRITE ? "write" : "read",
   43.84 +	   meta.block_number, meta.block_number,
   43.85 +	   meta.block_size, meta.block_size,
   43.86 +	   meta.device);
   43.87 +  
   43.88 +  sprintf (dump, "%s", header);
   43.89 +
   43.90 +  if (meta.buffer)
   43.91 +  {
   43.92 +    for (loop = 0; loop < 100; loop++)
   43.93 +    {
   43.94 +      int i = meta.buffer[loop];
   43.95 +    
   43.96 +      if (loop % 8 == 0)
   43.97 +      {
   43.98 +	sprintf (temp, "[%2d] ", loop);
   43.99 +	strcat(dump, temp);
  43.100 +      }
  43.101 +      else if (loop % 2 == 0)
  43.102 +      {
  43.103 +	strcat(dump, " ");
  43.104 +      }
  43.105 +
  43.106 +      sprintf (temp, " 0x%02x", i & 255);
  43.107 +      strcat(dump, temp);
  43.108 +      if ((loop + 1) % 8 == 0)
  43.109 +      {
  43.110 +	strcat(dump, "\n");
  43.111 +      }
  43.112 +    }
  43.113 +    strcat(dump, "\n\n");
  43.114 +  }
  43.115 +  
  43.116 +  if (data)
  43.117 +  {
  43.118 +    kfree(data);
  43.119 +  }
  43.120 +
  43.121 +  strncpy (page, dump, count);
  43.122 +  return strlen(page);
  43.123 +}
  43.124 +
  43.125 +int proc_write_bdt(struct file *file, const char *buffer,
  43.126 +		   unsigned long count, void *data)
  43.127 +{
  43.128 +  char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
  43.129 +  char  opcode;
  43.130 +  int  block_number = 0;
  43.131 +  int  block_size = 0;
  43.132 +  int  device = 0;
  43.133 +  int  mode;
  43.134 +
  43.135 +  if (copy_from_user(local, buffer, count))
  43.136 +  {
  43.137 +    return -EFAULT;
  43.138 +  }
  43.139 +  local[count] = '\0';
  43.140 +
  43.141 +  sscanf(local, "%c %i %i %i", 
  43.142 +	 &opcode, &block_number, &block_size, &device);
  43.143 +
  43.144 +  if (opcode == 'r' || opcode == 'R')
  43.145 +  {
  43.146 +    meta.operation = XEN_BLOCK_READ;
  43.147 +  }
  43.148 +  else if (opcode == 'w' || opcode == 'W')
  43.149 +  {
  43.150 +    meta.operation = XEN_BLOCK_WRITE;
  43.151 +  }
  43.152 +  else if (opcode == 'd' || opcode == 'D')
  43.153 +  {
  43.154 +    meta.operation = XEN_BLOCK_DEBUG;
  43.155 +    block_size = 10000;
  43.156 +  }
  43.157 +  else
  43.158 +  {
  43.159 +    printk(KERN_ALERT 
  43.160 +	   "block device test error: unknown opcode [%c]\n", opcode);
  43.161 +    return -EINVAL;
  43.162 +  }
  43.163 +
  43.164 +  if (opcode == 'r' || opcode == 'w' ||
  43.165 +      opcode == 'd' || opcode == 'D')
  43.166 +  {
  43.167 +    mode = XEN_BLOCK_SYNC;
  43.168 +  }
  43.169 +  else /* (opcode == 'R' || opcode == 'W') */
  43.170 +  {
  43.171 +    mode = XEN_BLOCK_ASYNC;
  43.172 +  }
  43.173 +
  43.174 +  if (data)
  43.175 +  {
  43.176 +    kfree(data);
  43.177 +  }
  43.178 +  data = kmalloc(block_size * sizeof(char), GFP_KERNEL);
  43.179 +  if (data == NULL)
  43.180 +  {
  43.181 +    kfree(local);
  43.182 +    return -ENOMEM;
  43.183 +  }
  43.184 +
  43.185 +  meta.block_number = block_number;
  43.186 +  meta.block_size   = block_size;
  43.187 +  meta.device       = device;
  43.188 +  meta.buffer       = data;
  43.189 +
  43.190 +  /* submit request */
  43.191 +  hypervisor_request(0, meta.operation, meta.buffer, 
  43.192 +		     meta.block_number, meta.block_size,
  43.193 +		     meta.device, mode);
  43.194 +
  43.195 +  kfree(local);
  43.196 +  return count;
  43.197 +}
  43.198 +			 
  43.199 +
  43.200 +static int __init init_module(void)
  43.201 +{
  43.202 +  int return_value = 0;
  43.203 +
  43.204 +  /* create proc entry */
  43.205 +  bdt = create_proc_entry("bdt", 0644, NULL);
  43.206 +  if (bdt == NULL)
  43.207 +  {
  43.208 +    return_value = -ENOMEM;
  43.209 +    goto error;
  43.210 +  }
  43.211 +  bdt->data       = NULL;
  43.212 +  bdt->read_proc  = proc_read_bdt;
  43.213 +  bdt->write_proc = proc_write_bdt;
  43.214 +  bdt->owner      = THIS_MODULE;
  43.215 +
  43.216 +  memset(&meta, 0, sizeof(meta));
  43.217 +  
  43.218 +  /* success */
  43.219 +  printk(KERN_ALERT "XenoLinux Block Device Test installed\n");
  43.220 +  return 0;
  43.221 +
  43.222 + error:
  43.223 +  return return_value;
  43.224 +}
  43.225 +
  43.226 +static void __exit cleanup_module(void)
  43.227 +{
  43.228 +  if (data)
  43.229 +  {
  43.230 +    kfree(data);
  43.231 +  }
  43.232 +  printk(KERN_ALERT "XenoLinux Block Device Test uninstalled\n");
  43.233 +}
  43.234 +
  43.235 +module_init(init_module);
  43.236 +module_exit(cleanup_module);
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_block.c	Thu Feb 13 15:58:34 2003 +0000
    44.3 @@ -0,0 +1,27 @@
    44.4 +/*
    44.5 + * domain 0 block driver interface
    44.6 + *
    44.7 + */
    44.8 +
    44.9 +#include <linux/config.h>
   44.10 +#include <linux/module.h>
   44.11 +#include <linux/kernel.h>
   44.12 +#include <linux/sched.h>
   44.13 +
   44.14 +static int __init init_module(void)
   44.15 +{
   44.16 +  request_module("xl_block");
   44.17 +  printk("Successfully installed domain 0 block interface\n");
   44.18 +
   44.19 +
   44.20 +  return 0;
   44.21 +}
   44.22 +
   44.23 +static void __exit cleanup_module(void)
   44.24 +{
   44.25 +  printk("Successfully de-installed domain-0 block interface\n");
   44.26 +  return 0;
   44.27 +}
   44.28 +
   44.29 +module_init(init_module);
   44.30 +module_exit(cleanup_module);
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/xenolinux-2.4.16-sparse/drivers/block/Config.in	Thu Feb 13 15:58:34 2003 +0000
    45.3 @@ -0,0 +1,51 @@
    45.4 +#
    45.5 +# Block device driver configuration
    45.6 +#
    45.7 +mainmenu_option next_comment
    45.8 +comment 'Block devices'
    45.9 +
   45.10 +tristate 'Normal PC floppy disk support' CONFIG_BLK_DEV_FD
   45.11 +if [ "$CONFIG_AMIGA" = "y" ]; then
   45.12 +   tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
   45.13 +fi
   45.14 +if [ "$CONFIG_ATARI" = "y" ]; then
   45.15 +   tristate 'Atari floppy support' CONFIG_ATARI_FLOPPY
   45.16 +fi
   45.17 +if [ "$CONFIG_MAC" = "y" ]; then
   45.18 +   dep_bool 'Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)' CONFIG_BLK_DEV_SWIM_IOP $CONFIG_EXPERIMENTAL
   45.19 +fi
   45.20 +if [ "$CONFIG_MCA" = "y" ]; then
   45.21 +   tristate 'PS/2 ESDI hard disk support' CONFIG_BLK_DEV_PS2
   45.22 +fi
   45.23 +if [ "$CONFIG_ZORRO" = "y" ]; then
   45.24 +   tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
   45.25 +fi
   45.26 +if [ "$CONFIG_ATARI" = "y" ]; then
   45.27 +   tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
   45.28 +   if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
   45.29 +      comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
   45.30 +      bool '  Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
   45.31 +      tristate '  Atari SLM laser printer support' CONFIG_ATARI_SLM
   45.32 +   fi
   45.33 +fi
   45.34 +dep_tristate 'XT hard disk support' CONFIG_BLK_DEV_XD $CONFIG_ISA
   45.35 +dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARPORT
   45.36 +if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   45.37 +   source drivers/block/paride/Config.in
   45.38 +fi
   45.39 +dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
   45.40 +dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
   45.41 +dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
   45.42 +
   45.43 +tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
   45.44 +dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
   45.45 +
   45.46 +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
   45.47 +if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
   45.48 +   int '  Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
   45.49 +fi
   45.50 +dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
   45.51 +
   45.52 +bool 'XenoLinux virtual block device support' CONFIG_XENOLINUX_BLOCK
   45.53 +
   45.54 +endmenu
    46.1 --- a/xenolinux-2.4.16-sparse/drivers/block/ll_rw_blk.c	Tue Feb 11 17:54:17 2003 +0000
    46.2 +++ b/xenolinux-2.4.16-sparse/drivers/block/ll_rw_blk.c	Thu Feb 13 15:58:34 2003 +0000
    46.3 @@ -1227,6 +1227,11 @@ int __init blk_dev_init(void)
    46.4  #ifdef CONFIG_SUN_JSFLASH
    46.5  	jsfd_init();
    46.6  #endif
    46.7 +
    46.8 +#ifdef CONFIG_XENOLINUX_BLOCK
    46.9 +    xlblk_init();
   46.10 +#endif
   46.11 +
   46.12  	return 0;
   46.13  };
   46.14  
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/xenolinux-2.4.16-sparse/fs/partitions/check.c	Thu Feb 13 15:58:34 2003 +0000
    47.3 @@ -0,0 +1,443 @@
    47.4 +/*
    47.5 + *  Code extracted from drivers/block/genhd.c
    47.6 + *  Copyright (C) 1991-1998  Linus Torvalds
    47.7 + *  Re-organised Feb 1998 Russell King
    47.8 + *
    47.9 + *  We now have independent partition support from the
   47.10 + *  block drivers, which allows all the partition code to
   47.11 + *  be grouped in one location, and it to be mostly self
   47.12 + *  contained.
   47.13 + *
   47.14 + *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
   47.15 + */
   47.16 +
   47.17 +#include <linux/config.h>
   47.18 +#include <linux/fs.h>
   47.19 +#include <linux/genhd.h>
   47.20 +#include <linux/kernel.h>
   47.21 +#include <linux/major.h>
   47.22 +#include <linux/blk.h>
   47.23 +#include <linux/init.h>
   47.24 +#include <linux/raid/md.h>
   47.25 +
   47.26 +#include "check.h"
   47.27 +
   47.28 +#include "acorn.h"
   47.29 +#include "amiga.h"
   47.30 +#include "atari.h"
   47.31 +#include "ldm.h"
   47.32 +#include "mac.h"
   47.33 +#include "msdos.h"
   47.34 +#include "osf.h"
   47.35 +#include "sgi.h"
   47.36 +#include "sun.h"
   47.37 +#include "ibm.h"
   47.38 +#include "ultrix.h"
   47.39 +
   47.40 +extern int *blk_size[];
   47.41 +
   47.42 +#define CHECK_DEBUG 0
   47.43 +
   47.44 +int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
   47.45 +
   47.46 +static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
   47.47 +#ifdef CONFIG_ACORN_PARTITION
   47.48 +	acorn_partition,
   47.49 +#endif
   47.50 +#ifdef CONFIG_LDM_PARTITION
   47.51 +	ldm_partition,		/* this must come before msdos */
   47.52 +#endif
   47.53 +#ifdef CONFIG_MSDOS_PARTITION
   47.54 +	msdos_partition,
   47.55 +#endif
   47.56 +#ifdef CONFIG_OSF_PARTITION
   47.57 +	osf_partition,
   47.58 +#endif
   47.59 +#ifdef CONFIG_SUN_PARTITION
   47.60 +	sun_partition,
   47.61 +#endif
   47.62 +#ifdef CONFIG_AMIGA_PARTITION
   47.63 +	amiga_partition,
   47.64 +#endif
   47.65 +#ifdef CONFIG_ATARI_PARTITION
   47.66 +	atari_partition,
   47.67 +#endif
   47.68 +#ifdef CONFIG_MAC_PARTITION
   47.69 +	mac_partition,
   47.70 +#endif
   47.71 +#ifdef CONFIG_SGI_PARTITION
   47.72 +	sgi_partition,
   47.73 +#endif
   47.74 +#ifdef CONFIG_ULTRIX_PARTITION
   47.75 +	ultrix_partition,
   47.76 +#endif
   47.77 +#ifdef CONFIG_IBM_PARTITION
   47.78 +	ibm_partition,
   47.79 +#endif
   47.80 +	NULL
   47.81 +};
   47.82 +
   47.83 +/*
   47.84 + *	This is ucking fugly but its probably the best thing for 2.4.x
   47.85 + *	Take it as a clear reminder than we should put the device name
   47.86 + *	generation in the object kdev_t points to in 2.5.
   47.87 + */
   47.88 + 
   47.89 +#ifdef CONFIG_ARCH_S390
   47.90 +int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
   47.91 +EXPORT_SYMBOL(genhd_dasd_name);
   47.92 +#endif
   47.93 +
   47.94 +/*
   47.95 + * disk_name() is used by partition check code and the md driver.
   47.96 + * It formats the devicename of the indicated disk into
   47.97 + * the supplied buffer (of size at least 32), and returns
   47.98 + * a pointer to that same buffer (for convenience).
   47.99 + */
  47.100 +
  47.101 +char *disk_name (struct gendisk *hd, int minor, char *buf)
  47.102 +{
  47.103 +	const char *maj = hd->major_name;
  47.104 +	unsigned int unit = (minor >> hd->minor_shift);
  47.105 +	unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
  47.106 +
  47.107 +	if ((unit < hd->nr_real) && hd->part[minor].de) {
  47.108 +		int pos;
  47.109 +
  47.110 +		pos = devfs_generate_path (hd->part[minor].de, buf, 64);
  47.111 +		if (pos >= 0)
  47.112 +			return buf + pos;
  47.113 +	}
  47.114 +
  47.115 +#ifdef CONFIG_ARCH_S390
  47.116 +	if (genhd_dasd_name
  47.117 +	    && genhd_dasd_name (buf, unit, part, hd) == 0)
  47.118 +		return buf;
  47.119 +#endif
  47.120 +	/*
  47.121 +	 * IDE devices use multiple major numbers, but the drives
  47.122 +	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
  47.123 +	 * This requires special handling here.
  47.124 +	 */
  47.125 +	switch (hd->major) {
  47.126 +		case IDE9_MAJOR:
  47.127 +			unit += 2;
  47.128 +		case IDE8_MAJOR:
  47.129 +			unit += 2;
  47.130 +		case IDE7_MAJOR:
  47.131 +			unit += 2;
  47.132 +		case IDE6_MAJOR:
  47.133 +			unit += 2;
  47.134 +		case IDE5_MAJOR:
  47.135 +			unit += 2;
  47.136 +		case IDE4_MAJOR:
  47.137 +			unit += 2;
  47.138 +		case IDE3_MAJOR:
  47.139 +			unit += 2;
  47.140 +		case IDE2_MAJOR:
  47.141 +			unit += 2;
  47.142 +		case IDE1_MAJOR:
  47.143 +			unit += 2;
  47.144 +		case IDE0_MAJOR:
  47.145 +			maj = "hd";
  47.146 +			break;
  47.147 +		case MD_MAJOR:
  47.148 +			sprintf(buf, "%s%d", maj, unit);
  47.149 +			return buf;
  47.150 +	}
  47.151 +	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
  47.152 +		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
  47.153 +		if (unit+'a' > 'z') {
  47.154 +			unit -= 26;
  47.155 +			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
  47.156 +			if (part)
  47.157 +				sprintf(buf + 4, "%d", part);
  47.158 +			return buf;
  47.159 +		}
  47.160 +	}
  47.161 +	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
  47.162 +		int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
  47.163 + 		if (part == 0)
  47.164 + 			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  47.165 + 		else
  47.166 + 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  47.167 + 		return buf;
  47.168 + 	}
  47.169 +	if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
  47.170 +                int ctlr = hd->major - COMPAQ_CISS_MAJOR;
  47.171 +                if (part == 0)
  47.172 +                        sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  47.173 +                else
  47.174 +                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  47.175 +                return buf;
  47.176 +	}
  47.177 +	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
  47.178 +		int ctlr = hd->major - DAC960_MAJOR;
  47.179 + 		if (part == 0)
  47.180 + 			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
  47.181 + 		else
  47.182 + 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
  47.183 + 		return buf;
  47.184 + 	}
  47.185 +	if (hd->major == ATARAID_MAJOR) {
  47.186 +		int disk = minor >> hd->minor_shift;
  47.187 +		int part = minor & (( 1 << hd->minor_shift) - 1);
  47.188 +		if (part == 0)
  47.189 +			sprintf(buf, "%s/d%d", maj, disk);
  47.190 +		else
  47.191 +			sprintf(buf, "%s/d%dp%d", maj, disk, part);
  47.192 +		return buf;
  47.193 +	}
  47.194 +	if (part)
  47.195 +		sprintf(buf, "%s%c%d", maj, unit+'a', part);
  47.196 +	else
  47.197 +		sprintf(buf, "%s%c", maj, unit+'a');
  47.198 +	return buf;
  47.199 +}
  47.200 +
  47.201 +/*
  47.202 + * Add a partitions details to the devices partition description.
  47.203 + */
  47.204 +void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
  47.205 +{
  47.206 +#ifndef CONFIG_DEVFS_FS
  47.207 +	char buf[40];
  47.208 +#endif
  47.209 +
  47.210 +	hd->part[minor].start_sect = start;
  47.211 +	hd->part[minor].nr_sects   = size;
  47.212 +#ifdef CONFIG_DEVFS_FS
  47.213 +	printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  47.214 +#else
  47.215 +	if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
  47.216 +	    (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
  47.217 +		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
  47.218 +	else
  47.219 +		printk(" %s", disk_name(hd, minor, buf));
  47.220 +#endif
  47.221 +}
  47.222 +
  47.223 +static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
  47.224 +{
  47.225 +	devfs_handle_t de = NULL;
  47.226 +	static int first_time = 1;
  47.227 +	unsigned long first_sector;
  47.228 +	struct block_device *bdev;
  47.229 +	char buf[64];
  47.230 +	int i;
  47.231 +
  47.232 +  if (CHECK_DEBUG) printk (KERN_ALERT "check.c::check_partition\n");
  47.233 +
  47.234 +	if (first_time)
  47.235 +		printk(KERN_INFO "Partition check:\n");
  47.236 +	first_time = 0;
  47.237 +	first_sector = hd->part[MINOR(dev)].start_sect;
  47.238 +
  47.239 +	/*
  47.240 +	 * This is a kludge to allow the partition check to be
  47.241 +	 * skipped for specific drives (e.g. IDE CD-ROM drives)
  47.242 +	 */
  47.243 +	if ((int)first_sector == -1) {
  47.244 +		hd->part[MINOR(dev)].start_sect = 0;
  47.245 +		return;
  47.246 +	}
  47.247 +
  47.248 +	if (hd->de_arr)
  47.249 +		de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
  47.250 +	i = devfs_generate_path (de, buf, sizeof buf);
  47.251 +	if (i >= 0)
  47.252 +		printk(KERN_INFO " /dev/%s:", buf + i);
  47.253 +	else
  47.254 +		printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
  47.255 +	bdev = bdget(kdev_t_to_nr(dev));
  47.256 +	bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
  47.257 +	bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
  47.258 +	for (i = 0; check_part[i]; i++) {
  47.259 +		int res;
  47.260 +		res = check_part[i](hd, bdev, first_sector, first_part_minor);
  47.261 +		if (res) {
  47.262 +			if (res < 0 &&  warn_no_part)
  47.263 +				printk(" unable to read partition table\n");
  47.264 +			goto setup_devfs;
  47.265 +		}
  47.266 +	}
  47.267 +
  47.268 +	printk(" unknown partition table\n");
  47.269 +setup_devfs:
  47.270 +	invalidate_bdev(bdev, 1);
  47.271 +	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  47.272 +	bdput(bdev);
  47.273 +	i = first_part_minor - 1;
  47.274 +	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
  47.275 +}
  47.276 +
  47.277 +#ifdef CONFIG_DEVFS_FS
  47.278 +static void devfs_register_partition (struct gendisk *dev, int minor, int part)
  47.279 +{
  47.280 +	int devnum = minor >> dev->minor_shift;
  47.281 +	devfs_handle_t dir;
  47.282 +	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  47.283 +	char devname[16];
  47.284 +
  47.285 +	if (dev->part[minor + part].de) return;
  47.286 +	dir = devfs_get_parent (dev->part[minor].de);
  47.287 +	if (!dir) return;
  47.288 +	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  47.289 +		devfs_flags |= DEVFS_FL_REMOVABLE;
  47.290 +	sprintf (devname, "part%d", part);
  47.291 +	dev->part[minor + part].de =
  47.292 +	    devfs_register (dir, devname, devfs_flags,
  47.293 +			    dev->major, minor + part,
  47.294 +			    S_IFBLK | S_IRUSR | S_IWUSR,
  47.295 +			    dev->fops, NULL);
  47.296 +}
  47.297 +
  47.298 +static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
  47.299 +
  47.300 +static void devfs_register_disc (struct gendisk *dev, int minor)
  47.301 +{
  47.302 +	int pos = 0;
  47.303 +	int devnum = minor >> dev->minor_shift;
  47.304 +	devfs_handle_t dir, slave;
  47.305 +	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
  47.306 +	char dirname[64], symlink[16];
  47.307 +	static devfs_handle_t devfs_handle;
  47.308 +
  47.309 +	if (dev->part[minor].de) return;
  47.310 +	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
  47.311 +		devfs_flags |= DEVFS_FL_REMOVABLE;
  47.312 +	if (dev->de_arr) {
  47.313 +		dir = dev->de_arr[devnum];
  47.314 +		if (!dir)  /*  Aware driver wants to block disc management  */
  47.315 +			return;
  47.316 +		pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
  47.317 +		if (pos < 0) return;
  47.318 +		strncpy (dirname + pos, "../", 3);
  47.319 +	}
  47.320 +	else {
  47.321 +		/*  Unaware driver: construct "real" directory  */
  47.322 +		sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
  47.323 +		dir = devfs_mk_dir (NULL, dirname + 3, NULL);
  47.324 +	}
  47.325 +	if (!devfs_handle)
  47.326 +		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
  47.327 +	dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
  47.328 +	sprintf (symlink, "disc%d", dev->part[minor].number);
  47.329 +	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
  47.330 +			  dirname + pos, &slave, NULL);
  47.331 +	dev->part[minor].de =
  47.332 +	    devfs_register (dir, "disc", devfs_flags, dev->major, minor,
  47.333 +			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
  47.334 +	devfs_auto_unregister (dev->part[minor].de, slave);
  47.335 +	if (!dev->de_arr)
  47.336 +		devfs_auto_unregister (slave, dir);
  47.337 +}
  47.338 +#endif  /*  CONFIG_DEVFS_FS  */
  47.339 +
  47.340 +void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
  47.341 +{
  47.342 +#ifdef CONFIG_DEVFS_FS
  47.343 +	int part;
  47.344 +
  47.345 +	if (!unregister)
  47.346 +		devfs_register_disc (dev, minor);
  47.347 +	for (part = 1; part < dev->max_p; part++) {
  47.348 +		if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
  47.349 +			devfs_unregister (dev->part[part + minor].de);
  47.350 +			dev->part[part + minor].de = NULL;
  47.351 +			continue;
  47.352 +		}
  47.353 +		devfs_register_partition (dev, minor, part);
  47.354 +	}
  47.355 +	if (unregister) {
  47.356 +		devfs_unregister (dev->part[minor].de);
  47.357 +		dev->part[minor].de = NULL;
  47.358 +		devfs_dealloc_unique_number (&disc_numspace,
  47.359 +					     dev->part[minor].number);
  47.360 +	}
  47.361 +#endif  /*  CONFIG_DEVFS_FS  */
  47.362 +}
  47.363 +
  47.364 +/*
  47.365 + * This function will re-read the partition tables for a given device,
  47.366 + * and set things back up again.  There are some important caveats,
  47.367 + * however.  You must ensure that no one is using the device, and no one
  47.368 + * can start using the device while this function is being executed.
  47.369 + *
  47.370 + * Much of the cleanup from the old partition tables should have already been
  47.371 + * done
  47.372 + */
  47.373 +
  47.374 +void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
  47.375 +	struct block_device_operations *ops, long size)
  47.376 +{
  47.377 +  if (CHECK_DEBUG)
  47.378 +  {
  47.379 +    if (gdev != NULL)
  47.380 +    printk (KERN_ALERT 
  47.381 +	    "check.c::register_disk gdev:%p dev:%d min:%u ops:%p sz:%ld\n",
  47.382 +	    gdev, dev, minors, ops, size);
  47.383 +  }
  47.384 +
  47.385 +	if (!gdev)
  47.386 +		return;
  47.387 +
  47.388 +	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
  47.389 +}
  47.390 +
  47.391 +void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
  47.392 +{
  47.393 +	int i;
  47.394 +	int first_minor	= drive << dev->minor_shift;
  47.395 +	int end_minor	= first_minor + dev->max_p;
  47.396 +
  47.397 +  if (CHECK_DEBUG) printk (KERN_ALERT "check.c::grok_partitions\n");
  47.398 +
  47.399 +	if(!dev->sizes)
  47.400 +		blk_size[dev->major] = NULL;
  47.401 +
  47.402 +	dev->part[first_minor].nr_sects = size;
  47.403 +	/* No such device or no minors to use for partitions */
  47.404 +	if (!size || minors == 1)
  47.405 +		return;
  47.406 +
  47.407 +	if (dev->sizes) {
  47.408 +		dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
  47.409 +		for (i = first_minor + 1; i < end_minor; i++)
  47.410 +			dev->sizes[i] = 0;
  47.411 +	}
  47.412 +	blk_size[dev->major] = dev->sizes;
  47.413 +	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
  47.414 +
  47.415 + 	/*
  47.416 + 	 * We need to set the sizes array before we will be able to access
  47.417 + 	 * any of the partitions on this device.
  47.418 + 	 */
  47.419 +	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
  47.420 +		for (i = first_minor; i < end_minor; i++)
  47.421 +			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
  47.422 +	}
  47.423 +}
  47.424 +
  47.425 +unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
  47.426 +{
  47.427 +	struct address_space *mapping = bdev->bd_inode->i_mapping;
  47.428 +	int sect = PAGE_CACHE_SIZE / 512;
  47.429 +	struct page *page;
  47.430 +
  47.431 +	page = read_cache_page(mapping, n/sect,
  47.432 +			(filler_t *)mapping->a_ops->readpage, NULL);
  47.433 +	if (!IS_ERR(page)) {
  47.434 +		wait_on_page(page);
  47.435 +		if (!Page_Uptodate(page))
  47.436 +			goto fail;
  47.437 +		if (PageError(page))
  47.438 +			goto fail;
  47.439 +		p->v = page;
  47.440 +		return (unsigned char *)page_address(page) + 512 * (n % sect);
  47.441 +fail:
  47.442 +		page_cache_release(page);
  47.443 +	}
  47.444 +	p->v = NULL;
  47.445 +	return NULL;
  47.446 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/xenolinux-2.4.16-sparse/fs/partitions/msdos.c	Thu Feb 13 15:58:34 2003 +0000
    48.3 @@ -0,0 +1,642 @@
    48.4 +/*
    48.5 + *  fs/partitions/msdos.c
    48.6 + *
    48.7 + *  Code extracted from drivers/block/genhd.c
    48.8 + *  Copyright (C) 1991-1998  Linus Torvalds
    48.9 + *
   48.10 + *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
   48.11 + *  in the early extended-partition checks and added DM partitions
   48.12 + *
   48.13 + *  Support for DiskManager v6.0x added by Mark Lord,
   48.14 + *  with information provided by OnTrack.  This now works for linux fdisk
   48.15 + *  and LILO, as well as loadlin and bootln.  Note that disks other than
   48.16 + *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
   48.17 + *
   48.18 + *  More flexible handling of extended partitions - aeb, 950831
   48.19 + *
   48.20 + *  Check partition table on IDE disks for common CHS translations
   48.21 + *
   48.22 + *  Re-organised Feb 1998 Russell King
   48.23 + */
   48.24 +
   48.25 +#include <linux/config.h>
   48.26 +#include <linux/fs.h>
   48.27 +#include <linux/genhd.h>
   48.28 +#include <linux/kernel.h>
   48.29 +#include <linux/major.h>
   48.30 +#include <linux/string.h>
   48.31 +#include <linux/blk.h>
   48.32 +
   48.33 +#ifdef CONFIG_BLK_DEV_IDE
   48.34 +#include <linux/ide.h>	/* IDE xlate */
   48.35 +#endif /* CONFIG_BLK_DEV_IDE */
   48.36 +
   48.37 +#define MSDOS_DEBUG 0
   48.38 +
   48.39 +#include <asm/system.h>
   48.40 +
   48.41 +#include "check.h"
   48.42 +#include "msdos.h"
   48.43 +
   48.44 +#if CONFIG_BLK_DEV_MD
   48.45 +extern void md_autodetect_dev(kdev_t dev);
   48.46 +#endif
   48.47 +
   48.48 +/*
   48.49 + * Many architectures don't like unaligned accesses, which is
   48.50 + * frequently the case with the nr_sects and start_sect partition
   48.51 + * table entries.
   48.52 + */
   48.53 +#include <asm/unaligned.h>
   48.54 +
   48.55 +#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
   48.56 +#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
   48.57 +				get_unaligned(&p->nr_sects);	\
   48.58 +				le32_to_cpu(__a); \
   48.59 +			})
   48.60 +
   48.61 +#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
   48.62 +				get_unaligned(&p->start_sect);	\
   48.63 +				le32_to_cpu(__a); \
   48.64 +			})
   48.65 +
   48.66 +static inline int is_extended_partition(struct partition *p)
   48.67 +{
   48.68 +	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
   48.69 +		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
   48.70 +		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
   48.71 +}
   48.72 +
   48.73 +/*
   48.74 + * partition_name() formats the short partition name into the supplied
   48.75 + * buffer, and returns a pointer to that buffer.
   48.76 + * Used by several partition types which makes conditional inclusion messy,
   48.77 + * use __attribute__ ((unused)) instead.
   48.78 + */
   48.79 +static char __attribute__ ((unused))
   48.80 +	*partition_name (struct gendisk *hd, int minor, char *buf)
   48.81 +{
   48.82 +#ifdef CONFIG_DEVFS_FS
   48.83 +	sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
   48.84 +	return buf;
   48.85 +#else
   48.86 +	return disk_name(hd, minor, buf);
   48.87 +#endif
   48.88 +}
   48.89 +
   48.90 +#define MSDOS_LABEL_MAGIC1	0x55
   48.91 +#define MSDOS_LABEL_MAGIC2	0xAA
   48.92 +
   48.93 +static inline int
   48.94 +msdos_magic_present(unsigned char *p)
   48.95 +{
   48.96 +	return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
   48.97 +}
   48.98 +
   48.99 +/*
  48.100 + * Create devices for each logical partition in an extended partition.
  48.101 + * The logical partitions form a linked list, with each entry being
  48.102 + * a partition table with two entries.  The first entry
  48.103 + * is the real data partition (with a start relative to the partition
  48.104 + * table start).  The second is a pointer to the next logical partition
  48.105 + * (with a start relative to the entire extended partition).
  48.106 + * We do not create a Linux partition for the partition tables, but
  48.107 + * only for the actual data partitions.
  48.108 + */
  48.109 +
  48.110 +static void extended_partition(struct gendisk *hd, struct block_device *bdev,
  48.111 +			int minor, unsigned long first_size, int *current_minor)
  48.112 +{
  48.113 +	struct partition *p;
  48.114 +	Sector sect;
  48.115 +	unsigned char *data;
  48.116 +	unsigned long first_sector, this_sector, this_size;
  48.117 +	int mask = (1 << hd->minor_shift) - 1;
  48.118 +	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  48.119 +	int loopct = 0;		/* number of links followed
  48.120 +				   without finding a data partition */
  48.121 +	int i;
  48.122 +
  48.123 +	this_sector = first_sector = hd->part[minor].start_sect;
  48.124 +	this_size = first_size;
  48.125 +
  48.126 +	while (1) {
  48.127 +		if (++loopct > 100)
  48.128 +			return;
  48.129 +		if ((*current_minor & mask) == 0)
  48.130 +			return;
  48.131 +		data = read_dev_sector(bdev, this_sector, &sect);
  48.132 +		if (!data)
  48.133 +			return;
  48.134 +
  48.135 +		if (!msdos_magic_present(data + 510))
  48.136 +			goto done; 
  48.137 +
  48.138 +		p = (struct partition *) (data + 0x1be);
  48.139 +
  48.140 +		/*
  48.141 +		 * Usually, the first entry is the real data partition,
  48.142 +		 * the 2nd entry is the next extended partition, or empty,
  48.143 +		 * and the 3rd and 4th entries are unused.
  48.144 +		 * However, DRDOS sometimes has the extended partition as
  48.145 +		 * the first entry (when the data partition is empty),
  48.146 +		 * and OS/2 seems to use all four entries.
  48.147 +		 */
  48.148 +
  48.149 +		/* 
  48.150 +		 * First process the data partition(s)
  48.151 +		 */
  48.152 +		for (i=0; i<4; i++, p++) {
  48.153 +			unsigned long offs, size, next;
  48.154 +			if (!NR_SECTS(p) || is_extended_partition(p))
  48.155 +				continue;
  48.156 +
  48.157 +			/* Check the 3rd and 4th entries -
  48.158 +			   these sometimes contain random garbage */
  48.159 +			offs = START_SECT(p)*sector_size;
  48.160 +			size = NR_SECTS(p)*sector_size;
  48.161 +			next = this_sector + offs;
  48.162 +			if (i >= 2) {
  48.163 +				if (offs + size > this_size)
  48.164 +					continue;
  48.165 +				if (next < first_sector)
  48.166 +					continue;
  48.167 +				if (next + size > first_sector + first_size)
  48.168 +					continue;
  48.169 +			}
  48.170 +
  48.171 +			add_gd_partition(hd, *current_minor, next, size);
  48.172 +#if CONFIG_BLK_DEV_MD
  48.173 +			if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  48.174 +			    md_autodetect_dev(MKDEV(hd->major,*current_minor));
  48.175 +			}
  48.176 +#endif
  48.177 +
  48.178 +			(*current_minor)++;
  48.179 +			loopct = 0;
  48.180 +			if ((*current_minor & mask) == 0)
  48.181 +				goto done;
  48.182 +		}
  48.183 +		/*
  48.184 +		 * Next, process the (first) extended partition, if present.
  48.185 +		 * (So far, there seems to be no reason to make
  48.186 +		 *  extended_partition()  recursive and allow a tree
  48.187 +		 *  of extended partitions.)
  48.188 +		 * It should be a link to the next logical partition.
  48.189 +		 * Create a minor for this just long enough to get the next
  48.190 +		 * partition table.  The minor will be reused for the next
  48.191 +		 * data partition.
  48.192 +		 */
  48.193 +		p -= 4;
  48.194 +		for (i=0; i<4; i++, p++)
  48.195 +			if (NR_SECTS(p) && is_extended_partition(p))
  48.196 +				break;
  48.197 +		if (i == 4)
  48.198 +			goto done;	 /* nothing left to do */
  48.199 +
  48.200 +		this_sector = first_sector + START_SECT(p) * sector_size;
  48.201 +		this_size = NR_SECTS(p) * sector_size;
  48.202 +		minor = *current_minor;
  48.203 +		put_dev_sector(sect);
  48.204 +	}
  48.205 +done:
  48.206 +	put_dev_sector(sect);
  48.207 +}
  48.208 +
  48.209 +/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
  48.210 +   indicates linux swap.  Be careful before believing this is Solaris. */
  48.211 +
  48.212 +static void
  48.213 +solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
  48.214 +		int minor, int *current_minor)
  48.215 +{
  48.216 +
  48.217 +#ifdef CONFIG_SOLARIS_X86_PARTITION
  48.218 +	long offset = hd->part[minor].start_sect;
  48.219 +	Sector sect;
  48.220 +	struct solaris_x86_vtoc *v;
  48.221 +	struct solaris_x86_slice *s;
  48.222 +	int mask = (1 << hd->minor_shift) - 1;
  48.223 +	int i;
  48.224 +	char buf[40];
  48.225 +
  48.226 +	v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
  48.227 +	if (!v)
  48.228 +		return;
  48.229 +	if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
  48.230 +		put_dev_sector(sect);
  48.231 +		return;
  48.232 +	}
  48.233 +	printk(" %s: <solaris:", partition_name(hd, minor, buf));
  48.234 +	if (le32_to_cpu(v->v_version) != 1) {
  48.235 +		printk("  cannot handle version %d vtoc>\n",
  48.236 +			le32_to_cpu(v->v_version));
  48.237 +		put_dev_sector(sect);
  48.238 +		return;
  48.239 +	}
  48.240 +	for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
  48.241 +		if ((*current_minor & mask) == 0)
  48.242 +			break;
  48.243 +		s = &v->v_slice[i];
  48.244 +
  48.245 +		if (s->s_size == 0)
  48.246 +			continue;
  48.247 +		printk(" [s%d]", i);
  48.248 +		/* solaris partitions are relative to current MS-DOS
  48.249 +		 * one but add_gd_partition starts relative to sector
  48.250 +		 * zero of the disk.  Therefore, must add the offset
  48.251 +		 * of the current partition */
  48.252 +		add_gd_partition(hd, *current_minor,
  48.253 +				 le32_to_cpu(s->s_start)+offset,
  48.254 +				 le32_to_cpu(s->s_size));
  48.255 +		(*current_minor)++;
  48.256 +	}
  48.257 +	put_dev_sector(sect);
  48.258 +	printk(" >\n");
  48.259 +#endif
  48.260 +}
  48.261 +
  48.262 +#ifdef CONFIG_BSD_DISKLABEL
  48.263 +static void
  48.264 +check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
  48.265 +	int minor, int *current_minor)
  48.266 +{
  48.267 +	struct hd_struct *lin_p;
  48.268 +		/* check relative position of partitions.  */
  48.269 +	for (lin_p = hd->part + 1 + minor;
  48.270 +	     lin_p - hd->part - minor < *current_minor; lin_p++) {
  48.271 +			/* no relationship -> try again */
  48.272 +		if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
  48.273 +		    lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
  48.274 +			continue;	
  48.275 +			/* equal -> no need to add */
  48.276 +		if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) && 
  48.277 +			lin_p->nr_sects == le32_to_cpu(bsd_p->p_size)) 
  48.278 +			return;
  48.279 +			/* bsd living within dos partition */
  48.280 +		if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect 
  48.281 +			+ lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size)) {
  48.282 +#ifdef DEBUG_BSD_DISKLABEL
  48.283 +			printk("w: %d %ld+%ld,%d+%d", 
  48.284 +				lin_p - hd->part, 
  48.285 +				lin_p->start_sect, lin_p->nr_sects, 
  48.286 +				le32_to_cpu(bsd_p->p_offset),
  48.287 +				le32_to_cpu(bsd_p->p_size));
  48.288 +#endif
  48.289 +			break;
  48.290 +		}
  48.291 +	 /* ouch: bsd and linux overlap. Don't even try for that partition */
  48.292 +#ifdef DEBUG_BSD_DISKLABEL
  48.293 +		printk("???: %d %ld+%ld,%d+%d",
  48.294 +			lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
  48.295 +			le32_to_cpu(bsd_p->p_offset), le32_to_cpu(bsd_p->p_size));
  48.296 +#endif
  48.297 +		printk("???");
  48.298 +		return;
  48.299 +	} /* if the bsd partition is not currently known to linux, we end
  48.300 +	   * up here 
  48.301 +	   */
  48.302 +	add_gd_partition(hd, *current_minor, le32_to_cpu(bsd_p->p_offset),
  48.303 +			 le32_to_cpu(bsd_p->p_size));
  48.304 +	(*current_minor)++;
  48.305 +}
  48.306 +
  48.307 +/* 
  48.308 + * Create devices for BSD partitions listed in a disklabel, under a
  48.309 + * dos-like partition. See extended_partition() for more information.
  48.310 + */
  48.311 +static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
  48.312 +	int minor, int *current_minor, char *name, int max_partitions)
  48.313 +{
  48.314 +	long offset = hd->part[minor].start_sect;
  48.315 +	Sector sect;
  48.316 +	struct bsd_disklabel *l;
  48.317 +	struct bsd_partition *p;
  48.318 +	int mask = (1 << hd->minor_shift) - 1;
  48.319 +	char buf[40];
  48.320 +
  48.321 +	l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
  48.322 +	if (!l)
  48.323 +		return;
  48.324 +	if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
  48.325 +		put_dev_sector(sect);
  48.326 +		return;
  48.327 +	}
  48.328 +	printk(" %s: <%s", partition_name(hd, minor, buf), name);
  48.329 +
  48.330 +	if (le16_to_cpu(l->d_npartitions) < max_partitions)
  48.331 +		max_partitions = le16_to_cpu(l->d_npartitions);
  48.332 +	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
  48.333 +		if ((*current_minor & mask) == 0)
  48.334 +			break;
  48.335 +		if (p->p_fstype == BSD_FS_UNUSED) 
  48.336 +			continue;
  48.337 +		check_and_add_bsd_partition(hd, p, minor, current_minor);
  48.338 +	}
  48.339 +	put_dev_sector(sect);
  48.340 +	printk(" >\n");
  48.341 +}
  48.342 +#endif
  48.343 +
  48.344 +static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
  48.345 +	int minor, int *current_minor)
  48.346 +{
  48.347 +#ifdef CONFIG_BSD_DISKLABEL
  48.348 +	do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
  48.349 +		BSD_MAXPARTITIONS);
  48.350 +#endif
  48.351 +}
  48.352 +
  48.353 +static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
  48.354 +		int minor, int *current_minor)
  48.355 +{
  48.356 +#ifdef CONFIG_BSD_DISKLABEL
  48.357 +	do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
  48.358 +			BSD_MAXPARTITIONS);
  48.359 +#endif
  48.360 +}
  48.361 +
  48.362 +static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
  48.363 +		int minor, int *current_minor)
  48.364 +{
  48.365 +#ifdef CONFIG_BSD_DISKLABEL
  48.366 +	do_bsd_partition(hd, bdev, minor, current_minor,
  48.367 +			"openbsd", OPENBSD_MAXPARTITIONS);
  48.368 +#endif
  48.369 +}
  48.370 +
  48.371 +/*
  48.372 + * Create devices for Unixware partitions listed in a disklabel, under a
  48.373 + * dos-like partition. See extended_partition() for more information.
  48.374 + */
  48.375 +static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
  48.376 +		int minor, int *current_minor)
  48.377 +{
  48.378 +#ifdef CONFIG_UNIXWARE_DISKLABEL
  48.379 +	long offset = hd->part[minor].start_sect;
  48.380 +	Sector sect;
  48.381 +	struct unixware_disklabel *l;
  48.382 +	struct unixware_slice *p;
  48.383 +	int mask = (1 << hd->minor_shift) - 1;
  48.384 +	char buf[40];
  48.385 +
  48.386 +	l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
  48.387 +	if (!l)
  48.388 +		return;
  48.389 +	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
  48.390 +	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
  48.391 +		put_dev_sector(sect);
  48.392 +		return;
  48.393 +	}
  48.394 +	printk(" %s: <unixware:", partition_name(hd, minor, buf));
  48.395 +	p = &l->vtoc.v_slice[1];
  48.396 +	/* I omit the 0th slice as it is the same as whole disk. */
  48.397 +	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
  48.398 +		if ((*current_minor & mask) == 0)
  48.399 +			break;
  48.400 +
  48.401 +		if (p->s_label != UNIXWARE_FS_UNUSED) {
  48.402 +			add_gd_partition(hd, *current_minor, START_SECT(p),
  48.403 +					 NR_SECTS(p));
  48.404 +			(*current_minor)++;
  48.405 +		}
  48.406 +		p++;
  48.407 +	}
  48.408 +	put_dev_sector(sect);
  48.409 +	printk(" >\n");
  48.410 +#endif
  48.411 +}
  48.412 +
  48.413 +/*
  48.414 + * Minix 2.0.0/2.0.2 subpartition support.
  48.415 + * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
  48.416 + * Rajeev V. Pillai    <rajeevvp@yahoo.com>
  48.417 + */
  48.418 +static void minix_partition(struct gendisk *hd, struct block_device *bdev,
  48.419 +		int minor, int *current_minor)
  48.420 +{
  48.421 +#ifdef CONFIG_MINIX_SUBPARTITION
  48.422 +	long offset = hd->part[minor].start_sect;
  48.423 +	Sector sect;
  48.424 +	unsigned char *data;
  48.425 +	struct partition *p;
  48.426 +	int mask = (1 << hd->minor_shift) - 1;
  48.427 +	int i;
  48.428 +	char buf[40];
  48.429 +
  48.430 +	data = read_dev_sector(bdev, offset, &sect);
  48.431 +	if (!data)
  48.432 +		return;
  48.433 +
  48.434 +	p = (struct partition *)(data + 0x1be);
  48.435 +
  48.436 +	/* The first sector of a Minix partition can have either
  48.437 +	 * a secondary MBR describing its subpartitions, or
  48.438 +	 * the normal boot sector. */
  48.439 +	if (msdos_magic_present (data + 510) &&
  48.440 +	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
  48.441 +
  48.442 +		printk(" %s: <minix:", partition_name(hd, minor, buf));
  48.443 +		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
  48.444 +			if ((*current_minor & mask) == 0)
  48.445 +				break;
  48.446 +			/* add each partition in use */
  48.447 +			if (SYS_IND(p) == MINIX_PARTITION) {
  48.448 +				add_gd_partition(hd, *current_minor,
  48.449 +					      START_SECT(p), NR_SECTS(p));
  48.450 +				(*current_minor)++;
  48.451 +			}
  48.452 +		}
  48.453 +		printk(" >\n");
  48.454 +	}
  48.455 +	put_dev_sector(sect);
  48.456 +#endif /* CONFIG_MINIX_SUBPARTITION */
  48.457 +}
  48.458 +
  48.459 +static struct {
  48.460 +	unsigned char id;
  48.461 +	void (*parse)(struct gendisk *, struct block_device *, int, int *);
  48.462 +} subtypes[] = {
  48.463 +	{BSD_PARTITION, bsd_partition},
  48.464 +	{NETBSD_PARTITION, netbsd_partition},
  48.465 +	{OPENBSD_PARTITION, openbsd_partition},
  48.466 +	{MINIX_PARTITION, minix_partition},
  48.467 +	{UNIXWARE_PARTITION, unixware_partition},
  48.468 +	{SOLARIS_X86_PARTITION, solaris_x86_partition},
  48.469 +	{0, NULL},
  48.470 +};
  48.471 +/*
  48.472 + * Look for various forms of IDE disk geometry translation
  48.473 + */
  48.474 +static int handle_ide_mess(struct block_device *bdev)
  48.475 +{
  48.476 +#ifdef CONFIG_BLK_DEV_IDE
  48.477 +	Sector sect;
  48.478 +	unsigned char *data;
  48.479 +	kdev_t dev = to_kdev_t(bdev->bd_dev);
  48.480 +	unsigned int sig;
  48.481 +	int heads = 0;
  48.482 +	struct partition *p;
  48.483 +	int i;
  48.484 +
  48.485 +	if (MSDOS_DEBUG)
  48.486 +	  printk (KERN_ALERT "handle_ide_mess ------------\n");
  48.487 +
  48.488 +	/*
  48.489 +	 * The i386 partition handling programs very often
  48.490 +	 * make partitions end on cylinder boundaries.
  48.491 +	 * There is no need to do so, and Linux fdisk doesnt always
  48.492 +	 * do this, and Windows NT on Alpha doesnt do this either,
  48.493 +	 * but still, this helps to guess #heads.
  48.494 +	 */
  48.495 +	data = read_dev_sector(bdev, 0, &sect);
  48.496 +	if (!data)
  48.497 +		return -1;
  48.498 +	if (!msdos_magic_present(data + 510)) {
  48.499 +		put_dev_sector(sect);
  48.500 +		return 0;
  48.501 +	}
  48.502 +	sig = le16_to_cpu(*(unsigned short *)(data + 2));
  48.503 +	p = (struct partition *) (data + 0x1be);
  48.504 +	for (i = 0; i < 4; i++) {
  48.505 +		struct partition *q = &p[i];
  48.506 +		if (NR_SECTS(q)) {
  48.507 +			if ((q->sector & 63) == 1 &&
  48.508 +			    (q->end_sector & 63) == 63)
  48.509 +				heads = q->end_head + 1;
  48.510 +			break;
  48.511 +		}
  48.512 +	}
  48.513 +	if (SYS_IND(p) == EZD_PARTITION) {
  48.514 +		/*
  48.515 +		 * Accesses to sector 0 must go to sector 1 instead.
  48.516 +		 */
  48.517 +		if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
  48.518 +			goto reread;
  48.519 +	} else if (SYS_IND(p) == DM6_PARTITION) {
  48.520 +
  48.521 +		/*
  48.522 +		 * Everything on the disk is offset by 63 sectors,
  48.523 +		 * including a "new" MBR with its own partition table.
  48.524 +		 */
  48.525 +		if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
  48.526 +			goto reread;
  48.527 +	} else if (sig <= 0x1ae &&
  48.528 +		   data[sig] == 0xAA && data[sig+1] == 0x55 &&
  48.529 +		   (data[sig+2] & 1)) {
  48.530 +		/* DM6 signature in MBR, courtesy of OnTrack */
  48.531 +		(void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
  48.532 +	} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
  48.533 +		   SYS_IND(p) == DM6_AUX3PARTITION) {
  48.534 +		/*
  48.535 +		 * DM6 on other than the first (boot) drive
  48.536 +		 */
  48.537 +		(void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
  48.538 +	} else {
  48.539 +		(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
  48.540 +	}
  48.541 +	put_dev_sector(sect);
  48.542 +
  48.543 +	if (MSDOS_DEBUG)
  48.544 +	  printk (KERN_ALERT "handle_ide_mess -------- %d\n", heads);
  48.545 +	return 1;
  48.546 +
  48.547 +reread:
  48.548 +	put_dev_sector(sect);
  48.549 +	/* Flush the cache */
  48.550 +	invalidate_bdev(bdev, 1);
  48.551 +	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  48.552 +#endif /* CONFIG_BLK_DEV_IDE */
  48.553 +	return 1;
  48.554 +}
  48.555 + 
  48.556 +int msdos_partition(struct gendisk *hd, struct block_device *bdev,
  48.557 +		    unsigned long first_sector, int first_part_minor)
  48.558 +{
  48.559 +	int i, minor = first_part_minor;
  48.560 +	Sector sect;
  48.561 +	struct partition *p;
  48.562 +	unsigned char *data;
  48.563 +	int mask = (1 << hd->minor_shift) - 1;
  48.564 +	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  48.565 +	int current_minor = first_part_minor;
  48.566 +	int err;
  48.567 +
  48.568 +  if (MSDOS_DEBUG) printk (KERN_ALERT "msdos.c::msdos_partition\n");
  48.569 +	err = handle_ide_mess(bdev);
  48.570 +	if (err <= 0)
  48.571 +		return err;
  48.572 +	data = read_dev_sector(bdev, 0, &sect);
  48.573 +	if (!data)
  48.574 +		return -1;
  48.575 +	if (!msdos_magic_present(data + 510)) {
  48.576 +		put_dev_sector(sect);
  48.577 +		return 0;
  48.578 +	}
  48.579 +	p = (struct partition *) (data + 0x1be);
  48.580 +
  48.581 +	/*
  48.582 +	 * Look for partitions in two passes:
  48.583 +	 * First find the primary and DOS-type extended partitions.
  48.584 +	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
  48.585 +	 */
  48.586 +
  48.587 +	current_minor += 4;
  48.588 +	for (i=1 ; i<=4 ; minor++,i++,p++) {
  48.589 +		if (!NR_SECTS(p))
  48.590 +			continue;
  48.591 +		add_gd_partition(hd, minor,
  48.592 +				first_sector+START_SECT(p)*sector_size,
  48.593 +				NR_SECTS(p)*sector_size);
  48.594 +#if CONFIG_BLK_DEV_MD
  48.595 +		if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  48.596 +			md_autodetect_dev(MKDEV(hd->major,minor));
  48.597 +		}
  48.598 +#endif
  48.599 +		if (is_extended_partition(p)) {
  48.600 +			unsigned long size = hd->part[minor].nr_sects;
  48.601 +			printk(" <");
  48.602 +			/* prevent someone doing mkfs or mkswap on an
  48.603 +			   extended partition, but leave room for LILO */
  48.604 +			if (size > 2)
  48.605 +				hd->part[minor].nr_sects = 2;
  48.606 +			extended_partition(hd, bdev, minor, size, &current_minor);
  48.607 +			printk(" >");
  48.608 +		}
  48.609 +	}
  48.610 +
  48.611 +	/*
  48.612 +	 *  Check for old-style Disk Manager partition table
  48.613 +	 */
  48.614 +	if (msdos_magic_present(data + 0xfc)) {
  48.615 +		p = (struct partition *) (0x1be + data);
  48.616 +		for (i = 4 ; i < 16 ; i++, current_minor++) {
  48.617 +			p--;
  48.618 +			if ((current_minor & mask) == 0)
  48.619 +				break;
  48.620 +			if (!(START_SECT(p) && NR_SECTS(p)))
  48.621 +				continue;
  48.622 +			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
  48.623 +		}
  48.624 +	}
  48.625 +	printk("\n");
  48.626 +
  48.627 +	/* second pass - output for each on a separate line */
  48.628 +	minor -= 4;
  48.629 +	p = (struct partition *) (0x1be + data);
  48.630 +	for (i=1 ; i<=4 ; minor++,i++,p++) {
  48.631 +		unsigned char id = SYS_IND(p);
  48.632 +		int n;
  48.633 +
  48.634 +		if (!NR_SECTS(p))
  48.635 +			continue;
  48.636 +
  48.637 +		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
  48.638 +			;
  48.639 +
  48.640 +		if (subtypes[n].parse)
  48.641 +			subtypes[n].parse(hd, bdev, minor, &current_minor);
  48.642 +	}
  48.643 +	put_dev_sector(sect);
  48.644 +	return 1;
  48.645 +}
    49.1 --- a/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h	Tue Feb 11 17:54:17 2003 +0000
    49.2 +++ b/xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor.h	Thu Feb 13 15:58:34 2003 +0000
    49.3 @@ -258,6 +258,16 @@ static inline int HYPERVISOR_network_op(
    49.4      return ret;
    49.5  }
    49.6  
    49.7 +static inline int HYPERVISOR_block_io_op(void)
    49.8 +{
    49.9 +    int ret;
   49.10 +    __asm__ __volatile__ (
   49.11 +        TRAP_INSTR
   49.12 +        : "=a" (ret) : "0" (__HYPERVISOR_block_io_op) ); 
   49.13 +
   49.14 +    return ret;
   49.15 +}
   49.16 +
   49.17  static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value)
   49.18  {
   49.19      int ret;
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/xenolinux-2.4.16-sparse/include/linux/blk.h	Thu Feb 13 15:58:34 2003 +0000
    50.3 @@ -0,0 +1,416 @@
    50.4 +#ifndef _BLK_H
    50.5 +#define _BLK_H
    50.6 +
    50.7 +#include <linux/blkdev.h>
    50.8 +#include <linux/locks.h>
    50.9 +#include <linux/config.h>
   50.10 +#include <linux/spinlock.h>
   50.11 +
   50.12 +/*
   50.13 + * Spinlock for protecting the request queue which
   50.14 + * is mucked around with in interrupts on potentially
   50.15 + * multiple CPU's..
   50.16 + */
   50.17 +extern spinlock_t io_request_lock;
   50.18 +
   50.19 +/*
   50.20 + * Initialization functions.
   50.21 + */
   50.22 +extern int isp16_init(void);
   50.23 +extern int cdu31a_init(void);
   50.24 +extern int acsi_init(void);
   50.25 +extern int mcd_init(void);
   50.26 +extern int mcdx_init(void);
   50.27 +extern int sbpcd_init(void);
   50.28 +extern int aztcd_init(void);
   50.29 +extern int sony535_init(void);
   50.30 +extern int gscd_init(void);
   50.31 +extern int cm206_init(void);
   50.32 +extern int optcd_init(void);
   50.33 +extern int sjcd_init(void);
   50.34 +extern int cdi_init(void);
   50.35 +extern int hd_init(void);
   50.36 +extern int ide_init(void);
   50.37 +extern int xd_init(void);
   50.38 +extern int mfm_init(void);
   50.39 +extern int loop_init(void);
   50.40 +extern int md_init(void);
   50.41 +extern int ap_init(void);
   50.42 +extern int ddv_init(void);
   50.43 +extern int z2_init(void);
   50.44 +extern int swim3_init(void);
   50.45 +extern int swimiop_init(void);
   50.46 +extern int amiga_floppy_init(void);
   50.47 +extern int atari_floppy_init(void);
   50.48 +extern int ez_init(void);
   50.49 +extern int bpcd_init(void);
   50.50 +extern int ps2esdi_init(void);
   50.51 +extern int jsfd_init(void);
   50.52 +extern int viodasd_init(void);
   50.53 +extern int viocd_init(void);
   50.54 +extern int xlblk_init(void);
   50.55 +
   50.56 +#if defined(CONFIG_ARCH_S390)
   50.57 +extern int dasd_init(void);
   50.58 +extern int xpram_init(void);
   50.59 +extern int tapeblock_init(void);
   50.60 +#endif /* CONFIG_ARCH_S390 */
   50.61 +
   50.62 +extern void set_device_ro(kdev_t dev,int flag);
   50.63 +void add_blkdev_randomness(int major);
   50.64 +
   50.65 +extern int floppy_init(void);
   50.66 +extern void rd_load(void);
   50.67 +extern int rd_init(void);
   50.68 +extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
   50.69 +extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
   50.70 +extern int rd_image_start;	/* starting block # of image */
   50.71 +
   50.72 +#ifdef CONFIG_BLK_DEV_INITRD
   50.73 +
   50.74 +#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
   50.75 +
   50.76 +extern unsigned long initrd_start,initrd_end;
   50.77 +extern int mount_initrd; /* zero if initrd should not be mounted */
   50.78 +extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
   50.79 +void initrd_init(void);
   50.80 +
   50.81 +#endif
   50.82 +
   50.83 +		 
   50.84 +/*
   50.85 + * end_request() and friends. Must be called with the request queue spinlock
   50.86 + * acquired. All functions called within end_request() _must_be_ atomic.
   50.87 + *
   50.88 + * Several drivers define their own end_request and call
   50.89 + * end_that_request_first() and end_that_request_last()
   50.90 + * for parts of the original function. This prevents
   50.91 + * code duplication in drivers.
   50.92 + */
   50.93 +
   50.94 +static inline void blkdev_dequeue_request(struct request * req)
   50.95 +{
   50.96 +	list_del(&req->queue);
   50.97 +}
   50.98 +
   50.99 +int end_that_request_first(struct request *req, int uptodate, char *name);
  50.100 +void end_that_request_last(struct request *req);
  50.101 +
  50.102 +#if defined(MAJOR_NR) || defined(IDE_DRIVER)
  50.103 +
  50.104 +#undef DEVICE_ON
  50.105 +#undef DEVICE_OFF
  50.106 +
  50.107 +/*
  50.108 + * Add entries as needed.
  50.109 + */
  50.110 +
  50.111 +#ifdef IDE_DRIVER
  50.112 +
  50.113 +#define DEVICE_NR(device)	(MINOR(device) >> PARTN_BITS)
  50.114 +#define DEVICE_NAME "ide"
  50.115 +
  50.116 +#elif (MAJOR_NR == RAMDISK_MAJOR)
  50.117 +
  50.118 +/* ram disk */
  50.119 +#define DEVICE_NAME "ramdisk"
  50.120 +#define DEVICE_NR(device) (MINOR(device))
  50.121 +#define DEVICE_NO_RANDOM
  50.122 +
  50.123 +#elif (MAJOR_NR == Z2RAM_MAJOR)
  50.124 +
  50.125 +/* Zorro II Ram */
  50.126 +#define DEVICE_NAME "Z2RAM"
  50.127 +#define DEVICE_REQUEST do_z2_request
  50.128 +#define DEVICE_NR(device) (MINOR(device))
  50.129 +
  50.130 +#elif (MAJOR_NR == FLOPPY_MAJOR)
  50.131 +
  50.132 +static void floppy_off(unsigned int nr);
  50.133 +
  50.134 +#define DEVICE_NAME "floppy"
  50.135 +#define DEVICE_INTR do_floppy
  50.136 +#define DEVICE_REQUEST do_fd_request
  50.137 +#define DEVICE_NR(device) ( (MINOR(device) & 3) | ((MINOR(device) & 0x80 ) >> 5 ))
  50.138 +#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
  50.139 +
  50.140 +#elif (MAJOR_NR == HD_MAJOR)
  50.141 +
  50.142 +/* Hard disk:  timeout is 6 seconds. */
  50.143 +#define DEVICE_NAME "hard disk"
  50.144 +#define DEVICE_INTR do_hd
  50.145 +#define TIMEOUT_VALUE (6*HZ)
  50.146 +#define DEVICE_REQUEST do_hd_request
  50.147 +#define DEVICE_NR(device) (MINOR(device)>>6)
  50.148 +
  50.149 +#elif (SCSI_DISK_MAJOR(MAJOR_NR))
  50.150 +
  50.151 +#define DEVICE_NAME "scsidisk"
  50.152 +#define TIMEOUT_VALUE (2*HZ)
  50.153 +#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
  50.154 +
  50.155 +/* Kludge to use the same number for both char and block major numbers */
  50.156 +#elif  (MAJOR_NR == MD_MAJOR) && defined(MD_DRIVER)
  50.157 +
  50.158 +#define DEVICE_NAME "Multiple devices driver"
  50.159 +#define DEVICE_REQUEST do_md_request
  50.160 +#define DEVICE_NR(device) (MINOR(device))
  50.161 +
  50.162 +#elif (MAJOR_NR == SCSI_TAPE_MAJOR)
  50.163 +
  50.164 +#define DEVICE_NAME "scsitape"
  50.165 +#define DEVICE_INTR do_st  
  50.166 +#define DEVICE_NR(device) (MINOR(device) & 0x7f)
  50.167 +
  50.168 +#elif (MAJOR_NR == OSST_MAJOR)
  50.169 +
  50.170 +#define DEVICE_NAME "onstream" 
  50.171 +#define DEVICE_INTR do_osst
  50.172 +#define DEVICE_NR(device) (MINOR(device) & 0x7f) 
  50.173 +#define DEVICE_ON(device) 
  50.174 +#define DEVICE_OFF(device) 
  50.175 +
  50.176 +#elif (MAJOR_NR == SCSI_CDROM_MAJOR)
  50.177 +
  50.178 +#define DEVICE_NAME "CD-ROM"
  50.179 +#define DEVICE_NR(device) (MINOR(device))
  50.180 +
  50.181 +#elif (MAJOR_NR == XT_DISK_MAJOR)
  50.182 +
  50.183 +#define DEVICE_NAME "xt disk"
  50.184 +#define DEVICE_REQUEST do_xd_request
  50.185 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  50.186 +
  50.187 +#elif (MAJOR_NR == PS2ESDI_MAJOR)
  50.188 +
  50.189 +#define DEVICE_NAME "PS/2 ESDI"
  50.190 +#define DEVICE_REQUEST do_ps2esdi_request
  50.191 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  50.192 +
  50.193 +#elif (MAJOR_NR == CDU31A_CDROM_MAJOR)
  50.194 +
  50.195 +#define DEVICE_NAME "CDU31A"
  50.196 +#define DEVICE_REQUEST do_cdu31a_request
  50.197 +#define DEVICE_NR(device) (MINOR(device))
  50.198 +
  50.199 +#elif (MAJOR_NR == ACSI_MAJOR) && (defined(CONFIG_ATARI_ACSI) || defined(CONFIG_ATARI_ACSI_MODULE))
  50.200 +
  50.201 +#define DEVICE_NAME "ACSI"
  50.202 +#define DEVICE_INTR do_acsi
  50.203 +#define DEVICE_REQUEST do_acsi_request
  50.204 +#define DEVICE_NR(device) (MINOR(device) >> 4)
  50.205 +
  50.206 +#elif (MAJOR_NR == MITSUMI_CDROM_MAJOR)
  50.207 +
  50.208 +#define DEVICE_NAME "Mitsumi CD-ROM"
  50.209 +/* #define DEVICE_INTR do_mcd */
  50.210 +#define DEVICE_REQUEST do_mcd_request
  50.211 +#define DEVICE_NR(device) (MINOR(device))
  50.212 +
  50.213 +#elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR)
  50.214 +
  50.215 +#define DEVICE_NAME "Mitsumi CD-ROM"
  50.216 +/* #define DEVICE_INTR do_mcdx */
  50.217 +#define DEVICE_REQUEST do_mcdx_request
  50.218 +#define DEVICE_NR(device) (MINOR(device))
  50.219 +
  50.220 +#elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR)
  50.221 +
  50.222 +#define DEVICE_NAME "Matsushita CD-ROM controller #1"
  50.223 +#define DEVICE_REQUEST do_sbpcd_request
  50.224 +#define DEVICE_NR(device) (MINOR(device))
  50.225 +
  50.226 +#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR)
  50.227 +
  50.228 +#define DEVICE_NAME "Matsushita CD-ROM controller #2"
  50.229 +#define DEVICE_REQUEST do_sbpcd2_request
  50.230 +#define DEVICE_NR(device) (MINOR(device))
  50.231 +
  50.232 +#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR)
  50.233 +
  50.234 +#define DEVICE_NAME "Matsushita CD-ROM controller #3"
  50.235 +#define DEVICE_REQUEST do_sbpcd3_request
  50.236 +#define DEVICE_NR(device) (MINOR(device))
  50.237 +
  50.238 +#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR)
  50.239 +
  50.240 +#define DEVICE_NAME "Matsushita CD-ROM controller #4"
  50.241 +#define DEVICE_REQUEST do_sbpcd4_request
  50.242 +#define DEVICE_NR(device) (MINOR(device))
  50.243 +
  50.244 +#elif (MAJOR_NR == AZTECH_CDROM_MAJOR)
  50.245 +
  50.246 +#define DEVICE_NAME "Aztech CD-ROM"
  50.247 +#define DEVICE_REQUEST do_aztcd_request
  50.248 +#define DEVICE_NR(device) (MINOR(device))
  50.249 +
  50.250 +#elif (MAJOR_NR == CDU535_CDROM_MAJOR)
  50.251 +
  50.252 +#define DEVICE_NAME "SONY-CDU535"
  50.253 +#define DEVICE_INTR do_cdu535
  50.254 +#define DEVICE_REQUEST do_cdu535_request
  50.255 +#define DEVICE_NR(device) (MINOR(device))
  50.256 +
  50.257 +#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR)
  50.258 +
  50.259 +#define DEVICE_NAME "Goldstar R420"
  50.260 +#define DEVICE_REQUEST do_gscd_request
  50.261 +#define DEVICE_NR(device) (MINOR(device))
  50.262 +
  50.263 +#elif (MAJOR_NR == CM206_CDROM_MAJOR)
  50.264 +#define DEVICE_NAME "Philips/LMS CD-ROM cm206"
  50.265 +#define DEVICE_REQUEST do_cm206_request
  50.266 +#define DEVICE_NR(device) (MINOR(device))
  50.267 +
  50.268 +#elif (MAJOR_NR == OPTICS_CDROM_MAJOR)
  50.269 +
  50.270 +#define DEVICE_NAME "DOLPHIN 8000AT CD-ROM"
  50.271 +#define DEVICE_REQUEST do_optcd_request
  50.272 +#define DEVICE_NR(device) (MINOR(device))
  50.273 +
  50.274 +#elif (MAJOR_NR == SANYO_CDROM_MAJOR)
  50.275 +
  50.276 +#define DEVICE_NAME "Sanyo H94A CD-ROM"
  50.277 +#define DEVICE_REQUEST do_sjcd_request
  50.278 +#define DEVICE_NR(device) (MINOR(device))
  50.279 +
  50.280 +#elif (MAJOR_NR == APBLOCK_MAJOR)
  50.281 +
  50.282 +#define DEVICE_NAME "apblock"
  50.283 +#define DEVICE_REQUEST ap_request
  50.284 +#define DEVICE_NR(device) (MINOR(device))
  50.285 +
  50.286 +#elif (MAJOR_NR == DDV_MAJOR)
  50.287 +
  50.288 +#define DEVICE_NAME "ddv"
  50.289 +#define DEVICE_REQUEST ddv_request
  50.290 +#define DEVICE_NR(device) (MINOR(device)>>PARTN_BITS)
  50.291 +
  50.292 +#elif (MAJOR_NR == MFM_ACORN_MAJOR)
  50.293 +
  50.294 +#define DEVICE_NAME "mfm disk"
  50.295 +#define DEVICE_INTR do_mfm
  50.296 +#define DEVICE_REQUEST do_mfm_request
  50.297 +#define DEVICE_NR(device) (MINOR(device) >> 6)
  50.298 +
  50.299 +#elif (MAJOR_NR == NBD_MAJOR)
  50.300 +
  50.301 +#define DEVICE_NAME "nbd"
  50.302 +#define DEVICE_REQUEST do_nbd_request
  50.303 +#define DEVICE_NR(device) (MINOR(device))
  50.304 +
  50.305 +#elif (MAJOR_NR == MDISK_MAJOR)
  50.306 +
  50.307 +#define DEVICE_NAME "mdisk"
  50.308 +#define DEVICE_REQUEST mdisk_request
  50.309 +#define DEVICE_NR(device) (MINOR(device))
  50.310 +
  50.311 +#elif (MAJOR_NR == DASD_MAJOR)
  50.312 +
  50.313 +#define DEVICE_NAME "dasd"
  50.314 +#define DEVICE_REQUEST do_dasd_request
  50.315 +#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)
  50.316 +
  50.317 +#elif (MAJOR_NR == I2O_MAJOR)
  50.318 +
  50.319 +#define DEVICE_NAME "I2O block"
  50.320 +#define DEVICE_REQUEST i2ob_request
  50.321 +#define DEVICE_NR(device) (MINOR(device)>>4)
  50.322 +
  50.323 +#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
  50.324 +
  50.325 +#define DEVICE_NAME "ida"
  50.326 +#define TIMEOUT_VALUE (25*HZ)
  50.327 +#define DEVICE_REQUEST do_ida_request
  50.328 +#define DEVICE_NR(device) (MINOR(device) >> 4)
  50.329 +
  50.330 +#elif (MAJOR_NR == XLBLK_MAJOR)
  50.331 +
  50.332 +#define DEVICE_NAME "blk"
  50.333 +#define DEVICE_REQUEST do_xlblk_request
  50.334 +/* #define DEVICE_INTR */
  50.335 +#define DEVICE_NR(device) (MINOR(device))
  50.336 +
  50.337 +#endif /* MAJOR_NR == whatever */
  50.338 +
  50.339 +/* provide DEVICE_xxx defaults, if not explicitly defined
  50.340 + * above in the MAJOR_NR==xxx if-elif tree */
  50.341 +#ifndef DEVICE_ON
  50.342 +#define DEVICE_ON(device) do {} while (0)
  50.343 +#endif
  50.344 +#ifndef DEVICE_OFF
  50.345 +#define DEVICE_OFF(device) do {} while (0)
  50.346 +#endif
  50.347 +
  50.348 +#if (MAJOR_NR != SCSI_TAPE_MAJOR) && (MAJOR_NR != OSST_MAJOR)
  50.349 +#if !defined(IDE_DRIVER)
  50.350 +
  50.351 +#ifndef CURRENT
  50.352 +#define CURRENT blkdev_entry_next_request(&blk_dev[MAJOR_NR].request_queue.queue_head)
  50.353 +#endif
  50.354 +#ifndef QUEUE_EMPTY
  50.355 +#define QUEUE_EMPTY list_empty(&blk_dev[MAJOR_NR].request_queue.queue_head)
  50.356 +#endif
  50.357 +
  50.358 +#ifndef DEVICE_NAME
  50.359 +#define DEVICE_NAME "unknown"
  50.360 +#endif
  50.361 +
  50.362 +#define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev)
  50.363 +
  50.364 +#ifdef DEVICE_INTR
  50.365 +static void (*DEVICE_INTR)(void) = NULL;
  50.366 +#endif
  50.367 +
  50.368 +#define SET_INTR(x) (DEVICE_INTR = (x))
  50.369 +
  50.370 +#ifdef DEVICE_REQUEST
  50.371 +static void (DEVICE_REQUEST)(request_queue_t *);
  50.372 +#endif 
  50.373 +  
  50.374 +#ifdef DEVICE_INTR
  50.375 +#define CLEAR_INTR SET_INTR(NULL)
  50.376 +#else
  50.377 +#define CLEAR_INTR
  50.378 +#endif
  50.379 +
  50.380 +#define INIT_REQUEST \
  50.381 +	if (QUEUE_EMPTY) {\
  50.382 +		CLEAR_INTR; \
  50.383 +		return; \
  50.384 +	} \
  50.385 +	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
  50.386 +		panic(DEVICE_NAME ": request list destroyed"); \
  50.387 +	if (CURRENT->bh) { \
  50.388 +		if (!buffer_locked(CURRENT->bh)) \
  50.389 +			panic(DEVICE_NAME ": block not locked"); \
  50.390 +	}
  50.391 +
  50.392 +#endif /* !defined(IDE_DRIVER) */
  50.393 +
  50.394 +
  50.395 +#ifndef LOCAL_END_REQUEST	/* If we have our own end_request, we do not want to include this mess */
  50.396 +
  50.397 +#if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
  50.398 +
  50.399 +static inline void end_request(int uptodate) {
  50.400 +	struct request *req = CURRENT;
  50.401 +
  50.402 +	if (end_that_request_first(req, uptodate, DEVICE_NAME))
  50.403 +		return;
  50.404 +
  50.405 +#ifndef DEVICE_NO_RANDOM
  50.406 +	add_blkdev_randomness(MAJOR(req->rq_dev));
  50.407 +#endif
  50.408 +	DEVICE_OFF(req->rq_dev);
  50.409 +	blkdev_dequeue_request(req);
  50.410 +	end_that_request_last(req);
  50.411 +}
  50.412 +
  50.413 +#endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
  50.414 +#endif /* LOCAL_END_REQUEST */
  50.415 +
  50.416 +#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
  50.417 +#endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
  50.418 +
  50.419 +#endif /* _BLK_H */
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/xenolinux-2.4.16-sparse/include/linux/major.h	Thu Feb 13 15:58:34 2003 +0000
    51.3 @@ -0,0 +1,199 @@
    51.4 +#ifndef _LINUX_MAJOR_H
    51.5 +#define _LINUX_MAJOR_H
    51.6 +
    51.7 +/*
    51.8 + * This file has definitions for major device numbers.
    51.9 + * For the device number assignments, see Documentation/devices.txt.
   51.10 + */
   51.11 +
   51.12 +/* limits */
   51.13 +
   51.14 +/*
   51.15 + * Important: Don't change this to 256.  Major number 255 is and must be
   51.16 + * reserved for future expansion into a larger dev_t space.
   51.17 + */
   51.18 +#define MAX_CHRDEV	255
   51.19 +#define MAX_BLKDEV	255
   51.20 +
   51.21 +#define UNNAMED_MAJOR	0
   51.22 +#define MEM_MAJOR	1
   51.23 +#define RAMDISK_MAJOR	1
   51.24 +#define FLOPPY_MAJOR	2
   51.25 +#define PTY_MASTER_MAJOR 2
   51.26 +#define IDE0_MAJOR	3
   51.27 +#define PTY_SLAVE_MAJOR 3
   51.28 +#define HD_MAJOR	IDE0_MAJOR
   51.29 +#define TTY_MAJOR	4
   51.30 +#define TTYAUX_MAJOR	5
   51.31 +#define LP_MAJOR	6
   51.32 +#define VCS_MAJOR	7
   51.33 +#define LOOP_MAJOR	7
   51.34 +#define SCSI_DISK0_MAJOR 8
   51.35 +#define SCSI_TAPE_MAJOR	9
   51.36 +#define MD_MAJOR        9
   51.37 +#define MISC_MAJOR	10
   51.38 +#define SCSI_CDROM_MAJOR 11
   51.39 +#define QIC02_TAPE_MAJOR 12
   51.40 +#define XT_DISK_MAJOR	13
   51.41 +#define SOUND_MAJOR	14
   51.42 +#define CDU31A_CDROM_MAJOR 15
   51.43 +#define JOYSTICK_MAJOR	15
   51.44 +#define GOLDSTAR_CDROM_MAJOR 16
   51.45 +#define OPTICS_CDROM_MAJOR 17
   51.46 +#define SANYO_CDROM_MAJOR 18
   51.47 +#define CYCLADES_MAJOR  19
   51.48 +#define CYCLADESAUX_MAJOR 20
   51.49 +#define MITSUMI_X_CDROM_MAJOR 20
   51.50 +#define MFM_ACORN_MAJOR 21	/* ARM Linux /dev/mfm */
   51.51 +#define SCSI_GENERIC_MAJOR 21
   51.52 +#define Z8530_MAJOR 34
   51.53 +#define DIGI_MAJOR 23
   51.54 +#define IDE1_MAJOR	22
   51.55 +#define DIGICU_MAJOR 22
   51.56 +#define MITSUMI_CDROM_MAJOR 23
   51.57 +#define CDU535_CDROM_MAJOR 24
   51.58 +#define STL_SERIALMAJOR 24
   51.59 +#define MATSUSHITA_CDROM_MAJOR 25
   51.60 +#define STL_CALLOUTMAJOR 25
   51.61 +#define MATSUSHITA_CDROM2_MAJOR 26
   51.62 +#define QIC117_TAPE_MAJOR 27
   51.63 +#define MATSUSHITA_CDROM3_MAJOR 27
   51.64 +#define MATSUSHITA_CDROM4_MAJOR 28
   51.65 +#define STL_SIOMEMMAJOR 28
   51.66 +#define ACSI_MAJOR	28
   51.67 +#define AZTECH_CDROM_MAJOR 29
   51.68 +#define GRAPHDEV_MAJOR	29	/* SparcLinux & Linux/68k /dev/fb */
   51.69 +#define SHMIQ_MAJOR	85	/* Linux/mips, SGI /dev/shmiq */
   51.70 +#define CM206_CDROM_MAJOR 32
   51.71 +#define IDE2_MAJOR	33
   51.72 +#define IDE3_MAJOR	34
   51.73 +#define XPRAM_MAJOR     35      /* expanded storage on S/390 = "slow ram" */
   51.74 +                                /* proposed by Peter                      */
   51.75 +#define NETLINK_MAJOR	36
   51.76 +#define PS2ESDI_MAJOR	36
   51.77 +#define IDETAPE_MAJOR	37
   51.78 +#define Z2RAM_MAJOR	37
   51.79 +#define APBLOCK_MAJOR   38   /* AP1000 Block device */
   51.80 +#define DDV_MAJOR       39   /* AP1000 DDV block device */
   51.81 +#define NBD_MAJOR	43   /* Network block device	*/
   51.82 +#define RISCOM8_NORMAL_MAJOR 48
   51.83 +#define DAC960_MAJOR	48	/* 48..55 */
   51.84 +#define RISCOM8_CALLOUT_MAJOR 49
   51.85 +#define MKISS_MAJOR	55
   51.86 +#define DSP56K_MAJOR    55   /* DSP56001 processor device */
   51.87 +
   51.88 +#define IDE4_MAJOR	56
   51.89 +#define IDE5_MAJOR	57
   51.90 +
   51.91 +#define LVM_BLK_MAJOR	58	/* Logical Volume Manager */
   51.92 +
   51.93 +#define SCSI_DISK1_MAJOR	65
   51.94 +#define SCSI_DISK2_MAJOR	66
   51.95 +#define SCSI_DISK3_MAJOR	67
   51.96 +#define SCSI_DISK4_MAJOR	68
   51.97 +#define SCSI_DISK5_MAJOR	69
   51.98 +#define SCSI_DISK6_MAJOR	70
   51.99 +#define SCSI_DISK7_MAJOR	71
  51.100 +
  51.101 +
  51.102 +#define COMPAQ_SMART2_MAJOR	72
  51.103 +#define COMPAQ_SMART2_MAJOR1	73
  51.104 +#define COMPAQ_SMART2_MAJOR2	74
  51.105 +#define COMPAQ_SMART2_MAJOR3	75
  51.106 +#define COMPAQ_SMART2_MAJOR4	76
  51.107 +#define COMPAQ_SMART2_MAJOR5	77
  51.108 +#define COMPAQ_SMART2_MAJOR6	78
  51.109 +#define COMPAQ_SMART2_MAJOR7	79
  51.110 +
  51.111 +#define SPECIALIX_NORMAL_MAJOR 75
  51.112 +#define SPECIALIX_CALLOUT_MAJOR 76
  51.113 +
  51.114 +#define COMPAQ_CISS_MAJOR 	104
  51.115 +#define COMPAQ_CISS_MAJOR1	105
  51.116 +#define COMPAQ_CISS_MAJOR2      106
  51.117 +#define COMPAQ_CISS_MAJOR3      107
  51.118 +#define COMPAQ_CISS_MAJOR4      108
  51.119 +#define COMPAQ_CISS_MAJOR5      109
  51.120 +#define COMPAQ_CISS_MAJOR6      110
  51.121 +#define COMPAQ_CISS_MAJOR7      111
  51.122 +
  51.123 +#define ATARAID_MAJOR		114
  51.124 +
  51.125 +#define DASD_MAJOR      94	/* Official assignations from Peter */
  51.126 +
  51.127 +#define MDISK_MAJOR     95	/* Official assignations from Peter */
  51.128 +
  51.129 +#define I2O_MAJOR		80	/* 80->87 */
  51.130 +
  51.131 +#define IDE6_MAJOR	88
  51.132 +#define IDE7_MAJOR	89
  51.133 +#define IDE8_MAJOR	90
  51.134 +#define IDE9_MAJOR	91
  51.135 +
  51.136 +#define UBD_MAJOR	98
  51.137 +
  51.138 +#define AURORA_MAJOR 79
  51.139 +
  51.140 +#define JSFD_MAJOR	99
  51.141 +
  51.142 +#define PHONE_MAJOR	100
  51.143 +
  51.144 +#define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
  51.145 +
  51.146 +#define	UMEM_MAJOR	116	/* http://www.umem.com/ Battery Backed RAM */
  51.147 +
  51.148 +#define XLBLK_MAJOR	123	/* XenoLinux Block Device */
  51.149 +
  51.150 +#define RTF_MAJOR	150
  51.151 +#define RAW_MAJOR	162
  51.152 +
  51.153 +#define USB_ACM_MAJOR		166
  51.154 +#define USB_ACM_AUX_MAJOR	167
  51.155 +#define USB_CHAR_MAJOR		180
  51.156 +
  51.157 +#define UNIX98_PTY_MASTER_MAJOR	128
  51.158 +#define UNIX98_PTY_MAJOR_COUNT	8
  51.159 +#define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
  51.160 +
  51.161 +#define VXVM_MAJOR		199	/* VERITAS volume i/o driver    */
  51.162 +#define VXSPEC_MAJOR		200	/* VERITAS volume config driver */
  51.163 +#define VXDMP_MAJOR		201	/* VERITAS volume multipath driver */
  51.164 +
  51.165 +#define MSR_MAJOR		202
  51.166 +#define CPUID_MAJOR		203
  51.167 +
  51.168 +#define OSST_MAJOR	206	/* OnStream-SCx0 SCSI tape */
  51.169 +
  51.170 +#define IBM_TTY3270_MAJOR       227	/* Official allocations now */
  51.171 +#define IBM_FS3270_MAJOR        228
  51.172 +
  51.173 +/*
  51.174 + * Tests for SCSI devices.
  51.175 + */
  51.176 +
  51.177 +#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
  51.178 +  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
  51.179 +  
  51.180 +#define SCSI_BLK_MAJOR(M) \
  51.181 +  (SCSI_DISK_MAJOR(M)	\
  51.182 +   || (M) == SCSI_CDROM_MAJOR)
  51.183 +
  51.184 +static __inline__ int scsi_blk_major(int m) {
  51.185 +	return SCSI_BLK_MAJOR(m);
  51.186 +}
  51.187 +
  51.188 +/*
  51.189 + * Tests for IDE devices
  51.190 + */
  51.191 +#define IDE_DISK_MAJOR(M)	((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
  51.192 +				(M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
  51.193 +				(M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
  51.194 +				(M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
  51.195 +				(M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
  51.196 +
  51.197 +static __inline__ int ide_blk_major(int m)
  51.198 +{
  51.199 +	return IDE_DISK_MAJOR(m);
  51.200 +}
  51.201 +
  51.202 +#endif
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/xenolinux-2.4.16-sparse/init/main.c	Thu Feb 13 15:58:34 2003 +0000
    52.3 @@ -0,0 +1,871 @@
    52.4 +/*
    52.5 + *  linux/init/main.c
    52.6 + *
    52.7 + *  Copyright (C) 1991, 1992  Linus Torvalds
    52.8 + *
    52.9 + *  GK 2/5/95  -  Changed to support mounting root fs via NFS
   52.10 + *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
   52.11 + *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
   52.12 + *  Simplified starting of init:  Michael A. Griffith <grif@acm.org> 
   52.13 + */
   52.14 +
   52.15 +#define __KERNEL_SYSCALLS__
   52.16 +
   52.17 +#include <linux/config.h>
   52.18 +#include <linux/proc_fs.h>
   52.19 +#include <linux/devfs_fs_kernel.h>
   52.20 +#include <linux/unistd.h>
   52.21 +#include <linux/string.h>
   52.22 +#include <linux/ctype.h>
   52.23 +#include <linux/delay.h>
   52.24 +#include <linux/utsname.h>
   52.25 +#include <linux/ioport.h>
   52.26 +#include <linux/init.h>
   52.27 +#include <linux/smp_lock.h>
   52.28 +#include <linux/blk.h>
   52.29 +#include <linux/hdreg.h>
   52.30 +#include <linux/iobuf.h>
   52.31 +#include <linux/bootmem.h>
   52.32 +#include <linux/tty.h>
   52.33 +
   52.34 +#include <asm/io.h>
   52.35 +#include <asm/bugs.h>
   52.36 +
   52.37 +#if defined(CONFIG_ARCH_S390)
   52.38 +#include <asm/s390mach.h>
   52.39 +#include <asm/ccwcache.h>
   52.40 +#endif
   52.41 +
   52.42 +#ifdef CONFIG_PCI
   52.43 +#include <linux/pci.h>
   52.44 +#endif
   52.45 +
   52.46 +#ifdef CONFIG_DIO
   52.47 +#include <linux/dio.h>
   52.48 +#endif
   52.49 +
   52.50 +#ifdef CONFIG_ZORRO
   52.51 +#include <linux/zorro.h>
   52.52 +#endif
   52.53 +
   52.54 +#ifdef CONFIG_MTRR
   52.55 +#  include <asm/mtrr.h>
   52.56 +#endif
   52.57 +
   52.58 +#ifdef CONFIG_NUBUS
   52.59 +#include <linux/nubus.h>
   52.60 +#endif
   52.61 +
   52.62 +#ifdef CONFIG_ISAPNP
   52.63 +#include <linux/isapnp.h>
   52.64 +#endif
   52.65 +
   52.66 +#ifdef CONFIG_IRDA
   52.67 +extern int irda_proto_init(void);
   52.68 +extern int irda_device_init(void);
   52.69 +#endif
   52.70 +
   52.71 +#ifdef CONFIG_X86_LOCAL_APIC
   52.72 +#include <asm/smp.h>
   52.73 +#endif
   52.74 +
   52.75 +#if defined(CONFIG_KDB)
   52.76 +#include <linux/kdb.h>
   52.77 +#endif
   52.78 +
   52.79 +/*
   52.80 + * Versions of gcc older than that listed below may actually compile
   52.81 + * and link okay, but the end product can have subtle run time bugs.
   52.82 + * To avoid associated bogus bug reports, we flatly refuse to compile
   52.83 + * with a gcc that is known to be too old from the very beginning.
   52.84 + */
   52.85 +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91)
   52.86 +#error Sorry, your GCC is too old. It builds incorrect kernels.
   52.87 +#endif
   52.88 +
   52.89 +extern char _stext, _etext;
   52.90 +extern char *linux_banner;
   52.91 +
   52.92 +static int init(void *);
   52.93 +
   52.94 +extern void init_IRQ(void);
   52.95 +extern void init_modules(void);
   52.96 +extern void sock_init(void);
   52.97 +extern void fork_init(unsigned long);
   52.98 +extern void mca_init(void);
   52.99 +extern void sbus_init(void);
  52.100 +extern void ppc_init(void);
  52.101 +extern void sysctl_init(void);
  52.102 +extern void signals_init(void);
  52.103 +extern int init_pcmcia_ds(void);
  52.104 +
  52.105 +extern void free_initmem(void);
  52.106 +
  52.107 +#ifdef CONFIG_TC
  52.108 +extern void tc_init(void);
  52.109 +#endif
  52.110 +
  52.111 +extern void ecard_init(void);
  52.112 +
  52.113 +#if defined(CONFIG_SYSVIPC)
  52.114 +extern void ipc_init(void);
  52.115 +#endif
  52.116 +
  52.117 +/*
  52.118 + * Boot command-line arguments
  52.119 + */
  52.120 +#define MAX_INIT_ARGS 8
  52.121 +#define MAX_INIT_ENVS 8
  52.122 +
  52.123 +extern void time_init(void);
  52.124 +extern void softirq_init(void);
  52.125 +
  52.126 +int rows, cols;
  52.127 +
  52.128 +#ifdef CONFIG_BLK_DEV_INITRD
  52.129 +unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
  52.130 +#endif
  52.131 +
  52.132 +int root_mountflags = MS_RDONLY;
  52.133 +char *execute_command;
  52.134 +char root_device_name[64];
  52.135 +
  52.136 +
  52.137 +static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
  52.138 +static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
  52.139 +
  52.140 +static int __init profile_setup(char *str)
  52.141 +{
  52.142 +    int par;
  52.143 +    if (get_option(&str,&par)) prof_shift = par;
  52.144 +	return 1;
  52.145 +}
  52.146 +
  52.147 +__setup("profile=", profile_setup);
  52.148 +
  52.149 +
  52.150 +static struct dev_name_struct {
  52.151 +	const char *name;
  52.152 +	const int num;
  52.153 +} root_dev_names[] __initdata = {
  52.154 +	{ "nfs",     0x00ff },
  52.155 +        { "blk",     0x7b00 },
  52.156 +	{ "hda",     0x0300 },
  52.157 +	{ "hdb",     0x0340 },
  52.158 +	{ "loop",    0x0700 },
  52.159 +	{ "hdc",     0x1600 },
  52.160 +	{ "hdd",     0x1640 },
  52.161 +	{ "hde",     0x2100 },
  52.162 +	{ "hdf",     0x2140 },
  52.163 +	{ "hdg",     0x2200 },
  52.164 +	{ "hdh",     0x2240 },
  52.165 +	{ "hdi",     0x3800 },
  52.166 +	{ "hdj",     0x3840 },
  52.167 +	{ "hdk",     0x3900 },
  52.168 +	{ "hdl",     0x3940 },
  52.169 +	{ "hdm",     0x5800 },
  52.170 +	{ "hdn",     0x5840 },
  52.171 +	{ "hdo",     0x5900 },
  52.172 +	{ "hdp",     0x5940 },
  52.173 +	{ "hdq",     0x5A00 },
  52.174 +	{ "hdr",     0x5A40 },
  52.175 +	{ "hds",     0x5B00 },
  52.176 +	{ "hdt",     0x5B40 },
  52.177 +	{ "sda",     0x0800 },
  52.178 +	{ "sdb",     0x0810 },
  52.179 +	{ "sdc",     0x0820 },
  52.180 +	{ "sdd",     0x0830 },
  52.181 +	{ "sde",     0x0840 },
  52.182 +	{ "sdf",     0x0850 },
  52.183 +	{ "sdg",     0x0860 },
  52.184 +	{ "sdh",     0x0870 },
  52.185 +	{ "sdi",     0x0880 },
  52.186 +	{ "sdj",     0x0890 },
  52.187 +	{ "sdk",     0x08a0 },
  52.188 +	{ "sdl",     0x08b0 },
  52.189 +	{ "sdm",     0x08c0 },
  52.190 +	{ "sdn",     0x08d0 },
  52.191 +	{ "sdo",     0x08e0 },
  52.192 +	{ "sdp",     0x08f0 },
  52.193 +	{ "ada",     0x1c00 },
  52.194 +	{ "adb",     0x1c10 },
  52.195 +	{ "adc",     0x1c20 },
  52.196 +	{ "add",     0x1c30 },
  52.197 +	{ "ade",     0x1c40 },
  52.198 +	{ "fd",      0x0200 },
  52.199 +	{ "md",      0x0900 },	     
  52.200 +	{ "xda",     0x0d00 },
  52.201 +	{ "xdb",     0x0d40 },
  52.202 +	{ "ram",     0x0100 },
  52.203 +	{ "scd",     0x0b00 },
  52.204 +	{ "mcd",     0x1700 },
  52.205 +	{ "cdu535",  0x1800 },
  52.206 +	{ "sonycd",  0x1800 },
  52.207 +	{ "aztcd",   0x1d00 },
  52.208 +	{ "cm206cd", 0x2000 },
  52.209 +	{ "gscd",    0x1000 },
  52.210 +	{ "sbpcd",   0x1900 },
  52.211 +	{ "eda",     0x2400 },
  52.212 +	{ "edb",     0x2440 },
  52.213 +	{ "pda",	0x2d00 },
  52.214 +	{ "pdb",	0x2d10 },
  52.215 +	{ "pdc",	0x2d20 },
  52.216 +	{ "pdd",	0x2d30 },
  52.217 +	{ "pcd",	0x2e00 },
  52.218 +	{ "pf",		0x2f00 },
  52.219 +	{ "apblock", APBLOCK_MAJOR << 8},
  52.220 +	{ "ddv", DDV_MAJOR << 8},
  52.221 +	{ "jsfd",    JSFD_MAJOR << 8},
  52.222 +#if defined(CONFIG_ARCH_S390)
  52.223 +	{ "dasda", (DASD_MAJOR << MINORBITS) },
  52.224 +	{ "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
  52.225 +	{ "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
  52.226 +	{ "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
  52.227 +	{ "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
  52.228 +	{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
  52.229 +	{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
  52.230 +	{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
  52.231 +#endif
  52.232 +#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
  52.233 +	{ "ida/c0d0p",0x4800 },
  52.234 +	{ "ida/c0d1p",0x4810 },
  52.235 +	{ "ida/c0d2p",0x4820 },
  52.236 +	{ "ida/c0d3p",0x4830 },
  52.237 +	{ "ida/c0d4p",0x4840 },
  52.238 +	{ "ida/c0d5p",0x4850 },
  52.239 +	{ "ida/c0d6p",0x4860 },
  52.240 +	{ "ida/c0d7p",0x4870 },
  52.241 +	{ "ida/c0d8p",0x4880 },
  52.242 +	{ "ida/c0d9p",0x4890 },
  52.243 +	{ "ida/c0d10p",0x48A0 },
  52.244 +	{ "ida/c0d11p",0x48B0 },
  52.245 +	{ "ida/c0d12p",0x48C0 },
  52.246 +	{ "ida/c0d13p",0x48D0 },
  52.247 +	{ "ida/c0d14p",0x48E0 },
  52.248 +	{ "ida/c0d15p",0x48F0 },
  52.249 +#endif
  52.250 +#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
  52.251 +	{ "cciss/c0d0p",0x6800 },
  52.252 +	{ "cciss/c0d1p",0x6810 },
  52.253 +	{ "cciss/c0d2p",0x6820 },
  52.254 +	{ "cciss/c0d3p",0x6830 },
  52.255 +	{ "cciss/c0d4p",0x6840 },
  52.256 +	{ "cciss/c0d5p",0x6850 },
  52.257 +	{ "cciss/c0d6p",0x6860 },
  52.258 +	{ "cciss/c0d7p",0x6870 },
  52.259 +	{ "cciss/c0d8p",0x6880 },
  52.260 +	{ "cciss/c0d9p",0x6890 },
  52.261 +	{ "cciss/c0d10p",0x68A0 },
  52.262 +	{ "cciss/c0d11p",0x68B0 },
  52.263 +	{ "cciss/c0d12p",0x68C0 },
  52.264 +	{ "cciss/c0d13p",0x68D0 },
  52.265 +	{ "cciss/c0d14p",0x68E0 },
  52.266 +	{ "cciss/c0d15p",0x68F0 },
  52.267 +#endif
  52.268 +	{ "nftla", 0x5d00 },
  52.269 +	{ "nftlb", 0x5d10 },
  52.270 +	{ "nftlc", 0x5d20 },
  52.271 +	{ "nftld", 0x5d30 },
  52.272 +	{ "ftla", 0x2c00 },
  52.273 +	{ "ftlb", 0x2c08 },
  52.274 +	{ "ftlc", 0x2c10 },
  52.275 +	{ "ftld", 0x2c18 },
  52.276 +	{ "mtdblock", 0x1f00 },
  52.277 +	{ NULL, 0 }
  52.278 +};
  52.279 +
  52.280 +kdev_t __init name_to_kdev_t(char *line)
  52.281 +{
  52.282 +	int base = 0;
  52.283 +
  52.284 +	if (strncmp(line,"/dev/",5) == 0) {
  52.285 +		struct dev_name_struct *dev = root_dev_names;
  52.286 +		line += 5;
  52.287 +		do {
  52.288 +			int len = strlen(dev->name);
  52.289 +			if (strncmp(line,dev->name,len) == 0) {
  52.290 +				line += len;
  52.291 +				base = dev->num;
  52.292 +				break;
  52.293 +			}
  52.294 +			dev++;
  52.295 +		} while (dev->name);
  52.296 +	}
  52.297 +	return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
  52.298 +}
  52.299 +
  52.300 +static int __init root_dev_setup(char *line)
  52.301 +{
  52.302 +	int i;
  52.303 +	char ch;
  52.304 +
  52.305 +	ROOT_DEV = name_to_kdev_t(line);
  52.306 +	memset (root_device_name, 0, sizeof root_device_name);
  52.307 +	if (strncmp (line, "/dev/", 5) == 0) line += 5;
  52.308 +	for (i = 0; i < sizeof root_device_name - 1; ++i)
  52.309 +	{
  52.310 +	    ch = line[i];
  52.311 +	    if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
  52.312 +	    root_device_name[i] = ch;
  52.313 +	}
  52.314 +	return 1;
  52.315 +}
  52.316 +
  52.317 +__setup("root=", root_dev_setup);
  52.318 +
  52.319 +static int __init checksetup(char *line)
  52.320 +{
  52.321 +	struct kernel_param *p;
  52.322 +
  52.323 +	p = &__setup_start;
  52.324 +	do {
  52.325 +		int n = strlen(p->str);
  52.326 +		if (!strncmp(line,p->str,n)) {
  52.327 +			if (p->setup_func(line+n))
  52.328 +				return 1;
  52.329 +		}
  52.330 +		p++;
  52.331 +	} while (p < &__setup_end);
  52.332 +	return 0;
  52.333 +}
  52.334 +
  52.335 +/* this should be approx 2 Bo*oMips to start (note initial shift), and will
  52.336 +   still work even if initially too large, it will just take slightly longer */
  52.337 +unsigned long loops_per_jiffy = (1<<12);
  52.338 +
  52.339 +/* This is the number of bits of precision for the loops_per_jiffy.  Each
  52.340 +   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
  52.341 +   better than 1% */
  52.342 +#define LPS_PREC 8
  52.343 +
  52.344 +void __init calibrate_delay(void)
  52.345 +{
  52.346 +	unsigned long ticks, loopbit;
  52.347 +	int lps_precision = LPS_PREC;
  52.348 +
  52.349 +	loops_per_jiffy = (1<<12);
  52.350 +
  52.351 +	printk("Calibrating delay loop... ");
  52.352 +	while (loops_per_jiffy <<= 1) {
  52.353 +		/* wait for "start of" clock tick */
  52.354 +		ticks = jiffies;
  52.355 +		while (ticks == jiffies)
  52.356 +			/* nothing */;
  52.357 +		/* Go .. */
  52.358 +		ticks = jiffies;
  52.359 +		__delay(loops_per_jiffy);
  52.360 +		ticks = jiffies - ticks;
  52.361 +		if (ticks)
  52.362 +			break;
  52.363 +	}
  52.364 +
  52.365 +/* Do a binary approximation to get loops_per_jiffy set to equal one clock
  52.366 +   (up to lps_precision bits) */
  52.367 +	loops_per_jiffy >>= 1;
  52.368 +	loopbit = loops_per_jiffy;
  52.369 +	while ( lps_precision-- && (loopbit >>= 1) ) {
  52.370 +		loops_per_jiffy |= loopbit;
  52.371 +		ticks = jiffies;
  52.372 +		while (ticks == jiffies);
  52.373 +		ticks = jiffies;
  52.374 +		__delay(loops_per_jiffy);
  52.375 +		if (jiffies != ticks)	/* longer than 1 tick */
  52.376 +			loops_per_jiffy &= ~loopbit;
  52.377 +	}
  52.378 +
  52.379 +/* Round the value and print it */	
  52.380 +	printk("%lu.%02lu BogoMIPS\n",
  52.381 +		loops_per_jiffy/(500000/HZ),
  52.382 +		(loops_per_jiffy/(5000/HZ)) % 100);
  52.383 +}
  52.384 +
  52.385 +static int __init readonly(char *str)
  52.386 +{
  52.387 +	if (*str)
  52.388 +		return 0;
  52.389 +	root_mountflags |= MS_RDONLY;
  52.390 +	return 1;
  52.391 +}
  52.392 +
  52.393 +static int __init readwrite(char *str)
  52.394 +{
  52.395 +	if (*str)
  52.396 +		return 0;
  52.397 +	root_mountflags &= ~MS_RDONLY;
  52.398 +	return 1;
  52.399 +}
  52.400 +
  52.401 +static int __init debug_kernel(char *str)
  52.402 +{
  52.403 +	if (*str)
  52.404 +		return 0;
  52.405 +	console_loglevel = 10;
  52.406 +	return 1;
  52.407 +}
  52.408 +
  52.409 +static int __init quiet_kernel(char *str)
  52.410 +{
  52.411 +	if (*str)
  52.412 +		return 0;
  52.413 +	console_loglevel = 4;
  52.414 +	return 1;
  52.415 +}
  52.416 +
  52.417 +__setup("ro", readonly);
  52.418 +__setup("rw", readwrite);
  52.419 +__setup("debug", debug_kernel);
  52.420 +__setup("quiet", quiet_kernel);
  52.421 +
  52.422 +/*
  52.423 + * This is a simple kernel command line parsing function: it parses
  52.424 + * the command line, and fills in the arguments/environment to init
  52.425 + * as appropriate. Any cmd-line option is taken to be an environment
  52.426 + * variable if it contains the character '='.
  52.427 + *
  52.428 + * This routine also checks for options meant for the kernel.
  52.429 + * These options are not given to init - they are for internal kernel use only.
  52.430 + */
  52.431 +static void __init parse_options(char *line)
  52.432 +{
  52.433 +	char *next,*quote;
  52.434 +	int args, envs;
  52.435 +
  52.436 +	if (!*line)
  52.437 +		return;
  52.438 +	args = 0;
  52.439 +	envs = 1;	/* TERM is set to 'linux' by default */
  52.440 +	next = line;
  52.441 +	while ((line = next) != NULL) {
  52.442 +                quote = strchr(line,'"');
  52.443 +                next = strchr(line, ' ');
  52.444 +                while (next != NULL && quote != NULL && quote < next) {
  52.445 +                        /* we found a left quote before the next blank
  52.446 +                         * now we have to find the matching right quote
  52.447 +                         */
  52.448 +                        next = strchr(quote+1, '"');
  52.449 +                        if (next != NULL) {
  52.450 +                                quote = strchr(next+1, '"');
  52.451 +                                next = strchr(next+1, ' ');
  52.452 +                        }
  52.453 +                }
  52.454 +                if (next != NULL)
  52.455 +                        *next++ = 0;
  52.456 +#if defined(CONFIG_KDB)
  52.457 +		/* kdb, kdb=on, kdb=off, kdb=early */
  52.458 +		if (strncmp(line, "kdb", 3) == 0) {
  52.459 +			if (line[3] == '\0') {
  52.460 +				/* Backward compatibility, kdb with no option means early activation */
  52.461 +				printk("Boot flag kdb with no options is obsolete, use kdb=early\n");
  52.462 +				kdb_on = 1;
  52.463 +				kdb_flags |= KDB_FLAG_EARLYKDB;
  52.464 +				continue;
  52.465 +			}
  52.466 +			if (line[3] == '=') {
  52.467 +				if (strcmp(line+4, "on") == 0) {
  52.468 +					kdb_on = 1;
  52.469 +					continue;
  52.470 +				}
  52.471 +				if (strcmp(line+4, "off") == 0) {
  52.472 +					kdb_on = 0;
  52.473 +					continue;
  52.474 +				}
  52.475 +				if (strcmp(line+4, "early") == 0) {
  52.476 +					kdb_on = 1;
  52.477 +					kdb_flags |= KDB_FLAG_EARLYKDB;
  52.478 +					continue;
  52.479 +				}
  52.480 +				printk("Boot flag %s not recognised, assumed to be environment variable\n", line);
  52.481 +			}
  52.482 +		}
  52.483 +#endif
  52.484 +		if (!strncmp(line,"init=",5)) {
  52.485 +			line += 5;
  52.486 +			execute_command = line;
  52.487 +			/* In case LILO is going to boot us with default command line,
  52.488 +			 * it prepends "auto" before the whole cmdline which makes
  52.489 +			 * the shell think it should execute a script with such name.
  52.490 +			 * So we ignore all arguments entered _before_ init=... [MJ]
  52.491 +			 */
  52.492 +			args = 0;
  52.493 +			continue;
  52.494 +		}
  52.495 +		if (checksetup(line))
  52.496 +			continue;
  52.497 +		
  52.498 +		/*
  52.499 +		 * Then check if it's an environment variable or
  52.500 +		 * an option.
  52.501 +		 */
  52.502 +		if (strchr(line,'=')) {
  52.503 +			if (envs >= MAX_INIT_ENVS)
  52.504 +				break;
  52.505 +			envp_init[++envs] = line;
  52.506 +		} else {
  52.507 +			if (args >= MAX_INIT_ARGS)
  52.508 +				break;
  52.509 +			if (*line)
  52.510 +				argv_init[++args] = line;
  52.511 +		}
  52.512 +	}
  52.513 +	argv_init[args+1] = NULL;
  52.514 +	envp_init[envs+1] = NULL;
  52.515 +}
  52.516 +
  52.517 +
  52.518 +extern void setup_arch(char **);
  52.519 +extern void cpu_idle(void);
  52.520 +
  52.521 +unsigned long wait_init_idle;
  52.522 +
  52.523 +#ifndef CONFIG_SMP
  52.524 +
  52.525 +#ifdef CONFIG_X86_LOCAL_APIC
  52.526 +static void __init smp_init(void)
  52.527 +{
  52.528 +	APIC_init_uniprocessor();
  52.529 +}
  52.530 +#else
  52.531 +#define smp_init()	do { } while (0)
  52.532 +#endif
  52.533 +
  52.534 +#else
  52.535 +
  52.536 +
  52.537 +/* Called by boot processor to activate the rest. */
  52.538 +static void __init smp_init(void)
  52.539 +{
  52.540 +	/* Get other processors into their bootup holding patterns. */
  52.541 +	smp_boot_cpus();
  52.542 +	wait_init_idle = cpu_online_map;
  52.543 +	clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */
  52.544 +
  52.545 +	smp_threads_ready=1;
  52.546 +	smp_commence();
  52.547 +
  52.548 +	/* Wait for the other cpus to set up their idle processes */
  52.549 +	printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle);
  52.550 +	while (wait_init_idle) {
  52.551 +		cpu_relax();
  52.552 +		barrier();
  52.553 +	}
  52.554 +	printk("All processors have done init_idle\n");
  52.555 +}
  52.556 +
  52.557 +#endif
  52.558 +
  52.559 +/*
  52.560 + * We need to finalize in a non-__init function or else race conditions
  52.561 + * between the root thread and the init thread may cause start_kernel to
  52.562 + * be reaped by free_initmem before the root thread has proceeded to
  52.563 + * cpu_idle.
  52.564 + */
  52.565 +
  52.566 +static void rest_init(void)
  52.567 +{
  52.568 +	kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
  52.569 +	unlock_kernel();
  52.570 +	current->need_resched = 1;
  52.571 + 	cpu_idle();
  52.572 +} 
  52.573 +
  52.574 +/*
  52.575 + *	Activate the first processor.
  52.576 + */
  52.577 +
  52.578 +asmlinkage void __init start_kernel(void)
  52.579 +{
  52.580 +	char * command_line;
  52.581 +	unsigned long mempages;
  52.582 +	extern char saved_command_line[];
  52.583 +/*
  52.584 + * Interrupts are still disabled. Do necessary setups, then
  52.585 + * enable them
  52.586 + */
  52.587 +	lock_kernel();
  52.588 +	printk(linux_banner);
  52.589 +	setup_arch(&command_line);
  52.590 +	printk("Kernel command line: %s\n", saved_command_line);
  52.591 +	parse_options(command_line);
  52.592 +	trap_init();
  52.593 +	init_IRQ();
  52.594 +	sched_init();
  52.595 +	softirq_init();
  52.596 +	time_init();
  52.597 +
  52.598 +	/*
  52.599 +	 * HACK ALERT! This is early. We're enabling the console before
  52.600 +	 * we've done PCI setups etc, and console_init() must be aware of
  52.601 +	 * this. But we do want output early, in case something goes wrong.
  52.602 +	 */
  52.603 +	console_init();
  52.604 +#ifdef CONFIG_MODULES
  52.605 +	init_modules();
  52.606 +#endif
  52.607 +	if (prof_shift) {
  52.608 +		unsigned int size;
  52.609 +		/* only text is profiled */
  52.610 +		prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
  52.611 +		prof_len >>= prof_shift;
  52.612 +		
  52.613 +		size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
  52.614 +		prof_buffer = (unsigned int *) alloc_bootmem(size);
  52.615 +	}
  52.616 +
  52.617 +	kmem_cache_init();
  52.618 +	sti();
  52.619 +	calibrate_delay();
  52.620 +#ifdef CONFIG_BLK_DEV_INITRD
  52.621 +	if (initrd_start && !initrd_below_start_ok &&
  52.622 +			initrd_start < min_low_pfn << PAGE_SHIFT) {
  52.623 +		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
  52.624 +		    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
  52.625 +		initrd_start = 0;
  52.626 +	}
  52.627 +#endif
  52.628 +	mem_init();
  52.629 +	kmem_cache_sizes_init();
  52.630 +#if defined(CONFIG_KDB)
  52.631 +	kdb_init();
  52.632 +	if (KDB_FLAG(EARLYKDB)) {
  52.633 +		KDB_ENTER();
  52.634 +	}
  52.635 +#endif
  52.636 +	mempages = num_physpages;
  52.637 +
  52.638 +	fork_init(mempages);
  52.639 +	proc_caches_init();
  52.640 +	vfs_caches_init(mempages);
  52.641 +	buffer_init(mempages);
  52.642 +	page_cache_init(mempages);
  52.643 +#if defined(CONFIG_ARCH_S390)
  52.644 +	ccwcache_init();
  52.645 +#endif
  52.646 +	signals_init();
  52.647 +#ifdef CONFIG_PROC_FS
  52.648 +	proc_root_init();
  52.649 +#endif
  52.650 +#if defined(CONFIG_SYSVIPC)
  52.651 +	ipc_init();
  52.652 +#endif
  52.653 +	check_bugs();
  52.654 +	printk("POSIX conformance testing by UNIFIX\n");
  52.655 +
  52.656 +	/* 
  52.657 +	 *	We count on the initial thread going ok 
  52.658 +	 *	Like idlers init is an unlocked kernel thread, which will
  52.659 +	 *	make syscalls (and thus be locked).
  52.660 +	 */
  52.661 +	smp_init();
  52.662 +	rest_init();
  52.663 +}
  52.664 +
  52.665 +#ifdef CONFIG_BLK_DEV_INITRD
  52.666 +static int do_linuxrc(void * shell)
  52.667 +{
  52.668 +	static char *argv[] = { "linuxrc", NULL, };
  52.669 +
  52.670 +	close(0);close(1);close(2);
  52.671 +	setsid();
  52.672 +	(void) open("/dev/console",O_RDWR,0);
  52.673 +	(void) dup(0);
  52.674 +	(void) dup(0);
  52.675 +	return execve(shell, argv, envp_init);
  52.676 +}
  52.677 +
  52.678 +#endif
  52.679 +
  52.680 +struct task_struct *child_reaper = &init_task;
  52.681 +
  52.682 +static void __init do_initcalls(void)
  52.683 +{
  52.684 +	initcall_t *call;
  52.685 +
  52.686 +	call = &__initcall_start;
  52.687 +	do {
  52.688 +		(*call)();
  52.689 +		call++;
  52.690 +	} while (call < &__initcall_end);
  52.691 +
  52.692 +	/* Make sure there is no pending stuff from the initcall sequence */
  52.693 +	flush_scheduled_tasks();
  52.694 +}
  52.695 +
  52.696 +/*
  52.697 + * Ok, the machine is now initialized. None of the devices
  52.698 + * have been touched yet, but the CPU subsystem is up and
  52.699 + * running, and memory and process management works.
  52.700 + *
  52.701 + * Now we can finally start doing some real work..
  52.702 + */
  52.703 +static void __init do_basic_setup(void)
  52.704 +{
  52.705 +
  52.706 +	/*
  52.707 +	 * Tell the world that we're going to be the grim
  52.708 +	 * reaper of innocent orphaned children.
  52.709 +	 *
  52.710 +	 * We don't want people to have to make incorrect
  52.711 +	 * assumptions about where in the task array this
  52.712 +	 * can be found.
  52.713 +	 */
  52.714 +	child_reaper = current;
  52.715 +
  52.716 +#if defined(CONFIG_MTRR)	/* Do this after SMP initialization */
  52.717 +/*
  52.718 + * We should probably create some architecture-dependent "fixup after
  52.719 + * everything is up" style function where this would belong better
  52.720 + * than in init/main.c..
  52.721 + */
  52.722 +	mtrr_init();
  52.723 +#endif
  52.724 +
  52.725 +#ifdef CONFIG_SYSCTL
  52.726 +	sysctl_init();
  52.727 +#endif
  52.728 +
  52.729 +	/*
  52.730 +	 * Ok, at this point all CPU's should be initialized, so
  52.731 +	 * we can start looking into devices..
  52.732 +	 */
  52.733 +#if defined(CONFIG_ARCH_S390)
  52.734 +	s390_init_machine_check();
  52.735 +#endif
  52.736 +
  52.737 +#ifdef CONFIG_PCI
  52.738 +	pci_init();
  52.739 +#endif
  52.740 +#ifdef CONFIG_SBUS
  52.741 +	sbus_init();
  52.742 +#endif
  52.743 +#if defined(CONFIG_PPC)
  52.744 +	ppc_init();
  52.745 +#endif
  52.746 +#ifdef CONFIG_MCA
  52.747 +	mca_init();
  52.748 +#endif
  52.749 +#ifdef CONFIG_ARCH_ACORN
  52.750 +	ecard_init();
  52.751 +#endif
  52.752 +#ifdef CONFIG_ZORRO
  52.753 +	zorro_init();
  52.754 +#endif
  52.755 +#ifdef CONFIG_DIO
  52.756 +	dio_init();
  52.757 +#endif
  52.758 +#ifdef CONFIG_NUBUS
  52.759 +	nubus_init();
  52.760 +#endif
  52.761 +#ifdef CONFIG_ISAPNP
  52.762 +	isapnp_init();
  52.763 +#endif
  52.764 +#ifdef CONFIG_TC
  52.765 +	tc_init();
  52.766 +#endif
  52.767 +
  52.768 +	/* Networking initialization needs a process context */ 
  52.769 +	sock_init();
  52.770 +
  52.771 +	start_context_thread();
  52.772 +	do_initcalls();
  52.773 +
  52.774 +#ifdef CONFIG_IRDA
  52.775 +	irda_proto_init();
  52.776 +	irda_device_init(); /* Must be done after protocol initialization */
  52.777 +#endif
  52.778 +#ifdef CONFIG_PCMCIA
  52.779 +	init_pcmcia_ds();		/* Do this last */
  52.780 +#endif
  52.781 +}
  52.782 +
  52.783 +extern void rd_load(void);
  52.784 +extern void initrd_load(void);
  52.785 +
  52.786 +/*
  52.787 + * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
  52.788 + */
  52.789 +static void prepare_namespace(void)
  52.790 +{
  52.791 +#ifdef CONFIG_BLK_DEV_INITRD
  52.792 +	int real_root_mountflags = root_mountflags;
  52.793 +	if (!initrd_start)
  52.794 +		mount_initrd = 0;
  52.795 +	if (mount_initrd)
  52.796 +		root_mountflags &= ~MS_RDONLY;
  52.797 +	real_root_dev = ROOT_DEV;
  52.798 +#endif
  52.799 +
  52.800 +#ifdef CONFIG_BLK_DEV_RAM
  52.801 +#ifdef CONFIG_BLK_DEV_INITRD
  52.802 +	if (mount_initrd)
  52.803 +		initrd_load();
  52.804 +	else
  52.805 +#endif
  52.806 +	rd_load();
  52.807 +#endif
  52.808 +
  52.809 +	/* Mount the root filesystem.. */
  52.810 +	mount_root();
  52.811 +
  52.812 +	mount_devfs_fs ();
  52.813 +
  52.814 +#ifdef CONFIG_BLK_DEV_INITRD
  52.815 +	root_mountflags = real_root_mountflags;
  52.816 +	if (mount_initrd && ROOT_DEV != real_root_dev
  52.817 +	    && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
  52.818 +		int error;
  52.819 +		int i, pid;
  52.820 +
  52.821 +		pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
  52.822 +		if (pid > 0) {
  52.823 +			while (pid != wait(&i)) {
  52.824 +				current->policy |= SCHED_YIELD;
  52.825 +				schedule();
  52.826 +			}
  52.827 +		}
  52.828 +		if (MAJOR(real_root_dev) != RAMDISK_MAJOR
  52.829 +		     || MINOR(real_root_dev) != 0) {
  52.830 +			error = change_root(real_root_dev,"/initrd");
  52.831 +			if (error)
  52.832 +				printk(KERN_ERR "Change root to /initrd: "
  52.833 +				    "error %d\n",error);
  52.834 +		}
  52.835 +	}
  52.836 +#endif
  52.837 +}
  52.838 +
  52.839 +static int init(void * unused)
  52.840 +{
  52.841 +	lock_kernel();
  52.842 +	do_basic_setup();
  52.843 +
  52.844 +	prepare_namespace();
  52.845 +
  52.846 +	/*
  52.847 +	 * Ok, we have completed the initial bootup, and
  52.848 +	 * we're essentially up and running. Get rid of the
  52.849 +	 * initmem segments and start the user-mode stuff..
  52.850 +	 */
  52.851 +	free_initmem();
  52.852 +	unlock_kernel();
  52.853 +
  52.854 +	if (open("/dev/console", O_RDWR, 0) < 0)
  52.855 +		printk("Warning: unable to open an initial console.\n");
  52.856 +
  52.857 +	(void) dup(0);
  52.858 +	(void) dup(0);
  52.859 +	
  52.860 +	/*
  52.861 +	 * We try each of these until one succeeds.
  52.862 +	 *
  52.863 +	 * The Bourne shell can be used instead of init if we are 
  52.864 +	 * trying to recover a really broken machine.
  52.865 +	 */
  52.866 +
  52.867 +	if (execute_command)
  52.868 +		execve(execute_command,argv_init,envp_init);
  52.869 +	execve("/sbin/init",argv_init,envp_init);
  52.870 +	execve("/etc/init",argv_init,envp_init);
  52.871 +	execve("/bin/init",argv_init,envp_init);
  52.872 +	execve("/bin/sh",argv_init,envp_init);
  52.873 +	panic("No init found.  Try passing init= option to kernel.");
  52.874 +}