ia64/xen-unstable
changeset 152:42a318e8648e
bitkeeper revision 1.27 (3e4bc0aaYLPRPEot-3f6sspi3HC6Xg)
Merge with recent checkins
Merge with recent checkins
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 *)®_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, ¤t->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, ®40); 24.51 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, ®42); 24.52 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, ®44); 24.53 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, ®48); 24.54 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, ®4a); 24.55 + * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, ®54); 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, ®40); 24.124 + pci_read_config_word(bmide_dev, 0x42, ®42); 24.125 + pci_read_config_byte(bmide_dev, 0x44, ®44); 24.126 + pci_read_config_byte(bmide_dev, 0x48, ®48); 24.127 + pci_read_config_byte(bmide_dev, 0x4a, ®4a); 24.128 + pci_read_config_byte(bmide_dev, 0x4b, ®4b); 24.129 + pci_read_config_byte(bmide_dev, 0x54, ®54); 24.130 + pci_read_config_byte(bmide_dev, 0x55, ®55); 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, ®4042); 24.299 + sitre = (reg4042 & 0x4000) ? 1 : 0; 24.300 + pci_read_config_word(dev, 0x44, ®44); 24.301 + pci_read_config_word(dev, 0x48, ®48); 24.302 + pci_read_config_word(dev, 0x4a, ®4a); 24.303 + pci_read_config_word(dev, 0x54, ®54); 24.304 + pci_read_config_byte(dev, 0x55, ®55); 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, ®54h); 24.503 + pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); 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, §); 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, §); 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, §); 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, §); 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, §); 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, §); 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, §); 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, ¤t_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, ¤t_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 +}