--- /dev/null
+--- linux-2.6.0-test6/arch/alpha/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/alpha/Kconfig 2003-10-05 00:36:11.000000000 -0700
+@@ -471,21 +471,6 @@ config EISA
+ bool
+ depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
+ default y
+- ---help---
+- The Extended Industry Standard Architecture (EISA) bus was
+- developed as an open alternative to the IBM MicroChannel bus.
+-
+- The EISA bus provided some of the features of the IBM MicroChannel
+- bus while maintaining backward compatibility with cards made for
+- the older ISA bus. The EISA bus saw limited use between 1988 and
+- 1995 when it was made obsolete by the PCI bus.
+-
+- Say Y here if you are building a kernel for an EISA-based machine.
+-
+- Otherwise, say N.
+-
+-config EISA_ALWAYS
+- def_bool EISA
+
+ config SMP
+ bool "Symmetric multi-processing support"
+--- linux-2.6.0-test6/arch/alpha/kernel/core_irongate.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/arch/alpha/kernel/core_irongate.c 2003-10-05 00:33:23.000000000 -0700
+@@ -391,7 +391,7 @@ irongate_ioremap(unsigned long addr, uns
+ cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
+ pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
+
+- if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
++ if (__alpha_remap_area_pages(vaddr,
+ pte, PAGE_SIZE, 0)) {
+ printk("AGP ioremap: FAILED to map...\n");
+ vfree(area->addr);
+--- linux-2.6.0-test6/arch/alpha/kernel/core_marvel.c 2003-08-22 19:23:39.000000000 -0700
++++ 25/arch/alpha/kernel/core_marvel.c 2003-10-05 00:33:23.000000000 -0700
+@@ -696,7 +696,7 @@ marvel_ioremap(unsigned long addr, unsig
+ }
+ pfn >>= 1; /* make it a true pfn */
+
+- if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
++ if (__alpha_remap_area_pages(vaddr,
+ pfn << PAGE_SHIFT,
+ PAGE_SIZE, 0)) {
+ printk("FAILED to map...\n");
+--- linux-2.6.0-test6/arch/alpha/kernel/core_titan.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/alpha/kernel/core_titan.c 2003-10-05 00:33:23.000000000 -0700
+@@ -534,7 +534,7 @@ titan_ioremap(unsigned long addr, unsign
+ }
+ pfn >>= 1; /* make it a true pfn */
+
+- if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr),
++ if (__alpha_remap_area_pages(vaddr,
+ pfn << PAGE_SHIFT,
+ PAGE_SIZE, 0)) {
+ printk("FAILED to map...\n");
+--- linux-2.6.0-test6/arch/alpha/kernel/setup.c 2003-08-22 19:23:39.000000000 -0700
++++ 25/arch/alpha/kernel/setup.c 2003-10-05 00:36:11.000000000 -0700
+@@ -33,6 +33,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/root_dev.h>
+ #include <linux/initrd.h>
++#include <linux/eisa.h>
+ #ifdef CONFIG_MAGIC_SYSRQ
+ #include <linux/sysrq.h>
+ #include <linux/reboot.h>
+@@ -680,6 +681,11 @@ setup_arch(char **cmdline_p)
+ /* Default root filesystem to sda2. */
+ ROOT_DEV = Root_SDA2;
+
++#ifdef CONFIG_EISA
++ /* FIXME: only set this when we actually have EISA in this box? */
++ EISA_bus = 1;
++#endif
++
+ /*
+ * Check ASN in HWRPB for validity, report if bad.
+ * FIXME: how was this failing? Should we trust it instead,
+@@ -1203,7 +1209,7 @@ show_cpuinfo(struct seq_file *f, void *s
+ platform_string(), nr_processors);
+
+ #ifdef CONFIG_SMP
+- seq_printf(f, "cpus active\t\t: %d\n"
++ seq_printf(f, "cpus active\t\t: %ld\n"
+ "cpu active mask\t\t: %016lx\n",
+ num_online_cpus(), cpu_present_mask);
+ #endif
+--- linux-2.6.0-test6/arch/alpha/kernel/smp.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/alpha/kernel/smp.c 2003-10-05 00:33:23.000000000 -0700
+@@ -597,7 +597,7 @@ smp_cpus_done(unsigned int max_cpus)
+ if (cpu_online(cpu))
+ bogosum += cpu_data[cpu].loops_per_jiffy;
+
+- printk(KERN_INFO "SMP: Total of %d processors activated "
++ printk(KERN_INFO "SMP: Total of %ld processors activated "
+ "(%lu.%02lu BogoMIPS).\n",
+ num_online_cpus(),
+ (bogosum + 2500) / (500000/HZ),
+--- linux-2.6.0-test6/arch/alpha/kernel/time.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/alpha/kernel/time.c 2003-10-05 00:33:23.000000000 -0700
+@@ -89,6 +89,16 @@ static inline __u32 rpcc(void)
+ return result;
+ }
+
++/*
++ * Scheduler clock - returns current time in nanosec units.
++ *
++ * Copied from ARM code for expediency... ;-}
++ */
++unsigned long long sched_clock(void)
++{
++ return (unsigned long long)jiffies * (1000000000 / HZ);
++}
++
+
+ /*
+ * timer_interrupt() needs to keep up the real-time clock,
+@@ -239,8 +249,9 @@ validate_cc_value(unsigned long cc)
+ * arch/i386/time.c.
+ */
+
+-#define CALIBRATE_LATCH (52 * LATCH)
+-#define CALIBRATE_TIME (52 * 1000020 / HZ)
++#define PIC_TICK_RATE 1193180UL
++#define CALIBRATE_LATCH 0xffff
++#define TIMEOUT_COUNT 0x100000
+
+ static unsigned long __init
+ calibrate_cc_with_pic(void)
+@@ -263,19 +274,15 @@ calibrate_cc_with_pic(void)
+
+ cc = rpcc();
+ do {
+- count+=100; /* by 1 takes too long to timeout from 0 */
+- } while ((inb(0x61) & 0x20) == 0 && count > 0);
++ count++;
++ } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT);
+ cc = rpcc() - cc;
+
+ /* Error: ECTCNEVERSET or ECPUTOOFAST. */
+- if (count <= 100)
+- return 0;
+-
+- /* Error: ECPUTOOSLOW. */
+- if (cc <= CALIBRATE_TIME)
++ if (count <= 1 || count == TIMEOUT_COUNT)
+ return 0;
+
+- return (cc * 1000000UL) / CALIBRATE_TIME;
++ return ((long)cc * PIC_TICK_RATE) / (CALIBRATE_LATCH + 1);
+ }
+
+ /* The Linux interpretation of the CMOS clock register contents:
+--- linux-2.6.0-test6/arch/alpha/mm/init.c 2003-07-27 12:14:38.000000000 -0700
++++ 25/arch/alpha/mm/init.c 2003-10-05 00:33:23.000000000 -0700
+@@ -210,7 +210,8 @@ callback_init(void * kernel_end)
+ /* Allocate one PGD and one PMD. In the case of SRM, we'll need
+ these to actually remap the console. There is an assumption
+ here that only one of each is needed, and this allows for 8MB.
+- Currently (late 1999), big consoles are still under 4MB.
++ On systems with larger consoles, additional pages will be
++ allocated as needed during the mapping process.
+
+ In the case of not SRM, but not CONFIG_ALPHA_LARGE_VMALLOC,
+ we need to allocate the PGD we use for vmalloc before we start
+@@ -237,6 +238,15 @@ callback_init(void * kernel_end)
+ unsigned long pfn = crb->map[i].pa >> PAGE_SHIFT;
+ crb->map[i].va = vaddr;
+ for (j = 0; j < crb->map[i].count; ++j) {
++ /* Newer console's (especially on larger
++ systems) may require more pages of
++ PTEs. Grab additional pages as needed. */
++ if (pmd != pmd_offset(pgd, vaddr)) {
++ memset(kernel_end, 0, PAGE_SIZE);
++ pmd = pmd_offset(pgd, vaddr);
++ pmd_set(pmd, (pte_t *)kernel_end);
++ kernel_end += PAGE_SIZE;
++ }
+ set_pte(pte_offset_kernel(pmd, vaddr),
+ pfn_pte(pfn, PAGE_KERNEL));
+ pfn++;
+--- linux-2.6.0-test6/arch/arm/boot/compressed/head.S 2003-06-14 12:18:33.000000000 -0700
++++ 25/arch/arm/boot/compressed/head.S 2003-10-05 00:33:23.000000000 -0700
+@@ -477,6 +477,12 @@ proc_types:
+ @ b __arm6_cache_off
+ @ b __armv3_cache_flush
+
++ .word 0x00000000 @ old ARM ID
++ .word 0x0000f000
++ mov pc, lr
++ mov pc, lr
++ mov pc, lr
++
+ .word 0x41007000 @ ARM7/710
+ .word 0xfff8fe00
+ b __arm7_cache_off
+@@ -489,6 +495,14 @@ proc_types:
+ b __armv4_cache_off
+ mov pc, lr
+
++ .word 0x00007000 @ ARM7 IDs
++ .word 0x0000f000
++ mov pc, lr
++ mov pc, lr
++ mov pc, lr
++
++ @ Everything from here on will be the new ID system.
++
+ .word 0x41129200 @ ARM920T
+ .word 0xff00fff0
+ b __armv4_cache_on
+@@ -507,8 +521,16 @@ proc_types:
+ b __armv4_cache_off
+ b __armv4_cache_flush
+
+- .word 0x69050000 @ xscale
+- .word 0xffff0000
++ @ These match on the architecture ID
++
++ .word 0x00050000 @ ARMv5TE
++ .word 0x000f0000
++ b __armv4_cache_on
++ b __armv4_cache_off
++ b __armv4_cache_flush
++
++ .word 0x00060000 @ ARMv5TEJ
++ .word 0x000f0000
+ b __armv4_cache_on
+ b __armv4_cache_off
+ b __armv4_cache_flush
+--- linux-2.6.0-test6/arch/arm/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/Kconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -239,7 +239,7 @@ config DISCONTIGMEM
+
+ # Now handle the bus types
+ config PCI
+- bool "PCI support" if ARCH_INTEGRATOR
++ bool "PCI support" if ARCH_INTEGRATOR_AP
+ default y if ARCH_FTVPCI || ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX
+ help
+ Find out whether you have a PCI motherboard. PCI is the name of a
+@@ -645,8 +645,6 @@ source "drivers/misc/Kconfig"
+
+ source "drivers/usb/Kconfig"
+
+-source "net/bluetooth/Kconfig"
+-
+
+ menu "Kernel hacking"
+
+--- linux-2.6.0-test6/arch/arm/kernel/apm.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/arm/kernel/apm.c 2003-10-05 00:33:23.000000000 -0700
+@@ -179,13 +179,10 @@ static void queue_event(apm_event_t even
+ wake_up_interruptible(&apm_waitqueue);
+ }
+
+-/* defined in pm.c */
+-extern int suspend(void);
+-
+ static int apm_suspend(void)
+ {
+ struct list_head *l;
+- int err = suspend();
++ int err = pm_suspend(PM_SUSPEND_MEM);
+
+ /*
+ * Anyone on the APM queues will think we're still suspended.
+--- linux-2.6.0-test6/arch/arm/kernel/entry-armv.S 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/kernel/entry-armv.S 2003-10-05 00:33:23.000000000 -0700
+@@ -439,20 +439,25 @@ ENTRY(soft_irq_mask)
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ /* FIXME: should not be using soo many LDRs here */
+- ldr \irqnr, =IO_ADDRESS(INTEGRATOR_IC_BASE)
+- ldr \irqstat, [\irqnr, #IRQ_STATUS] @ get masked status
+- ldr \irqnr, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
+- ldr \irqnr, [\irqnr, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
+- orr \irqstat, \irqstat, \irqnr, lsl #INTEGRATOR_CM_INT0
++ ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
++ mov \irqnr, #IRQ_PIC_START
++ ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status
++ ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
++ teq \irqstat, #0
++ ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
++ moveq \irqnr, #IRQ_CIC_START
+
+- mov \irqnr, #0
+-1001: tst \irqstat, #1
++1001: tst \irqstat, #15
+ bne 1002f
++ add \irqnr, \irqnr, #4
++ movs \irqstat, \irqstat, lsr #4
++ bne 1001b
++1002: tst \irqstat, #1
++ bne 1003f
+ add \irqnr, \irqnr, #1
+- mov \irqstat, \irqstat, lsr #1
+- cmp \irqnr, #22
+- bcc 1001b
+-1002: /* EQ will be set if we reach 22 */
++ movs \irqstat, \irqstat, lsr #1
++ bne 1002b
++1003: /* EQ will be set if no irqs pending */
+ .endm
+
+ .macro irq_prio_table
+--- linux-2.6.0-test6/arch/arm/kernel/pm.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/arm/kernel/pm.c 2003-10-05 00:33:23.000000000 -0700
+@@ -9,68 +9,18 @@
+ * sleep.
+ */
+ #include <linux/config.h>
++#include <linux/init.h>
++#include <linux/sysctl.h>
+ #include <linux/pm.h>
+-#include <linux/device.h>
+-#include <linux/sysdev.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+
+-#include <asm/leds.h>
+-#include <asm/system.h>
+-
+-/*
+- * Tell the linker that pm_do_suspend may not be present.
+- */
+-extern int pm_do_suspend(void) __attribute__((weak));
+-
+-int suspend(void)
+-{
+- int ret;
+-
+- if (!pm_do_suspend)
+- return -ENOSYS;
+-
+- /*
+- * Suspend "legacy" devices.
+- */
+- ret = pm_send_all(PM_SUSPEND, (void *)3);
+- if (ret != 0)
+- goto out;
+-
+- ret = device_suspend(3);
+- if (ret)
+- goto resume_legacy;
+-
+- local_irq_disable();
+- leds_event(led_stop);
+-
+- sysdev_suspend(3);
+-
+- ret = pm_do_suspend();
+-
+- sysdev_resume();
+-
+- leds_event(led_start);
+- local_irq_enable();
+-
+- device_resume();
+-
+- resume_legacy:
+- pm_send_all(PM_RESUME, (void *)0);
+-
+- out:
+- return ret;
+-}
+-
+ #ifdef CONFIG_SYSCTL
+ /*
+ * We really want this to die. It's a disgusting hack using unallocated
+ * sysctl numbers. We should be using a real interface.
+ */
+
+-#include <linux/init.h>
+-#include <linux/sysctl.h>
+-
+ static int
+ pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+@@ -79,7 +29,7 @@ pm_sysctl_proc_handler(ctl_table *ctl, i
+ printk("PM: task %s (pid %d) uses deprecated sysctl PM interface\n",
+ current->comm, current->pid);
+ if (write)
+- ret = suspend();
++ ret = pm_suspend(PM_SUSPEND_MEM);
+ return ret;
+ }
+
+--- linux-2.6.0-test6/arch/arm/kernel/process.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/kernel/process.c 2003-10-05 00:33:23.000000000 -0700
+@@ -117,12 +117,10 @@ __setup("reboot=", reboot_setup);
+
+ void machine_halt(void)
+ {
+- leds_event(led_halted);
+ }
+
+ void machine_power_off(void)
+ {
+- leds_event(led_halted);
+ if (pm_power_off)
+ pm_power_off();
+ }
+--- linux-2.6.0-test6/arch/arm/kernel/setup.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/kernel/setup.c 2003-10-05 00:33:23.000000000 -0700
+@@ -182,7 +182,7 @@ static const char *proc_arch[] = {
+ "5",
+ "5T",
+ "5TE",
+- "?(8)",
++ "5TEJ",
+ "?(9)",
+ "?(10)",
+ "?(11)",
+--- linux-2.6.0-test6/arch/arm/kernel/signal.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/arm/kernel/signal.c 2003-10-05 00:33:23.000000000 -0700
+@@ -21,6 +21,7 @@
+ #include <linux/tty.h>
+ #include <linux/binfmts.h>
+ #include <linux/elf.h>
++#include <linux/suspend.h>
+
+ #include <asm/pgalloc.h>
+ #include <asm/ucontext.h>
+@@ -539,6 +540,11 @@ static int do_signal(sigset_t *oldset, s
+ if (!user_mode(regs))
+ return 0;
+
++ if (current->flags & PF_FREEZE) {
++ refrigerator(0);
++ goto no_signal;
++ }
++
+ if (current->ptrace & PT_SINGLESTEP)
+ ptrace_cancel_bpt(current);
+
+@@ -550,6 +556,7 @@ static int do_signal(sigset_t *oldset, s
+ return 1;
+ }
+
++ no_signal:
+ /*
+ * No signal to deliver to the process - restart the syscall.
+ */
+--- linux-2.6.0-test6/arch/arm/kernel/time.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/kernel/time.c 2003-10-05 00:33:23.000000000 -0700
+@@ -26,6 +26,7 @@
+ #include <linux/timex.h>
+ #include <linux/errno.h>
+ #include <linux/profile.h>
++#include <linux/sysdev.h>
+
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+@@ -72,8 +73,6 @@ unsigned long (*gettimeoffset)(void) = d
+ */
+ unsigned long long sched_clock(void)
+ {
+- unsigned long long this_offset;
+-
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+ }
+
+@@ -137,6 +136,47 @@ static void dummy_leds_event(led_event_t
+
+ void (*leds_event)(led_event_t) = dummy_leds_event;
+
++static int leds_suspend(struct sys_device *dev, u32 state)
++{
++ leds_event(led_stop);
++ return 0;
++}
++
++static int leds_resume(struct sys_device *dev)
++{
++ leds_event(led_start);
++ return 0;
++}
++
++static int leds_shutdown(struct sys_device *dev)
++{
++ leds_event(led_halted);
++ return 0;
++}
++
++static struct sysdev_class leds_sysclass = {
++ set_kset_name("leds"),
++ .shutdown = leds_shutdown,
++ .suspend = leds_suspend,
++ .resume = leds_resume,
++};
++
++static struct sys_device leds_device = {
++ .id = 0,
++ .cls = &leds_sysclass,
++};
++
++static int __init leds_init(void)
++{
++ int ret;
++ ret = sysdev_class_register(&leds_sysclass);
++ if (ret == 0)
++ ret = sys_device_register(&leds_device);
++ return ret;
++}
++
++device_initcall(leds_init);
++
+ EXPORT_SYMBOL(leds_event);
+ #endif
+
+--- linux-2.6.0-test6/arch/arm/kernel/traps.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/arm/kernel/traps.c 2003-10-05 00:33:23.000000000 -0700
+@@ -212,10 +212,10 @@ NORET_TYPE void die(const char *str, str
+ printk("CPU: %d\n", smp_processor_id());
+ show_regs(regs);
+ printk("Process %s (pid: %d, stack limit = 0x%p)\n",
+- current->comm, current->pid, tsk->thread_info + 1);
++ tsk->comm, tsk->pid, tsk->thread_info + 1);
+
+ if (!user_mode(regs) || in_interrupt()) {
+- dump_mem("Stack: ", (unsigned long)(regs + 1), 8192+(unsigned long)tsk->thread_info);
++ dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info);
+ dump_backtrace(regs, tsk);
+ dump_instr(regs);
+ }
+--- linux-2.6.0-test6/arch/arm/lib/io-readsl-armv4.S 2003-06-14 12:18:30.000000000 -0700
++++ 25/arch/arm/lib/io-readsl-armv4.S 2003-10-05 00:33:23.000000000 -0700
+@@ -9,7 +9,6 @@
+ */
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+-#include <asm/hardware.h>
+
+ /*
+ * Note that some reads can be aligned on half-word boundaries.
+@@ -31,6 +30,10 @@ ENTRY(__raw_readsl)
+ blt 4f
+ bgt 6f
+
++#ifndef __ARMEB__
++
++ /* little endian code */
++
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+ 3: subs r2, r2, #1
+@@ -68,3 +71,48 @@ ENTRY(__raw_readsl)
+ strb ip, [r1]
+ mov pc, lr
+
++#else
++
++ /* big endian code */
++
++
++ mov r3, ip, lsr #16
++ strh r3, [r1], #2
++3: mov r3, ip, lsl #16
++ subs r2, r2, #1
++ ldrne ip, [r0]
++ orrne r3, r3, ip, lsr #16
++ strne r3, [r1], #4
++ bne 3b
++ strh ip, [r1], #2
++ mov pc, lr
++
++4: mov r3, ip, lsr #24
++ strb r3, [r1], #1
++ mov r3, ip, lsr #8
++ strh r3, [r1], #2
++5: mov r3, ip, lsl #24
++ subs r2, r2, #1
++ ldrne ip, [r0]
++ orrne r3, r3, ip, lsr #8
++ strne r3, [r1], #4
++ bne 5b
++ strb ip, [r1], #1
++ mov pc, lr
++
++6: mov r3, ip, lsr #24
++ strb r3, [r1], #1
++7: mov r3, ip, lsl #8
++ subs r2, r2, #1
++ ldrne ip, [r0]
++ orrne r3, r3, ip, lsr #24
++ strne r3, [r1], #4
++ bne 7b
++ mov r3, ip, lsr #8
++ strh r3, [r1], #2
++ strb ip, [r1], #1
++ mov pc, lr
++
++#endif
++
++
+--- linux-2.6.0-test6/arch/arm/lib/io-readsw-armv4.S 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/arm/lib/io-readsw-armv4.S 2003-10-05 00:33:23.000000000 -0700
+@@ -9,7 +9,14 @@
+ */
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+-#include <asm/hardware.h>
++
++ .macro pack, rd, hw1, hw2
++#ifndef __ARMEB__
++ orr \rd, \hw1, \hw2, lsl #16
++#else
++ orr \rd, \hw2, \hw1, lsl #16
++#endif
++ .endm
+
+ .insw_bad_alignment:
+ adr r0, .insw_bad_align_msg
+@@ -41,19 +48,19 @@ ENTRY(__raw_readsw)
+
+ .insw_8_lp: ldrh r3, [r0]
+ ldrh r4, [r0]
+- orr r3, r3, r4, lsl #16
++ pack r3, r3, r4
+
+ ldrh r4, [r0]
+ ldrh r5, [r0]
+- orr r4, r4, r5, lsl #16
++ pack r4, r4, r5
+
+ ldrh r5, [r0]
+ ldrh ip, [r0]
+- orr r5, r5, ip, lsl #16
++ pack r5, r5, ip
+
+ ldrh ip, [r0]
+ ldrh lr, [r0]
+- orr ip, ip, lr, lsl #16
++ pack ip, ip, lr
+
+ stmia r1!, {r3 - r5, ip}
+
+@@ -68,11 +75,11 @@ ENTRY(__raw_readsw)
+
+ ldrh r3, [r0]
+ ldrh r4, [r0]
+- orr r3, r3, r4, lsl #16
++ pack r3, r3, r4
+
+ ldrh r4, [r0]
+ ldrh ip, [r0]
+- orr r4, r4, ip, lsl #16
++ pack r4, r4, ip
+
+ stmia r1!, {r3, r4}
+
+@@ -81,7 +88,7 @@ ENTRY(__raw_readsw)
+
+ ldrh r3, [r0]
+ ldrh ip, [r0]
+- orr r3, r3, ip, lsl #16
++ pack r3, r3, ip
+
+ str r3, [r1], #4
+
+--- linux-2.6.0-test6/arch/arm/lib/io-writesw-armv4.S 2003-06-14 12:18:34.000000000 -0700
++++ 25/arch/arm/lib/io-writesw-armv4.S 2003-10-05 00:33:23.000000000 -0700
+@@ -9,7 +9,18 @@
+ */
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+-#include <asm/hardware.h>
++
++ .macro outword, rd
++#ifndef __ARMEB__
++ strh \rd, [r0]
++ mov \rd, \rd, lsr #16
++ strh \rd, [r0]
++#else
++ mov lr, \rd, lsr #16
++ strh lr, [r0]
++ strh \rd, [r0]
++#endif
++ .endm
+
+ .outsw_bad_alignment:
+ adr r0, .outsw_bad_align_msg
+@@ -40,20 +51,10 @@ ENTRY(__raw_writesw)
+ bmi .no_outsw_8
+
+ .outsw_8_lp: ldmia r1!, {r3, r4, r5, ip}
+-
+- strh r3, [r0]
+- mov r3, r3, lsr #16
+- strh r3, [r0]
+- strh r4, [r0]
+- mov r4, r4, lsr #16
+- strh r4, [r0]
+- strh r5, [r0]
+- mov r5, r5, lsr #16
+- strh r5, [r0]
+- strh ip, [r0]
+- mov ip, ip, lsr #16
+- strh ip, [r0]
+-
++ outword r3
++ outword r4
++ outword r5
++ outword ip
+ subs r2, r2, #8
+ bpl .outsw_8_lp
+
+@@ -64,20 +65,14 @@ ENTRY(__raw_writesw)
+ beq .no_outsw_4
+
+ ldmia r1!, {r3, ip}
+- strh r3, [r0]
+- mov r3, r3, lsr #16
+- strh r3, [r0]
+- strh ip, [r0]
+- mov ip, ip, lsr #16
+- strh ip, [r0]
++ outword r3
++ outword ip
+
+ .no_outsw_4: tst r2, #2
+ beq .no_outsw_2
+
+ ldr r3, [r1], #4
+- strh r3, [r0]
+- mov r3, r3, lsr #16
+- strh r3, [r0]
++ outword r3
+
+ .no_outsw_2: tst r2, #1
+ ldrneh r3, [r1]
+--- linux-2.6.0-test6/arch/arm/lib/lib1funcs.S 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/lib/lib1funcs.S 2003-10-05 00:33:23.000000000 -0700
+@@ -1,7 +1,12 @@
+-@ libgcc1 routines for ARM cpu.
+-@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
++/*
++ * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
++ *
++ * Author: Nicolas Pitre <nico@cam.org>
++ * - contributed to gcc-3.4 on Sep 30, 2003
++ * - adapted for the Linux kernel on Oct 2, 2003
++ */
+
+-/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
++/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+@@ -10,11 +15,12 @@ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+-compiled version of this file with other programs, and to distribute
+-those programs without any restriction coming from the use of this
+-file. (The General Public License restrictions do apply in other
+-respects; for example, they cover modification of the file, and
+-distribution when not linked into another program.)
++compiled version of this file into combinations with other programs,
++and to distribute those combinations without any restriction coming
++from the use of this file. (The General Public License restrictions
++do apply in other respects; for example, they cover modification of
++the file, and distribution when not linked into a combine
++executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+@@ -26,286 +32,283 @@ along with this program; see the file CO
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+-/* As a special exception, if you link this library with other files,
+- some of which are compiled with GCC, to produce an executable,
+- this library does not by itself cause the resulting executable
+- to be covered by the GNU General Public License.
+- This exception does not however invalidate any other reasons why
+- the executable file might be covered by the GNU General Public License.
+- */
+-/* This code is derived from gcc 2.95.3
+- * 29/07/01 Adapted for linux
+- * 27/03/03 Ian Molton Clean up CONFIG_CPU
+- */
+
+ #include <linux/linkage.h>
+ #include <asm/assembler.h>
+-#include <asm/hardware.h>
+
+-#define RET mov
+-#define RETc(x) mov##x
+-#define RETCOND
+-
+-dividend .req r0
+-divisor .req r1
+-result .req r2
+-overdone .req r2
+-curbit .req r3
++
++.macro ARM_DIV_BODY dividend, divisor, result, curbit
++
++#if __LINUX_ARM_ARCH__ >= 5
++
++ clz \curbit, \divisor
++ clz \result, \dividend
++ sub \result, \curbit, \result
++ mov \curbit, #1
++ mov \divisor, \divisor, lsl \result
++ mov \curbit, \curbit, lsl \result
++ mov \result, #0
+
+-ENTRY(__udivsi3)
+- cmp divisor, #0
+- beq Ldiv0
+- mov curbit, #1
+- mov result, #0
+- cmp dividend, divisor
+- bcc Lgot_result_udivsi3
+-1:
++#else
++
++ @ Initially shift the divisor left 3 bits if possible,
++ @ set curbit accordingly. This allows for curbit to be located
++ @ at the left end of each 4 bit nibbles in the division loop
++ @ to save one loop in most cases.
++ tst \divisor, #0xe0000000
++ moveq \divisor, \divisor, lsl #3
++ moveq \curbit, #8
++ movne \curbit, #1
++
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+- cmp divisor, #0x10000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #4
+- movcc curbit, curbit, lsl #4
+- bcc 1b
++1: cmp \divisor, #0x10000000
++ cmplo \divisor, \dividend
++ movlo \divisor, \divisor, lsl #4
++ movlo \curbit, \curbit, lsl #4
++ blo 1b
+
+-2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+- cmp divisor, #0x80000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #1
+- movcc curbit, curbit, lsl #1
+- bcc 2b
+-
+-3:
+- @ Test for possible subtractions, and note which bits
+- @ are done in the result. On the final pass, this may subtract
+- @ too much from the dividend, but the result will be ok, since the
+- @ "bit" will have been shifted out at the bottom.
+- cmp dividend, divisor
+- subcs dividend, dividend, divisor
+- orrcs result, result, curbit
+- cmp dividend, divisor, lsr #1
+- subcs dividend, dividend, divisor, lsr #1
+- orrcs result, result, curbit, lsr #1
+- cmp dividend, divisor, lsr #2
+- subcs dividend, dividend, divisor, lsr #2
+- orrcs result, result, curbit, lsr #2
+- cmp dividend, divisor, lsr #3
+- subcs dividend, dividend, divisor, lsr #3
+- orrcs result, result, curbit, lsr #3
+- cmp dividend, #0 @ Early termination?
+- movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+- movne divisor, divisor, lsr #4
+- bne 3b
+-Lgot_result_udivsi3:
+- mov r0, result
+- RET pc, lr
++1: cmp \divisor, #0x80000000
++ cmplo \divisor, \dividend
++ movlo \divisor, \divisor, lsl #1
++ movlo \curbit, \curbit, lsl #1
++ blo 1b
+
+-Ldiv0:
+- str lr, [sp, #-4]!
+- bl __div0
+- mov r0, #0 @ about as wrong as it could be
+- ldmia sp!, {pc}RETCOND
++ mov \result, #0
+
+-/* __umodsi3 ----------------------- */
++#endif
++
++ @ Division loop
++1: cmp \dividend, \divisor
++ subhs \dividend, \dividend, \divisor
++ orrhs \result, \result, \curbit
++ cmp \dividend, \divisor, lsr #1
++ subhs \dividend, \dividend, \divisor, lsr #1
++ orrhs \result, \result, \curbit, lsr #1
++ cmp \dividend, \divisor, lsr #2
++ subhs \dividend, \dividend, \divisor, lsr #2
++ orrhs \result, \result, \curbit, lsr #2
++ cmp \dividend, \divisor, lsr #3
++ subhs \dividend, \dividend, \divisor, lsr #3
++ orrhs \result, \result, \curbit, lsr #3
++ cmp \dividend, #0 @ Early termination?
++ movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
++ movne \divisor, \divisor, lsr #4
++ bne 1b
++
++.endm
++
++
++.macro ARM_DIV2_ORDER divisor, order
++
++#if __LINUX_ARM_ARCH__ >= 5
++
++ clz \order, \divisor
++ rsb \order, \order, #31
++
++#else
++
++ cmp \divisor, #(1 << 16)
++ movhs \divisor, \divisor, lsr #16
++ movhs \order, #16
++ movlo \order, #0
++
++ cmp \divisor, #(1 << 8)
++ movhs \divisor, \divisor, lsr #8
++ addhs \order, \order, #8
++
++ cmp \divisor, #(1 << 4)
++ movhs \divisor, \divisor, lsr #4
++ addhs \order, \order, #4
++
++ cmp \divisor, #(1 << 2)
++ addhi \order, \order, #3
++ addls \order, \order, \divisor, lsr #1
++
++#endif
++
++.endm
++
++
++.macro ARM_MOD_BODY dividend, divisor, order, spare
++
++#if __LINUX_ARM_ARCH__ >= 5
++
++ clz \order, \divisor
++ clz \spare, \dividend
++ sub \order, \order, \spare
++ mov \divisor, \divisor, lsl \order
++
++#else
++
++ mov \order, #0
+
+-ENTRY(__umodsi3)
+- cmp divisor, #0
+- beq Ldiv0
+- mov curbit, #1
+- cmp dividend, divisor
+- RETc(cc) pc, lr
+-1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+- cmp divisor, #0x10000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #4
+- movcc curbit, curbit, lsl #4
+- bcc 1b
++1: cmp \divisor, #0x10000000
++ cmplo \divisor, \dividend
++ movlo \divisor, \divisor, lsl #4
++ addlo \order, \order, #4
++ blo 1b
+
+-2:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+- cmp divisor, #0x80000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #1
+- movcc curbit, curbit, lsl #1
+- bcc 2b
+-
+-3:
+- @ Test for possible subtractions. On the final pass, this may
+- @ subtract too much from the dividend, so keep track of which
+- @ subtractions are done, we can fix them up afterwards...
+- mov overdone, #0
+- cmp dividend, divisor
+- subcs dividend, dividend, divisor
+- cmp dividend, divisor, lsr #1
+- subcs dividend, dividend, divisor, lsr #1
+- orrcs overdone, overdone, curbit, ror #1
+- cmp dividend, divisor, lsr #2
+- subcs dividend, dividend, divisor, lsr #2
+- orrcs overdone, overdone, curbit, ror #2
+- cmp dividend, divisor, lsr #3
+- subcs dividend, dividend, divisor, lsr #3
+- orrcs overdone, overdone, curbit, ror #3
+- mov ip, curbit
+- cmp dividend, #0 @ Early termination?
+- movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+- movne divisor, divisor, lsr #4
+- bne 3b
+-
+- @ Any subtractions that we should not have done will be recorded in
+- @ the top three bits of "overdone". Exactly which were not needed
+- @ are governed by the position of the bit, stored in ip.
+- @ If we terminated early, because dividend became zero,
+- @ then none of the below will match, since the bit in ip will not be
+- @ in the bottom nibble.
+- ands overdone, overdone, #0xe0000000
+- RETc(eq) pc, lr @ No fixups needed
+- tst overdone, ip, ror #3
+- addne dividend, dividend, divisor, lsr #3
+- tst overdone, ip, ror #2
+- addne dividend, dividend, divisor, lsr #2
+- tst overdone, ip, ror #1
+- addne dividend, dividend, divisor, lsr #1
+- RET pc, lr
++1: cmp \divisor, #0x80000000
++ cmplo \divisor, \dividend
++ movlo \divisor, \divisor, lsl #1
++ addlo \order, \order, #1
++ blo 1b
++
++#endif
++
++ @ Perform all needed substractions to keep only the reminder.
++ @ Do comparisons in batch of 4 first.
++ subs \order, \order, #3 @ yes, 3 is intended here
++ blt 2f
++
++1: cmp \dividend, \divisor
++ subhs \dividend, \dividend, \divisor
++ cmp \dividend, \divisor, lsr #1
++ subhs \dividend, \dividend, \divisor, lsr #1
++ cmp \dividend, \divisor, lsr #2
++ subhs \dividend, \dividend, \divisor, lsr #2
++ cmp \dividend, \divisor, lsr #3
++ subhs \dividend, \dividend, \divisor, lsr #3
++ cmp \dividend, #1
++ mov \divisor, \divisor, lsr #4
++ subges \order, \order, #4
++ bge 1b
++
++ tst \order, #3
++ teqne \dividend, #0
++ beq 5f
++
++ @ Either 1, 2 or 3 comparison/substractions are left.
++2: cmn \order, #2
++ blt 4f
++ beq 3f
++ cmp \dividend, \divisor
++ subhs \dividend, \dividend, \divisor
++ mov \divisor, \divisor, lsr #1
++3: cmp \dividend, \divisor
++ subhs \dividend, \dividend, \divisor
++ mov \divisor, \divisor, lsr #1
++4: cmp \dividend, \divisor
++ subhs \dividend, \dividend, \divisor
++5:
++.endm
++
++
++ENTRY(__udivsi3)
++
++ subs r2, r1, #1
++ moveq pc, lr
++ bcc Ldiv0
++ cmp r0, r1
++ bls 11f
++ tst r1, r2
++ beq 12f
++
++ ARM_DIV_BODY r0, r1, r2, r3
++
++ mov r0, r2
++ mov pc, lr
++
++11: moveq r0, #1
++ movne r0, #0
++ mov pc, lr
++
++12: ARM_DIV2_ORDER r1, r2
++
++ mov r0, r0, lsr r2
++ mov pc, lr
++
++
++ENTRY(__umodsi3)
++
++ subs r2, r1, #1 @ compare divisor with 1
++ bcc Ldiv0
++ cmpne r0, r1 @ compare dividend with divisor
++ moveq r0, #0
++ tsthi r1, r2 @ see if divisor is power of 2
++ andeq r0, r0, r2
++ movls pc, lr
++
++ ARM_MOD_BODY r0, r1, r2, r3
++
++ mov pc, lr
++
+
+ ENTRY(__divsi3)
+- eor ip, dividend, divisor @ Save the sign of the result.
+- mov curbit, #1
+- mov result, #0
+- cmp divisor, #0
+- rsbmi divisor, divisor, #0 @ Loops below use unsigned.
++
++ cmp r1, #0
++ eor ip, r0, r1 @ save the sign of the result.
+ beq Ldiv0
+- cmp dividend, #0
+- rsbmi dividend, dividend, #0
+- cmp dividend, divisor
+- bcc Lgot_result_divsi3
++ rsbmi r1, r1, #0 @ loops below use unsigned.
++ subs r2, r1, #1 @ division by 1 or -1 ?
++ beq 10f
++ movs r3, r0
++ rsbmi r3, r0, #0 @ positive dividend value
++ cmp r3, r1
++ bls 11f
++ tst r1, r2 @ divisor is power of 2 ?
++ beq 12f
+
+-1:
+- @ Unless the divisor is very big, shift it up in multiples of
+- @ four bits, since this is the amount of unwinding in the main
+- @ division loop. Continue shifting until the divisor is
+- @ larger than the dividend.
+- cmp divisor, #0x10000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #4
+- movcc curbit, curbit, lsl #4
+- bcc 1b
++ ARM_DIV_BODY r3, r1, r0, r2
+
+-2:
+- @ For very big divisors, we must shift it a bit at a time, or
+- @ we will be in danger of overflowing.
+- cmp divisor, #0x80000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #1
+- movcc curbit, curbit, lsl #1
+- bcc 2b
+-
+-3:
+- @ Test for possible subtractions, and note which bits
+- @ are done in the result. On the final pass, this may subtract
+- @ too much from the dividend, but the result will be ok, since the
+- @ "bit" will have been shifted out at the bottom.
+- cmp dividend, divisor
+- subcs dividend, dividend, divisor
+- orrcs result, result, curbit
+- cmp dividend, divisor, lsr #1
+- subcs dividend, dividend, divisor, lsr #1
+- orrcs result, result, curbit, lsr #1
+- cmp dividend, divisor, lsr #2
+- subcs dividend, dividend, divisor, lsr #2
+- orrcs result, result, curbit, lsr #2
+- cmp dividend, divisor, lsr #3
+- subcs dividend, dividend, divisor, lsr #3
+- orrcs result, result, curbit, lsr #3
+- cmp dividend, #0 @ Early termination?
+- movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+- movne divisor, divisor, lsr #4
+- bne 3b
+-Lgot_result_divsi3:
+- mov r0, result
+ cmp ip, #0
+ rsbmi r0, r0, #0
+- RET pc, lr
++ mov pc, lr
++
++10: teq ip, r0 @ same sign ?
++ rsbmi r0, r0, #0
++ mov pc, lr
++
++11: movlo r0, #0
++ moveq r0, ip, asr #31
++ orreq r0, r0, #1
++ mov pc, lr
++
++12: ARM_DIV2_ORDER r1, r2
++
++ cmp ip, #0
++ mov r0, r3, lsr r2
++ rsbmi r0, r0, #0
++ mov pc, lr
++
+
+ ENTRY(__modsi3)
+- mov curbit, #1
+- cmp divisor, #0
+- rsbmi divisor, divisor, #0 @ Loops below use unsigned.
++
++ cmp r1, #0
+ beq Ldiv0
+- @ Need to save the sign of the dividend, unfortunately, we need
+- @ ip later on; this is faster than pushing lr and using that.
+- str dividend, [sp, #-4]!
+- cmp dividend, #0
+- rsbmi dividend, dividend, #0
+- cmp dividend, divisor
+- bcc Lgot_result_modsi3
++ rsbmi r1, r1, #0 @ loops below use unsigned.
++ movs ip, r0 @ preserve sign of dividend
++ rsbmi r0, r0, #0 @ if negative make positive
++ subs r2, r1, #1 @ compare divisor with 1
++ cmpne r0, r1 @ compare dividend with divisor
++ moveq r0, #0
++ tsthi r1, r2 @ see if divisor is power of 2
++ andeq r0, r0, r2
++ bls 10f
++
++ ARM_MOD_BODY r0, r1, r2, r3
++
++10: cmp ip, #0
++ rsbmi r0, r0, #0
++ mov pc, lr
++
++
++Ldiv0:
++
++ str lr, [sp, #-4]!
++ bl __div0
++ mov r0, #0 @ About as wrong as it could be.
++ ldr pc, [sp], #4
+
+-1:
+- @ Unless the divisor is very big, shift it up in multiples of
+- @ four bits, since this is the amount of unwinding in the main
+- @ division loop. Continue shifting until the divisor is
+- @ larger than the dividend.
+- cmp divisor, #0x10000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #4
+- movcc curbit, curbit, lsl #4
+- bcc 1b
+
+-2:
+- @ For very big divisors, we must shift it a bit at a time, or
+- @ we will be in danger of overflowing.
+- cmp divisor, #0x80000000
+- cmpcc divisor, dividend
+- movcc divisor, divisor, lsl #1
+- movcc curbit, curbit, lsl #1
+- bcc 2b
+-
+-3:
+- @ Test for possible subtractions. On the final pass, this may
+- @ subtract too much from the dividend, so keep track of which
+- @ subtractions are done, we can fix them up afterwards...
+- mov overdone, #0
+- cmp dividend, divisor
+- subcs dividend, dividend, divisor
+- cmp dividend, divisor, lsr #1
+- subcs dividend, dividend, divisor, lsr #1
+- orrcs overdone, overdone, curbit, ror #1
+- cmp dividend, divisor, lsr #2
+- subcs dividend, dividend, divisor, lsr #2
+- orrcs overdone, overdone, curbit, ror #2
+- cmp dividend, divisor, lsr #3
+- subcs dividend, dividend, divisor, lsr #3
+- orrcs overdone, overdone, curbit, ror #3
+- mov ip, curbit
+- cmp dividend, #0 @ Early termination?
+- movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+- movne divisor, divisor, lsr #4
+- bne 3b
+-
+- @ Any subtractions that we should not have done will be recorded in
+- @ the top three bits of "overdone". Exactly which were not needed
+- @ are governed by the position of the bit, stored in ip.
+- @ If we terminated early, because dividend became zero,
+- @ then none of the below will match, since the bit in ip will not be
+- @ in the bottom nibble.
+- ands overdone, overdone, #0xe0000000
+- beq Lgot_result_modsi3
+- tst overdone, ip, ror #3
+- addne dividend, dividend, divisor, lsr #3
+- tst overdone, ip, ror #2
+- addne dividend, dividend, divisor, lsr #2
+- tst overdone, ip, ror #1
+- addne dividend, dividend, divisor, lsr #1
+-Lgot_result_modsi3:
+- ldr ip, [sp], #4
+- cmp ip, #0
+- rsbmi dividend, dividend, #0
+- RET pc, lr
+--- linux-2.6.0-test6/arch/arm/mach-integrator/core.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/mach-integrator/core.c 2003-10-05 00:33:23.000000000 -0700
+@@ -1,134 +1,59 @@
+ /*
+- * linux/arch/arm/mach-integrator/arch.c
++ * linux/arch/arm/mach-integrator/core.c
+ *
+- * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ * it under the terms of the GNU General Public License version 2, as
++ * published by the Free Software Foundation.
+ */
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/list.h>
+ #include <linux/device.h>
+-#include <linux/slab.h>
+-#include <linux/string.h>
+
+ #include <asm/hardware.h>
+-#include <asm/io.h>
+ #include <asm/irq.h>
+-#include <asm/setup.h>
+-#include <asm/mach-types.h>
+ #include <asm/hardware/amba.h>
+-#include <asm/hardware/amba_kmi.h>
+-
+-#include <asm/arch/lm.h>
+-
+-#include <asm/mach/arch.h>
+-#include <asm/mach/irq.h>
+-#include <asm/mach/map.h>
+-
+-/*
+- * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
+- * is the (PA >> 12).
+- *
+- * Setup a VA for the Integrator interrupt controller (for header #0,
+- * just for now).
+- */
+-#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE)
+-#define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE)
+-#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_IC_OFFSET
+-
+-/*
+- * Logical Physical
+- * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M)
+- * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M)
+- * ed000000 62000000 PCI V3 regs PHYS_PCI_V3_BASE (max 64k)
+- * ee000000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M)
+- * ef000000 Cache flush
+- * f1000000 10000000 Core module registers
+- * f1100000 11000000 System controller registers
+- * f1200000 12000000 EBI registers
+- * f1300000 13000000 Counter/Timer
+- * f1400000 14000000 Interrupt controller
+- * f1500000 15000000 RTC
+- * f1600000 16000000 UART 0
+- * f1700000 17000000 UART 1
+- * f1a00000 1a000000 Debug LEDs
+- * f1b00000 1b000000 GPIO
+- */
+
+-static struct map_desc integrator_io_desc[] __initdata = {
+- { IO_ADDRESS(INTEGRATOR_HDR_BASE), INTEGRATOR_HDR_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_SC_BASE), INTEGRATOR_SC_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_EBI_BASE), INTEGRATOR_EBI_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_CT_BASE), INTEGRATOR_CT_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_IC_BASE), INTEGRATOR_IC_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE },
+- { IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
+- { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
+- { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
+- { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_64K, MT_DEVICE },
+- { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE }
++static struct amba_device rtc_device = {
++ .dev = {
++ .bus_id = "mb:15",
++ },
++ .res = {
++ .start = INTEGRATOR_RTC_BASE,
++ .end = INTEGRATOR_RTC_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = IRQ_RTCINT,
++ .periphid = 0x00041030,
+ };
+
+-static void __init integrator_map_io(void)
+-{
+- iotable_init(integrator_io_desc, ARRAY_SIZE(integrator_io_desc));
+-}
+-
+-#define ALLPCI ( (1 << IRQ_PCIINT0) | (1 << IRQ_PCIINT1) | (1 << IRQ_PCIINT2) | (1 << IRQ_PCIINT3) )
+-
+-static void sc_mask_irq(unsigned int irq)
+-{
+- writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+-}
+-
+-static void sc_unmask_irq(unsigned int irq)
+-{
+- writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
+-}
+-
+-static struct irqchip sc_chip = {
+- .ack = sc_mask_irq,
+- .mask = sc_mask_irq,
+- .unmask = sc_unmask_irq,
++static struct amba_device uart0_device = {
++ .dev = {
++ .bus_id = "mb:16",
++ },
++ .res = {
++ .start = INTEGRATOR_UART0_BASE,
++ .end = INTEGRATOR_UART0_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = IRQ_UARTINT0,
++ .periphid = 0x0041010,
+ };
+
+-static void __init integrator_init_irq(void)
+-{
+- unsigned int i;
+-
+- /* Disable all interrupts initially. */
+- /* Do the core module ones */
+- writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+-
+- /* do the header card stuff next */
+- writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+- writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
+-
+- for (i = 0; i < NR_IRQS; i++) {
+- if (((1 << i) && INTEGRATOR_SC_VALID_INT) != 0) {
+- set_irq_chip(i, &sc_chip);
+- set_irq_handler(i, do_level_IRQ);
+- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+- }
+- }
+-}
++static struct amba_device uart1_device = {
++ .dev = {
++ .bus_id = "mb:17",
++ },
++ .res = {
++ .start = INTEGRATOR_UART1_BASE,
++ .end = INTEGRATOR_UART1_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = IRQ_UARTINT1,
++ .periphid = 0x0041010,
++};
+
+ static struct amba_device kmi0_device = {
+ .dev = {
+@@ -136,7 +61,7 @@ static struct amba_device kmi0_device =
+ },
+ .res = {
+ .start = KMI0_BASE,
+- .end = KMI0_BASE + KMI_SIZE - 1,
++ .end = KMI0_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = IRQ_KMIINT0,
+@@ -149,7 +74,7 @@ static struct amba_device kmi1_device =
+ },
+ .res = {
+ .start = KMI1_BASE,
+- .end = KMI1_BASE + KMI_SIZE - 1,
++ .end = KMI1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .irq = IRQ_KMIINT1,
+@@ -157,52 +82,23 @@ static struct amba_device kmi1_device =
+ };
+
+ static struct amba_device *amba_devs[] __initdata = {
++ &rtc_device,
++ &uart0_device,
++ &uart1_device,
+ &kmi0_device,
+ &kmi1_device,
+ };
+
+-static int __init register_devices(void)
++static int __init integrator_init(void)
+ {
+- unsigned long sc_dec;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+-
+ amba_device_register(d, &iomem_resource);
+ }
+
+- sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+- for (i = 0; i < 4; i++) {
+- struct lm_device *lmdev;
+-
+- if ((sc_dec & (16 << i)) == 0)
+- continue;
+-
+- lmdev = kmalloc(sizeof(struct lm_device), GFP_KERNEL);
+- if (!lmdev)
+- continue;
+-
+- memset(lmdev, 0, sizeof(struct lm_device));
+-
+- lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
+- lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
+- lmdev->resource.flags = IORESOURCE_MEM;
+- lmdev->irq = IRQ_EXPINT0 + i;
+- lmdev->id = i;
+-
+- lm_device_register(lmdev);
+- }
+-
+ return 0;
+ }
+
+-arch_initcall(register_devices);
+-
+-MACHINE_START(INTEGRATOR, "ARM-Integrator")
+- MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
+- BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
+- BOOT_PARAMS(0x00000100)
+- MAPIO(integrator_map_io)
+- INITIRQ(integrator_init_irq)
+-MACHINE_END
++arch_initcall(integrator_init);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/arm/mach-integrator/integrator_ap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -0,0 +1,294 @@
++/*
++ * linux/arch/arm/mach-integrator/integrator_ap.c
++ *
++ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/device.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/sysdev.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/hardware/amba.h>
++#include <asm/hardware/amba_kmi.h>
++
++#include <asm/arch/lm.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/map.h>
++
++
++/*
++ * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
++ * is the (PA >> 12).
++ *
++ * Setup a VA for the Integrator interrupt controller (for header #0,
++ * just for now).
++ */
++#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE)
++#define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE)
++#define VA_EBI_BASE IO_ADDRESS(INTEGRATOR_EBI_BASE)
++#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_IC_OFFSET
++
++/*
++ * Logical Physical
++ * e8000000 40000000 PCI memory PHYS_PCI_MEM_BASE (max 512M)
++ * ec000000 61000000 PCI config space PHYS_PCI_CONFIG_BASE (max 16M)
++ * ed000000 62000000 PCI V3 regs PHYS_PCI_V3_BASE (max 64k)
++ * ee000000 60000000 PCI IO PHYS_PCI_IO_BASE (max 16M)
++ * ef000000 Cache flush
++ * f1000000 10000000 Core module registers
++ * f1100000 11000000 System controller registers
++ * f1200000 12000000 EBI registers
++ * f1300000 13000000 Counter/Timer
++ * f1400000 14000000 Interrupt controller
++ * f1500000 15000000 RTC
++ * f1600000 16000000 UART 0
++ * f1700000 17000000 UART 1
++ * f1a00000 1a000000 Debug LEDs
++ * f1b00000 1b000000 GPIO
++ */
++
++static struct map_desc ap_io_desc[] __initdata = {
++ { IO_ADDRESS(INTEGRATOR_HDR_BASE), INTEGRATOR_HDR_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_SC_BASE), INTEGRATOR_SC_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_EBI_BASE), INTEGRATOR_EBI_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_CT_BASE), INTEGRATOR_CT_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_IC_BASE), INTEGRATOR_IC_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE },
++ { IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
++ { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
++ { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
++ { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_64K, MT_DEVICE },
++ { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE }
++};
++
++static void __init ap_map_io(void)
++{
++ iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
++}
++
++#define INTEGRATOR_SC_VALID_INT 0x003fffff
++
++static void sc_mask_irq(unsigned int irq)
++{
++ writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
++}
++
++static void sc_unmask_irq(unsigned int irq)
++{
++ writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
++}
++
++static struct irqchip sc_chip = {
++ .ack = sc_mask_irq,
++ .mask = sc_mask_irq,
++ .unmask = sc_unmask_irq,
++};
++
++static void __init ap_init_irq(void)
++{
++ unsigned int i;
++
++ /* Disable all interrupts initially. */
++ /* Do the core module ones */
++ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
++
++ /* do the header card stuff next */
++ writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
++ writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
++
++ for (i = 0; i < NR_IRQS; i++) {
++ if (((1 << i) && INTEGRATOR_SC_VALID_INT) != 0) {
++ set_irq_chip(i, &sc_chip);
++ set_irq_handler(i, do_level_IRQ);
++ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
++ }
++ }
++}
++
++#ifdef CONFIG_PM
++static unsigned long ic_irq_enable;
++
++static int irq_suspend(struct sys_device *dev, u32 state)
++{
++ ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
++ return 0;
++}
++
++static int irq_resume(struct sys_device *dev)
++{
++ /* disable all irq sources */
++ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
++ writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
++ writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
++
++ writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
++ return 0;
++}
++#else
++#define irq_suspend NULL
++#define irq_resume NULL
++#endif
++
++static struct sysdev_class irq_class = {
++ set_kset_name("irq"),
++ .suspend = irq_suspend,
++ .resume = irq_resume,
++};
++
++static struct sys_device irq_device = {
++ .id = 0,
++ .cls = &irq_class,
++};
++
++static int __init irq_init_sysfs(void)
++{
++ int ret = sysdev_class_register(&irq_class);
++ if (ret == 0)
++ ret = sys_device_register(&irq_device);
++ return ret;
++}
++
++device_initcall(irq_init_sysfs);
++
++/*
++ * Flash handling.
++ */
++#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
++#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
++#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
++#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
++
++static int ap_flash_init(void)
++{
++ u32 tmp;
++
++ writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
++
++ tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
++ writel(tmp, EBI_CSR1);
++
++ if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
++ writel(0xa05f, EBI_LOCK);
++ writel(tmp, EBI_CSR1);
++ writel(0, EBI_LOCK);
++ }
++ return 0;
++}
++
++static void ap_flash_exit(void)
++{
++ u32 tmp;
++
++ writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
++
++ tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
++ writel(tmp, EBI_CSR1);
++
++ if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
++ writel(0xa05f, EBI_LOCK);
++ writel(tmp, EBI_CSR1);
++ writel(0, EBI_LOCK);
++ }
++}
++
++static void ap_flash_set_vpp(int on)
++{
++ unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
++
++ writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
++}
++
++static struct flash_platform_data ap_flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = ap_flash_init,
++ .exit = ap_flash_exit,
++ .set_vpp = ap_flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = INTEGRATOR_FLASH_BASE,
++ .end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "armflash",
++ .id = 0,
++ .dev = {
++ .platform_data = &ap_flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++static int __init ap_init(void)
++{
++ unsigned long sc_dec;
++ int i;
++
++ platform_add_device(&cfi_flash_device);
++
++ sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
++ for (i = 0; i < 4; i++) {
++ struct lm_device *lmdev;
++
++ if ((sc_dec & (16 << i)) == 0)
++ continue;
++
++ lmdev = kmalloc(sizeof(struct lm_device), GFP_KERNEL);
++ if (!lmdev)
++ continue;
++
++ memset(lmdev, 0, sizeof(struct lm_device));
++
++ lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
++ lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
++ lmdev->resource.flags = IORESOURCE_MEM;
++ lmdev->irq = IRQ_AP_EXPINT0 + i;
++ lmdev->id = i;
++
++ lm_device_register(lmdev);
++ }
++
++ return 0;
++}
++
++arch_initcall(ap_init);
++
++MACHINE_START(INTEGRATOR, "ARM-Integrator")
++ MAINTAINER("ARM Ltd/Deep Blue Solutions Ltd")
++ BOOT_MEM(0x00000000, 0x16000000, 0xf1600000)
++ BOOT_PARAMS(0x00000100)
++ MAPIO(ap_map_io)
++ INITIRQ(ap_init_irq)
++MACHINE_END
+--- linux-2.6.0-test6/arch/arm/mach-integrator/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/mach-integrator/Kconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -1,8 +1,15 @@
+ menu "Integrator Options"
+ depends on ARCH_INTEGRATOR
+
++config ARCH_INTEGRATOR_AP
++ bool "Support Integrator/AP and Integrator/PP2 platforms"
++ help
++ Include support for the ARM(R) Integrator/AP and
++ Integrator/PP2 platforms.
++
+ config INTEGRATOR_IMPD1
+ tristate "Include support for Integrator/IM-PD1"
++ depends on ARCH_INTEGRATOR_AP
+ help
+ The IM-PD1 is an add-on logic module for the Integrator which
+ allows ARM(R) Ltd PrimeCells to be developed and evaluated.
+--- linux-2.6.0-test6/arch/arm/mach-integrator/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/mach-integrator/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -4,9 +4,10 @@
+
+ # Object file lists.
+
+-obj-y := core.o lm.o time.o
++obj-y := core.o lm.o time.o
++obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
+
+-obj-$(CONFIG_LEDS) += leds.o
+-obj-$(CONFIG_PCI) += pci_v3.o pci.o
++obj-$(CONFIG_LEDS) += leds.o
++obj-$(CONFIG_PCI) += pci_v3.o pci.o
+ obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
+ obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
+--- linux-2.6.0-test6/arch/arm/mach-integrator/pci.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/arm/mach-integrator/pci.c 2003-10-05 00:33:23.000000000 -0700
+@@ -96,7 +96,7 @@ static u8 __init integrator_swizzle(stru
+ }
+
+ static int irq_tab[4] __initdata = {
+- IRQ_PCIINT0, IRQ_PCIINT1, IRQ_PCIINT2, IRQ_PCIINT3
++ IRQ_AP_PCIINT0, IRQ_AP_PCIINT1, IRQ_AP_PCIINT2, IRQ_AP_PCIINT3
+ };
+
+ /*
+--- linux-2.6.0-test6/arch/arm/mach-integrator/pci_v3.c 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/arm/mach-integrator/pci_v3.c 2003-10-05 00:33:23.000000000 -0700
+@@ -575,7 +575,7 @@ void __init pci_v3_preinit(void)
+ /*
+ * Grab the PCI error interrupt.
+ */
+- ret = request_irq(IRQ_V3INT, v3_irq, 0, "V3", NULL);
++ ret = request_irq(IRQ_AP_V3INT, v3_irq, 0, "V3", NULL);
+ if (ret)
+ printk(KERN_ERR "PCI: unable to grab PCI error "
+ "interrupt: %d\n", ret);
+@@ -596,7 +596,7 @@ void __init pci_v3_postinit(void)
+ v3_writeb(V3_LB_IMASK, 0x68);
+
+ #if 0
+- ret = request_irq(IRQ_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
++ ret = request_irq(IRQ_AP_LBUSTIMEOUT, lb_timeout, 0, "bus timeout", NULL);
+ if (ret)
+ printk(KERN_ERR "PCI: unable to grab local bus timeout "
+ "interrupt: %d\n", ret);
+--- linux-2.6.0-test6/arch/arm/mach-pxa/irq.c 2003-06-14 12:18:33.000000000 -0700
++++ 25/arch/arm/mach-pxa/irq.c 2003-10-05 00:33:23.000000000 -0700
+@@ -58,7 +58,19 @@ static int pxa_gpio_irq_type(unsigned in
+ {
+ int gpio, idx;
+
+- gpio = irq - ((irq >= IRQ_GPIO(2)) ? IRQ_GPIO(2) + 2 : IRQ_GPIO(0));
++ gpio = IRQ_TO_GPIO(irq);
++ idx = gpio >> 5;
++
++ if (type == IRQT_PROBE) {
++ /* Don't mess with enabled GPIOs using preconfigured edges or
++ GPIOs set to alternate function during probe */
++ if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
++ GPIO_bit(gpio))
++ return 0;
++ if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
++ return 0;
++ type = __IRQT_RISEDGE | __IRQT_FALEDGE;
++ }
+
+ printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio);
+
+@@ -78,10 +90,8 @@ static int pxa_gpio_irq_type(unsigned in
+
+ printk("edges\n");
+
+- idx = gpio >> 5;
+ GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+ GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+-
+ return 0;
+ }
+
+--- linux-2.6.0-test6/arch/arm/mach-pxa/leds.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/mach-pxa/leds.c 2003-10-05 00:33:23.000000000 -0700
+@@ -7,6 +7,7 @@
+ *
+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
+ */
++#include <linux/compiler.h>
+ #include <linux/init.h>
+
+ #include <asm/leds.h>
+--- linux-2.6.0-test6/arch/arm/mach-pxa/lubbock.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/arm/mach-pxa/lubbock.c 2003-10-05 00:33:23.000000000 -0700
+@@ -78,7 +78,7 @@ static void __init lubbock_init_irq(void
+ pxa_init_irq();
+
+ /* setup extra lubbock irqs */
+- for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_IRQ(5); irq++) {
++ for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
+ set_irq_chip(irq, &lubbock_irq_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+@@ -124,6 +124,7 @@ static struct map_desc lubbock_io_desc[]
+ { 0xf0000000, 0x08000000, 0x00100000, MT_DEVICE }, /* CPLD */
+ { 0xf1000000, 0x0c000000, 0x00100000, MT_DEVICE }, /* LAN91C96 IO */
+ { 0xf1100000, 0x0e000000, 0x00100000, MT_DEVICE }, /* LAN91C96 Attr */
++ { 0xf4000000, 0x10000000, 0x00800000, MT_DEVICE }, /* SA1111 */
+ };
+
+ static void __init lubbock_map_io(void)
+--- linux-2.6.0-test6/arch/arm/mach-pxa/pm.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/mach-pxa/pm.c 2003-10-05 00:33:23.000000000 -0700
+@@ -11,13 +11,14 @@
+ * modify it under the terms of the GNU General Public License.
+ */
+ #include <linux/config.h>
++#include <linux/init.h>
++#include <linux/suspend.h>
+ #include <linux/errno.h>
+ #include <linux/time.h>
+
+ #include <asm/hardware.h>
+ #include <asm/memory.h>
+ #include <asm/system.h>
+-#include <asm/leds.h>
+
+
+ /*
+@@ -60,13 +61,16 @@ enum { SLEEP_SAVE_START = 0,
+ };
+
+
+-int pm_do_suspend(void)
++static int pxa_pm_enter(u32 state)
+ {
+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
+ unsigned long checksum = 0;
+ unsigned long delta;
+ int i;
+
++ if (state != PM_SUSPEND_MEM)
++ return -EINVAL;
++
+ /* preserve current time */
+ delta = xtime.tv_sec - RCNR;
+
+@@ -194,3 +198,37 @@ unsigned long sleep_phys_sp(void *sp)
+ {
+ return virt_to_phys(sp);
+ }
++
++/*
++ * Called after processes are frozen, but before we shut down devices.
++ */
++static int pxa_pm_prepare(u32 state)
++{
++ return 0;
++}
++
++/*
++ * Called after devices are re-setup, but before processes are thawed.
++ */
++static int pxa_pm_finish(u32 state)
++{
++ return 0;
++}
++
++/*
++ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
++ */
++static struct pm_ops pxa_pm_ops = {
++ .pm_disk_mode = PM_DISK_FIRMWARE,
++ .prepare = pxa_pm_prepare,
++ .enter = pxa_pm_enter,
++ .finish = pxa_pm_finish,
++};
++
++static int __init pxa_pm_init(void)
++{
++ pm_set_ops(&pxa_pm_ops);
++ return 0;
++}
++
++late_initcall(pxa_pm_init);
+--- linux-2.6.0-test6/arch/arm/mach-sa1100/leds.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/arm/mach-sa1100/leds.c 2003-10-05 00:33:23.000000000 -0700
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (C) 2001 Nicolas Pitre
+ */
++#include <linux/compiler.h>
+ #include <linux/init.h>
+
+ #include <asm/leds.h>
+--- linux-2.6.0-test6/arch/arm/mach-sa1100/pm.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/arm/mach-sa1100/pm.c 2003-10-05 00:33:23.000000000 -0700
+@@ -22,6 +22,8 @@
+ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
+ * Storage is local on the stack now.
+ */
++#include <linux/init.h>
++#include <linux/suspend.h>
+ #include <linux/errno.h>
+ #include <linux/time.h>
+
+@@ -54,11 +56,14 @@ enum { SLEEP_SAVE_SP = 0,
+ };
+
+
+-int pm_do_suspend(void)
++static int sa11x0_pm_enter(u32 state)
+ {
+ unsigned long sleep_save[SLEEP_SAVE_SIZE];
+ unsigned long delta, gpio;
+
++ if (state != PM_SUSPEND_MEM)
++ return -EINVAL;
++
+ /* preserve current time */
+ delta = xtime.tv_sec - RCNR;
+ gpio = GPLR;
+@@ -139,3 +144,37 @@ unsigned long sleep_phys_sp(void *sp)
+ {
+ return virt_to_phys(sp);
+ }
++
++/*
++ * Called after processes are frozen, but before we shut down devices.
++ */
++static int sa11x0_pm_prepare(u32 state)
++{
++ return 0;
++}
++
++/*
++ * Called after devices are re-setup, but before processes are thawed.
++ */
++static int sa11x0_pm_finish(u32 state)
++{
++ return 0;
++}
++
++/*
++ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
++ */
++static struct pm_ops sa11x0_pm_ops = {
++ .pm_disk_mode = PM_DISK_FIRMWARE,
++ .prepare = sa11x0_pm_prepare,
++ .enter = sa11x0_pm_enter,
++ .finish = sa11x0_pm_finish,
++};
++
++static int __init sa11x0_pm_init(void)
++{
++ pm_set_ops(&sa11x0_pm_ops);
++ return 0;
++}
++
++late_initcall(sa11x0_pm_init);
+--- linux-2.6.0-test6/arch/arm/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/arm/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -182,7 +182,6 @@ define archhelp
+ echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+ echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+ echo ' bootpImage - Combined zImage and initial RAM disk'
+- echo ' initrd - Create an initial image'
+ echo ' install - Install uncompressed kernel'
+ echo ' zinstall - Install compressed kernel'
+ echo ' Install using (your) ~/bin/installkernel or'
+--- linux-2.6.0-test6/arch/arm/mm/discontig.c 2003-06-14 12:18:31.000000000 -0700
++++ 25/arch/arm/mm/discontig.c 2003-10-05 00:34:40.000000000 -0700
+@@ -15,7 +15,7 @@
+ #include <linux/init.h>
+ #include <linux/bootmem.h>
+
+-#if NR_NODES != 4
++#if MAX_NUMNODES != 4
+ #error Fix Me Please
+ #endif
+
+@@ -23,9 +23,9 @@
+ * Our node_data structure for discontiguous memory.
+ */
+
+-static bootmem_data_t node_bootmem_data[NR_NODES];
++static bootmem_data_t node_bootmem_data[MAX_NUMNODES];
+
+-pg_data_t discontig_node_data[NR_NODES] = {
++pg_data_t discontig_node_data[MAX_NUMNODES] = {
+ { .bdata = &node_bootmem_data[0] },
+ { .bdata = &node_bootmem_data[1] },
+ { .bdata = &node_bootmem_data[2] },
+--- linux-2.6.0-test6/arch/arm/mm/init.c 2003-07-10 18:50:30.000000000 -0700
++++ 25/arch/arm/mm/init.c 2003-10-05 00:34:40.000000000 -0700
+@@ -33,12 +33,6 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+
+-#ifndef CONFIG_DISCONTIGMEM
+-#define NR_NODES 1
+-#else
+-#define NR_NODES 4
+-#endif
+-
+ #ifdef CONFIG_CPU_32
+ #define TABLE_OFFSET (PTRS_PER_PTE)
+ #else
+@@ -178,7 +172,7 @@ find_memend_and_nodes(struct meminfo *mi
+ {
+ unsigned int i, bootmem_pages = 0, memend_pfn = 0;
+
+- for (i = 0; i < NR_NODES; i++) {
++ for (i = 0; i < MAX_NUMNODES; i++) {
+ np[i].start = -1U;
+ np[i].end = 0;
+ np[i].bootmap_pages = 0;
+@@ -207,7 +201,7 @@ find_memend_and_nodes(struct meminfo *mi
+ * we have, we're in trouble. (maybe we ought to
+ * limit, instead of bugging?)
+ */
+- if (numnodes > NR_NODES)
++ if (numnodes > MAX_NUMNODES)
+ BUG();
+ }
+
+@@ -365,7 +359,7 @@ static inline void free_bootmem_node_ban
+ */
+ void __init bootmem_init(struct meminfo *mi)
+ {
+- struct node_info node_info[NR_NODES], *np = node_info;
++ struct node_info node_info[MAX_NUMNODES], *np = node_info;
+ unsigned int bootmap_pages, bootmap_pfn, map_pg;
+ int node, initrd_node;
+
+--- linux-2.6.0-test6/arch/arm/mm/ioremap.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/arm/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -150,7 +150,7 @@ __ioremap(unsigned long phys_addr, size_
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/cris/mm/ioremap.c 2003-07-10 18:50:30.000000000 -0700
++++ 25/arch/cris/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -157,7 +157,7 @@ void * __ioremap(unsigned long phys_addr
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/h8300/README 2003-06-14 12:18:26.000000000 -0700
++++ 25/arch/h8300/README 2003-10-05 00:33:23.000000000 -0700
+@@ -16,7 +16,7 @@ H8S is planning.
+
+ 3.H8MAX
+ Under development
+- see http://www.strawbelly-linux.com (Japanese Only)
++ see http://www.strawberry-linux.com (Japanese Only)
+
+ * Toolchain Version
+ gcc-3.1 or higher and patch
+--- linux-2.6.0-test6/arch/i386/boot/setup.S 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/boot/setup.S 2003-10-05 00:36:48.000000000 -0700
+@@ -162,7 +162,7 @@ cmd_line_ptr: .long 0 # (Header versio
+ # can be located anywhere in
+ # low memory 0x10000 or higher.
+
+-ramdisk_max: .long MAXMEM-1 # (Header version 0x0203 or later)
++ramdisk_max: .long __MAXMEM-1 # (Header version 0x0203 or later)
+ # The highest safe address for
+ # the contents of an initrd
+
+--- linux-2.6.0-test6/arch/i386/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/Kconfig 2003-10-05 00:36:48.000000000 -0700
+@@ -397,6 +397,54 @@ config X86_OOSTORE
+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6
+ default y
+
++config X86_4G
++ bool "4 GB kernel-space and 4 GB user-space virtual memory support"
++ help
++ This option is only useful for systems that have more than 1 GB
++ of RAM.
++
++ The default kernel VM layout leaves 1 GB of virtual memory for
++ kernel-space mappings, and 3 GB of VM for user-space applications.
++ This option ups both the kernel-space VM and the user-space VM to
++ 4 GB.
++
++ The cost of this option is additional TLB flushes done at
++ system-entry points that transition from user-mode into kernel-mode.
++ I.e. system calls and page faults, and IRQs that interrupt user-mode
++ code. There's also additional overhead to kernel operations that copy
++ memory to/from user-space. The overhead from this is hard to tell and
++ depends on the workload - it can be anything from no visible overhead
++ to 20-30% overhead. A good rule of thumb is to count with a runtime
++ overhead of 20%.
++
++ The upside is the much increased kernel-space VM, which more than
++ quadruples the maximum amount of RAM supported. Kernels compiled with
++ this option boot on 64GB of RAM and still have more than 3.1 GB of
++ 'lowmem' left. Another bonus is that highmem IO bouncing decreases,
++ if used with drivers that still use bounce-buffers.
++
++ There's also a 33% increase in user-space VM size - database
++ applications might see a boost from this.
++
++ But the cost of the TLB flushes and the runtime overhead has to be
++ weighed against the bonuses offered by the larger VM spaces. The
++ dividing line depends on the actual workload - there might be 4 GB
++ systems that benefit from this option. Systems with less than 4 GB
++ of RAM will rarely see a benefit from this option - but it's not
++ out of question, the exact circumstances have to be considered.
++
++config X86_SWITCH_PAGETABLES
++ def_bool X86_4G
++
++config X86_4G_VM_LAYOUT
++ def_bool X86_4G
++
++config X86_UACCESS_INDIRECT
++ def_bool X86_4G
++
++config X86_HIGH_ENTRY
++ def_bool X86_4G
++
+ config HPET_TIMER
+ bool "HPET Timer Support"
+ help
+@@ -793,7 +841,8 @@ config HAVE_DEC_LOCK
+ # Summit needs it only when NUMA is on
+ config BOOT_IOREMAP
+ bool
+- depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA)
++ depends on X86_PC
++# depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA)) || X86_GENERICARCH
+ default y
+
+ endmenu
+@@ -1030,6 +1079,25 @@ config PCI_DIRECT
+ depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+ default y
+
++config PCI_USE_VECTOR
++ bool "Vector-based interrupt indexing"
++ depends on X86_LOCAL_APIC
++ default n
++ help
++ This replaces the current existing IRQ-based index interrupt scheme
++ with the vector-base index scheme. The advantages of vector base
++ over IRQ base are listed below:
++ 1) Support MSI implementation.
++ 2) Support future IOxAPIC hotplug
++
++ Note that this enables MSI, Message Signaled Interrupt, on all
++ MSI capable device functions detected if users also install the
++ MSI patch. Message Signal Interrupt enables an MSI-capable
++ hardware device to send an inbound Memory Write on its PCI bus
++ instead of asserting IRQ signal on device IRQ pin.
++
++ If you don't know what to do here, say N.
++
+ source "drivers/pci/Kconfig"
+
+ config ISA
+@@ -1231,6 +1299,15 @@ config DEBUG_PAGEALLOC
+ This results in a large slowdown, but helps to find certain types
+ of memory corruptions.
+
++config SPINLINE
++ bool "Spinlock inlining"
++ depends on DEBUG_KERNEL
++ help
++ This will change spinlocks from out of line to inline, making them
++ account cost to the callers in readprofile, rather than the lock
++ itself (as ".text.lock.filename"). This can be helpful for finding
++ the callers of locks.
++
+ config DEBUG_HIGHMEM
+ bool "Highmem debugging"
+ depends on DEBUG_KERNEL && HIGHMEM
+@@ -1247,20 +1324,208 @@ config DEBUG_INFO
+ Say Y here only if you plan to use gdb to debug the kernel.
+ If you don't debug the kernel, you can say N.
+
++config LOCKMETER
++ bool "Kernel lock metering"
++ depends on SMP && !PREEMPT
++ help
++ Say Y to enable kernel lock metering, which adds overhead to SMP locks,
++ but allows you to see various statistics using the lockstat command.
++
+ config DEBUG_SPINLOCK_SLEEP
+ bool "Sleep-inside-spinlock checking"
+ help
+ If you say Y here, various routines which may sleep will become very
+ noisy if they are called with a spinlock held.
+
++config KGDB
++ bool "Include kgdb kernel debugger"
++ depends on DEBUG_KERNEL
++ help
++ If you say Y here, the system will be compiled with the debug
++ option (-g) and a debugging stub will be included in the
++ kernel. This stub communicates with gdb on another (host)
++ computer via a serial port. The host computer should have
++ access to the kernel binary file (vmlinux) and a serial port
++ that is connected to the target machine. Gdb can be made to
++ configure the serial port or you can use stty and setserial to
++ do this. See the 'target' command in gdb. This option also
++ configures in the ability to request a breakpoint early in the
++ boot process. To request the breakpoint just include 'kgdb'
++ as a boot option when booting the target machine. The system
++ will then break as soon as it looks at the boot options. This
++ option also installs a breakpoint in panic and sends any
++ kernel faults to the debugger. For more information see the
++ Documentation/i386/kgdb.txt file.
++
++choice
++ depends on KGDB
++ prompt "Debug serial port BAUD"
++ default KGDB_115200BAUD
++ help
++ Gdb and the kernel stub need to agree on the baud rate to be
++ used. Some systems (x86 family at this writing) allow this to
++ be configured.
++
++config KGDB_9600BAUD
++ bool "9600"
++
++config KGDB_19200BAUD
++ bool "19200"
++
++config KGDB_38400BAUD
++ bool "38400"
++
++config KGDB_57600BAUD
++ bool "57600"
++
++config KGDB_115200BAUD
++ bool "115200"
++endchoice
++
++config KGDB_PORT
++ hex "hex I/O port address of the debug serial port"
++ depends on KGDB
++ default 3f8
++ help
++ Some systems (x86 family at this writing) allow the port
++ address to be configured. The number entered is assumed to be
++ hex, don't put 0x in front of it. The standard address are:
++ COM1 3f8 , irq 4 and COM2 2f8 irq 3. Setserial /dev/ttySx
++ will tell you what you have. It is good to test the serial
++ connection with a live system before trying to debug.
++
++config KGDB_IRQ
++ int "IRQ of the debug serial port"
++ depends on KGDB
++ default 4
++ help
++ This is the irq for the debug port. If everything is working
++ correctly and the kernel has interrupts on a control C to the
++ port should cause a break into the kernel debug stub.
++
++config DEBUG_INFO
++ bool
++ depends on KGDB
++ default y
++
++config KGDB_MORE
++ bool "Add any additional compile options"
++ depends on KGDB
++ default n
++ help
++ Saying yes here turns on the ability to enter additional
++ compile options.
++
++
++config KGDB_OPTIONS
++ depends on KGDB_MORE
++ string "Additional compile arguments"
++ default "-O1"
++ help
++ This option allows you enter additional compile options for
++ the whole kernel compile. Each platform will have a default
++ that seems right for it. For example on PPC "-ggdb -O1", and
++ for i386 "-O1". Note that by configuring KGDB "-g" is already
++ turned on. In addition, on i386 platforms
++ "-fomit-frame-pointer" is deleted from the standard compile
++ options.
++
++config NO_KGDB_CPUS
++ int "Number of CPUs"
++ depends on KGDB && SMP
++ default NR_CPUS
++ help
++
++ This option sets the number of cpus for kgdb ONLY. It is used
++ to prune some internal structures so they look "nice" when
++ displayed with gdb. This is to overcome possibly larger
++ numbers that may have been entered above. Enter the real
++ number to get nice clean kgdb_info displays.
++
++config KGDB_TS
++ bool "Enable kgdb time stamp macros?"
++ depends on KGDB
++ default n
++ help
++ Kgdb event macros allow you to instrument your code with calls
++ to the kgdb event recording function. The event log may be
++ examined with gdb at a break point. Turning on this
++ capability also allows you to choose how many events to
++ keep. Kgdb always keeps the lastest events.
++
++choice
++ depends on KGDB_TS
++ prompt "Max number of time stamps to save?"
++ default KGDB_TS_128
++
++config KGDB_TS_64
++ bool "64"
++
++config KGDB_TS_128
++ bool "128"
++
++config KGDB_TS_256
++ bool "256"
++
++config KGDB_TS_512
++ bool "512"
++
++config KGDB_TS_1024
++ bool "1024"
++
++endchoice
++
++config STACK_OVERFLOW_TEST
++ bool "Turn on kernel stack overflow testing?"
++ depends on KGDB
++ default n
++ help
++ This option enables code in the front line interrupt handlers
++ to check for kernel stack overflow on interrupts and system
++ calls. This is part of the kgdb code on x86 systems.
++
++config KGDB_CONSOLE
++ bool "Enable serial console thru kgdb port"
++ depends on KGDB
++ default n
++ help
++ This option enables the command line "console=kgdb" option.
++ When the system is booted with this option in the command line
++ all kernel printk output is sent to gdb (as well as to other
++ consoles). For this to work gdb must be connected. For this
++ reason, this command line option will generate a breakpoint if
++ gdb has not yet connected. After the gdb continue command is
++ given all pent up console output will be printed by gdb on the
++ host machine. Neither this option, nor KGDB require the
++ serial driver to be configured.
++
++config KGDB_SYSRQ
++ bool "Turn on SysRq 'G' command to do a break?"
++ depends on KGDB
++ default y
++ help
++ This option includes an option in the SysRq code that allows
++ you to enter SysRq G which generates a breakpoint to the KGDB
++ stub. This will work if the keyboard is alive and can
++ interrupt the system. Because of constraints on when the
++ serial port interrupt can be enabled, this code may allow you
++ to interrupt the system before the serial port control C is
++ available. Just say yes here.
++
+ config FRAME_POINTER
+ bool "Compile the kernel with frame pointers"
++ default KGDB
+ help
+ If you say Y here the resulting kernel image will be slightly larger
+ and slower, but it will give very useful debugging information.
+ If you don't debug the kernel, you can say N, but we may not be able
+ to solve problems without frame pointers.
+
++config MAGIC_SYSRQ
++ bool
++ depends on KGDB_SYSRQ
++ default y
++
+ config X86_EXTRA_IRQS
+ bool
+ depends on X86_LOCAL_APIC || X86_VOYAGER
+@@ -1303,3 +1568,8 @@ config X86_TRAMPOLINE
+ bool
+ depends on SMP || X86_VISWS
+ default y
++
++config PC
++ bool
++ depends on X86 && !EMBEDDED
++ default y
+--- linux-2.6.0-test6/arch/i386/kernel/acpi/boot.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/i386/kernel/acpi/boot.c 2003-10-05 00:36:22.000000000 -0700
+@@ -26,6 +26,7 @@
+ #include <linux/init.h>
+ #include <linux/config.h>
+ #include <linux/acpi.h>
++#include <linux/efi.h>
+ #include <asm/pgalloc.h>
+ #include <asm/io_apic.h>
+ #include <asm/apic.h>
+@@ -183,8 +184,7 @@ acpi_parse_lapic_nmi (
+
+ #endif /*CONFIG_X86_LOCAL_APIC*/
+
+-#ifdef CONFIG_X86_IO_APIC
+-
++#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+
+ static int __init
+ acpi_parse_ioapic (
+@@ -297,6 +297,10 @@ acpi_find_rsdp (void)
+ {
+ unsigned long rsdp_phys = 0;
+
++ if (efi.acpi20)
++ return __pa(efi.acpi20);
++ else if (efi.acpi)
++ return __pa(efi.acpi);
+ /*
+ * Scan memory looking for the RSDP signature. First search EBDA (low
+ * memory) paragraphs and then search upper memory (E0000-FFFFF).
+@@ -368,7 +372,6 @@ acpi_boot_init (void)
+
+ result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
+ if (!result) {
+- printk(KERN_WARNING PREFIX "MADT not present\n");
+ return 0;
+ }
+ else if (result < 0) {
+@@ -416,7 +419,7 @@ acpi_boot_init (void)
+
+ #endif /*CONFIG_X86_LOCAL_APIC*/
+
+-#ifdef CONFIG_X86_IO_APIC
++#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+
+ /*
+ * I/O APIC
+@@ -472,7 +475,8 @@ acpi_boot_init (void)
+ acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
+
+ acpi_ioapic = 1;
+-#endif /*CONFIG_X86_IO_APIC*/
++
++#endif /* CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER */
+
+ #ifdef CONFIG_X86_LOCAL_APIC
+ if (acpi_lapic && acpi_ioapic) {
+@@ -480,6 +484,7 @@ acpi_boot_init (void)
+ clustered_apic_check();
+ }
+ #endif
++
+ #ifdef CONFIG_HPET_TIMER
+ acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
+ #endif
+--- linux-2.6.0-test6/arch/i386/kernel/asm-offsets.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/i386/kernel/asm-offsets.c 2003-10-05 00:36:48.000000000 -0700
+@@ -4,9 +4,11 @@
+ * to extract and format the required data.
+ */
+
++#include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <asm/ucontext.h>
+ #include "sigframe.h"
++#include <asm/fixmap.h>
+
+ #define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+@@ -28,4 +30,17 @@ void foo(void)
+
+ DEFINE(RT_SIGFRAME_sigcontext,
+ offsetof (struct rt_sigframe, uc.uc_mcontext));
++ DEFINE(TI_task, offsetof (struct thread_info, task));
++ DEFINE(TI_exec_domain, offsetof (struct thread_info, exec_domain));
++ DEFINE(TI_flags, offsetof (struct thread_info, flags));
++ DEFINE(TI_preempt_count, offsetof (struct thread_info, preempt_count));
++ DEFINE(TI_addr_limit, offsetof (struct thread_info, addr_limit));
++ DEFINE(TI_real_stack, offsetof (struct thread_info, real_stack));
++ DEFINE(TI_virtual_stack, offsetof (struct thread_info, virtual_stack));
++ DEFINE(TI_user_pgd, offsetof (struct thread_info, user_pgd));
++
++ DEFINE(FIX_ENTRY_TRAMPOLINE_0_addr, __fix_to_virt(FIX_ENTRY_TRAMPOLINE_0));
++ DEFINE(FIX_VSYSCALL_addr, __fix_to_virt(FIX_VSYSCALL));
++ DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
++ DEFINE(task_thread_db7, offsetof (struct task_struct, thread.debugreg[7]));
+ }
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/common.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/cpu/common.c 2003-10-05 00:36:48.000000000 -0700
+@@ -510,16 +510,20 @@ void __init cpu_init (void)
+ BUG();
+ enter_lazy_tlb(&init_mm, current);
+
+- load_esp0(t, thread->esp0);
+- set_tss_desc(cpu,t);
++ t->esp0 = thread->esp0;
++ set_tss_desc(cpu, t);
+ cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
+ load_TR_desc();
+- load_LDT(&init_mm.context);
++ if (cpu)
++ load_LDT(&init_mm.context);
+
+ /* Set up doublefault TSS pointer in the GDT */
+ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+ cpu_gdt_table[cpu][GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff;
+
++ if (cpu)
++ trap_init_virtual_GDT();
++
+ /* Clear %fs and %gs. */
+ asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
+
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-10-05 00:33:23.000000000 -0700
+@@ -231,7 +231,7 @@ acpi_processor_set_performance (
+ int state)
+ {
+ u16 port = 0;
+- u8 value = 0;
++ u16 value = 0;
+ int i = 0;
+ struct cpufreq_freqs cpufreq_freqs;
+
+@@ -282,9 +282,9 @@ acpi_processor_set_performance (
+ value = (u16) perf->states[state].control;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "Writing 0x%02x to port 0x%04x\n", value, port));
++ "Writing 0x%04x to port 0x%04x\n", value, port));
+
+- outb(value, port);
++ outw(value, port);
+
+ /*
+ * Then we read the 'status_register' and compare the value with the
+@@ -296,12 +296,12 @@ acpi_processor_set_performance (
+ port = perf->status_register;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+- "Looking for 0x%02x from port 0x%04x\n",
+- (u8) perf->states[state].status, port));
++ "Looking for 0x%04x from port 0x%04x\n",
++ (u16) perf->states[state].status, port));
+
+ for (i=0; i<100; i++) {
+- value = inb(port);
+- if (value == (u8) perf->states[state].status)
++ value = inw(port);
++ if (value == (u16) perf->states[state].status)
+ break;
+ udelay(10);
+ }
+@@ -309,7 +309,7 @@ acpi_processor_set_performance (
+ /* notify cpufreq */
+ cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+
+- if (value != perf->states[state].status) {
++ if (value != (u16) perf->states[state].status) {
+ unsigned int tmp = cpufreq_freqs.new;
+ cpufreq_freqs.new = cpufreq_freqs.old;
+ cpufreq_freqs.old = tmp;
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/cpufreq/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/Kconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -88,6 +88,16 @@ config X86_POWERNOW_K7
+
+ If in doubt, say N.
+
++config X86_POWERNOW_K8
++ tristate "AMD Opteron/Athlon64 PowerNow!"
++ depends on CPU_FREQ_TABLE
++ help
++ This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
++
++ For details, take a look at linux/Documentation/cpu-freq.
++
++ If in doubt, say N.
++
+ config X86_GX_SUSPMOD
+ tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
+ depends on CPU_FREQ
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/cpufreq/longhaul.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/longhaul.c 2003-10-05 00:33:23.000000000 -0700
+@@ -70,21 +70,6 @@ static unsigned int calc_speed (int mult
+ }
+
+
+-static unsigned int longhaul_get_cpu_fsb (void)
+-{
+- unsigned long lo, hi;
+- unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
+- unsigned int invalue=0;
+-
+- if (fsb == 0) {
+- rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
+- invalue = (lo & (1<<18|1<<19)) >>18;
+- fsb = eblcr_fsb_table[invalue];
+- }
+- return fsb;
+-}
+-
+-
+ static int longhaul_get_cpu_mult (void)
+ {
+ unsigned long invalue=0,lo, hi;
+@@ -168,7 +153,7 @@ static void longhaul_setstate (unsigned
+ break;
+
+ /*
+- * Longhaul v3. (Ezra-T [C5M], Nehemiag [C5N])
++ * Longhaul v3. (Ezra-T [C5M], Nehemiah [C5N])
+ * This can also do voltage scaling, but see above.
+ * Ezra-T was alleged to do FSB scaling too, but it never worked in practice.
+ */
+@@ -193,6 +178,39 @@ static void longhaul_setstate (unsigned
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
++/*
++ * Centaur decided to make life a little more tricky.
++ * Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
++ * Samuel2 and above have to try and guess what the FSB is.
++ * We do this by assuming we booted at maximum multiplier, and interpolate
++ * between that value multiplied by possible FSBs and cpu_mhz which
++ * was calculated at boot time. Really ugly, but no other way to do this.
++ */
++static int _guess (int guess, int maxmult)
++{
++ int target;
++
++ target = ((maxmult/10)*guess);
++ if (maxmult%10 != 0)
++ target += (guess/2);
++ target &= ~0xf;
++ return target;
++}
++
++static int guess_fsb(int maxmult)
++{
++ int speed = (cpu_khz/1000) & ~0xf;
++ int i;
++ int speeds[3] = { 66, 100, 133 };
++
++ for (i=0; i<3; i++) {
++ if (_guess(speeds[i],maxmult) == speed)
++ return speeds[i];
++ }
++ return 0;
++}
++
++
+
+ static int __init longhaul_get_ranges (void)
+ {
+@@ -203,8 +221,8 @@ static int __init longhaul_get_ranges (v
+ -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
+ unsigned int j, k = 0;
+ union msr_longhaul longhaul;
+-
+- fsb = longhaul_get_cpu_fsb();
++ unsigned long lo, hi;
++ unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
+
+ switch (longhaul_version) {
+ case 1:
+@@ -212,6 +230,9 @@ static int __init longhaul_get_ranges (v
+ Assume min=3.0x & max = whatever we booted at. */
+ minmult = 30;
+ maxmult = longhaul_get_cpu_mult();
++ rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
++ invalue = (lo & (1<<18|1<<19)) >>18;
++ fsb = eblcr_fsb_table[invalue];
+ break;
+
+ case 2 ... 3:
+@@ -222,14 +243,13 @@ static int __init longhaul_get_ranges (v
+ invalue += 16;
+ maxmult=multipliers[invalue];
+
+-#if 0
+ invalue = longhaul.bits.MinMHzBR;
+- if (longhaul.bits.MinMHzBR4);
+- invalue += 16;
+- minmult = multipliers[invalue];
+-#else
+- minmult = 30; /* as per spec */
+-#endif
++ if (longhaul.bits.MinMHzBR4 == 1)
++ minmult = 30;
++ else
++ minmult = multipliers[invalue];
++
++ fsb = guess_fsb(maxmult);
+ break;
+ }
+
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/cpufreq/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -1,5 +1,6 @@
+ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
+ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
++obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
+ obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
+ obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o
+ obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2003-10-05 00:33:23.000000000 -0700
+@@ -0,0 +1,1020 @@
++/*
++ * (c) 2003 Advanced Micro Devices, Inc.
++ * Your use of this code is subject to the terms and conditions of the
++ * GNU general public license version 2. See "../../../COPYING" or
++ * http://www.gnu.org/licenses/gpl.html
++ *
++ * Support : paul.devriendt@amd.com
++ *
++ * Based on the powernow-k7.c module written by Dave Jones.
++ * (C) 2003 Dave Jones <davej@codemonkey.ork.uk> on behalf of SuSE Labs
++ * Licensed under the terms of the GNU GPL License version 2.
++ * Based upon datasheets & sample CPUs kindly provided by AMD.
++ *
++ * Processor information obtained from Chapter 9 (Power and Thermal Management)
++ * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
++ * Opteron Processors", revision 3.03, available for download from www.amd.com
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++
++#include <asm/msr.h>
++#include <asm/io.h>
++#include <asm/delay.h>
++
++#define PFX "powernow-k8: "
++#define BFX PFX "BIOS error: "
++#define VERSION "version 1.00.08 - September 26, 2003"
++#include "powernow-k8.h"
++
++#ifdef CONFIG_PREEMPT
++#warning this driver has not been tested on a preempt system
++#endif
++
++static u32 vstable; /* voltage stabalization time, from PSB, units 20 us */
++static u32 plllock; /* pll lock time, from PSB, units 1 us */
++static u32 numps; /* number of p-states, from PSB */
++static u32 rvo; /* ramp voltage offset, from PSB */
++static u32 irt; /* isochronous relief time, from PSB */
++static u32 vidmvs; /* usable value calculated from mvs, from PSB */
++struct pst_s *ppst; /* array of p states, valid for this part */
++static u32 currvid; /* keep track of the current fid / vid */
++static u32 currfid;
++
++/*
++The PSB table supplied by BIOS allows for the definition of the number of
++p-states that can be used when running on a/c, and the number of p-states
++that can be used when running on battery. This allows laptop manufacturers
++to force the system to save power when running from battery. The relationship
++is :
++ 1 <= number_of_battery_p_states <= maximum_number_of_p_states
++
++This driver does NOT have the support in it to detect transitions from
++a/c power to battery power, and thus trigger the transition to a lower
++p-state if required. This is because I need ACPI and the 2.6 kernel to do
++this, and this is a 2.4 kernel driver. Check back for a new improved driver
++for the 2.6 kernel soon.
++
++This code therefore assumes it is on battery at all times, and thus
++restricts performance to number_of_battery_p_states. For desktops,
++ number_of_battery_p_states == maximum_number_of_pstates,
++so this is not actually a restriction.
++*/
++
++static u32 batps; /* limit on the number of p states when on battery */
++ /* - set by BIOS in the PSB/PST */
++
++static struct cpufreq_driver cpufreq_amd64_driver = {
++ .verify = drv_verify,
++ .target = drv_target,
++ .init = drv_cpu_init,
++ .name = "cpufreq-amd64",
++ .owner = THIS_MODULE,
++};
++
++#define SEARCH_UP 1
++#define SEARCH_DOWN 0
++
++/* Return a frequency in MHz, given an input fid */
++u32
++find_freq_from_fid(u32 fid)
++{
++ return 800 + (fid * 100);
++}
++
++/* Return a fid matching an input frequency in MHz */
++u32
++find_fid_from_freq(u32 freq)
++{
++ return (freq - 800) / 100;
++}
++
++/* Return the vco fid for an input fid */
++static u32
++convert_fid_to_vco_fid(u32 fid)
++{
++ if (fid < HI_FID_TABLE_BOTTOM) {
++ return 8 + (2 * fid);
++ } else {
++ return fid;
++ }
++}
++
++/* Sort the fid/vid frequency table into ascending order by fid. The spec */
++/* implies that it will be sorted by BIOS, but, it only implies it, and I */
++/* prefer not to trust when I can check. */
++/* Yes, it is a simple bubble sort, but the PST is really small, so the */
++/* choice of algorithm is pretty irrelevant. */
++static inline void
++sort_pst(struct pst_s *ppst, u32 numpstates)
++{
++ u32 i;
++ u8 tempfid;
++ u8 tempvid;
++ int swaps = 1;
++
++ while (swaps) {
++ swaps = 0;
++ for (i = 0; i < (numpstates - 1); i++) {
++ if (ppst[i].fid > ppst[i + 1].fid) {
++ swaps = 1;
++ tempfid = ppst[i].fid;
++ tempvid = ppst[i].vid;
++ ppst[i].fid = ppst[i + 1].fid;
++ ppst[i].vid = ppst[i + 1].vid;
++ ppst[i + 1].fid = tempfid;
++ ppst[i + 1].vid = tempvid;
++ }
++ }
++ }
++
++ return;
++}
++
++/* Return 1 if the pending bit is set. Unless we are actually just told the */
++/* processor to transition a state, seeing this bit set is really bad news. */
++static inline int
++pending_bit_stuck(void)
++{
++ u32 lo;
++ u32 hi;
++
++ rdmsr(MSR_FIDVID_STATUS, lo, hi);
++ return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
++}
++
++/* Update the global current fid / vid values from the status msr. Returns 1 */
++/* on error. */
++static int
++query_current_values_with_pending_wait(void)
++{
++ u32 lo;
++ u32 hi;
++ u32 i = 0;
++
++ lo = MSR_S_LO_CHANGE_PENDING;
++ while (lo & MSR_S_LO_CHANGE_PENDING) {
++ if (i++ > 0x1000000) {
++ printk(KERN_ERR PFX "detected change pending stuck\n");
++ return 1;
++ }
++ rdmsr(MSR_FIDVID_STATUS, lo, hi);
++ }
++
++ currvid = hi & MSR_S_HI_CURRENT_VID;
++ currfid = lo & MSR_S_LO_CURRENT_FID;
++
++ return 0;
++}
++
++/* the isochronous relief time */
++static inline void
++count_off_irt(void)
++{
++ udelay((1 << irt) * 10);
++ return;
++}
++
++/* the voltage stabalization time */
++static inline void
++count_off_vst(void)
++{
++ udelay(vstable * VST_UNITS_20US);
++ return;
++}
++
++/* write the new fid value along with the other control fields to the msr */
++static int
++write_new_fid(u32 fid)
++{
++ u32 lo;
++ u32 savevid = currvid;
++
++ if ((fid & INVALID_FID_MASK) || (currvid & INVALID_VID_MASK)) {
++ printk(KERN_ERR PFX "internal error - overflow on fid write\n");
++ return 1;
++ }
++
++ lo = fid | (currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
++
++ dprintk(KERN_DEBUG PFX "writing fid %x, lo %x, hi %x\n",
++ fid, lo, plllock * PLL_LOCK_CONVERSION);
++
++ wrmsr(MSR_FIDVID_CTL, lo, plllock * PLL_LOCK_CONVERSION);
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ count_off_irt();
++
++ if (savevid != currvid) {
++ printk(KERN_ERR PFX
++ "vid changed on fid transition, save %x, currvid %x\n",
++ savevid, currvid);
++ return 1;
++ }
++
++ if (fid != currfid) {
++ printk(KERN_ERR PFX
++ "fid transition failed, fid %x, currfid %x\n",
++ fid, currfid);
++ return 1;
++ }
++
++ return 0;
++}
++
++/* Write a new vid to the hardware */
++static int
++write_new_vid(u32 vid)
++{
++ u32 lo;
++ u32 savefid = currfid;
++
++ if ((currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) {
++ printk(KERN_ERR PFX "internal error - overflow on vid write\n");
++ return 1;
++ }
++
++ lo = currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
++
++ dprintk(KERN_DEBUG PFX "writing vid %x, lo %x, hi %x\n",
++ vid, lo, STOP_GRANT_5NS);
++
++ wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
++
++ if (query_current_values_with_pending_wait()) {
++ return 1;
++ }
++
++ if (savefid != currfid) {
++ printk(KERN_ERR PFX
++ "fid changed on vid transition, save %x currfid %x\n",
++ savefid, currfid);
++ return 1;
++ }
++
++ if (vid != currvid) {
++ printk(KERN_ERR PFX
++ "vid transition failed, vid %x, currvid %x\n",
++ vid, currvid);
++ return 1;
++ }
++
++ return 0;
++}
++
++/* Reduce the vid by the max of step or reqvid. */
++/* Decreasing vid codes represent increasing voltages : */
++/* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. */
++static int
++decrease_vid_code_by_step(u32 reqvid, u32 step)
++{
++ if ((currvid - reqvid) > step)
++ reqvid = currvid - step;
++
++ if (write_new_vid(reqvid))
++ return 1;
++
++ count_off_vst();
++
++ return 0;
++}
++
++/* Change the fid and vid, by the 3 phases. */
++static inline int
++transition_fid_vid(u32 reqfid, u32 reqvid)
++{
++ if (core_voltage_pre_transition(reqvid))
++ return 1;
++
++ if (core_frequency_transition(reqfid))
++ return 1;
++
++ if (core_voltage_post_transition(reqvid))
++ return 1;
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ if ((reqfid != currfid) || (reqvid != currvid)) {
++ printk(KERN_ERR PFX "failed: req 0x%x 0x%x, curr 0x%x 0x%x\n",
++ reqfid, reqvid, currfid, currvid);
++ return 1;
++ }
++
++ dprintk(KERN_INFO PFX
++ "transitioned: new fid 0x%x, vid 0x%x\n", currfid, currvid);
++
++ return 0;
++}
++
++/* Phase 1 - core voltage transition ... setup appropriate voltage for the */
++/* fid transition. */
++static inline int
++core_voltage_pre_transition(u32 reqvid)
++{
++ u32 rvosteps = rvo;
++ u32 savefid = currfid;
++
++ dprintk(KERN_DEBUG PFX
++ "ph1: start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo %x\n",
++ currfid, currvid, reqvid, rvo);
++
++ while (currvid > reqvid) {
++ dprintk(KERN_DEBUG PFX "ph1: curr 0x%x, requesting vid 0x%x\n",
++ currvid, reqvid);
++ if (decrease_vid_code_by_step(reqvid, vidmvs))
++ return 1;
++ }
++
++ while (rvosteps > 0) {
++ if (currvid == 0) {
++ rvosteps = 0;
++ } else {
++ dprintk(KERN_DEBUG PFX
++ "ph1: changing vid for rvo, requesting 0x%x\n",
++ currvid - 1);
++ if (decrease_vid_code_by_step(currvid - 1, 1))
++ return 1;
++ rvosteps--;
++ }
++ }
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ if (savefid != currfid) {
++ printk(KERN_ERR PFX "ph1 err, currfid changed 0x%x\n", currfid);
++ return 1;
++ }
++
++ dprintk(KERN_DEBUG PFX "ph1 complete, currfid 0x%x, currvid 0x%x\n",
++ currfid, currvid);
++
++ return 0;
++}
++
++/* Phase 2 - core frequency transition */
++static inline int
++core_frequency_transition(u32 reqfid)
++{
++ u32 vcoreqfid;
++ u32 vcocurrfid;
++ u32 vcofiddiff;
++ u32 savevid = currvid;
++
++ if ((reqfid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
++ printk(KERN_ERR PFX "ph2 illegal lo-lo transition 0x%x 0x%x\n",
++ reqfid, currfid);
++ return 1;
++ }
++
++ if (currfid == reqfid) {
++ printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", currfid);
++ return 0;
++ }
++
++ dprintk(KERN_DEBUG PFX
++ "ph2 starting, currfid 0x%x, currvid 0x%x, reqfid 0x%x\n",
++ currfid, currvid, reqfid);
++
++ vcoreqfid = convert_fid_to_vco_fid(reqfid);
++ vcocurrfid = convert_fid_to_vco_fid(currfid);
++ vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
++ : vcoreqfid - vcocurrfid;
++
++ while (vcofiddiff > 2) {
++ if (reqfid > currfid) {
++ if (currfid > LO_FID_TABLE_TOP) {
++ if (write_new_fid(currfid + 2)) {
++ return 1;
++ }
++ } else {
++ if (write_new_fid
++ (2 + convert_fid_to_vco_fid(currfid))) {
++ return 1;
++ }
++ }
++ } else {
++ if (write_new_fid(currfid - 2))
++ return 1;
++ }
++
++ vcocurrfid = convert_fid_to_vco_fid(currfid);
++ vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
++ : vcoreqfid - vcocurrfid;
++ }
++
++ if (write_new_fid(reqfid))
++ return 1;
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ if (currfid != reqfid) {
++ printk(KERN_ERR PFX
++ "ph2 mismatch, failed fid transition, curr %x, req %x\n",
++ currfid, reqfid);
++ return 1;
++ }
++
++ if (savevid != currvid) {
++ printk(KERN_ERR PFX
++ "ph2 vid changed, save %x, curr %x\n", savevid,
++ currvid);
++ return 1;
++ }
++
++ dprintk(KERN_DEBUG PFX "ph2 complete, currfid 0x%x, currvid 0x%x\n",
++ currfid, currvid);
++
++ return 0;
++}
++
++/* Phase 3 - core voltage transition flow ... jump to the final vid. */
++static inline int
++core_voltage_post_transition(u32 reqvid)
++{
++ u32 savefid = currfid;
++ u32 savereqvid = reqvid;
++
++ dprintk(KERN_DEBUG PFX "ph3 starting, currfid 0x%x, currvid 0x%x\n",
++ currfid, currvid);
++
++ if (reqvid != currvid) {
++ if (write_new_vid(reqvid))
++ return 1;
++
++ if (savefid != currfid) {
++ printk(KERN_ERR PFX
++ "ph3: bad fid change, save %x, curr %x\n",
++ savefid, currfid);
++ return 1;
++ }
++
++ if (currvid != reqvid) {
++ printk(KERN_ERR PFX
++ "ph3: failed vid transition\n, req %x, curr %x",
++ reqvid, currvid);
++ return 1;
++ }
++ }
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ if (savereqvid != currvid) {
++ dprintk(KERN_ERR PFX "ph3 failed, currvid 0x%x\n", currvid);
++ return 1;
++ }
++
++ if (savefid != currfid) {
++ dprintk(KERN_ERR PFX "ph3 failed, currfid changed 0x%x\n",
++ currfid);
++ return 1;
++ }
++
++ dprintk(KERN_DEBUG PFX "ph3 complete, currfid 0x%x, currvid 0x%x\n",
++ currfid, currvid);
++
++ return 0;
++}
++
++static inline int
++check_supported_cpu(void)
++{
++ struct cpuinfo_x86 *c = cpu_data;
++ u32 eax, ebx, ecx, edx;
++
++ if (num_online_cpus() != 1) {
++ printk(KERN_INFO PFX "multiprocessor systems not supported\n");
++ return 0;
++ }
++
++ if (c->x86_vendor != X86_VENDOR_AMD) {
++ printk(KERN_INFO PFX "Not an AMD processor\n");
++ return 0;
++ }
++
++ eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
++ if ((eax & CPUID_XFAM_MOD) == ATHLON64_XFAM_MOD) {
++ dprintk(KERN_DEBUG PFX "AMD Althon 64 Processor found\n");
++ if ((eax & CPUID_F1_STEP) < ATHLON64_REV_C0) {
++ printk(KERN_INFO PFX "Revision C0 or better "
++ "AMD Athlon 64 processor required\n");
++ return 0;
++ }
++ } else if ((eax & CPUID_XFAM_MOD) == OPTERON_XFAM_MOD) {
++ dprintk(KERN_DEBUG PFX "AMD Opteron Processor found\n");
++ } else {
++ printk(KERN_INFO PFX
++ "AMD Athlon 64 or AMD Opteron processor required\n");
++ return 0;
++ }
++
++ eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
++ if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
++ printk(KERN_INFO PFX
++ "No frequency change capabilities detected\n");
++ return 0;
++ }
++
++ cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
++ if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
++ printk(KERN_INFO PFX "Power state transitions not supported\n");
++ return 0;
++ }
++
++ printk(KERN_INFO PFX "Found AMD Athlon 64 / Opteron processor "
++ "supporting p-state transitions\n");
++
++ return 1;
++}
++
++/* Find and validate the PSB/PST table in BIOS. */
++static inline int
++find_psb_table(void)
++{
++ struct psb_s *psb;
++ struct pst_s *pst;
++ unsigned i, j;
++ u32 lastfid;
++ u32 mvs;
++ u8 maxvid;
++
++ for (i = 0xc0000; i < 0xffff0; i += 0x10) {
++ /* Scan BIOS looking for the signature. */
++ /* It can not be at ffff0 - it is too big. */
++
++ psb = phys_to_virt(i);
++ if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
++ continue;
++
++ dprintk(KERN_DEBUG PFX "found PSB header at 0x%p\n", psb);
++
++ dprintk(KERN_DEBUG PFX "table vers: 0x%x\n", psb->tableversion);
++ if (psb->tableversion != PSB_VERSION_1_4) {
++ printk(KERN_INFO BFX "PSB table is not v1.4\n");
++ return -ENODEV;
++ }
++
++ dprintk(KERN_DEBUG PFX "flags: 0x%x\n", psb->flags1);
++ if (psb->flags1) {
++ printk(KERN_ERR BFX "unknown flags\n");
++ return -ENODEV;
++ }
++
++ vstable = psb->voltagestabilizationtime;
++ printk(KERN_INFO PFX "voltage stable time: %d (units 20us)\n",
++ vstable);
++
++ dprintk(KERN_DEBUG PFX "flags2: 0x%x\n", psb->flags2);
++ rvo = psb->flags2 & 3;
++ irt = ((psb->flags2) >> 2) & 3;
++ mvs = ((psb->flags2) >> 4) & 3;
++ vidmvs = 1 << mvs;
++ batps = ((psb->flags2) >> 6) & 3;
++ printk(KERN_INFO PFX "p states on battery: %d ", batps);
++ switch (batps) {
++ case 0:
++ printk("- all available\n");
++ break;
++ case 1:
++ printk("- only the minimum\n");
++ break;
++ case 2:
++ printk("- only the 2 lowest\n");
++ break;
++ case 3:
++ printk("- only the 3 lowest\n");
++ break;
++ }
++ printk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo);
++ printk(KERN_INFO PFX "isochronous relief time: %d\n", irt);
++ printk(KERN_INFO PFX "maximum voltage step: %d\n", mvs);
++
++ dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst);
++ if (psb->numpst != 1) {
++ printk(KERN_ERR BFX "numpst must be 1\n");
++ return -ENODEV;
++ }
++
++ dprintk(KERN_DEBUG PFX "cpuid: 0x%x\n", psb->cpuid);
++
++ plllock = psb->plllocktime;
++ printk(KERN_INFO PFX "pll lock time: 0x%x\n", plllock);
++
++ maxvid = psb->maxvid;
++ printk(KERN_INFO PFX "maxfid: 0x%x\n", psb->maxfid);
++ printk(KERN_INFO PFX "maxvid: 0x%x\n", maxvid);
++
++ numps = psb->numpstates;
++ printk(KERN_INFO PFX "numpstates: 0x%x\n", numps);
++ if (numps < 2) {
++ printk(KERN_ERR BFX "no p states to transition\n");
++ return -ENODEV;
++ }
++
++ if (batps == 0) {
++ batps = numps;
++ } else if (batps > numps) {
++ printk(KERN_ERR BFX "batterypstates > numpstates\n");
++ batps = numps;
++ } else {
++ printk(KERN_ERR PFX
++ "Restricting operation to %d p-states\n", batps);
++ printk(KERN_ERR PFX
++ "Check for an updated driver to access all "
++ "%d p-states\n", numps);
++ }
++
++ if ((numps <= 1) || (batps <= 1)) {
++ printk(KERN_ERR PFX "only 1 p-state to transition\n");
++ return -ENODEV;
++ }
++
++ ppst = kmalloc(sizeof (struct pst_s) * numps, GFP_KERNEL);
++ if (!ppst) {
++ printk(KERN_ERR PFX "ppst memory alloc failure\n");
++ return -ENOMEM;
++ }
++
++ pst = (struct pst_s *) (psb + 1);
++ for (j = 0; j < numps; j++) {
++ ppst[j].fid = pst[j].fid;
++ ppst[j].vid = pst[j].vid;
++ printk(KERN_INFO PFX
++ " %d : fid 0x%x, vid 0x%x\n", j,
++ ppst[j].fid, ppst[j].vid);
++ }
++ sort_pst(ppst, numps);
++
++ lastfid = ppst[0].fid;
++ if (lastfid > LO_FID_TABLE_TOP)
++ printk(KERN_INFO BFX "first fid not in lo freq tbl\n");
++
++ if ((lastfid > MAX_FID) || (lastfid & 1) || (ppst[0].vid > LEAST_VID)) {
++ printk(KERN_ERR BFX "first fid/vid bad (0x%x - 0x%x)\n",
++ lastfid, ppst[0].vid);
++ kfree(ppst);
++ return -ENODEV;
++ }
++
++ for (j = 1; j < numps; j++) {
++ if ((lastfid >= ppst[j].fid)
++ || (ppst[j].fid & 1)
++ || (ppst[j].fid < HI_FID_TABLE_BOTTOM)
++ || (ppst[j].fid > MAX_FID)
++ || (ppst[j].vid > LEAST_VID)) {
++ printk(KERN_ERR BFX
++ "invalid fid/vid in pst(%x %x)\n",
++ ppst[j].fid, ppst[j].vid);
++ kfree(ppst);
++ return -ENODEV;
++ }
++ lastfid = ppst[j].fid;
++ }
++
++ for (j = 0; j < numps; j++) {
++ if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */
++ printk(KERN_ERR BFX
++ "0 vid exceeded with pstate %d\n", j);
++ return -ENODEV;
++ }
++ if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */
++ printk(KERN_ERR BFX
++ "maxvid exceeded with pstate %d\n", j);
++ return -ENODEV;
++ }
++ }
++
++ if (query_current_values_with_pending_wait()) {
++ kfree(ppst);
++ return -EIO;
++ }
++
++ printk(KERN_INFO PFX "currfid 0x%x, currvid 0x%x\n",
++ currfid, currvid);
++
++ for (j = 0; j < numps; j++)
++ if ((ppst[j].fid==currfid) && (ppst[j].vid==currvid))
++ return (0);
++
++ printk(KERN_ERR BFX "currfid/vid do not match PST, ignoring\n");
++ return 0;
++ }
++
++ printk(KERN_ERR BFX "no PSB\n");
++ return -ENODEV;
++}
++
++/* Converts a frequency (that might not necessarily be a multiple of 200) */
++/* to a fid. */
++u32
++find_closest_fid(u32 freq, int searchup)
++{
++ if (searchup == SEARCH_UP)
++ freq += MIN_FREQ_RESOLUTION - 1;
++
++ freq = (freq / MIN_FREQ_RESOLUTION) * MIN_FREQ_RESOLUTION;
++
++ if (freq < MIN_FREQ)
++ freq = MIN_FREQ;
++ else if (freq > MAX_FREQ)
++ freq = MAX_FREQ;
++
++ return find_fid_from_freq(freq);
++}
++
++static int
++find_match(u32 * ptargfreq, u32 * pmin, u32 * pmax, int searchup, u32 * pfid,
++ u32 * pvid)
++{
++ u32 availpstates = batps;
++ u32 targfid = find_closest_fid(*ptargfreq, searchup);
++ u32 minfid = find_closest_fid(*pmin, SEARCH_DOWN);
++ u32 maxfid = find_closest_fid(*pmax, SEARCH_UP);
++ u32 minidx = 0;
++ u32 maxidx = availpstates - 1;
++ u32 targidx = 0xffffffff;
++ int i;
++
++ dprintk(KERN_DEBUG PFX "find match: freq %d MHz, min %d, max %d\n",
++ *ptargfreq, *pmin, *pmax);
++
++ /* Restrict values to the frequency choices in the PST */
++ if (minfid < ppst[0].fid)
++ minfid = ppst[0].fid;
++ if (maxfid > ppst[maxidx].fid)
++ maxfid = ppst[maxidx].fid;
++
++ /* Find appropriate PST index for the minimim fid */
++ for (i = 0; i < (int) availpstates; i++) {
++ if (minfid >= ppst[i].fid)
++ minidx = i;
++ }
++
++ /* Find appropriate PST index for the maximum fid */
++ for (i = availpstates - 1; i >= 0; i--) {
++ if (maxfid <= ppst[i].fid)
++ maxidx = i;
++ }
++
++ if (minidx > maxidx)
++ maxidx = minidx;
++
++ /* Frequency ids are now constrained by limits matching PST entries */
++ minfid = ppst[minidx].fid;
++ maxfid = ppst[maxidx].fid;
++
++ /* Limit the target frequency to these limits */
++ if (targfid < minfid)
++ targfid = minfid;
++ else if (targfid > maxfid)
++ targfid = maxfid;
++
++ /* Find the best target index into the PST, contrained by the range */
++ if (searchup == SEARCH_UP) {
++ for (i = maxidx; i >= (int) minidx; i--) {
++ if (targfid <= ppst[i].fid)
++ targidx = i;
++ }
++ } else {
++ for (i = minidx; i <= (int) maxidx; i++) {
++ if (targfid >= ppst[i].fid)
++ targidx = i;
++ }
++ }
++
++ if (targidx == 0xffffffff) {
++ printk(KERN_ERR PFX "could not find target\n");
++ return 1;
++ }
++
++ *pmin = find_freq_from_fid(minfid);
++ *pmax = find_freq_from_fid(maxfid);
++ *ptargfreq = find_freq_from_fid(ppst[targidx].fid);
++
++ if (pfid)
++ *pfid = ppst[targidx].fid;
++ if (pvid)
++ *pvid = ppst[targidx].vid;
++
++ return 0;
++}
++
++/* Take a frequency, and issue the fid/vid transition command */
++static inline int
++transition_frequency(u32 * preq, u32 * pmin, u32 * pmax, u32 searchup)
++{
++ u32 fid;
++ u32 vid;
++ int res;
++ struct cpufreq_freqs freqs;
++
++ if (find_match(preq, pmin, pmax, searchup, &fid, &vid))
++ return 1;
++
++ dprintk(KERN_DEBUG PFX "table matched fid 0x%x, giving vid 0x%x\n",
++ fid, vid);
++
++ if (query_current_values_with_pending_wait())
++ return 1;
++
++ if ((currvid == vid) && (currfid == fid)) {
++ dprintk(KERN_DEBUG PFX
++ "target matches current values (fid 0x%x, vid 0x%x)\n",
++ fid, vid);
++ return 0;
++ }
++
++ if ((fid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
++ printk(KERN_ERR PFX
++ "ignoring illegal change in lo freq table-%x to %x\n",
++ currfid, fid);
++ return 1;
++ }
++
++ dprintk(KERN_DEBUG PFX "changing to fid 0x%x, vid 0x%x\n", fid, vid);
++
++ freqs.cpu = 0; /* only true because SMP not supported */
++
++ freqs.old = find_freq_from_fid(currfid);
++ freqs.new = find_freq_from_fid(fid);
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++
++ res = transition_fid_vid(fid, vid);
++
++ freqs.new = find_freq_from_fid(currfid);
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++ return res;
++}
++
++/* Driver entry point to switch to the target frequency */
++static int
++drv_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
++{
++ u32 checkfid = currfid;
++ u32 checkvid = currvid;
++ u32 reqfreq = targfreq / 1000;
++ u32 minfreq = pol->min / 1000;
++ u32 maxfreq = pol->max / 1000;
++
++ if (ppst == 0) {
++ printk(KERN_ERR PFX "targ: ppst 0\n");
++ return -ENODEV;
++ }
++
++ if (pending_bit_stuck()) {
++ printk(KERN_ERR PFX "drv targ fail: change pending bit set\n");
++ return -EIO;
++ }
++
++ dprintk(KERN_DEBUG PFX "targ: %d kHz, min %d, max %d, relation %d\n",
++ targfreq, pol->min, pol->max, relation);
++
++ if (query_current_values_with_pending_wait())
++ return -EIO;
++
++ dprintk(KERN_DEBUG PFX "targ: curr fid 0x%x, vid 0x%x\n",
++ currfid, currvid);
++
++ if ((checkvid != currvid) || (checkfid != currfid)) {
++ printk(KERN_ERR PFX
++ "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
++ checkfid, currfid, checkvid, currvid);
++ }
++
++ if (transition_frequency(&reqfreq, &minfreq, &maxfreq,
++ relation ==
++ CPUFREQ_RELATION_H ? SEARCH_UP : SEARCH_DOWN))
++ {
++ printk(KERN_ERR PFX "transition frequency failed\n");
++ return 1;
++ }
++
++ pol->cur = 1000 * find_freq_from_fid(currfid);
++
++ return 0;
++}
++
++/* Driver entry point to verify the policy and range of frequencies */
++static int
++drv_verify(struct cpufreq_policy *pol)
++{
++ u32 min = pol->min / 1000;
++ u32 max = pol->max / 1000;
++ u32 targ = min;
++ int res;
++
++ if (ppst == 0) {
++ printk(KERN_ERR PFX "verify - ppst 0\n");
++ return -ENODEV;
++ }
++
++ if (pending_bit_stuck()) {
++ printk(KERN_ERR PFX "failing verify, change pending bit set\n");
++ return -EIO;
++ }
++
++ dprintk(KERN_DEBUG PFX
++ "ver: cpu%d, min %d, max %d, cur %d, pol %d\n", pol->cpu,
++ pol->min, pol->max, pol->cur, pol->policy);
++
++ if (pol->cpu != 0) {
++ printk(KERN_ERR PFX "verify - cpu not 0\n");
++ return -ENODEV;
++ }
++
++ res = find_match(&targ, &min, &max,
++ pol->policy == CPUFREQ_POLICY_POWERSAVE ?
++ SEARCH_DOWN : SEARCH_UP, 0, 0);
++ if (!res) {
++ pol->min = min * 1000;
++ pol->max = max * 1000;
++ }
++ return res;
++}
++
++/* per CPU init entry point to the driver */
++static int __init
++drv_cpu_init(struct cpufreq_policy *pol)
++{
++ if (pol->cpu != 0) {
++ printk(KERN_ERR PFX "init not cpu 0\n");
++ return -ENODEV;
++ }
++
++ pol->policy = CPUFREQ_POLICY_PERFORMANCE; /* boot as fast as we can */
++
++ /* Take a crude guess here. */
++ pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US)
++ + (3 * (1 << irt) * 10);
++
++ if (query_current_values_with_pending_wait())
++ return -EIO;
++
++ pol->cur = 1000 * find_freq_from_fid(currfid);
++ dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur);
++
++ /* min/max the cpu is capable of */
++ pol->cpuinfo.min_freq = 1000 * find_freq_from_fid(ppst[0].fid);
++ pol->cpuinfo.max_freq = 1000 * find_freq_from_fid(ppst[numps-1].fid);
++ pol->min = 1000 * find_freq_from_fid(ppst[0].fid);
++ pol->max = 1000 * find_freq_from_fid(ppst[batps - 1].fid);
++
++ printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n",
++ currfid, currvid);
++
++ return 0;
++}
++
++/* driver entry point for init */
++static int __init
++drv_init(void)
++{
++ int rc;
++
++ printk(KERN_INFO PFX VERSION "\n");
++
++ if (check_supported_cpu() == 0)
++ return -ENODEV;
++
++ rc = find_psb_table();
++ if (rc)
++ return rc;
++
++ if (pending_bit_stuck()) {
++ printk(KERN_ERR PFX "drv_init fail, change pending bit set\n");
++ kfree(ppst);
++ return -EIO;
++ }
++
++ return cpufreq_register_driver(&cpufreq_amd64_driver);
++}
++
++/* driver entry point for term */
++static void __exit
++drv_exit(void)
++{
++ dprintk(KERN_INFO PFX "drv_exit\n");
++
++ cpufreq_unregister_driver(&cpufreq_amd64_driver);
++ kfree(ppst);
++}
++
++MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
++MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
++MODULE_LICENSE("GPL");
++
++module_init(drv_init);
++module_exit(drv_exit);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2003-10-05 00:33:23.000000000 -0700
+@@ -0,0 +1,126 @@
++/*
++ * (c) 2003 Advanced Micro Devices, Inc.
++ * Your use of this code is subject to the terms and conditions of the
++ * GNU general public license version 2. See "../../../COPYING" or
++ * http://www.gnu.org/licenses/gpl.html
++ */
++
++/* processor's cpuid instruction support */
++#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
++#define CPUID_F1_FAM 0x00000f00 /* family mask */
++#define CPUID_F1_XFAM 0x0ff00000 /* extended family mask */
++#define CPUID_F1_MOD 0x000000f0 /* model mask */
++#define CPUID_F1_STEP 0x0000000f /* stepping level mask */
++#define CPUID_XFAM_MOD 0x0ff00ff0 /* xtended fam, fam + model */
++#define ATHLON64_XFAM_MOD 0x00000f40 /* xtended fam, fam + model */
++#define OPTERON_XFAM_MOD 0x00000f50 /* xtended fam, fam + model */
++#define ATHLON64_REV_C0 8
++#define CPUID_GET_MAX_CAPABILITIES 0x80000000
++#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
++#define P_STATE_TRANSITION_CAPABLE 6
++
++/* Model Specific Registers for p-state transitions. MSRs are 64-bit. For */
++/* writes (wrmsr - opcode 0f 30), the register number is placed in ecx, and */
++/* the value to write is placed in edx:eax. For reads (rdmsr - opcode 0f 32), */
++/* the register number is placed in ecx, and the data is returned in edx:eax. */
++
++#define MSR_FIDVID_CTL 0xc0010041
++#define MSR_FIDVID_STATUS 0xc0010042
++
++/* Field definitions within the FID VID Low Control MSR : */
++#define MSR_C_LO_INIT_FID_VID 0x00010000
++#define MSR_C_LO_NEW_VID 0x00001f00
++#define MSR_C_LO_NEW_FID 0x0000002f
++#define MSR_C_LO_VID_SHIFT 8
++
++/* Field definitions within the FID VID High Control MSR : */
++#define MSR_C_HI_STP_GNT_TO 0x000fffff
++
++/* Field definitions within the FID VID Low Status MSR : */
++#define MSR_S_LO_CHANGE_PENDING 0x80000000 /* cleared when completed */
++#define MSR_S_LO_MAX_RAMP_VID 0x1f000000
++#define MSR_S_LO_MAX_FID 0x003f0000
++#define MSR_S_LO_START_FID 0x00003f00
++#define MSR_S_LO_CURRENT_FID 0x0000003f
++
++/* Field definitions within the FID VID High Status MSR : */
++#define MSR_S_HI_MAX_WORKING_VID 0x001f0000
++#define MSR_S_HI_START_VID 0x00001f00
++#define MSR_S_HI_CURRENT_VID 0x0000001f
++
++/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
++#define LO_FID_TABLE_TOP 6
++#define HI_FID_TABLE_BOTTOM 8
++
++#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */
++#define HI_VCOFREQ_TABLE_BOTTOM 1600
++
++#define MIN_FREQ_RESOLUTION 200 /* fids jump by 2 matching freq jumps by 200 */
++
++#define MAX_FID 0x2a /* Spec only gives FID values as far as 5 GHz */
++
++#define LEAST_VID 0x1e /* Lowest (numerically highest) useful vid value */
++
++#define MIN_FREQ 800 /* Min and max freqs, per spec */
++#define MAX_FREQ 5000
++
++#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */
++
++#define INVALID_VID_MASK 0xffffffe0 /* not a valid vid if these bits are set */
++
++#define STOP_GRANT_5NS 1 /* min poss memory access latency for voltage change */
++
++#define PLL_LOCK_CONVERSION (1000/5) /* ms to ns, then divide by clock period */
++
++#define MAXIMUM_VID_STEPS 1 /* Current cpus only allow a single step of 25mV */
++
++#define VST_UNITS_20US 20 /* Voltage Stabalization Time is in units of 20us */
++
++/*
++Version 1.4 of the PSB table. This table is constructed by BIOS and is
++to tell the OS's power management driver which VIDs and FIDs are
++supported by this particular processor. This information is obtained from
++the data sheets for each processor model by the system vendor and
++incorporated into the BIOS.
++If the data in the PSB / PST is wrong, then this driver will program the
++wrong values into hardware, which is very likely to lead to a crash.
++*/
++
++#define PSB_ID_STRING "AMDK7PNOW!"
++#define PSB_ID_STRING_LEN 10
++
++#define PSB_VERSION_1_4 0x14
++
++struct psb_s {
++ u8 signature[10];
++ u8 tableversion;
++ u8 flags1;
++ u16 voltagestabilizationtime;
++ u8 flags2;
++ u8 numpst;
++ u32 cpuid;
++ u8 plllocktime;
++ u8 maxfid;
++ u8 maxvid;
++ u8 numpstates;
++};
++
++/* Pairs of fid/vid values are appended to the version 1.4 PSB table. */
++struct pst_s {
++ u8 fid;
++ u8 vid;
++};
++
++#ifdef DEBUG
++#define dprintk(msg...) printk(msg)
++#else
++#define dprintk(msg...) do { } while(0)
++#endif
++
++static inline int core_voltage_pre_transition(u32 reqvid);
++static inline int core_voltage_post_transition(u32 reqvid);
++static inline int core_frequency_transition(u32 reqfid);
++static int drv_verify(struct cpufreq_policy *pol);
++static int drv_target(struct cpufreq_policy *pol, unsigned targfreq,
++ unsigned relation);
++static int __init drv_cpu_init(struct cpufreq_policy *pol);
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/intel.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/cpu/intel.c 2003-10-05 00:36:48.000000000 -0700
+@@ -8,11 +8,10 @@
+ #include <asm/processor.h>
+ #include <asm/msr.h>
+ #include <asm/uaccess.h>
++#include <asm/desc.h>
+
+ #include "cpu.h"
+
+-extern int trap_init_f00f_bug(void);
+-
+ #ifdef CONFIG_X86_INTEL_USERCOPY
+ /*
+ * Alignment at which movsl is preferred for bulk memory copies.
+@@ -157,7 +156,7 @@ static void __init init_intel(struct cpu
+
+ c->f00f_bug = 1;
+ if ( !f00f_workaround_enabled ) {
+- trap_init_f00f_bug();
++ trap_init_virtual_IDT();
+ printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
+ f00f_workaround_enabled = 1;
+ }
+@@ -238,12 +237,9 @@ static void __init init_intel(struct cpu
+ }
+
+ /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
+- if ( c->x86 == 6) {
+- unsigned model_mask = (c->x86_model << 8) + c->x86_mask;
+- if (model_mask < 0x0303)
+- clear_bit(X86_FEATURE_SEP, c->x86_capability);
+- }
+-
++ if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
++ clear_bit(X86_FEATURE_SEP, c->x86_capability);
++
+ /* Names for the Pentium II/Celeron processors
+ detectable only by also checking the cache size.
+ Dixon is NOT a Celeron. */
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/k7.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/k7.c 2003-10-05 00:33:23.000000000 -0700
+@@ -17,7 +17,7 @@
+ #include "mce.h"
+
+ /* Machine Check Handler For AMD Athlon/Duron */
+-static void k7_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void k7_machine_check(struct pt_regs * regs, long error_code)
+ {
+ int recover=1;
+ u32 alow, ahigh, high, low;
+@@ -31,7 +31,7 @@ static void k7_machine_check(struct pt_r
+ printk (KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n",
+ smp_processor_id(), mcgsth, mcgstl);
+
+- for (i=0; i<nr_mce_banks; i++) {
++ for (i=1; i<nr_mce_banks; i++) {
+ rdmsr (MSR_IA32_MC0_STATUS+i*4,low, high);
+ if (high&(1<<31)) {
+ if (high & (1<<29))
+@@ -81,6 +81,9 @@ void __init amd_mcheck_init(struct cpuin
+ wrmsr (MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+ nr_mce_banks = l & 0xff;
+
++ /* Clear status for MC index 0 separately, we don't touch CTL,
++ * as some Athlons cause spurious MCEs when its enabled. */
++ wrmsr (MSR_IA32_MC0_STATUS, 0x0, 0x0);
+ for (i=1; i<nr_mce_banks; i++) {
+ wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+ wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/mce.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/mce.c 2003-10-05 00:33:23.000000000 -0700
+@@ -18,18 +18,13 @@ int mce_disabled __initdata = 0;
+ int nr_mce_banks;
+
+ /* Handle unconfigured int18 (should never happen) */
+-static void unexpected_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void unexpected_machine_check(struct pt_regs * regs, long error_code)
+ {
+ printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
+ }
+
+ /* Call the installed machine check handler for this CPU setup. */
+-void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+-
+-asmlinkage void do_machine_check(struct pt_regs * regs, long error_code)
+-{
+- machine_check_vector(regs, error_code);
+-}
++void asmlinkage (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+
+ /* This has to be run for each processor */
+ void __init mcheck_init(struct cpuinfo_x86 *c)
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/mce.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/mce.h 2003-10-05 00:33:23.000000000 -0700
+@@ -7,7 +7,7 @@ void intel_p6_mcheck_init(struct cpuinfo
+ void winchip_mcheck_init(struct cpuinfo_x86 *c);
+
+ /* Call the installed machine check handler for this CPU setup. */
+-extern void (*machine_check_vector)(struct pt_regs *, long error_code);
++extern asmlinkage void (*machine_check_vector)(struct pt_regs *, long error_code);
+
+ extern int mce_disabled __initdata;
+ extern int nr_mce_banks;
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/p4.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/p4.c 2003-10-05 00:33:23.000000000 -0700
+@@ -148,7 +148,7 @@ done:
+ return mce_num_extended_msrs;
+ }
+
+-static void intel_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_code)
+ {
+ int recover=1;
+ u32 alow, ahigh, high, low;
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/p5.c 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/p5.c 2003-10-05 00:33:23.000000000 -0700
+@@ -16,7 +16,7 @@
+ #include "mce.h"
+
+ /* Machine check handler for Pentium class Intel */
+-static void pentium_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void pentium_machine_check(struct pt_regs * regs, long error_code)
+ {
+ u32 loaddr, hi, lotype;
+ rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/p6.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/p6.c 2003-10-05 00:33:23.000000000 -0700
+@@ -16,7 +16,7 @@
+ #include "mce.h"
+
+ /* Machine Check Handler For PII/PIII */
+-static void intel_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void intel_machine_check(struct pt_regs * regs, long error_code)
+ {
+ int recover=1;
+ u32 alow, ahigh, high, low;
+--- linux-2.6.0-test6/arch/i386/kernel/cpu/mcheck/winchip.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/arch/i386/kernel/cpu/mcheck/winchip.c 2003-10-05 00:33:23.000000000 -0700
+@@ -15,7 +15,7 @@
+ #include "mce.h"
+
+ /* Machine check handler for WinChip C6 */
+-static void winchip_machine_check(struct pt_regs * regs, long error_code)
++static asmlinkage void winchip_machine_check(struct pt_regs * regs, long error_code)
+ {
+ printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
+ }
+--- linux-2.6.0-test6/arch/i386/kernel/dmi_scan.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/dmi_scan.c 2003-10-05 00:33:23.000000000 -0700
+@@ -939,11 +939,6 @@ static __initdata struct dmi_blacklist d
+ MATCH(DMI_BOARD_NAME, "CUR-DLS"),
+ NO_MATCH, NO_MATCH }},
+
+- { force_acpi_ht, "ASUS A7V", {
+- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+- MATCH(DMI_BOARD_NAME, "<A7V>"),
+- MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1011"), NO_MATCH }},
+-
+ { force_acpi_ht, "ABIT i440BX-W83977", {
+ MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
+ MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
+@@ -978,7 +973,10 @@ static __initdata struct dmi_blacklist d
+ { disable_acpi_pci, "ASUS A7V", {
+ MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+ MATCH(DMI_BOARD_NAME, "<A7V>"),
+- MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), NO_MATCH }},
++ /* newer BIOS, Revision 1011, does work */
++ MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
++ NO_MATCH }},
++
+ #endif
+
+ { NULL, }
+--- linux-2.6.0-test6/arch/i386/kernel/doublefault.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/doublefault.c 2003-10-05 00:36:48.000000000 -0700
+@@ -7,12 +7,13 @@
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/desc.h>
++#include <asm/fixmap.h>
+
+ #define DOUBLEFAULT_STACKSIZE (1024)
+ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
+ #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
+
+-#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000)
++#define ptr_ok(x) (((x) > __PAGE_OFFSET && (x) < (__PAGE_OFFSET + 0x01000000)) || ((x) >= FIXADDR_START))
+
+ static void doublefault_fn(void)
+ {
+@@ -38,8 +39,8 @@ static void doublefault_fn(void)
+
+ printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n",
+ t->eax, t->ebx, t->ecx, t->edx);
+- printk("esi = %08lx, edi = %08lx\n",
+- t->esi, t->edi);
++ printk("esi = %08lx, edi = %08lx, ebp = %08lx\n",
++ t->esi, t->edi, t->ebp);
+ }
+ }
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/efi.c 2003-10-05 00:36:25.000000000 -0700
+@@ -0,0 +1,611 @@
++/*
++ * Extensible Firmware Interface
++ *
++ * Based on Extensible Firmware Interface Specification version 1.0
++ *
++ * Copyright (C) 1999 VA Linux Systems
++ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
++ * Copyright (C) 1999-2002 Hewlett-Packard Co.
++ * David Mosberger-Tang <davidm@hpl.hp.com>
++ * Stephane Eranian <eranian@hpl.hp.com>
++ *
++ * All EFI Runtime Services are not implemented yet as EFI only
++ * supports physical mode addressing on SoftSDV. This is to be fixed
++ * in a future version. --drummond 1999-07-20
++ *
++ * Implemented EFI runtime services and virtual mode calls. --davidm
++ *
++ * Goutham Rao: <goutham.rao@intel.com>
++ * Skip non-WB memory and ignore empty memory ranges.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/types.h>
++#include <linux/time.h>
++#include <linux/spinlock.h>
++#include <linux/bootmem.h>
++#include <linux/ioport.h>
++#include <linux/proc_fs.h>
++#include <linux/efi.h>
++
++#include <asm/setup.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/desc.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
++
++#define EFI_DEBUG 0
++#define PFX "EFI: "
++
++extern efi_status_t asmlinkage efi_call_phys(void *, ...);
++
++struct efi efi;
++struct efi efi_phys __initdata;
++struct efi_memory_map memmap __initdata;
++
++/*
++ * We require an early boot_ioremap mapping mechanism initially
++ */
++extern void * boot_ioremap(unsigned long, unsigned long);
++
++/*
++ * efi_dir is allocated here, but the directory isn't created
++ * here, as proc_mkdir() doesn't work this early in the bootup
++ * process. Therefore, each module, like efivars, must test for
++ * if (!efi_dir) efi_dir = proc_mkdir("efi", NULL);
++ * prior to creating their own entries under /proc/efi.
++ */
++#ifdef CONFIG_PROC_FS
++struct proc_dir_entry *efi_dir;
++#endif
++
++
++/*
++ * To make EFI call EFI runtime service in physical addressing mode we need
++ * prelog/epilog before/after the invocation to disable interrupt, to
++ * claim EFI runtime service handler exclusively and to duplicate a memory in
++ * low memory space say 0 - 3G.
++ */
++
++static unsigned long efi_rt_eflags;
++static spinlock_t efi_rt_lock = SPIN_LOCK_UNLOCKED;
++static pgd_t efi_bak_pg_dir_pointer[2];
++
++static void efi_call_phys_prelog(void)
++{
++ unsigned long cr4;
++ unsigned long temp;
++
++ spin_lock(&efi_rt_lock);
++ local_irq_save(efi_rt_eflags);
++
++ /*
++ * If I don't have PSE, I should just duplicate two entries in page
++ * directory. If I have PSE, I just need to duplicate one entry in
++ * page directory.
++ */
++ __asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
++
++ if (cr4 & X86_CR4_PSE) {
++ efi_bak_pg_dir_pointer[0].pgd =
++ swapper_pg_dir[pgd_index(0)].pgd;
++ swapper_pg_dir[0].pgd =
++ swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
++ } else {
++ efi_bak_pg_dir_pointer[0].pgd =
++ swapper_pg_dir[pgd_index(0)].pgd;
++ efi_bak_pg_dir_pointer[1].pgd =
++ swapper_pg_dir[pgd_index(0x400000)].pgd;
++ swapper_pg_dir[pgd_index(0)].pgd =
++ swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
++ temp = PAGE_OFFSET + 0x400000;
++ swapper_pg_dir[pgd_index(0x400000)].pgd =
++ swapper_pg_dir[pgd_index(temp)].pgd;
++ }
++
++ /*
++ * After the lock is released, the original page table is restored.
++ */
++ local_flush_tlb();
++
++ cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
++ __asm__ __volatile__("lgdt %0":"=m"
++ (*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
++}
++
++static void efi_call_phys_epilog(void)
++{
++ unsigned long cr4;
++
++ cpu_gdt_descr[0].address =
++ (unsigned long) __va(cpu_gdt_descr[0].address);
++ __asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
++ __asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
++
++ if (cr4 & X86_CR4_PSE) {
++ swapper_pg_dir[pgd_index(0)].pgd =
++ efi_bak_pg_dir_pointer[0].pgd;
++ } else {
++ swapper_pg_dir[pgd_index(0)].pgd =
++ efi_bak_pg_dir_pointer[0].pgd;
++ swapper_pg_dir[pgd_index(0x400000)].pgd =
++ efi_bak_pg_dir_pointer[1].pgd;
++ }
++
++ /*
++ * After the lock is released, the original page table is restored.
++ */
++ local_flush_tlb();
++
++ local_irq_restore(efi_rt_eflags);
++ spin_unlock(&efi_rt_lock);
++}
++
++static efi_status_t
++phys_efi_set_virtual_address_map(unsigned long memory_map_size,
++ unsigned long descriptor_size,
++ u32 descriptor_version,
++ efi_memory_desc_t *virtual_map)
++{
++ efi_status_t status;
++
++ efi_call_phys_prelog();
++ status = efi_call_phys(efi_phys.set_virtual_address_map,
++ memory_map_size, descriptor_size,
++ descriptor_version, virtual_map);
++ efi_call_phys_epilog();
++ return status;
++}
++
++efi_status_t
++phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
++{
++ efi_status_t status;
++
++ efi_call_phys_prelog();
++ status = efi_call_phys(efi_phys.get_time, tm, tc);
++ efi_call_phys_epilog();
++ return status;
++}
++
++void efi_gettimeofday(struct timespec *tv)
++{
++ efi_time_t tm;
++
++ memset(tv, 0, sizeof(*tv));
++ if ((*efi.get_time) (&tm, 0) != EFI_SUCCESS)
++ return;
++
++ tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute,
++ tm.second);
++ tv->tv_nsec = tm.nanosecond;
++}
++
++int is_available_memory(efi_memory_desc_t * md)
++{
++ if (!(md->attribute & EFI_MEMORY_WB))
++ return 0;
++
++ switch (md->type) {
++ case EFI_LOADER_CODE:
++ case EFI_LOADER_DATA:
++ case EFI_BOOT_SERVICES_CODE:
++ case EFI_BOOT_SERVICES_DATA:
++ case EFI_CONVENTIONAL_MEMORY:
++ return 1;
++ }
++ return 0;
++}
++
++/*
++ * We need to map the EFI memory map again after paging_init().
++ */
++void __init efi_map_memmap(void)
++{
++ memmap.map = NULL;
++
++ memmap.map = (efi_memory_desc_t *)
++ bt_ioremap((unsigned long) memmap.phys_map,
++ (memmap.nr_map * sizeof(efi_memory_desc_t)));
++
++ if (memmap.map == NULL)
++ printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
++}
++
++void __init print_efi_memmap(void)
++{
++ efi_memory_desc_t *md;
++ int i;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++ printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
++ "range=[0x%016llx-0x%016llx) (%lluMB)\n",
++ i, md->type, md->attribute, md->phys_addr,
++ md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
++ (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
++ }
++}
++
++/*
++ * Walks the EFI memory map and calls CALLBACK once for each EFI
++ * memory descriptor that has memory that is available for kernel use.
++ */
++void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
++{
++ int prev_valid = 0;
++ struct range {
++ unsigned long start;
++ unsigned long end;
++ } prev, curr;
++ efi_memory_desc_t *md;
++ unsigned long start, end;
++ int i;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++
++ if ((md->num_pages == 0) || (!is_available_memory(md)))
++ continue;
++
++ curr.start = md->phys_addr;
++ curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
++
++ if (!prev_valid) {
++ prev = curr;
++ prev_valid = 1;
++ } else {
++ if (curr.start < prev.start)
++ printk(KERN_INFO PFX "Unordered memory map\n");
++ if (prev.end == curr.start)
++ prev.end = curr.end;
++ else {
++ start =
++ (unsigned long) (PAGE_ALIGN(prev.start));
++ end = (unsigned long) (prev.end & PAGE_MASK);
++ if ((end > start)
++ && (*callback) (start, end, arg) < 0)
++ return;
++ prev = curr;
++ }
++ }
++ }
++ if (prev_valid) {
++ start = (unsigned long) PAGE_ALIGN(prev.start);
++ end = (unsigned long) (prev.end & PAGE_MASK);
++ if (end > start)
++ (*callback) (start, end, arg);
++ }
++}
++
++void __init efi_init(void)
++{
++ efi_config_table_t *config_tables;
++ efi_runtime_services_t *runtime;
++ efi_char16_t *c16;
++ char vendor[100] = "unknown";
++ unsigned long num_config_tables;
++ int i = 0;
++
++ memset(&efi, 0, sizeof(efi) );
++ memset(&efi_phys, 0, sizeof(efi_phys));
++
++ efi_phys.systab = EFI_SYSTAB;
++ memmap.phys_map = EFI_MEMMAP;
++ memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
++ memmap.desc_version = EFI_MEMDESC_VERSION;
++
++ efi.systab = (efi_system_table_t *)
++ boot_ioremap((unsigned long) efi_phys.systab,
++ sizeof(efi_system_table_t));
++ /*
++ * Verify the EFI Table
++ */
++ if (efi.systab == NULL)
++ printk(KERN_ERR PFX "Woah! Couldn't map the EFI system table.\n");
++ if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
++ printk(KERN_ERR PFX "Woah! EFI system table signature incorrect\n");
++ if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
++ printk(KERN_ERR PFX
++ "Warning: EFI system table major version mismatch: "
++ "got %d.%02d, expected %d.%02d\n",
++ efi.systab->hdr.revision >> 16,
++ efi.systab->hdr.revision & 0xffff,
++ EFI_SYSTEM_TABLE_REVISION >> 16,
++ EFI_SYSTEM_TABLE_REVISION & 0xffff);
++ /*
++ * Grab some details from the system table
++ */
++ num_config_tables = efi.systab->nr_tables;
++ config_tables = (efi_config_table_t *)efi.systab->tables;
++ runtime = efi.systab->runtime;
++
++ /*
++ * Show what we know for posterity
++ */
++ c16 = (efi_char16_t *) boot_ioremap(efi.systab->fw_vendor, 2);
++ if (c16) {
++ for (i = 0; i < sizeof(vendor) && *c16; ++i)
++ vendor[i] = *c16++;
++ vendor[i] = '\0';
++ } else
++ printk(KERN_ERR PFX "Could not map the firmware vendor!\n");
++
++ printk(KERN_INFO PFX "EFI v%u.%.02u by %s \n",
++ efi.systab->hdr.revision >> 16,
++ efi.systab->hdr.revision & 0xffff, vendor);
++
++ /*
++ * Let's see what config tables the firmware passed to us.
++ */
++ config_tables = (efi_config_table_t *)
++ boot_ioremap((unsigned long) config_tables,
++ num_config_tables * sizeof(efi_config_table_t));
++
++ if (config_tables == NULL)
++ printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n");
++
++ for (i = 0; i < num_config_tables; i++) {
++ if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
++ efi.mps = (void *)config_tables[i].table;
++ printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table);
++ } else
++ if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
++ efi.acpi20 = __va(config_tables[i].table);
++ printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table);
++ } else
++ if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
++ efi.acpi = __va(config_tables[i].table);
++ printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
++ } else
++ if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
++ efi.smbios = (void *) config_tables[i].table;
++ printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
++ } else
++ if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
++ efi.hcdp = (void *)config_tables[i].table;
++ printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table);
++ } else
++ if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) {
++ efi.uga = (void *)config_tables[i].table;
++ printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table);
++ }
++ }
++ printk("\n");
++
++ /*
++ * Check out the runtime services table. We need to map
++ * the runtime services table so that we can grab the physical
++ * address of several of the EFI runtime functions, needed to
++ * set the firmware into virtual mode.
++ */
++
++ runtime = (efi_runtime_services_t *) boot_ioremap((unsigned long)
++ runtime,
++ sizeof(efi_runtime_services_t));
++ if (runtime != NULL) {
++ /*
++ * We will only need *early* access to the following
++ * two EFI runtime services before set_virtual_address_map
++ * is invoked.
++ */
++ efi_phys.get_time = (efi_get_time_t *) runtime->get_time;
++ efi_phys.set_virtual_address_map =
++ (efi_set_virtual_address_map_t *)
++ runtime->set_virtual_address_map;
++ } else
++ printk(KERN_ERR PFX "Could not map the runtime service table!\n");
++
++ /* Map the EFI memory map for use until paging_init() */
++
++ memmap.map = (efi_memory_desc_t *)
++ boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
++
++ if (memmap.map == NULL)
++ printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
++
++ if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
++ printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
++ "match the one from EFI!\n");
++ }
++#if EFI_DEBUG
++ print_efi_memmap();
++#endif
++}
++
++/*
++ * This function will switch the EFI runtime services to virtual mode.
++ * Essentially, look through the EFI memmap and map every region that
++ * has the runtime attribute bit set in its memory descriptor and update
++ * that memory descriptor with the virtual address obtained from ioremap().
++ * This enables the runtime services to be called without having to
++ * thunk back into physical mode for every invocation.
++ */
++
++void __init efi_enter_virtual_mode(void)
++{
++ efi_memory_desc_t *md;
++ efi_status_t status;
++ int i;
++
++ efi.systab = NULL;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++
++ if (md->attribute & EFI_MEMORY_RUNTIME) {
++ md->virt_addr =
++ (unsigned long)ioremap(md->phys_addr,
++ md->num_pages << EFI_PAGE_SHIFT);
++ if (!(unsigned long)md->virt_addr) {
++ printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
++ (unsigned long)md->phys_addr);
++ }
++
++ if (((unsigned long)md->phys_addr <=
++ (unsigned long)efi_phys.systab) &&
++ ((unsigned long)efi_phys.systab <
++ md->phys_addr +
++ ((unsigned long)md->num_pages <<
++ EFI_PAGE_SHIFT))) {
++ unsigned long addr;
++
++ addr = md->virt_addr - md->phys_addr +
++ (unsigned long)efi_phys.systab;
++ efi.systab = (efi_system_table_t *)addr;
++ }
++ }
++ }
++
++ if (!efi.systab)
++ BUG();
++
++ status = phys_efi_set_virtual_address_map(
++ sizeof(efi_memory_desc_t) * memmap.nr_map,
++ sizeof(efi_memory_desc_t),
++ memmap.desc_version,
++ memmap.phys_map);
++
++ if (status != EFI_SUCCESS) {
++ printk (KERN_ALERT "You are screwed! "
++ "Unable to switch EFI into virtual mode "
++ "(status=%lx)\n", status);
++ panic("EFI call to SetVirtualAddressMap() failed!");
++ }
++
++ /*
++ * Now that EFI is in virtual mode, update the function
++ * pointers in the runtime service table to the new virtual addresses.
++ */
++
++ efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
++ efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
++ efi.get_wakeup_time = (efi_get_wakeup_time_t *)
++ efi.systab->runtime->get_wakeup_time;
++ efi.set_wakeup_time = (efi_set_wakeup_time_t *)
++ efi.systab->runtime->set_wakeup_time;
++ efi.get_variable = (efi_get_variable_t *)
++ efi.systab->runtime->get_variable;
++ efi.get_next_variable = (efi_get_next_variable_t *)
++ efi.systab->runtime->get_next_variable;
++ efi.set_variable = (efi_set_variable_t *)
++ efi.systab->runtime->set_variable;
++ efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
++ efi.systab->runtime->get_next_high_mono_count;
++ efi.reset_system = (efi_reset_system_t *)
++ efi.systab->runtime->reset_system;
++}
++
++void __init
++efi_initialize_iomem_resources(struct resource *code_resource,
++ struct resource *data_resource)
++{
++ struct resource *res;
++ efi_memory_desc_t *md;
++ int i;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++
++ if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
++ 0x100000000ULL)
++ continue;
++ res = alloc_bootmem_low(sizeof(struct resource));
++ switch (md->type) {
++ case EFI_RESERVED_TYPE:
++ res->name = "Reserved Memory";
++ break;
++ case EFI_LOADER_CODE:
++ res->name = "Loader Code";
++ break;
++ case EFI_LOADER_DATA:
++ res->name = "Loader Data";
++ break;
++ case EFI_BOOT_SERVICES_DATA:
++ res->name = "BootServices Data";
++ break;
++ case EFI_BOOT_SERVICES_CODE:
++ res->name = "BootServices Code";
++ break;
++ case EFI_RUNTIME_SERVICES_CODE:
++ res->name = "Runtime Service Code";
++ break;
++ case EFI_RUNTIME_SERVICES_DATA:
++ res->name = "Runtime Service Data";
++ break;
++ case EFI_CONVENTIONAL_MEMORY:
++ res->name = "Conventional Memory";
++ break;
++ case EFI_UNUSABLE_MEMORY:
++ res->name = "Unusable Memory";
++ break;
++ case EFI_ACPI_RECLAIM_MEMORY:
++ res->name = "ACPI Reclaim";
++ break;
++ case EFI_ACPI_MEMORY_NVS:
++ res->name = "ACPI NVS";
++ break;
++ case EFI_MEMORY_MAPPED_IO:
++ res->name = "Memory Mapped IO";
++ break;
++ case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
++ res->name = "Memory Mapped IO Port Space";
++ break;
++ default:
++ res->name = "Reserved";
++ break;
++ }
++ res->start = md->phys_addr;
++ res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1);
++ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++ if (request_resource(&iomem_resource, res) < 0)
++ printk(KERN_ERR PFX "Failed to allocate res %s : 0x%lx-0x%lx\n",
++ res->name, res->start, res->end);
++ /*
++ * We don't know which region contains kernel data so we try
++ * it repeatedly and let the resource manager test it.
++ */
++ if (md->type == EFI_CONVENTIONAL_MEMORY) {
++ request_resource(res, code_resource);
++ request_resource(res, data_resource);
++ }
++ }
++}
++
++/*
++ * Convenience functions to obtain memory types and attributes
++ */
++
++u32 efi_mem_type(unsigned long phys_addr)
++{
++ efi_memory_desc_t *md;
++ int i;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++ if ((md->phys_addr <= phys_addr) && (phys_addr <
++ (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
++ return md->type;
++ }
++ return 0;
++}
++
++u64 efi_mem_attributes(unsigned long phys_addr)
++{
++ efi_memory_desc_t *md;
++ int i;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++ if ((md->phys_addr <= phys_addr) && (phys_addr <
++ (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
++ return md->attribute;
++ }
++ return 0;
++}
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/efi_stub.S 2003-10-05 00:36:22.000000000 -0700
+@@ -0,0 +1,125 @@
++/*
++ * EFI call stub for IA32.
++ *
++ * This stub allows us to make EFI calls in physical mode with interrupts
++ * turned off.
++ */
++
++#include <linux/config.h>
++#include <linux/linkage.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++
++/*
++ * efi_call_phys(void *, ...) is a function with variable parameters.
++ * All the callers of this function assure that all the parameters are 4-bytes.
++ */
++
++/*
++ * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
++ * So we'd better save all of them at the beginning of this function and restore
++ * at the end no matter how many we use, because we can not assure EFI runtime
++ * service functions will comply with gcc calling convention, too.
++ */
++
++.text
++.section .text, "a"
++ENTRY(efi_call_phys)
++ /*
++ * 0. The function can only be called in Linux kernel. So CS has been
++ * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
++ * the values of these registers are the same. And, the corresponding
++ * GDT entries are identical. So I will do nothing about segment reg
++ * and GDT, but change GDT base register in prelog and epilog.
++ */
++
++ /*
++ * 1. Now I am running with EIP = <physical address> + PAGE_OFFSET.
++ * But to make it smoothly switch from virtual mode to flat mode.
++ * The mapping of lower virtual memory has been created in prelog and
++ * epilog.
++ */
++ movl $1f, %edx
++ subl $__PAGE_OFFSET, %edx
++ jmp *%edx
++1:
++
++ /*
++ * 2. Now on the top of stack is the return
++ * address in the caller of efi_call_phys(), then parameter 1,
++ * parameter 2, ..., param n. To make things easy, we save the return
++ * address of efi_call_phys in a global variable.
++ */
++ popl %edx
++ movl %edx, saved_return_addr
++ /* get the function pointer into ECX*/
++ popl %ecx
++ movl %ecx, efi_rt_function_ptr
++ movl $2f, %edx
++ subl $__PAGE_OFFSET, %edx
++ pushl %edx
++
++ /*
++ * 3. Clear PG bit in %CR0.
++ */
++ movl %cr0, %edx
++ andl $0x7fffffff, %edx
++ movl %edx, %cr0
++ jmp 1f
++1:
++
++ /*
++ * 4. Adjust stack pointer.
++ */
++ subl $__PAGE_OFFSET, %esp
++
++ /*
++ * 5. Call the physical function.
++ */
++ jmp *%ecx
++
++2:
++ /*
++ * 6. After EFI runtime service returns, control will return to
++ * following instruction. We'd better readjust stack pointer first.
++ */
++ addl $__PAGE_OFFSET, %esp
++
++ /*
++ * 7. Restore PG bit
++ */
++ movl %cr0, %edx
++ orl $0x80000000, %edx
++ movl %edx, %cr0
++ jmp 1f
++1:
++ /*
++ * 8. Now restore the virtual mode from flat mode by
++ * adding EIP with PAGE_OFFSET.
++ */
++ movl $1f, %edx
++ jmp *%edx
++1:
++
++ /*
++ * 9. Balance the stack. And because EAX contain the return value,
++ * we'd better not clobber it.
++ */
++ leal efi_rt_function_ptr, %edx
++ movl (%edx), %ecx
++ pushl %ecx
++
++ /*
++ * 10. Push the saved return address onto the stack and return.
++ */
++ leal saved_return_addr, %edx
++ movl (%edx), %ecx
++ pushl %ecx
++ ret
++.previous
++
++.data
++saved_return_addr:
++ .long 0
++efi_rt_function_ptr:
++ .long 0
+--- linux-2.6.0-test6/arch/i386/kernel/entry.S 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/entry.S 2003-10-05 00:36:48.000000000 -0700
+@@ -43,11 +43,25 @@
+ #include <linux/config.h>
+ #include <linux/linkage.h>
+ #include <asm/thread_info.h>
++#include <asm/asm_offsets.h>
+ #include <asm/errno.h>
+ #include <asm/segment.h>
++#include <asm/page.h>
+ #include <asm/smp.h>
+ #include <asm/page.h>
+ #include "irq_vectors.h"
++ /* We do not recover from a stack overflow, but at least
++ * we know it happened and should be able to track it down.
++ */
++#ifdef CONFIG_STACK_OVERFLOW_TEST
++#define STACK_OVERFLOW_TEST \
++ testl $7680,%esp; \
++ jnz 10f; \
++ call stack_overflow; \
++10:
++#else
++#define STACK_OVERFLOW_TEST
++#endif
+
+ EBX = 0x00
+ ECX = 0x04
+@@ -85,7 +99,102 @@ TSS_ESP0_OFFSET = (4 - 0x200)
+ #define resume_kernel restore_all
+ #endif
+
+-#define SAVE_ALL \
++#ifdef CONFIG_X86_HIGH_ENTRY
++
++#ifdef CONFIG_X86_SWITCH_PAGETABLES
++
++#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
++/*
++ * If task is preempted in __SWITCH_KERNELSPACE, and moved to another cpu,
++ * __switch_to repoints %esp to the appropriate virtual stack; but %ebp is
++ * left stale, so we must check whether to repeat the real stack calculation.
++ */
++#define repeat_if_esp_changed \
++ xorl %esp, %ebp; \
++ testl $0xffffe000, %ebp; \
++ jnz 0b
++#else
++#define repeat_if_esp_changed
++#endif
++
++/* clobbers ebx, edx and ebp */
++
++#define __SWITCH_KERNELSPACE \
++ cmpl $0xff000000, %esp; \
++ jb 1f; \
++ \
++ /* \
++ * switch pagetables and load the real stack, \
++ * keep the stack offset: \
++ */ \
++ \
++ movl $swapper_pg_dir-__PAGE_OFFSET, %edx; \
++ \
++ /* GET_THREAD_INFO(%ebp) intermixed */ \
++0: \
++ movl %esp, %ebp; \
++ movl %esp, %ebx; \
++ andl $0xffffe000, %ebp; \
++ andl $0x00001fff, %ebx; \
++ orl TI_real_stack(%ebp), %ebx; \
++ repeat_if_esp_changed; \
++ \
++ movl %edx, %cr3; \
++ movl %ebx, %esp; \
++1:
++
++#endif
++
++
++#define __SWITCH_USERSPACE \
++ /* interrupted any of the user return paths? */ \
++ \
++ movl EIP(%esp), %eax; \
++ \
++ cmpl $int80_ret_start_marker, %eax; \
++ jb 33f; /* nope - continue with sysexit check */\
++ cmpl $int80_ret_end_marker, %eax; \
++ jb 22f; /* yes - switch to virtual stack */ \
++33: \
++ cmpl $sysexit_ret_start_marker, %eax; \
++ jb 44f; /* nope - continue with user check */ \
++ cmpl $sysexit_ret_end_marker, %eax; \
++ jb 22f; /* yes - switch to virtual stack */ \
++ /* return to userspace? */ \
++44: \
++ movl EFLAGS(%esp),%ecx; \
++ movb CS(%esp),%cl; \
++ testl $(VM_MASK | 3),%ecx; \
++ jz 2f; \
++22: \
++ /* \
++ * switch to the virtual stack, then switch to \
++ * the userspace pagetables. \
++ */ \
++ \
++ GET_THREAD_INFO(%ebp); \
++ movl TI_virtual_stack(%ebp), %edx; \
++ movl TI_user_pgd(%ebp), %ecx; \
++ \
++ movl %esp, %ebx; \
++ andl $0x1fff, %ebx; \
++ orl %ebx, %edx; \
++int80_ret_start_marker: \
++ movl %edx, %esp; \
++ movl %ecx, %cr3; \
++ \
++ __RESTORE_ALL; \
++int80_ret_end_marker: \
++2:
++
++#else /* !CONFIG_X86_HIGH_ENTRY */
++
++#define __SWITCH_KERNELSPACE
++#define __SWITCH_USERSPACE
++
++#endif
++
++#define __SAVE_ALL \
+ cld; \
+ pushl %es; \
+ pushl %ds; \
+@@ -100,7 +209,7 @@ TSS_ESP0_OFFSET = (4 - 0x200)
+ movl %edx, %ds; \
+ movl %edx, %es;
+
+-#define RESTORE_INT_REGS \
++#define __RESTORE_INT_REGS \
+ popl %ebx; \
+ popl %ecx; \
+ popl %edx; \
+@@ -109,29 +218,28 @@ TSS_ESP0_OFFSET = (4 - 0x200)
+ popl %ebp; \
+ popl %eax
+
+-#define RESTORE_REGS \
+- RESTORE_INT_REGS; \
+-1: popl %ds; \
+-2: popl %es; \
++#define __RESTORE_REGS \
++ __RESTORE_INT_REGS; \
++111: popl %ds; \
++222: popl %es; \
+ .section .fixup,"ax"; \
+-3: movl $0,(%esp); \
+- jmp 1b; \
+-4: movl $0,(%esp); \
+- jmp 2b; \
++444: movl $0,(%esp); \
++ jmp 111b; \
++555: movl $0,(%esp); \
++ jmp 222b; \
+ .previous; \
+ .section __ex_table,"a";\
+ .align 4; \
+- .long 1b,3b; \
+- .long 2b,4b; \
++ .long 111b,444b;\
++ .long 222b,555b;\
+ .previous
+
+-
+-#define RESTORE_ALL \
+- RESTORE_REGS \
++#define __RESTORE_ALL \
++ __RESTORE_REGS \
+ addl $4, %esp; \
+-1: iret; \
++333: iret; \
+ .section .fixup,"ax"; \
+-2: sti; \
++666: sti; \
+ movl $(__USER_DS), %edx; \
+ movl %edx, %ds; \
+ movl %edx, %es; \
+@@ -140,10 +248,19 @@ TSS_ESP0_OFFSET = (4 - 0x200)
+ .previous; \
+ .section __ex_table,"a";\
+ .align 4; \
+- .long 1b,2b; \
++ .long 333b,666b;\
+ .previous
+
++#define SAVE_ALL \
++ __SAVE_ALL; \
++ __SWITCH_KERNELSPACE; \
++ STACK_OVERFLOW_TEST;
++
++#define RESTORE_ALL \
++ __SWITCH_USERSPACE; \
++ __RESTORE_ALL;
+
++.section .entry.text,"ax"
+
+ ENTRY(lcall7)
+ pushfl # We get a different stack layout with call
+@@ -161,7 +278,7 @@ do_lcall:
+ movl %edx,EIP(%ebp) # Now we move them to their "normal" places
+ movl %ecx,CS(%ebp) #
+ andl $-8192, %ebp # GET_THREAD_INFO
+- movl TI_EXEC_DOMAIN(%ebp), %edx # Get the execution domain
++ movl TI_exec_domain(%ebp), %edx # Get the execution domain
+ call *4(%edx) # Call the lcall7 handler for the domain
+ addl $4, %esp
+ popl %eax
+@@ -206,7 +323,7 @@ ENTRY(resume_userspace)
+ cli # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+- movl TI_FLAGS(%ebp), %ecx
++ movl TI_flags(%ebp), %ecx
+ andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
+ # int/exception return?
+ jne work_pending
+@@ -214,18 +331,18 @@ ENTRY(resume_userspace)
+
+ #ifdef CONFIG_PREEMPT
+ ENTRY(resume_kernel)
+- cmpl $0,TI_PRE_COUNT(%ebp) # non-zero preempt_count ?
++ cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
+ jnz restore_all
+ need_resched:
+- movl TI_FLAGS(%ebp), %ecx # need_resched set ?
++ movl TI_flags(%ebp), %ecx # need_resched set ?
+ testb $_TIF_NEED_RESCHED, %cl
+ jz restore_all
+ testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
+ jz restore_all
+- movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
++ movl $PREEMPT_ACTIVE,TI_preempt_count(%ebp)
+ sti
+ call schedule
+- movl $0,TI_PRE_COUNT(%ebp)
++ movl $0,TI_preempt_count(%ebp)
+ cli
+ jmp need_resched
+ #endif
+@@ -244,37 +361,50 @@ sysenter_past_esp:
+ pushl $(__USER_CS)
+ pushl $SYSENTER_RETURN
+
+-/*
+- * Load the potential sixth argument from user stack.
+- * Careful about security.
+- */
+- cmpl $__PAGE_OFFSET-3,%ebp
+- jae syscall_fault
+-1: movl (%ebp),%ebp
+-.section __ex_table,"a"
+- .align 4
+- .long 1b,syscall_fault
+-.previous
+-
+ pushl %eax
+ SAVE_ALL
+ GET_THREAD_INFO(%ebp)
+ cmpl $(nr_syscalls), %eax
+ jae syscall_badsys
+
+- testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebp)
++ testb $_TIF_SYSCALL_TRACE,TI_flags(%ebp)
+ jnz syscall_trace_entry
+ call *sys_call_table(,%eax,4)
+ movl %eax,EAX(%esp)
+ cli
+- movl TI_FLAGS(%ebp), %ecx
++ movl TI_flags(%ebp), %ecx
+ testw $_TIF_ALLWORK_MASK, %cx
+ jne syscall_exit_work
++
++#ifdef CONFIG_X86_SWITCH_PAGETABLES
++
++ GET_THREAD_INFO(%ebp)
++ movl TI_virtual_stack(%ebp), %edx
++ movl TI_user_pgd(%ebp), %ecx
++ movl %esp, %ebx
++ andl $0x1fff, %ebx
++ orl %ebx, %edx
++sysexit_ret_start_marker:
++ movl %edx, %esp
++ movl %ecx, %cr3
++#endif
++ /*
++ * only ebx is not restored by the userspace sysenter vsyscall
++ * code, it assumes it to be callee-saved.
++ */
++ movl EBX(%esp), %ebx
++
+ /* if something modifies registers it must also disable sysexit */
++
+ movl EIP(%esp), %edx
+ movl OLDESP(%esp), %ecx
++
+ sti
+ sysexit
++#ifdef CONFIG_X86_SWITCH_PAGETABLES
++sysexit_ret_end_marker:
++ nop
++#endif
+
+
+ # system call handler stub
+@@ -285,7 +415,7 @@ ENTRY(system_call)
+ cmpl $(nr_syscalls), %eax
+ jae syscall_badsys
+ # system call tracing in operation
+- testb $_TIF_SYSCALL_TRACE,TI_FLAGS(%ebp)
++ testb $_TIF_SYSCALL_TRACE,TI_flags(%ebp)
+ jnz syscall_trace_entry
+ syscall_call:
+ call *sys_call_table(,%eax,4)
+@@ -294,10 +424,23 @@ syscall_exit:
+ cli # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+- movl TI_FLAGS(%ebp), %ecx
++ movl TI_flags(%ebp), %ecx
+ testw $_TIF_ALLWORK_MASK, %cx # current->work
+ jne syscall_exit_work
+ restore_all:
++#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
++ movl EFLAGS(%esp), %eax # mix EFLAGS and CS
++ movb CS(%esp), %al
++ testl $(VM_MASK | 3), %eax
++ jz resume_kernelX # returning to kernel or vm86-space
++
++ cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
++ jz resume_kernelX
++
++ int $3
++
++resume_kernelX:
++#endif
+ RESTORE_ALL
+
+ # perform work that needs to be done immediately before resumption
+@@ -310,7 +453,7 @@ work_resched:
+ cli # make sure we don't miss an interrupt
+ # setting need_resched or sigpending
+ # between sampling and the iret
+- movl TI_FLAGS(%ebp), %ecx
++ movl TI_flags(%ebp), %ecx
+ andl $_TIF_WORK_MASK, %ecx # is there any work to be done other
+ # than syscall tracing?
+ jz restore_all
+@@ -325,6 +468,22 @@ work_notifysig: # deal with pending s
+ # vm86-space
+ xorl %edx, %edx
+ call do_notify_resume
++
++#if CONFIG_X86_HIGH_ENTRY
++ /*
++ * Reload db7 if necessary:
++ */
++ movl TI_flags(%ebp), %ecx
++ testb $_TIF_DB7, %cl
++ jnz work_db7
++
++ jmp restore_all
++
++work_db7:
++ movl TI_task(%ebp), %edx;
++ movl task_thread_db7(%edx), %edx;
++ movl %edx, %db7;
++#endif
+ jmp restore_all
+
+ ALIGN
+@@ -380,7 +539,7 @@ syscall_badsys:
+ */
+ .data
+ ENTRY(interrupt)
+-.text
++.previous
+
+ vector=0
+ ENTRY(irq_entries_start)
+@@ -390,7 +549,7 @@ ENTRY(irq_entries_start)
+ jmp common_interrupt
+ .data
+ .long 1b
+-.text
++.previous
+ vector=vector+1
+ .endr
+
+@@ -431,12 +590,17 @@ error_code:
+ movl ES(%esp), %edi # get the function address
+ movl %eax, ORIG_EAX(%esp)
+ movl %ecx, ES(%esp)
+- movl %esp, %edx
+ pushl %esi # push the error code
+- pushl %edx # push the pt_regs pointer
+ movl $(__USER_DS), %edx
+ movl %edx, %ds
+ movl %edx, %es
++
++/* clobbers edx, ebx and ebp */
++ __SWITCH_KERNELSPACE
++
++ leal 4(%esp), %edx # prepare pt_regs
++ pushl %edx # push pt_regs
++
+ call *%edi
+ addl $8, %esp
+ jmp ret_from_exception
+@@ -527,7 +691,7 @@ nmi_stack_correct:
+ pushl %edx
+ call do_nmi
+ addl $8, %esp
+- RESTORE_ALL
++ jmp restore_all
+
+ nmi_stack_fixup:
+ FIX_STACK(12,nmi_stack_correct, 1)
+@@ -595,7 +759,7 @@ ENTRY(page_fault)
+ #ifdef CONFIG_X86_MCE
+ ENTRY(machine_check)
+ pushl $0
+- pushl $do_machine_check
++ pushl machine_check_vector
+ jmp error_code
+ #endif
+
+@@ -604,6 +768,8 @@ ENTRY(spurious_interrupt_bug)
+ pushl $do_spurious_interrupt_bug
+ jmp error_code
+
++.previous
++
+ .data
+ ENTRY(sys_call_table)
+ .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
+@@ -879,5 +1045,60 @@ ENTRY(sys_call_table)
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
+ .long sys_fadvise64_64
++ .long sys_ni_syscall /* sys_vserver */
+
+ nr_syscalls=(.-sys_call_table)/4
++
++
++# Here we do call frames. We cheat a bit as we only really need
++# correct frames at locations we can actually look at from a
++# debugger. Since the break instruction trap actually goes thru
++# some of this code, we don't really need info on those areas, but
++# only after the fact. I.e. if we can not step or break in a
++# location or end up with a return address pointing at the
++# location, we don't need a correct call frame for it.
++
++#if 0
++
++#include <linux/dwarf2-lang.h>
++/*
++ * The register numbers as known by gdb
++ */
++#define _EAX 0
++#define _ECX 1
++#define _EDX 2
++#define _EBX 3
++#define _ESP 4
++#define _EBP 5
++#define _ESI 6
++#define _EDI 7
++#define _PC 8
++#define _EIP 8
++#define _PS 9
++#define _EFLAGS 9
++#define _CS 10
++#define _SS 11
++#define _DS 12
++#define _ES 13
++#define _FS 14
++#define _GS 15
++
++ CFI_preamble(c1,_PC,1,1)
++ CFA_define_reference(_ESP,OLDESP)
++ CFA_define_offset(_EIP,EIP)
++ CFA_define_offset(_EBX,EBX)
++ CFA_define_offset(_ECX,ECX)
++ CFA_define_offset(_EDX,EDX)
++ CFA_define_offset(_ESI,ESI)
++ CFA_define_offset(_EDI,EDI)
++ CFA_define_offset(_EBP,EBP)
++ CFA_define_offset(_EAX,EAX)
++ CFA_define_offset(_EFLAGS,EFLAGS)
++ CFA_define_offset(_CS,CS)
++ CFA_define_offset(_DS,DS)
++ CFA_define_offset(_ES,ES)
++ CFI_postamble(c1)
++
++ FDE_preamble(c1,f1,ret_from_intr,(divide_error - ret_from_intr))
++ FDE_postamble(f1)
++#endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/entry_trampoline.c 2003-10-05 00:36:48.000000000 -0700
+@@ -0,0 +1,75 @@
++/*
++ * linux/arch/i386/kernel/entry_trampoline.c
++ *
++ * (C) Copyright 2003 Ingo Molnar
++ *
++ * This file contains the needed support code for 4GB userspace
++ */
++
++#include <linux/init.h>
++#include <linux/smp.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/highmem.h>
++#include <asm/desc.h>
++#include <asm/atomic_kmap.h>
++
++extern char __entry_tramp_start, __entry_tramp_end, __start___entry_text;
++
++void __init init_entry_mappings(void)
++{
++#ifdef CONFIG_X86_HIGH_ENTRY
++ void *tramp;
++
++ /*
++ * We need a high IDT and GDT for the 4G/4G split:
++ */
++ trap_init_virtual_IDT();
++
++ __set_fixmap(FIX_ENTRY_TRAMPOLINE_0, __pa((unsigned long)&__entry_tramp_start), PAGE_KERNEL);
++ __set_fixmap(FIX_ENTRY_TRAMPOLINE_1, __pa((unsigned long)&__entry_tramp_start) + PAGE_SIZE, PAGE_KERNEL);
++ tramp = (void *)fix_to_virt(FIX_ENTRY_TRAMPOLINE_0);
++
++ printk("mapped 4G/4G trampoline to %p.\n", tramp);
++ BUG_ON((void *)&__start___entry_text != tramp);
++ /*
++ * Virtual kernel stack:
++ */
++ BUG_ON(__kmap_atomic_vaddr(KM_VSTACK0) & 8191);
++ BUG_ON(sizeof(struct desc_struct)*NR_CPUS*GDT_ENTRIES > 2*PAGE_SIZE);
++ BUG_ON((unsigned int)&__entry_tramp_end - (unsigned int)&__entry_tramp_start > 2*PAGE_SIZE);
++
++ /*
++ * set up the initial thread's virtual stack related
++ * fields:
++ */
++ current->thread.stack_page0 = virt_to_page((char *)current->thread_info);
++ current->thread.stack_page1 = virt_to_page((char *)current->thread_info + PAGE_SIZE);
++ current->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK0);
++
++ __kunmap_atomic_type(KM_VSTACK0);
++ __kunmap_atomic_type(KM_VSTACK1);
++ __kmap_atomic(current->thread.stack_page0, KM_VSTACK0);
++ __kmap_atomic(current->thread.stack_page1, KM_VSTACK1);
++
++#endif
++ printk("current: %p\n", current);
++ printk("current->thread_info: %p\n", current->thread_info);
++ current->thread_info->real_stack = (void *)current->thread_info;
++ current->thread_info->user_pgd = NULL;
++ current->thread.esp0 = (unsigned long)current->thread_info->real_stack + THREAD_SIZE;
++}
++
++
++
++void __init entry_trampoline_setup(void)
++{
++ /*
++ * old IRQ entries set up by the boot code will still hang
++ * around - they are a sign of hw trouble anyway, now they'll
++ * produce a double fault message.
++ */
++ trap_init_virtual_GDT();
++}
+--- linux-2.6.0-test6/arch/i386/kernel/head.S 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/head.S 2003-10-05 00:36:48.000000000 -0700
+@@ -16,6 +16,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/desc.h>
+ #include <asm/cache.h>
++#include <asm/asm_offsets.h>
+
+ #define OLD_CL_MAGIC_ADDR 0x90020
+ #define OLD_CL_MAGIC 0xA33F
+@@ -330,7 +331,7 @@ ENTRY(stack_start)
+
+ /* This is the default interrupt "handler" :-) */
+ int_msg:
+- .asciz "Unknown interrupt\n"
++ .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
+ ALIGN
+ ignore_int:
+ cld
+@@ -342,9 +343,17 @@ ignore_int:
+ movl $(__KERNEL_DS),%eax
+ movl %eax,%ds
+ movl %eax,%es
++ pushl 16(%esp)
++ pushl 24(%esp)
++ pushl 32(%esp)
++ pushl 40(%esp)
+ pushl $int_msg
+ call printk
+ popl %eax
++ popl %eax
++ popl %eax
++ popl %eax
++ popl %eax
+ popl %ds
+ popl %es
+ popl %edx
+@@ -377,23 +386,27 @@ cpu_gdt_descr:
+ .fill NR_CPUS-1,8,0 # space for the other GDT descriptors
+
+ /*
+- * This is initialized to create an identity-mapping at 0-8M (for bootup
+- * purposes) and another mapping of the 0-8M area at virtual address
++ * This is initialized to create an identity-mapping at 0-16M (for bootup
++ * purposes) and another mapping of the 0-16M area at virtual address
+ * PAGE_OFFSET.
+ */
+ .org 0x1000
+ ENTRY(swapper_pg_dir)
+ .long 0x00102007
+ .long 0x00103007
+- .fill BOOT_USER_PGD_PTRS-2,4,0
+- /* default: 766 entries */
++ .long 0x00104007
++ .long 0x00105007
++ .fill BOOT_USER_PGD_PTRS-4,4,0
++ /* default: 764 entries */
+ .long 0x00102007
+ .long 0x00103007
+- /* default: 254 entries */
+- .fill BOOT_KERNEL_PGD_PTRS-2,4,0
++ .long 0x00104007
++ .long 0x00105007
++ /* default: 252 entries */
++ .fill BOOT_KERNEL_PGD_PTRS-4,4,0
+
+ /*
+- * The page tables are initialized to only 8MB here - the final page
++ * The page tables are initialized to only 16MB here - the final page
+ * tables are set up later depending on memory size.
+ */
+ .org 0x2000
+@@ -402,15 +415,21 @@ ENTRY(pg0)
+ .org 0x3000
+ ENTRY(pg1)
+
++.org 0x4000
++ENTRY(pg2)
++
++.org 0x5000
++ENTRY(pg3)
++
+ /*
+ * empty_zero_page must immediately follow the page tables ! (The
+ * initialization loop counts until empty_zero_page)
+ */
+
+-.org 0x4000
++.org 0x6000
+ ENTRY(empty_zero_page)
+
+-.org 0x5000
++.org 0x7000
+
+ /*
+ * Real beginning of normal "text" segment
+@@ -419,12 +438,12 @@ ENTRY(stext)
+ ENTRY(_stext)
+
+ /*
+- * This starts the data section. Note that the above is all
+- * in the text section because it has alignment requirements
+- * that we cannot fulfill any other way.
++ * This starts the data section.
+ */
+ .data
+
++.align PAGE_SIZE_asm
++
+ /*
+ * The Global Descriptor Table contains 28 quadwords, per-CPU.
+ */
+@@ -439,7 +458,9 @@ ENTRY(boot_gdt_table)
+ .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
+ .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
+ #endif
+- .align L1_CACHE_BYTES
++
++.align PAGE_SIZE_asm
++
+ ENTRY(cpu_gdt_table)
+ .quad 0x0000000000000000 /* NULL descriptor */
+ .quad 0x0000000000000000 /* 0x0b reserved */
+--- linux-2.6.0-test6/arch/i386/kernel/i386_ksyms.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/i386_ksyms.c 2003-10-05 00:36:48.000000000 -0700
+@@ -98,7 +98,6 @@ EXPORT_SYMBOL_NOVERS(__down_failed_inter
+ EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
+ EXPORT_SYMBOL_NOVERS(__up_wakeup);
+ /* Networking helper routines. */
+-EXPORT_SYMBOL(csum_partial_copy_generic);
+ /* Delay loops */
+ EXPORT_SYMBOL(__ndelay);
+ EXPORT_SYMBOL(__udelay);
+@@ -112,13 +111,17 @@ EXPORT_SYMBOL_NOVERS(__get_user_4);
+ EXPORT_SYMBOL(strpbrk);
+ EXPORT_SYMBOL(strstr);
+
++#if !defined(CONFIG_X86_UACCESS_INDIRECT)
+ EXPORT_SYMBOL(strncpy_from_user);
+-EXPORT_SYMBOL(__strncpy_from_user);
++EXPORT_SYMBOL(__direct_strncpy_from_user);
+ EXPORT_SYMBOL(clear_user);
+ EXPORT_SYMBOL(__clear_user);
+ EXPORT_SYMBOL(__copy_from_user_ll);
+ EXPORT_SYMBOL(__copy_to_user_ll);
+ EXPORT_SYMBOL(strnlen_user);
++#else /* CONFIG_X86_UACCESS_INDIRECT */
++EXPORT_SYMBOL(direct_csum_partial_copy_generic);
++#endif
+
+ EXPORT_SYMBOL(dma_alloc_coherent);
+ EXPORT_SYMBOL(dma_free_coherent);
+--- linux-2.6.0-test6/arch/i386/kernel/i387.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/i386/kernel/i387.c 2003-10-05 00:36:48.000000000 -0700
+@@ -219,6 +219,7 @@ void set_fpu_mxcsr( struct task_struct *
+ static int convert_fxsr_to_user( struct _fpstate __user *buf,
+ struct i387_fxsave_struct *fxsave )
+ {
++ struct _fpreg tmp[8]; /* 80 bytes scratch area */
+ unsigned long env[7];
+ struct _fpreg __user *to;
+ struct _fpxreg *from;
+@@ -235,23 +236,25 @@ static int convert_fxsr_to_user( struct
+ if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) )
+ return 1;
+
+- to = &buf->_st[0];
++ to = tmp;
+ from = (struct _fpxreg *) &fxsave->st_space[0];
+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
+ unsigned long *t = (unsigned long *)to;
+ unsigned long *f = (unsigned long *)from;
+
+- if (__put_user(*f, t) ||
+- __put_user(*(f + 1), t + 1) ||
+- __put_user(from->exponent, &to->exponent))
+- return 1;
++ *t = *f;
++ *(t + 1) = *(f+1);
++ to->exponent = from->exponent;
+ }
++ if (copy_to_user(buf->_st, tmp, sizeof(struct _fpreg [8])))
++ return 1;
+ return 0;
+ }
+
+ static int convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
+ struct _fpstate __user *buf )
+ {
++ struct _fpreg tmp[8]; /* 80 bytes scratch area */
+ unsigned long env[7];
+ struct _fpxreg *to;
+ struct _fpreg __user *from;
+@@ -259,6 +262,8 @@ static int convert_fxsr_from_user( struc
+
+ if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
+ return 1;
++ if (copy_from_user(tmp, buf->_st, sizeof(struct _fpreg [8])))
++ return 1;
+
+ fxsave->cwd = (unsigned short)(env[0] & 0xffff);
+ fxsave->swd = (unsigned short)(env[1] & 0xffff);
+@@ -270,15 +275,14 @@ static int convert_fxsr_from_user( struc
+ fxsave->fos = env[6];
+
+ to = (struct _fpxreg *) &fxsave->st_space[0];
+- from = &buf->_st[0];
++ from = tmp;
+ for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
+ unsigned long *t = (unsigned long *)to;
+ unsigned long *f = (unsigned long *)from;
+
+- if (__get_user(*t, f) ||
+- __get_user(*(t + 1), f + 1) ||
+- __get_user(to->exponent, &from->exponent))
+- return 1;
++ *t = *f;
++ *(t + 1) = *(f + 1);
++ to->exponent = from->exponent;
+ }
+ return 0;
+ }
+@@ -549,13 +553,3 @@ int dump_task_extended_fpu(struct task_s
+ }
+ return fpvalid;
+ }
+-
+-
+-#ifdef CONFIG_SMP
+-void dump_smp_unlazy_fpu(void)
+-{
+- unlazy_fpu(current);
+- return;
+-}
+-#endif
+-
+--- linux-2.6.0-test6/arch/i386/kernel/i8259.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/arch/i386/kernel/i8259.c 2003-10-05 00:36:20.000000000 -0700
+@@ -419,8 +419,10 @@ void __init init_IRQ(void)
+ * us. (some of these will be overridden and become
+ * 'special' SMP interrupts)
+ */
+- for (i = 0; i < NR_IRQS; i++) {
++ for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
+ int vector = FIRST_EXTERNAL_VECTOR + i;
++ if (i >= NR_IRQS)
++ break;
+ if (vector != SYSCALL_VECTOR)
+ set_intr_gate(vector, interrupt[i]);
+ }
+--- linux-2.6.0-test6/arch/i386/kernel/init_task.c 2003-06-14 12:18:35.000000000 -0700
++++ 25/arch/i386/kernel/init_task.c 2003-10-05 00:36:48.000000000 -0700
+@@ -23,7 +23,7 @@ struct mm_struct init_mm = INIT_MM(init_
+ */
+ union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+- { INIT_THREAD_INFO(init_task) };
++ { INIT_THREAD_INFO(init_task, init_thread_union) };
+
+ /*
+ * Initial task structure.
+@@ -39,5 +39,5 @@ struct task_struct init_task = INIT_TASK
+ * section. Since TSS's are completely CPU-local, we want them
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ */
+-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
++struct tss_struct init_tss[NR_CPUS] __attribute__((__section__(".data.tss"))) = { [0 ... NR_CPUS-1] = INIT_TSS };
+
+--- linux-2.6.0-test6/arch/i386/kernel/io_apic.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/io_apic.c 2003-10-05 00:36:27.000000000 -0700
+@@ -76,6 +76,14 @@ static struct irq_pin_list {
+ int apic, pin, next;
+ } irq_2_pin[PIN_MAP_SIZE];
+
++#ifdef CONFIG_PCI_USE_VECTOR
++int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};
++#define vector_to_irq(vector) \
++ (platform_legacy_irq(vector) ? vector : vector_irq[vector])
++#else
++#define vector_to_irq(vector) (vector)
++#endif
++
+ /*
+ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
+ * shared ISA-space IRQs, so we have to support them. We are super
+@@ -249,7 +257,7 @@ static void clear_IO_APIC (void)
+ clear_IO_APIC_pin(apic, pin);
+ }
+
+-static void set_ioapic_affinity(unsigned int irq, cpumask_t cpumask)
++static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
+ {
+ unsigned long flags;
+ int pin;
+@@ -288,7 +296,7 @@ static void set_ioapic_affinity(unsigned
+
+ extern cpumask_t irq_affinity[NR_IRQS];
+
+-static cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
++cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
+
+ #define IRQBALANCE_CHECK_ARCH -999
+ static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
+@@ -670,13 +678,11 @@ static int __init irqbalance_disable(cha
+
+ __setup("noirqbalance", irqbalance_disable);
+
+-static void set_ioapic_affinity(unsigned int irq, cpumask_t mask);
+-
+ static inline void move_irq(int irq)
+ {
+ /* note - we hold the desc->lock */
+ if (unlikely(!cpus_empty(pending_irq_balance_cpumask[irq]))) {
+- set_ioapic_affinity(irq, pending_irq_balance_cpumask[irq]);
++ set_ioapic_affinity_irq(irq, pending_irq_balance_cpumask[irq]);
+ cpus_clear(pending_irq_balance_cpumask[irq]);
+ }
+ }
+@@ -853,7 +859,7 @@ void __init setup_ioapic_dest(cpumask_t
+ if (irq_entry == -1)
+ continue;
+ irq = pin_2_irq(irq_entry, ioapic, pin);
+- set_ioapic_affinity(irq, mask);
++ set_ioapic_affinity_irq(irq, mask);
+ }
+
+ }
+@@ -1138,12 +1144,14 @@ static inline int IO_APIC_irq_trigger(in
+ return 0;
+ }
+
+-int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
++u8 *irq_vector;
++int nr_irqs;
+
+-static int __init assign_irq_vector(int irq)
++#ifndef CONFIG_PCI_USE_VECTOR
++int __init assign_irq_vector(int irq)
+ {
+ static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+- BUG_ON(irq >= NR_IRQS);
++ BUG_ON(irq >= nr_irqs);
+ if (IO_APIC_VECTOR(irq) > 0)
+ return IO_APIC_VECTOR(irq);
+ next:
+@@ -1157,11 +1165,36 @@ next:
+ }
+
+ IO_APIC_VECTOR(irq) = current_vector;
++
+ return current_vector;
+ }
++#endif
+
+-static struct hw_interrupt_type ioapic_level_irq_type;
+-static struct hw_interrupt_type ioapic_edge_irq_type;
++static struct hw_interrupt_type ioapic_level_type;
++static struct hw_interrupt_type ioapic_edge_type;
++
++#define IOAPIC_AUTO -1
++#define IOAPIC_EDGE 0
++#define IOAPIC_LEVEL 1
++
++static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
++{
++ if (use_pci_vector() && !platform_legacy_irq(irq)) {
++ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++ trigger == IOAPIC_LEVEL)
++ irq_desc[vector].handler = &ioapic_level_type;
++ else
++ irq_desc[vector].handler = &ioapic_edge_type;
++ set_intr_gate(vector, interrupt[vector]);
++ } else {
++ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
++ trigger == IOAPIC_LEVEL)
++ irq_desc[irq].handler = &ioapic_level_type;
++ else
++ irq_desc[irq].handler = &ioapic_edge_type;
++ set_intr_gate(vector, interrupt[irq]);
++ }
++}
+
+ void __init setup_IO_APIC_irqs(void)
+ {
+@@ -1219,13 +1252,7 @@ void __init setup_IO_APIC_irqs(void)
+ if (IO_APIC_IRQ(irq)) {
+ vector = assign_irq_vector(irq);
+ entry.vector = vector;
+-
+- if (IO_APIC_irq_trigger(irq))
+- irq_desc[irq].handler = &ioapic_level_irq_type;
+- else
+- irq_desc[irq].handler = &ioapic_edge_irq_type;
+-
+- set_intr_gate(vector, interrupt[irq]);
++ ioapic_register_intr(irq, vector, IOAPIC_AUTO);
+
+ if (!apic && (irq < 16))
+ disable_8259A_irq(irq);
+@@ -1272,7 +1299,7 @@ void __init setup_ExtINT_IRQ0_pin(unsign
+ * The timer IRQ doesn't have to know that behind the
+ * scene we have a 8259A-master in AEOI mode ...
+ */
+- irq_desc[0].handler = &ioapic_edge_irq_type;
++ irq_desc[0].handler = &ioapic_edge_type;
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+@@ -1762,9 +1789,6 @@ static int __init timer_irq_works(void)
+ * that was delayed but this is now handled in the device
+ * independent code.
+ */
+-#define enable_edge_ioapic_irq unmask_IO_APIC_irq
+-
+-static void disable_edge_ioapic_irq (unsigned int irq) { /* nothing */ }
+
+ /*
+ * Starting up a edge-triggered IO-APIC interrupt is
+@@ -1775,7 +1799,6 @@ static void disable_edge_ioapic_irq (uns
+ * This is not complete - we should be able to fake
+ * an edge even if it isn't on the 8259A...
+ */
+-
+ static unsigned int startup_edge_ioapic_irq(unsigned int irq)
+ {
+ int was_pending = 0;
+@@ -1793,8 +1816,6 @@ static unsigned int startup_edge_ioapic_
+ return was_pending;
+ }
+
+-#define shutdown_edge_ioapic_irq disable_edge_ioapic_irq
+-
+ /*
+ * Once we have recorded IRQ_PENDING already, we can mask the
+ * interrupt for real. This prevents IRQ storms from unhandled
+@@ -1809,9 +1830,6 @@ static void ack_edge_ioapic_irq(unsigned
+ ack_APIC_irq();
+ }
+
+-static void end_edge_ioapic_irq (unsigned int i) { /* nothing */ }
+-
+-
+ /*
+ * Level triggered interrupts can just be masked,
+ * and shutting down and starting up the interrupt
+@@ -1833,10 +1851,6 @@ static unsigned int startup_level_ioapic
+ return 0; /* don't check for pending */
+ }
+
+-#define shutdown_level_ioapic_irq mask_IO_APIC_irq
+-#define enable_level_ioapic_irq unmask_IO_APIC_irq
+-#define disable_level_ioapic_irq mask_IO_APIC_irq
+-
+ static void end_level_ioapic_irq (unsigned int irq)
+ {
+ unsigned long v;
+@@ -1863,6 +1877,7 @@ static void end_level_ioapic_irq (unsign
+ * The idea is from Manfred Spraul. --macro
+ */
+ i = IO_APIC_VECTOR(irq);
++
+ v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
+
+ ack_APIC_irq();
+@@ -1897,7 +1912,57 @@ static void end_level_ioapic_irq (unsign
+ }
+ }
+
+-static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
++#ifdef CONFIG_PCI_USE_VECTOR
++static unsigned int startup_edge_ioapic_vector(unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ return startup_edge_ioapic_irq(irq);
++}
++
++static void ack_edge_ioapic_vector(unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ ack_edge_ioapic_irq(irq);
++}
++
++static unsigned int startup_level_ioapic_vector (unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ return startup_level_ioapic_irq (irq);
++}
++
++static void end_level_ioapic_vector (unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ end_level_ioapic_irq(irq);
++}
++
++static void mask_IO_APIC_vector (unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ mask_IO_APIC_irq(irq);
++}
++
++static void unmask_IO_APIC_vector (unsigned int vector)
++{
++ int irq = vector_to_irq(vector);
++
++ unmask_IO_APIC_irq(irq);
++}
++
++static void set_ioapic_affinity_vector (unsigned int vector,
++ unsigned long cpu_mask)
++{
++ int irq = vector_to_irq(vector);
++
++ set_ioapic_affinity_irq(irq, cpu_mask);
++}
++#endif
+
+ /*
+ * Level and edge triggered IO-APIC interrupts need different handling,
+@@ -1907,26 +1972,25 @@ static void mask_and_ack_level_ioapic_ir
+ * edge-triggered handler, without risking IRQ storms and other ugly
+ * races.
+ */
+-
+-static struct hw_interrupt_type ioapic_edge_irq_type = {
++static struct hw_interrupt_type ioapic_edge_type = {
+ .typename = "IO-APIC-edge",
+- .startup = startup_edge_ioapic_irq,
+- .shutdown = shutdown_edge_ioapic_irq,
+- .enable = enable_edge_ioapic_irq,
+- .disable = disable_edge_ioapic_irq,
+- .ack = ack_edge_ioapic_irq,
+- .end = end_edge_ioapic_irq,
++ .startup = startup_edge_ioapic,
++ .shutdown = shutdown_edge_ioapic,
++ .enable = enable_edge_ioapic,
++ .disable = disable_edge_ioapic,
++ .ack = ack_edge_ioapic,
++ .end = end_edge_ioapic,
+ .set_affinity = set_ioapic_affinity,
+ };
+
+-static struct hw_interrupt_type ioapic_level_irq_type = {
++static struct hw_interrupt_type ioapic_level_type = {
+ .typename = "IO-APIC-level",
+- .startup = startup_level_ioapic_irq,
+- .shutdown = shutdown_level_ioapic_irq,
+- .enable = enable_level_ioapic_irq,
+- .disable = disable_level_ioapic_irq,
+- .ack = mask_and_ack_level_ioapic_irq,
+- .end = end_level_ioapic_irq,
++ .startup = startup_level_ioapic,
++ .shutdown = shutdown_level_ioapic,
++ .enable = enable_level_ioapic,
++ .disable = disable_level_ioapic,
++ .ack = mask_and_ack_level_ioapic,
++ .end = end_level_ioapic,
+ .set_affinity = set_ioapic_affinity,
+ };
+
+@@ -1946,7 +2010,13 @@ static inline void init_IO_APIC_traps(vo
+ * 0x80, because int 0x80 is hm, kind of importantish. ;)
+ */
+ for (irq = 0; irq < NR_IRQS ; irq++) {
+- if (IO_APIC_IRQ(irq) && !IO_APIC_VECTOR(irq)) {
++ int tmp = irq;
++ if (use_pci_vector()) {
++ if (!platform_legacy_irq(tmp))
++ if ((tmp = vector_to_irq(tmp)) == -1)
++ continue;
++ }
++ if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) {
+ /*
+ * Hmm.. We don't have an entry for this,
+ * so default to an old-fashioned 8259
+@@ -2378,10 +2448,12 @@ int io_apic_set_pci_routing (int ioapic,
+ "IRQ %d Mode:%i Active:%i)\n", ioapic,
+ mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
+
++ if (use_pci_vector() && !platform_legacy_irq(irq))
++ irq = IO_APIC_VECTOR(irq);
+ if (edge_level) {
+- irq_desc[irq].handler = &ioapic_level_irq_type;
++ irq_desc[irq].handler = &ioapic_level_type;
+ } else {
+- irq_desc[irq].handler = &ioapic_edge_irq_type;
++ irq_desc[irq].handler = &ioapic_edge_type;
+ }
+
+ set_intr_gate(entry.vector, interrupt[irq]);
+--- linux-2.6.0-test6/arch/i386/kernel/irq.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/irq.c 2003-10-05 00:33:50.000000000 -0700
+@@ -44,6 +44,7 @@
+ #include <asm/delay.h>
+ #include <asm/desc.h>
+ #include <asm/irq.h>
++#include <asm/kgdb.h>
+
+ /*
+ * Linux has a controller-independent x86 interrupt architecture.
+@@ -499,6 +500,17 @@ out:
+
+ irq_exit();
+
++#ifdef CONFIG_KGDB
++ /*
++ * We need to do this after clearing out of all the interrupt
++ * machinery because kgdb will reenter the NIC driver and the IRQ
++ * system. synchronize_irq() (at least) will deadlock.
++ */
++ if (kgdb_eth_need_breakpoint[smp_processor_id()]) {
++ kgdb_eth_need_breakpoint[smp_processor_id()] = 0;
++ BREAKPOINT;
++ }
++#endif
+ return 1;
+ }
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/kernel/kgdb_stub.c 2003-10-05 00:33:51.000000000 -0700
+@@ -0,0 +1,2492 @@
++/*
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ */
++
++/*
++ * Copyright (c) 2000 VERITAS Software Corporation.
++ *
++ */
++/****************************************************************************
++ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
++ *
++ * Module name: remcom.c $
++ * Revision: 1.34 $
++ * Date: 91/03/09 12:29:49 $
++ * Contributor: Lake Stevens Instrument Division$
++ *
++ * Description: low level support for gdb debugger. $
++ *
++ * Considerations: only works on target hardware $
++ *
++ * Written by: Glenn Engel $
++ * Updated by: David Grothe <dave@gcom.com>
++ * Updated by: Robert Walsh <rjwalsh@durables.org>
++ * Updated by: wangdi <wangdi@clusterfs.com>
++ * ModuleState: Experimental $
++ *
++ * NOTES: See Below $
++ *
++ * Modified for 386 by Jim Kingdon, Cygnus Support.
++ * Compatibility with 2.1.xx kernel by David Grothe <dave@gcom.com>
++ *
++ * Changes to allow auto initilization. All that is needed is that it
++ * be linked with the kernel and a break point (int 3) be executed.
++ * The header file <asm/kgdb.h> defines BREAKPOINT to allow one to do
++ * this. It should also be possible, once the interrupt system is up, to
++ * call putDebugChar("+"). Once this is done, the remote debugger should
++ * get our attention by sending a ^C in a packet. George Anzinger
++ * <george@mvista.com>
++ * Integrated into 2.2.5 kernel by Tigran Aivazian <tigran@sco.com>
++ * Added thread support, support for multiple processors,
++ * support for ia-32(x86) hardware debugging.
++ * Amit S. Kale ( akale@veritas.com )
++ *
++ * Modified to support debugging over ethernet by Robert Walsh
++ * <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
++ * code by San Mehat.
++ *
++ *
++ * To enable debugger support, two things need to happen. One, a
++ * call to set_debug_traps() is necessary in order to allow any breakpoints
++ * or error conditions to be properly intercepted and reported to gdb.
++ * Two, a breakpoint needs to be generated to begin communication. This
++ * is most easily accomplished by a call to breakpoint(). Breakpoint()
++ * simulates a breakpoint by executing an int 3.
++ *
++ *************
++ *
++ * The following gdb commands are supported:
++ *
++ * command function Return value
++ *
++ * g return the value of the CPU registers hex data or ENN
++ * G set the value of the CPU registers OK or ENN
++ *
++ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
++ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
++ *
++ * c Resume at current address SNN ( signal NN)
++ * cAA..AA Continue at address AA..AA SNN
++ *
++ * s Step one instruction SNN
++ * sAA..AA Step one instruction from AA..AA SNN
++ *
++ * k kill
++ *
++ * ? What was the last sigval ? SNN (signal NN)
++ *
++ * All commands and responses are sent with a packet which includes a
++ * checksum. A packet consists of
++ *
++ * $<packet info>#<checksum>.
++ *
++ * where
++ * <packet info> :: <characters representing the command or response>
++ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
++ *
++ * When a packet is received, it is first acknowledged with either '+' or '-'.
++ * '+' indicates a successful transfer. '-' indicates a failed transfer.
++ *
++ * Example:
++ *
++ * Host: Reply:
++ * $m0,10#2a +$00010203040506070809101112131415#42
++ *
++ ****************************************************************************/
++#define KGDB_VERSION "<20030915.1651.33>"
++#include <linux/config.h>
++#include <linux/types.h>
++#include <asm/string.h> /* for strcpy */
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <asm/vm86.h>
++#include <asm/system.h>
++#include <asm/ptrace.h> /* for linux pt_regs struct */
++#include <asm/kgdb_local.h>
++#include <linux/list.h>
++#include <asm/atomic.h>
++#include <asm/processor.h>
++#include <linux/irq.h>
++#include <asm/desc.h>
++#include <linux/inet.h>
++#include <linux/kallsyms.h>
++
++/************************************************************************
++ *
++ * external low-level support routines
++ */
++typedef void (*Function) (void); /* pointer to a function */
++
++/* Thread reference */
++typedef unsigned char threadref[8];
++
++extern int tty_putDebugChar(int); /* write a single character */
++extern int tty_getDebugChar(void); /* read and return a single char */
++extern void tty_flushDebugChar(void); /* flush pending characters */
++extern int eth_putDebugChar(int); /* write a single character */
++extern int eth_getDebugChar(void); /* read and return a single char */
++extern void eth_flushDebugChar(void); /* flush pending characters */
++extern void kgdb_eth_set_trapmode(int);
++extern void kgdb_eth_reply_arp(void); /*send arp request */
++extern volatile int kgdb_eth_is_initializing;
++
++
++/************************************************************************/
++/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
++/* at least NUMREGBYTES*2 are needed for register packets */
++/* Longer buffer is needed to list all threads */
++#define BUFMAX 400
++
++char *kgdb_version = KGDB_VERSION;
++
++/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
++int debug_regs = 0; /* set to non-zero to print registers */
++
++/* filled in by an external module */
++char *gdb_module_offsets;
++
++static const char hexchars[] = "0123456789abcdef";
++
++/* Number of bytes of registers. */
++#define NUMREGBYTES 64
++/*
++ * Note that this register image is in a different order than
++ * the register image that Linux produces at interrupt time.
++ *
++ * Linux's register image is defined by struct pt_regs in ptrace.h.
++ * Just why GDB uses a different order is a historical mystery.
++ */
++enum regnames { _EAX, /* 0 */
++ _ECX, /* 1 */
++ _EDX, /* 2 */
++ _EBX, /* 3 */
++ _ESP, /* 4 */
++ _EBP, /* 5 */
++ _ESI, /* 6 */
++ _EDI, /* 7 */
++ _PC /* 8 also known as eip */ ,
++ _PS /* 9 also known as eflags */ ,
++ _CS, /* 10 */
++ _SS, /* 11 */
++ _DS, /* 12 */
++ _ES, /* 13 */
++ _FS, /* 14 */
++ _GS /* 15 */
++};
++
++/*************************** ASSEMBLY CODE MACROS *************************/
++/*
++ * Put the error code here just in case the user cares.
++ * Likewise, the vector number here (since GDB only gets the signal
++ * number through the usual means, and that's not very specific).
++ * The called_from is the return address so he can tell how we entered kgdb.
++ * This will allow him to seperate out the various possible entries.
++ */
++#define REMOTE_DEBUG 0 /* set != to turn on printing (also available in info) */
++
++#define PID_MAX PID_MAX_DEFAULT
++
++#ifdef CONFIG_SMP
++void smp_send_nmi_allbutself(void);
++#define IF_SMP(x) x
++#undef MAX_NO_CPUS
++#ifndef CONFIG_NO_KGDB_CPUS
++#define CONFIG_NO_KGDB_CPUS 2
++#endif
++#if CONFIG_NO_KGDB_CPUS > NR_CPUS
++#define MAX_NO_CPUS NR_CPUS
++#else
++#define MAX_NO_CPUS CONFIG_NO_KGDB_CPUS
++#endif
++#define hold_init hold_on_sstep: 1,
++#define MAX_CPU_MASK (unsigned long)((1LL << MAX_NO_CPUS) - 1LL)
++#define NUM_CPUS num_online_cpus()
++#else
++#define IF_SMP(x)
++#define hold_init
++#undef MAX_NO_CPUS
++#define MAX_NO_CPUS 1
++#define NUM_CPUS 1
++#endif
++#define NOCPU (struct task_struct *)0xbad1fbad
++/* *INDENT-OFF* */
++struct kgdb_info {
++ int used_malloc;
++ void *called_from;
++ long long entry_tsc;
++ int errcode;
++ int vector;
++ int print_debug_info;
++#ifdef CONFIG_SMP
++ int hold_on_sstep;
++ struct {
++ volatile struct task_struct *task;
++ int pid;
++ int hold;
++ struct pt_regs *regs;
++ } cpus_waiting[MAX_NO_CPUS];
++#endif
++} kgdb_info = {hold_init print_debug_info:REMOTE_DEBUG, vector:-1};
++
++/* *INDENT-ON* */
++
++#define used_m kgdb_info.used_malloc
++/*
++ * This is little area we set aside to contain the stack we
++ * need to build to allow gdb to call functions. We use one
++ * per cpu to avoid locking issues. We will do all this work
++ * with interrupts off so that should take care of the protection
++ * issues.
++ */
++#define LOOKASIDE_SIZE 200 /* should be more than enough */
++#define MALLOC_MAX 200 /* Max malloc size */
++struct {
++ unsigned int esp;
++ int array[LOOKASIDE_SIZE];
++} fn_call_lookaside[MAX_NO_CPUS];
++
++static int trap_cpu;
++static unsigned int OLD_esp;
++
++#define END_OF_LOOKASIDE &fn_call_lookaside[trap_cpu].array[LOOKASIDE_SIZE]
++#define IF_BIT 0x200
++#define TF_BIT 0x100
++
++#define MALLOC_ROUND 8-1
++
++static char malloc_array[MALLOC_MAX];
++IF_SMP(static void to_gdb(const char *mess));
++void *
++malloc(int size)
++{
++
++ if (size <= (MALLOC_MAX - used_m)) {
++ int old_used = used_m;
++ used_m += ((size + MALLOC_ROUND) & (~MALLOC_ROUND));
++ return &malloc_array[old_used];
++ } else {
++ return NULL;
++ }
++}
++
++/*
++ * I/O dispatch functions...
++ * Based upon kgdb_eth, either call the ethernet
++ * handler or the serial one..
++ */
++void
++putDebugChar(int c)
++{
++ if (kgdb_eth == -1) {
++ tty_putDebugChar(c);
++ } else {
++ eth_putDebugChar(c);
++ }
++}
++
++int
++getDebugChar(void)
++{
++ if (kgdb_eth == -1) {
++ return tty_getDebugChar();
++ } else {
++ return eth_getDebugChar();
++ }
++}
++
++void
++flushDebugChar(void)
++{
++ if (kgdb_eth == -1) {
++ tty_flushDebugChar();
++ } else {
++ eth_flushDebugChar();
++ }
++}
++
++/*
++ * Gdb calls functions by pushing agruments, including a return address
++ * on the stack and the adjusting EIP to point to the function. The
++ * whole assumption in GDB is that we are on a different stack than the
++ * one the "user" i.e. code that hit the break point, is on. This, of
++ * course is not true in the kernel. Thus various dodges are needed to
++ * do the call without directly messing with EIP (which we can not change
++ * as it is just a location and not a register. To adjust it would then
++ * require that we move every thing below EIP up or down as needed. This
++ * will not work as we may well have stack relative pointer on the stack
++ * (such as the pointer to regs, for example).
++
++ * So here is what we do:
++ * We detect gdb attempting to store into the stack area and instead, store
++ * into the fn_call_lookaside.array at the same relative location as if it
++ * were the area ESP pointed at. We also trap ESP modifications
++ * and uses these to adjust fn_call_lookaside.esp. On entry
++ * fn_call_lookaside.esp will be set to point at the last entry in
++ * fn_call_lookaside.array. This allows us to check if it has changed, and
++ * if so, on exit, we add the registers we will use to do the move and a
++ * trap/ interrupt return exit sequence. We then adjust the eflags in the
++ * regs array (remember we now have a copy in the fn_call_lookaside.array) to
++ * kill the interrupt bit, AND we change EIP to point at our set up stub.
++ * As part of the register set up we preset the registers to point at the
++ * begining and end of the fn_call_lookaside.array, so all the stub needs to
++ * do is move words from the array to the stack until ESP= the desired value
++ * then do the rti. This will then transfer to the desired function with
++ * all the correct registers. Nifty huh?
++ */
++extern asmlinkage void fn_call_stub(void);
++extern asmlinkage void fn_rtn_stub(void);
++/* *INDENT-OFF* */
++__asm__("fn_rtn_stub:\n\t"
++ "movl %eax,%esp\n\t"
++ "fn_call_stub:\n\t"
++ "1:\n\t"
++ "addl $-4,%ebx\n\t"
++ "movl (%ebx), %eax\n\t"
++ "pushl %eax\n\t"
++ "cmpl %esp,%ecx\n\t"
++ "jne 1b\n\t"
++ "popl %eax\n\t"
++ "popl %ebx\n\t"
++ "popl %ecx\n\t"
++ "iret \n\t");
++/* *INDENT-ON* */
++#define gdb_i386vector kgdb_info.vector
++#define gdb_i386errcode kgdb_info.errcode
++#define waiting_cpus kgdb_info.cpus_waiting
++#define remote_debug kgdb_info.print_debug_info
++#define hold_cpu(cpu) kgdb_info.cpus_waiting[cpu].hold
++/* gdb locks */
++
++#ifdef CONFIG_SMP
++static int in_kgdb_called;
++static spinlock_t waitlocks[MAX_NO_CPUS] =
++ {[0 ... MAX_NO_CPUS - 1] = SPIN_LOCK_UNLOCKED };
++/*
++ * The following array has the thread pointer of each of the "other"
++ * cpus. We make it global so it can be seen by gdb.
++ */
++volatile int in_kgdb_entry_log[MAX_NO_CPUS];
++volatile struct pt_regs *in_kgdb_here_log[MAX_NO_CPUS];
++/*
++static spinlock_t continuelocks[MAX_NO_CPUS];
++*/
++spinlock_t kgdb_spinlock = SPIN_LOCK_UNLOCKED;
++/* waiters on our spinlock plus us */
++static atomic_t spinlock_waiters = ATOMIC_INIT(1);
++static int spinlock_count = 0;
++static int spinlock_cpu = 0;
++/*
++ * Note we use nested spin locks to account for the case where a break
++ * point is encountered when calling a function by user direction from
++ * kgdb. Also there is the memory exception recursion to account for.
++ * Well, yes, but this lets other cpus thru too. Lets add a
++ * cpu id to the lock.
++ */
++#define KGDB_SPIN_LOCK(x) if( spinlock_count == 0 || \
++ spinlock_cpu != smp_processor_id()){\
++ atomic_inc(&spinlock_waiters); \
++ while (! spin_trylock(x)) {\
++ in_kgdb(®s);\
++ }\
++ atomic_dec(&spinlock_waiters); \
++ spinlock_count = 1; \
++ spinlock_cpu = smp_processor_id(); \
++ }else{ \
++ spinlock_count++; \
++ }
++#define KGDB_SPIN_UNLOCK(x) if( --spinlock_count == 0) spin_unlock(x)
++#else
++unsigned kgdb_spinlock = 0;
++#define KGDB_SPIN_LOCK(x) --*x
++#define KGDB_SPIN_UNLOCK(x) ++*x
++#endif
++
++int
++hex(char ch)
++{
++ if ((ch >= 'a') && (ch <= 'f'))
++ return (ch - 'a' + 10);
++ if ((ch >= '0') && (ch <= '9'))
++ return (ch - '0');
++ if ((ch >= 'A') && (ch <= 'F'))
++ return (ch - 'A' + 10);
++ return (-1);
++}
++
++/* scan for the sequence $<data>#<checksum> */
++void
++getpacket(char *buffer)
++{
++ unsigned char checksum;
++ unsigned char xmitcsum;
++ int i;
++ int count;
++ char ch;
++
++ do {
++ /* wait around for the start character, ignore all other characters */
++ while ((ch = (getDebugChar() & 0x7f)) != '$') ;
++ checksum = 0;
++ xmitcsum = -1;
++
++ count = 0;
++
++ /* now, read until a # or end of buffer is found */
++ while (count < BUFMAX) {
++ ch = getDebugChar() & 0x7f;
++ if (ch == '#')
++ break;
++ checksum = checksum + ch;
++ buffer[count] = ch;
++ count = count + 1;
++ }
++ buffer[count] = 0;
++
++ if (ch == '#') {
++ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
++ xmitcsum += hex(getDebugChar() & 0x7f);
++ if ((remote_debug) && (checksum != xmitcsum)) {
++ printk
++ ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
++ checksum, xmitcsum, buffer);
++ }
++
++ if (checksum != xmitcsum)
++ putDebugChar('-'); /* failed checksum */
++ else {
++ putDebugChar('+'); /* successful transfer */
++ /* if a sequence char is present, reply the sequence ID */
++ if (buffer[2] == ':') {
++ putDebugChar(buffer[0]);
++ putDebugChar(buffer[1]);
++ /* remove sequence chars from buffer */
++ count = strlen(buffer);
++ for (i = 3; i <= count; i++)
++ buffer[i - 3] = buffer[i];
++ }
++ }
++ }
++ } while (checksum != xmitcsum);
++
++ if (remote_debug)
++ printk("R:%s\n", buffer);
++ flushDebugChar();
++}
++
++/* send the packet in buffer. */
++
++void
++putpacket(char *buffer)
++{
++ unsigned char checksum;
++ int count;
++ char ch;
++
++ /* $<packet info>#<checksum>. */
++
++ if (kgdb_eth == -1) {
++ do {
++ if (remote_debug)
++ printk("T:%s\n", buffer);
++ putDebugChar('$');
++ checksum = 0;
++ count = 0;
++
++ while ((ch = buffer[count])) {
++ putDebugChar(ch);
++ checksum += ch;
++ count += 1;
++ }
++
++ putDebugChar('#');
++ putDebugChar(hexchars[checksum >> 4]);
++ putDebugChar(hexchars[checksum % 16]);
++ flushDebugChar();
++
++ } while ((getDebugChar() & 0x7f) != '+');
++ } else {
++ /*
++ * For udp, we can not transfer too much bytes once.
++ * We only transfer MAX_SEND_COUNT size bytes each time
++ */
++
++#define MAX_SEND_COUNT 30
++
++ int send_count = 0, i = 0;
++ char send_buf[MAX_SEND_COUNT];
++
++ do {
++ if (remote_debug)
++ printk("T:%s\n", buffer);
++ putDebugChar('$');
++ checksum = 0;
++ count = 0;
++ send_count = 0;
++ while ((ch = buffer[count])) {
++ if (send_count >= MAX_SEND_COUNT) {
++ for(i = 0; i < MAX_SEND_COUNT; i++) {
++ putDebugChar(send_buf[i]);
++ }
++ flushDebugChar();
++ send_count = 0;
++ } else {
++ send_buf[send_count] = ch;
++ checksum += ch;
++ count ++;
++ send_count++;
++ }
++ }
++ for(i = 0; i < send_count; i++)
++ putDebugChar(send_buf[i]);
++ putDebugChar('#');
++ putDebugChar(hexchars[checksum >> 4]);
++ putDebugChar(hexchars[checksum % 16]);
++ flushDebugChar();
++ } while ((getDebugChar() & 0x7f) != '+');
++ }
++}
++
++static char remcomInBuffer[BUFMAX];
++static char remcomOutBuffer[BUFMAX];
++static short error;
++
++void
++debug_error(char *format, char *parm)
++{
++ if (remote_debug)
++ printk(format, parm);
++}
++
++static void
++print_regs(struct pt_regs *regs)
++{
++ printk("EAX=%08lx ", regs->eax);
++ printk("EBX=%08lx ", regs->ebx);
++ printk("ECX=%08lx ", regs->ecx);
++ printk("EDX=%08lx ", regs->edx);
++ printk("\n");
++ printk("ESI=%08lx ", regs->esi);
++ printk("EDI=%08lx ", regs->edi);
++ printk("EBP=%08lx ", regs->ebp);
++ printk("ESP=%08lx ", (long) ®s->esp);
++ printk("\n");
++ printk(" DS=%08x ", regs->xds);
++ printk(" ES=%08x ", regs->xes);
++ printk(" SS=%08x ", __KERNEL_DS);
++ printk(" FL=%08lx ", regs->eflags);
++ printk("\n");
++ printk(" CS=%08x ", regs->xcs);
++ printk(" IP=%08lx ", regs->eip);
++#if 0
++ printk(" FS=%08x ", regs->fs);
++ printk(" GS=%08x ", regs->gs);
++#endif
++ printk("\n");
++
++} /* print_regs */
++
++#define NEW_esp fn_call_lookaside[trap_cpu].esp
++
++static void
++regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs)
++{
++ gdb_regs[_EAX] = regs->eax;
++ gdb_regs[_EBX] = regs->ebx;
++ gdb_regs[_ECX] = regs->ecx;
++ gdb_regs[_EDX] = regs->edx;
++ gdb_regs[_ESI] = regs->esi;
++ gdb_regs[_EDI] = regs->edi;
++ gdb_regs[_EBP] = regs->ebp;
++ gdb_regs[_DS] = regs->xds;
++ gdb_regs[_ES] = regs->xes;
++ gdb_regs[_PS] = regs->eflags;
++ gdb_regs[_CS] = regs->xcs;
++ gdb_regs[_PC] = regs->eip;
++ /* Note, as we are a debugging the kernel, we will always
++ * trap in kernel code, this means no priviledge change,
++ * and so the pt_regs structure is not completely valid. In a non
++ * privilege change trap, only EFLAGS, CS and EIP are put on the stack,
++ * SS and ESP are not stacked, this means that the last 2 elements of
++ * pt_regs is not valid (they would normally refer to the user stack)
++ * also, using regs+1 is no good because you end up will a value that is
++ * 2 longs (8) too high. This used to cause stepping over functions
++ * to fail, so my fix is to use the address of regs->esp, which
++ * should point at the end of the stack frame. Note I have ignored
++ * completely exceptions that cause an error code to be stacked, such
++ * as double fault. Stuart Hughes, Zentropix.
++ * original code: gdb_regs[_ESP] = (int) (regs + 1) ;
++
++ * this is now done on entry and moved to OLD_esp (as well as NEW_esp).
++ */
++ gdb_regs[_ESP] = NEW_esp;
++ gdb_regs[_SS] = __KERNEL_DS;
++ gdb_regs[_FS] = 0xFFFF;
++ gdb_regs[_GS] = 0xFFFF;
++} /* regs_to_gdb_regs */
++
++static void
++gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs)
++{
++ regs->eax = gdb_regs[_EAX];
++ regs->ebx = gdb_regs[_EBX];
++ regs->ecx = gdb_regs[_ECX];
++ regs->edx = gdb_regs[_EDX];
++ regs->esi = gdb_regs[_ESI];
++ regs->edi = gdb_regs[_EDI];
++ regs->ebp = gdb_regs[_EBP];
++ regs->xds = gdb_regs[_DS];
++ regs->xes = gdb_regs[_ES];
++ regs->eflags = gdb_regs[_PS];
++ regs->xcs = gdb_regs[_CS];
++ regs->eip = gdb_regs[_PC];
++ NEW_esp = gdb_regs[_ESP]; /* keep the value */
++#if 0 /* can't change these */
++ regs->esp = gdb_regs[_ESP];
++ regs->xss = gdb_regs[_SS];
++ regs->fs = gdb_regs[_FS];
++ regs->gs = gdb_regs[_GS];
++#endif
++
++} /* gdb_regs_to_regs */
++extern void scheduling_functions_start_here(void);
++extern void scheduling_functions_end_here(void);
++#define first_sched ((unsigned long) scheduling_functions_start_here)
++#define last_sched ((unsigned long) scheduling_functions_end_here)
++
++int thread_list = 0;
++
++void
++get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs)
++{
++ unsigned long stack_page;
++ int count = 0;
++ IF_SMP(int i);
++ if (!p || p == current) {
++ regs_to_gdb_regs(gdb_regs, regs);
++ return;
++ }
++#ifdef CONFIG_SMP
++ for (i = 0; i < MAX_NO_CPUS; i++) {
++ if (p == kgdb_info.cpus_waiting[i].task) {
++ regs_to_gdb_regs(gdb_regs,
++ kgdb_info.cpus_waiting[i].regs);
++ gdb_regs[_ESP] =
++ (int) &kgdb_info.cpus_waiting[i].regs->esp;
++
++ return;
++ }
++ }
++#endif
++ memset(gdb_regs, 0, NUMREGBYTES);
++ gdb_regs[_ESP] = p->thread.esp;
++ gdb_regs[_PC] = p->thread.eip;
++ gdb_regs[_EBP] = *(int *) gdb_regs[_ESP];
++ gdb_regs[_EDI] = *(int *) (gdb_regs[_ESP] + 4);
++ gdb_regs[_ESI] = *(int *) (gdb_regs[_ESP] + 8);
++
++/*
++ * This code is to give a more informative notion of where a process
++ * is waiting. It is used only when the user asks for a thread info
++ * list. If he then switches to the thread, s/he will find the task
++ * is in schedule, but a back trace should show the same info we come
++ * up with. This code was shamelessly purloined from process.c. It was
++ * then enhanced to provide more registers than simply the program
++ * counter.
++ */
++
++ if (!thread_list) {
++ return;
++ }
++
++ if (p->state == TASK_RUNNING)
++ return;
++ stack_page = (unsigned long) p->thread_info;
++ if (gdb_regs[_ESP] < stack_page || gdb_regs[_ESP] > 8188 + stack_page)
++ return;
++ /* include/asm-i386/system.h:switch_to() pushes ebp last. */
++ do {
++ if (gdb_regs[_EBP] < stack_page ||
++ gdb_regs[_EBP] > 8184 + stack_page)
++ return;
++ gdb_regs[_PC] = *(unsigned long *) (gdb_regs[_EBP] + 4);
++ gdb_regs[_ESP] = gdb_regs[_EBP] + 8;
++ gdb_regs[_EBP] = *(unsigned long *) gdb_regs[_EBP];
++ if (gdb_regs[_PC] < first_sched || gdb_regs[_PC] >= last_sched)
++ return;
++ } while (count++ < 16);
++ return;
++}
++
++/* Indicate to caller of mem2hex or hex2mem that there has been an
++ error. */
++static volatile int mem_err = 0;
++static volatile int mem_err_expected = 0;
++static volatile int mem_err_cnt = 0;
++static int garbage_loc = -1;
++
++int
++get_char(char *addr)
++{
++ return *addr;
++}
++
++void
++set_char(char *addr, int val, int may_fault)
++{
++ /*
++ * This code traps references to the area mapped to the kernel
++ * stack as given by the regs and, instead, stores to the
++ * fn_call_lookaside[cpu].array
++ */
++ if (may_fault &&
++ (unsigned int) addr < OLD_esp &&
++ ((unsigned int) addr > (OLD_esp - (unsigned int) LOOKASIDE_SIZE))) {
++ addr = (char *) END_OF_LOOKASIDE - ((char *) OLD_esp - addr);
++ }
++ *addr = val;
++}
++
++/* convert the memory pointed to by mem into hex, placing result in buf */
++/* return a pointer to the last char put in buf (null) */
++/* If MAY_FAULT is non-zero, then we should set mem_err in response to
++ a fault; if zero treat a fault like any other fault in the stub. */
++char *
++mem2hex(char *mem, char *buf, int count, int may_fault)
++{
++ int i;
++ unsigned char ch;
++
++ if (may_fault) {
++ mem_err_expected = 1;
++ mem_err = 0;
++ }
++ for (i = 0; i < count; i++) {
++ /* printk("%lx = ", mem) ; */
++
++ ch = get_char(mem++);
++
++ /* printk("%02x\n", ch & 0xFF) ; */
++ if (may_fault && mem_err) {
++ if (remote_debug)
++ printk("Mem fault fetching from addr %lx\n",
++ (long) (mem - 1));
++ *buf = 0; /* truncate buffer */
++ return (buf);
++ }
++ *buf++ = hexchars[ch >> 4];
++ *buf++ = hexchars[ch % 16];
++ }
++ *buf = 0;
++ if (may_fault)
++ mem_err_expected = 0;
++ return (buf);
++}
++
++/* convert the hex array pointed to by buf into binary to be placed in mem */
++/* return a pointer to the character AFTER the last byte written */
++/* NOTE: We use the may fault flag to also indicate if the write is to
++ * the registers (0) or "other" memory (!=0)
++ */
++char *
++hex2mem(char *buf, char *mem, int count, int may_fault)
++{
++ int i;
++ unsigned char ch;
++
++ if (may_fault) {
++ mem_err_expected = 1;
++ mem_err = 0;
++ }
++ for (i = 0; i < count; i++) {
++ ch = hex(*buf++) << 4;
++ ch = ch + hex(*buf++);
++ set_char(mem++, ch, may_fault);
++
++ if (may_fault && mem_err) {
++ if (remote_debug)
++ printk("Mem fault storing to addr %lx\n",
++ (long) (mem - 1));
++ return (mem);
++ }
++ }
++ if (may_fault)
++ mem_err_expected = 0;
++ return (mem);
++}
++
++/**********************************************/
++/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
++/* RETURN NUMBER OF CHARS PROCESSED */
++/**********************************************/
++int
++hexToInt(char **ptr, int *intValue)
++{
++ int numChars = 0;
++ int hexValue;
++
++ *intValue = 0;
++
++ while (**ptr) {
++ hexValue = hex(**ptr);
++ if (hexValue >= 0) {
++ *intValue = (*intValue << 4) | hexValue;
++ numChars++;
++ } else
++ break;
++
++ (*ptr)++;
++ }
++
++ return (numChars);
++}
++
++#define stubhex(h) hex(h)
++#ifdef old_thread_list
++
++static int
++stub_unpack_int(char *buff, int fieldlength)
++{
++ int nibble;
++ int retval = 0;
++
++ while (fieldlength) {
++ nibble = stubhex(*buff++);
++ retval |= nibble;
++ fieldlength--;
++ if (fieldlength)
++ retval = retval << 4;
++ }
++ return retval;
++}
++#endif
++static char *
++pack_hex_byte(char *pkt, int byte)
++{
++ *pkt++ = hexchars[(byte >> 4) & 0xf];
++ *pkt++ = hexchars[(byte & 0xf)];
++ return pkt;
++}
++
++#define BUF_THREAD_ID_SIZE 16
++
++static char *
++pack_threadid(char *pkt, threadref * id)
++{
++ char *limit;
++ unsigned char *altid;
++
++ altid = (unsigned char *) id;
++ limit = pkt + BUF_THREAD_ID_SIZE;
++ while (pkt < limit)
++ pkt = pack_hex_byte(pkt, *altid++);
++ return pkt;
++}
++
++#ifdef old_thread_list
++static char *
++unpack_byte(char *buf, int *value)
++{
++ *value = stub_unpack_int(buf, 2);
++ return buf + 2;
++}
++
++static char *
++unpack_threadid(char *inbuf, threadref * id)
++{
++ char *altref;
++ char *limit = inbuf + BUF_THREAD_ID_SIZE;
++ int x, y;
++
++ altref = (char *) id;
++
++ while (inbuf < limit) {
++ x = stubhex(*inbuf++);
++ y = stubhex(*inbuf++);
++ *altref++ = (x << 4) | y;
++ }
++ return inbuf;
++}
++#endif
++void
++int_to_threadref(threadref * id, int value)
++{
++ unsigned char *scan;
++
++ scan = (unsigned char *) id;
++ {
++ int i = 4;
++ while (i--)
++ *scan++ = 0;
++ }
++ *scan++ = (value >> 24) & 0xff;
++ *scan++ = (value >> 16) & 0xff;
++ *scan++ = (value >> 8) & 0xff;
++ *scan++ = (value & 0xff);
++}
++int
++int_to_hex_v(unsigned char * id, int value)
++{
++ unsigned char *start = id;
++ int shift;
++ int ch;
++
++ for (shift = 28; shift >= 0; shift -= 4) {
++ if ((ch = (value >> shift) & 0xf) || (id != start)) {
++ *id = hexchars[ch];
++ id++;
++ }
++ }
++ if (id == start)
++ *id++ = '0';
++ return id - start;
++}
++#ifdef old_thread_list
++
++static int
++threadref_to_int(threadref * ref)
++{
++ int i, value = 0;
++ unsigned char *scan;
++
++ scan = (char *) ref;
++ scan += 4;
++ i = 4;
++ while (i-- > 0)
++ value = (value << 8) | ((*scan++) & 0xff);
++ return value;
++}
++#endif
++static int
++cmp_str(char *s1, char *s2, int count)
++{
++ while (count--) {
++ if (*s1++ != *s2++)
++ return 0;
++ }
++ return 1;
++}
++
++#if 1 /* this is a hold over from 2.4 where O(1) was "sometimes" */
++extern struct task_struct *kgdb_get_idle(int cpu);
++#define idle_task(cpu) kgdb_get_idle(cpu)
++#else
++#define idle_task(cpu) init_tasks[cpu]
++#endif
++
++extern int kgdb_pid_init_done;
++
++struct task_struct *
++getthread(int pid)
++{
++ struct task_struct *thread;
++ if (pid >= PID_MAX && pid <= (PID_MAX + MAX_NO_CPUS)) {
++
++ return idle_task(pid - PID_MAX);
++ } else {
++ /*
++ * find_task_by_pid is relatively safe all the time
++ * Other pid functions require lock downs which imply
++ * that we may be interrupting them (as we get here
++ * in the middle of most any lock down).
++ * Still we don't want to call until the table exists!
++ */
++ if (kgdb_pid_init_done){
++ thread = find_task_by_pid(pid);
++ if (thread) {
++ return thread;
++ }
++ }
++ }
++ return NULL;
++}
++/* *INDENT-OFF* */
++struct hw_breakpoint {
++ unsigned enabled;
++ unsigned type;
++ unsigned len;
++ unsigned addr;
++} breakinfo[4] = { {enabled:0},
++ {enabled:0},
++ {enabled:0},
++ {enabled:0}};
++/* *INDENT-ON* */
++unsigned hw_breakpoint_status;
++void
++correct_hw_break(void)
++{
++ int breakno;
++ int correctit;
++ int breakbit;
++ unsigned dr7;
++
++ asm volatile ("movl %%db7, %0\n":"=r" (dr7)
++ :);
++ /* *INDENT-OFF* */
++ do {
++ unsigned addr0, addr1, addr2, addr3;
++ asm volatile ("movl %%db0, %0\n"
++ "movl %%db1, %1\n"
++ "movl %%db2, %2\n"
++ "movl %%db3, %3\n"
++ :"=r" (addr0), "=r"(addr1),
++ "=r"(addr2), "=r"(addr3)
++ :);
++ } while (0);
++ /* *INDENT-ON* */
++ correctit = 0;
++ for (breakno = 0; breakno < 3; breakno++) {
++ breakbit = 2 << (breakno << 1);
++ if (!(dr7 & breakbit) && breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 |= breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ dr7 |= (((breakinfo[breakno].len << 2) |
++ breakinfo[breakno].type) << 16) <<
++ (breakno << 2);
++ switch (breakno) {
++ case 0:
++ asm volatile ("movl %0, %%dr0\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 1:
++ asm volatile ("movl %0, %%dr1\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 2:
++ asm volatile ("movl %0, %%dr2\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++
++ case 3:
++ asm volatile ("movl %0, %%dr3\n"::"r"
++ (breakinfo[breakno].addr));
++ break;
++ }
++ } else if ((dr7 & breakbit) && !breakinfo[breakno].enabled) {
++ correctit = 1;
++ dr7 &= ~breakbit;
++ dr7 &= ~(0xf0000 << (breakno << 2));
++ }
++ }
++ if (correctit) {
++ asm volatile ("movl %0, %%db7\n"::"r" (dr7));
++ }
++}
++
++int
++remove_hw_break(unsigned breakno)
++{
++ if (!breakinfo[breakno].enabled) {
++ return -1;
++ }
++ breakinfo[breakno].enabled = 0;
++ return 0;
++}
++
++int
++set_hw_break(unsigned breakno, unsigned type, unsigned len, unsigned addr)
++{
++ if (breakinfo[breakno].enabled) {
++ return -1;
++ }
++ breakinfo[breakno].enabled = 1;
++ breakinfo[breakno].type = type;
++ breakinfo[breakno].len = len;
++ breakinfo[breakno].addr = addr;
++ return 0;
++}
++
++#ifdef CONFIG_SMP
++static int in_kgdb_console = 0;
++
++int
++in_kgdb(struct pt_regs *regs)
++{
++ unsigned flags;
++ int cpu = smp_processor_id();
++ in_kgdb_called = 1;
++ if (!spin_is_locked(&kgdb_spinlock)) {
++ if (in_kgdb_here_log[cpu] || /* we are holding this cpu */
++ in_kgdb_console) { /* or we are doing slow i/o */
++ return 1;
++ }
++ return 0;
++ }
++
++ /* As I see it the only reason not to let all cpus spin on
++ * the same spin_lock is to allow selected ones to proceed.
++ * This would be a good thing, so we leave it this way.
++ * Maybe someday.... Done !
++
++ * in_kgdb() is called from an NMI so we don't pretend
++ * to have any resources, like printk() for example.
++ */
++
++ kgdb_local_irq_save(flags); /* only local here, to avoid hanging */
++ /*
++ * log arival of this cpu
++ * The NMI keeps on ticking. Protect against recurring more
++ * than once, and ignor the cpu that has the kgdb lock
++ */
++ in_kgdb_entry_log[cpu]++;
++ in_kgdb_here_log[cpu] = regs;
++ if (cpu == spinlock_cpu || waiting_cpus[cpu].task) {
++ goto exit_in_kgdb;
++ }
++ /*
++ * For protection of the initilization of the spin locks by kgdb
++ * it locks the kgdb spinlock before it gets the wait locks set
++ * up. We wait here for the wait lock to be taken. If the
++ * kgdb lock goes away first?? Well, it could be a slow exit
++ * sequence where the wait lock is removed prior to the kgdb lock
++ * so if kgdb gets unlocked, we just exit.
++ */
++ while (spin_is_locked(&kgdb_spinlock) &&
++ !spin_is_locked(waitlocks + cpu)) ;
++ if (!spin_is_locked(&kgdb_spinlock)) {
++ goto exit_in_kgdb;
++ }
++ waiting_cpus[cpu].task = current;
++ waiting_cpus[cpu].pid = (current->pid) ? : (PID_MAX + cpu);
++ waiting_cpus[cpu].regs = regs;
++
++ spin_unlock_wait(waitlocks + cpu);
++ /*
++ * log departure of this cpu
++ */
++ waiting_cpus[cpu].task = 0;
++ waiting_cpus[cpu].pid = 0;
++ waiting_cpus[cpu].regs = 0;
++ correct_hw_break();
++ exit_in_kgdb:
++ in_kgdb_here_log[cpu] = 0;
++ kgdb_local_irq_restore(flags);
++ return 1;
++ /*
++ spin_unlock(continuelocks + smp_processor_id());
++ */
++}
++
++void
++smp__in_kgdb(struct pt_regs regs)
++{
++ ack_APIC_irq();
++ in_kgdb(®s);
++}
++#else
++int
++in_kgdb(struct pt_regs *regs)
++{
++ return (kgdb_spinlock);
++}
++#endif
++
++void
++printexceptioninfo(int exceptionNo, int errorcode, char *buffer)
++{
++ unsigned dr6;
++ int i;
++ switch (exceptionNo) {
++ case 1: /* debug exception */
++ break;
++ case 3: /* breakpoint */
++ sprintf(buffer, "Software breakpoint");
++ return;
++ default:
++ sprintf(buffer, "Details not available");
++ return;
++ }
++ asm volatile ("movl %%db6, %0\n":"=r" (dr6)
++ :);
++ if (dr6 & 0x4000) {
++ sprintf(buffer, "Single step");
++ return;
++ }
++ for (i = 0; i < 4; ++i) {
++ if (dr6 & (1 << i)) {
++ sprintf(buffer, "Hardware breakpoint %d", i);
++ return;
++ }
++ }
++ sprintf(buffer, "Unknown trap");
++ return;
++}
++
++/*
++ * This function does all command procesing for interfacing to gdb.
++ *
++ * NOTE: The INT nn instruction leaves the state of the interrupt
++ * enable flag UNCHANGED. That means that when this routine
++ * is entered via a breakpoint (INT 3) instruction from code
++ * that has interrupts enabled, then interrupts will STILL BE
++ * enabled when this routine is entered. The first thing that
++ * we do here is disable interrupts so as to prevent recursive
++ * entries and bothersome serial interrupts while we are
++ * trying to run the serial port in polled mode.
++ *
++ * For kernel version 2.1.xx the kgdb_cli() actually gets a spin lock so
++ * it is always necessary to do a restore_flags before returning
++ * so as to let go of that lock.
++ */
++int
++kgdb_handle_exception(int exceptionVector,
++ int signo, int err_code, struct pt_regs *linux_regs)
++{
++ struct task_struct *usethread = NULL;
++ struct task_struct *thread_list_start = 0, *thread = NULL;
++ int addr, length;
++ unsigned long address;
++ int breakno, breaktype;
++ char *ptr;
++ int newPC;
++ threadref thref;
++ int threadid;
++ int thread_min = PID_MAX + MAX_NO_CPUS;
++#ifdef old_thread_list
++ int maxthreads;
++#endif
++ int nothreads;
++ unsigned long flags;
++ int gdb_regs[NUMREGBYTES / 4];
++ int dr6;
++ IF_SMP(int entry_state = 0); /* 0, ok, 1, no nmi, 2 sync failed */
++#define NO_NMI 1
++#define NO_SYNC 2
++#define regs (*linux_regs)
++#define NUMREGS NUMREGBYTES/4
++ /*
++ * If the entry is not from the kernel then return to the Linux
++ * trap handler and let it process the interrupt normally.
++ */
++ if ((linux_regs->eflags & VM_MASK) || (3 & linux_regs->xcs)) {
++ printk("ignoring non-kernel exception\n");
++ print_regs(®s);
++ return (0);
++ }
++ /*
++ * If we're using eth mode, set the 'mode' in the netdevice.
++ */
++
++ __asm__("movl %%cr2,%0":"=r" (address));
++
++ if (kgdb_eth != -1) {
++ kgdb_eth_set_trapmode(1);
++ }
++
++ kgdb_local_irq_save(flags);
++
++ /* Get kgdb spinlock */
++
++ KGDB_SPIN_LOCK(&kgdb_spinlock);
++ rdtscll(kgdb_info.entry_tsc);
++ /*
++ * We depend on this spinlock and the NMI watch dog to control the
++ * other cpus. They will arrive at "in_kgdb()" as a result of the
++ * NMI and will wait there for the following spin locks to be
++ * released.
++ */
++#ifdef CONFIG_SMP
++
++#if 0
++ if (cpu_callout_map & ~MAX_CPU_MASK) {
++ printk("kgdb : too many cpus, possibly not mapped"
++ " in contiguous space, change MAX_NO_CPUS"
++ " in kgdb_stub and make new kernel.\n"
++ " cpu_callout_map is %lx\n", cpu_callout_map);
++ goto exit_just_unlock;
++ }
++#endif
++ if (spinlock_count == 1) {
++ int time, end_time, dum;
++ int i;
++ int cpu_logged_in[MAX_NO_CPUS] = {[0 ... MAX_NO_CPUS - 1] = (0)
++ };
++ if (remote_debug) {
++ printk("kgdb : cpu %d entry, syncing others\n",
++ smp_processor_id());
++ }
++ for (i = 0; i < MAX_NO_CPUS; i++) {
++ /*
++ * Use trylock as we may already hold the lock if
++ * we are holding the cpu. Net result is all
++ * locked.
++ */
++ spin_trylock(&waitlocks[i]);
++ }
++ for (i = 0; i < MAX_NO_CPUS; i++)
++ cpu_logged_in[i] = 0;
++ /*
++ * Wait for their arrival. We know the watch dog is active if
++ * in_kgdb() has ever been called, as it is always called on a
++ * watchdog tick.
++ */
++ rdtsc(dum, time);
++ end_time = time + 2; /* Note: we use the High order bits! */
++ i = 1;
++ if (num_online_cpus() > 1) {
++ int me_in_kgdb = in_kgdb_entry_log[smp_processor_id()];
++ smp_send_nmi_allbutself();
++ while (i < num_online_cpus() && time != end_time) {
++ int j;
++ for (j = 0; j < MAX_NO_CPUS; j++) {
++ if (waiting_cpus[j].task &&
++ !cpu_logged_in[j]) {
++ i++;
++ cpu_logged_in[j] = 1;
++ if (remote_debug) {
++ printk
++ ("kgdb : cpu %d arrived at kgdb\n",
++ j);
++ }
++ break;
++ } else if (!waiting_cpus[j].task &&
++ !cpu_online(j)) {
++ waiting_cpus[j].task = NOCPU;
++ cpu_logged_in[j] = 1;
++ waiting_cpus[j].hold = 1;
++ break;
++ }
++ if (!waiting_cpus[j].task &&
++ in_kgdb_here_log[j]) {
++
++ int wait = 100000;
++ while (wait--) ;
++ if (!waiting_cpus[j].task &&
++ in_kgdb_here_log[j]) {
++ printk
++ ("kgdb : cpu %d stall"
++ " in in_kgdb\n",
++ j);
++ i++;
++ cpu_logged_in[j] = 1;
++ waiting_cpus[j].task =
++ (struct task_struct
++ *) 1;
++ }
++ }
++ }
++
++ if (in_kgdb_entry_log[smp_processor_id()] >
++ (me_in_kgdb + 10)) {
++ break;
++ }
++
++ rdtsc(dum, time);
++ }
++ if (i < num_online_cpus()) {
++ printk
++ ("kgdb : time out, proceeding without sync\n");
++#if 0
++ printk("kgdb : Waiting_cpus: 0 = %d, 1 = %d\n",
++ waiting_cpus[0].task != 0,
++ waiting_cpus[1].task != 0);
++ printk("kgdb : Cpu_logged in: 0 = %d, 1 = %d\n",
++ cpu_logged_in[0], cpu_logged_in[1]);
++ printk
++ ("kgdb : in_kgdb_here_log in: 0 = %d, 1 = %d\n",
++ in_kgdb_here_log[0] != 0,
++ in_kgdb_here_log[1] != 0);
++#endif
++ entry_state = NO_SYNC;
++ } else {
++#if 0
++ int ent =
++ in_kgdb_entry_log[smp_processor_id()] -
++ me_in_kgdb;
++ printk("kgdb : sync after %d entries\n", ent);
++#endif
++ }
++ } else {
++ if (remote_debug) {
++ printk
++ ("kgdb : %d cpus, but watchdog not active\n"
++ "proceeding without locking down other cpus\n",
++ num_online_cpus());
++ entry_state = NO_NMI;
++ }
++ }
++ }
++#endif
++
++ if (remote_debug) {
++ printk("handle_exception(exceptionVector=%d, "
++ "signo=%d, err_code=%d, linux_regs=%p)\n",
++ exceptionVector, signo, err_code, linux_regs);
++ printk(" address: %lx\n", address);
++
++ if (debug_regs) {
++ print_regs(®s);
++ show_trace(current, (unsigned long *)®s);
++ }
++ }
++
++ /* Disable hardware debugging while we are in kgdb */
++ /* Get the debug register status register */
++/* *INDENT-OFF* */
++ __asm__("movl %0,%%db7"
++ : /* no output */
++ :"r"(0));
++
++ asm volatile ("movl %%db6, %0\n"
++ :"=r" (hw_breakpoint_status)
++ :);
++
++/* *INDENT-ON* */
++ switch (exceptionVector) {
++ case 0: /* divide error */
++ case 1: /* debug exception */
++ case 2: /* NMI */
++ case 3: /* breakpoint */
++ case 4: /* overflow */
++ case 5: /* bounds check */
++ case 6: /* invalid opcode */
++ case 7: /* device not available */
++ case 8: /* double fault (errcode) */
++ case 10: /* invalid TSS (errcode) */
++ case 12: /* stack fault (errcode) */
++ case 16: /* floating point error */
++ case 17: /* alignment check (errcode) */
++ default: /* any undocumented */
++ break;
++ case 11: /* segment not present (errcode) */
++ case 13: /* general protection (errcode) */
++ case 14: /* page fault (special errcode) */
++ case 19: /* cache flush denied */
++ if (mem_err_expected) {
++ /*
++ * This fault occured because of the
++ * get_char or set_char routines. These
++ * two routines use either eax of edx to
++ * indirectly reference the location in
++ * memory that they are working with.
++ * For a page fault, when we return the
++ * instruction will be retried, so we
++ * have to make sure that these
++ * registers point to valid memory.
++ */
++ mem_err = 1; /* set mem error flag */
++ mem_err_expected = 0;
++ mem_err_cnt++; /* helps in debugging */
++ /* make valid address */
++ regs.eax = (long) &garbage_loc;
++ /* make valid address */
++ regs.edx = (long) &garbage_loc;
++ if (remote_debug)
++ printk("Return after memory error: "
++ "mem_err_cnt=%d\n", mem_err_cnt);
++ if (debug_regs)
++ print_regs(®s);
++ goto exit_kgdb;
++ }
++ break;
++ }
++ if (remote_debug)
++ printk("kgdb : entered kgdb on cpu %d\n", smp_processor_id());
++
++ gdb_i386vector = exceptionVector;
++ gdb_i386errcode = err_code;
++ kgdb_info.called_from = __builtin_return_address(0);
++#ifdef CONFIG_SMP
++ /*
++ * OK, we can now communicate, lets tell gdb about the sync.
++ * but only if we had a problem.
++ */
++ switch (entry_state) {
++ case NO_NMI:
++ to_gdb("NMI not active, other cpus not stopped\n");
++ break;
++ case NO_SYNC:
++ to_gdb("Some cpus not stopped, see 'kgdb_info' for details\n");
++ default:;
++ }
++
++#endif
++/*
++ * Set up the gdb function call area.
++ */
++ trap_cpu = smp_processor_id();
++ OLD_esp = NEW_esp = (int) (&linux_regs->esp);
++
++ IF_SMP(once_again:)
++ /* reply to host that an exception has occurred */
++ remcomOutBuffer[0] = 'S';
++ remcomOutBuffer[1] = hexchars[signo >> 4];
++ remcomOutBuffer[2] = hexchars[signo % 16];
++ remcomOutBuffer[3] = 0;
++
++ if (kgdb_eth_is_initializing) {
++ kgdb_eth_is_initializing = 0;
++ } else {
++ putpacket(remcomOutBuffer);
++ }
++
++ kgdb_eth_reply_arp();
++ while (1 == 1) {
++ error = 0;
++ remcomOutBuffer[0] = 0;
++ getpacket(remcomInBuffer);
++ switch (remcomInBuffer[0]) {
++ case '?':
++ remcomOutBuffer[0] = 'S';
++ remcomOutBuffer[1] = hexchars[signo >> 4];
++ remcomOutBuffer[2] = hexchars[signo % 16];
++ remcomOutBuffer[3] = 0;
++ break;
++ case 'd':
++ remote_debug = !(remote_debug); /* toggle debug flag */
++ printk("Remote debug %s\n",
++ remote_debug ? "on" : "off");
++ break;
++ case 'g': /* return the value of the CPU registers */
++ get_gdb_regs(usethread, ®s, gdb_regs);
++ mem2hex((char *) gdb_regs,
++ remcomOutBuffer, NUMREGBYTES, 0);
++ break;
++ case 'G': /* set the value of the CPU registers - return OK */
++ hex2mem(&remcomInBuffer[1],
++ (char *) gdb_regs, NUMREGBYTES, 0);
++ if (!usethread || usethread == current) {
++ gdb_regs_to_regs(gdb_regs, ®s);
++ strcpy(remcomOutBuffer, "OK");
++ } else {
++ strcpy(remcomOutBuffer, "E00");
++ }
++ break;
++
++ case 'P':{ /* set the value of a single CPU register -
++ return OK */
++ /*
++ * For some reason, gdb wants to talk about psudo
++ * registers (greater than 15). These may have
++ * meaning for ptrace, but for us it is safe to
++ * ignor them. We do this by dumping them into
++ * _GS which we also ignor, but do have memory for.
++ */
++ int regno;
++
++ ptr = &remcomInBuffer[1];
++ regs_to_gdb_regs(gdb_regs, ®s);
++ if ((!usethread || usethread == current) &&
++ hexToInt(&ptr, ®no) &&
++ *ptr++ == '=' && (regno >= 0)) {
++ regno =
++ (regno >= NUMREGS ? _GS : regno);
++ hex2mem(ptr, (char *) &gdb_regs[regno],
++ 4, 0);
++ gdb_regs_to_regs(gdb_regs, ®s);
++ strcpy(remcomOutBuffer, "OK");
++ break;
++ }
++ strcpy(remcomOutBuffer, "E01");
++ break;
++ }
++
++ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
++ case 'm':
++ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
++ ptr = &remcomInBuffer[1];
++ if (hexToInt(&ptr, &addr) &&
++ (*(ptr++) == ',') && (hexToInt(&ptr, &length))) {
++ ptr = 0;
++ /*
++ * hex doubles the byte count
++ */
++ if (length > (BUFMAX / 2))
++ length = BUFMAX / 2;
++ mem2hex((char *) addr,
++ remcomOutBuffer, length, 1);
++ if (mem_err) {
++ strcpy(remcomOutBuffer, "E03");
++ debug_error("memory fault\n", NULL);
++ }
++ }
++
++ if (ptr) {
++ strcpy(remcomOutBuffer, "E01");
++ debug_error
++ ("malformed read memory command: %s\n",
++ remcomInBuffer);
++ }
++ break;
++
++ /* MAA..AA,LLLL:
++ Write LLLL bytes at address AA.AA return OK */
++ case 'M':
++ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
++ ptr = &remcomInBuffer[1];
++ if (hexToInt(&ptr, &addr) &&
++ (*(ptr++) == ',') &&
++ (hexToInt(&ptr, &length)) && (*(ptr++) == ':')) {
++ hex2mem(ptr, (char *) addr, length, 1);
++
++ if (mem_err) {
++ strcpy(remcomOutBuffer, "E03");
++ debug_error("memory fault\n", NULL);
++ } else {
++ strcpy(remcomOutBuffer, "OK");
++ }
++
++ ptr = 0;
++ }
++ if (ptr) {
++ strcpy(remcomOutBuffer, "E02");
++ debug_error
++ ("malformed write memory command: %s\n",
++ remcomInBuffer);
++ }
++ break;
++ case 'S':
++ remcomInBuffer[0] = 's';
++ case 'C':
++ /* Csig;AA..AA where ;AA..AA is optional
++ * continue with signal
++ * Since signals are meaning less to us, delete that
++ * part and then fall into the 'c' code.
++ */
++ ptr = &remcomInBuffer[1];
++ length = 2;
++ while (*ptr && *ptr != ';') {
++ length++;
++ ptr++;
++ }
++ if (*ptr) {
++ do {
++ ptr++;
++ *(ptr - length++) = *ptr;
++ } while (*ptr);
++ } else {
++ remcomInBuffer[1] = 0;
++ }
++
++ /* cAA..AA Continue at address AA..AA(optional) */
++ /* sAA..AA Step one instruction from AA..AA(optional) */
++ /* D detach, reply OK and then continue */
++ case 'c':
++ case 's':
++ case 'D':
++
++ /* try to read optional parameter,
++ pc unchanged if no parm */
++ ptr = &remcomInBuffer[1];
++ if (hexToInt(&ptr, &addr)) {
++ if (remote_debug)
++ printk("Changing EIP to 0x%x\n", addr);
++
++ regs.eip = addr;
++ }
++
++ newPC = regs.eip;
++
++ if (kgdb_eth != -1) {
++ kgdb_eth_set_trapmode(0);
++ }
++
++ /* clear the trace bit */
++ regs.eflags &= 0xfffffeff;
++
++ /* set the trace bit if we're stepping */
++ if (remcomInBuffer[0] == 's')
++ regs.eflags |= 0x100;
++
++ /* detach is a friendly version of continue. Note that
++ debugging is still enabled (e.g hit control C)
++ */
++ if (remcomInBuffer[0] == 'D') {
++ strcpy(remcomOutBuffer, "OK");
++ putpacket(remcomOutBuffer);
++ }
++
++ if (remote_debug) {
++ printk("Resuming execution\n");
++ print_regs(®s);
++ }
++ asm volatile ("movl %%db6, %0\n":"=r" (dr6)
++ :);
++ if (!(dr6 & 0x4000)) {
++ for (breakno = 0; breakno < 4; ++breakno) {
++ if (dr6 & (1 << breakno) &&
++ (breakinfo[breakno].type == 0)) {
++ /* Set restore flag */
++ regs.eflags |= 0x10000;
++ break;
++ }
++ }
++ }
++ correct_hw_break();
++ asm volatile ("movl %0, %%db6\n"::"r" (0));
++ goto exit_kgdb;
++
++ /* kill the program */
++ case 'k': /* do nothing */
++ break;
++
++ /* query */
++ case 'q':
++ nothreads = 0;
++ switch (remcomInBuffer[1]) {
++ case 'f':
++ threadid = 1;
++ thread_list = 2;
++ thread_list_start = (usethread ? : current);
++ case 's':
++ if (!cmp_str(&remcomInBuffer[2],
++ "ThreadInfo", 10))
++ break;
++
++ remcomOutBuffer[nothreads++] = 'm';
++ for (; threadid < PID_MAX + MAX_NO_CPUS;
++ threadid++) {
++ thread = getthread(threadid);
++ if (thread) {
++ nothreads += int_to_hex_v(
++ &remcomOutBuffer[
++ nothreads],
++ threadid);
++ if (thread_min > threadid)
++ thread_min = threadid;
++ remcomOutBuffer[
++ nothreads] = ',';
++ nothreads++;
++ if (nothreads > BUFMAX - 10)
++ break;
++ }
++ }
++ if (remcomOutBuffer[nothreads - 1] == 'm') {
++ remcomOutBuffer[nothreads - 1] = 'l';
++ } else {
++ nothreads--;
++ }
++ remcomOutBuffer[nothreads] = 0;
++ break;
++
++#ifdef old_thread_list /* Old thread info request */
++ case 'L':
++ /* List threads */
++ thread_list = 2;
++ thread_list_start = (usethread ? : current);
++ unpack_byte(remcomInBuffer + 3, &maxthreads);
++ unpack_threadid(remcomInBuffer + 5, &thref);
++ do {
++ int buf_thread_limit =
++ (BUFMAX - 22) / BUF_THREAD_ID_SIZE;
++ if (maxthreads > buf_thread_limit) {
++ maxthreads = buf_thread_limit;
++ }
++ } while (0);
++ remcomOutBuffer[0] = 'q';
++ remcomOutBuffer[1] = 'M';
++ remcomOutBuffer[4] = '0';
++ pack_threadid(remcomOutBuffer + 5, &thref);
++
++ threadid = threadref_to_int(&thref);
++ for (nothreads = 0;
++ nothreads < maxthreads &&
++ threadid < PID_MAX + MAX_NO_CPUS;
++ threadid++) {
++ thread = getthread(threadid);
++ if (thread) {
++ int_to_threadref(&thref,
++ threadid);
++ pack_threadid(remcomOutBuffer +
++ 21 +
++ nothreads * 16,
++ &thref);
++ nothreads++;
++ if (thread_min > threadid)
++ thread_min = threadid;
++ }
++ }
++
++ if (threadid == PID_MAX + MAX_NO_CPUS) {
++ remcomOutBuffer[4] = '1';
++ }
++ pack_hex_byte(remcomOutBuffer + 2, nothreads);
++ remcomOutBuffer[21 + nothreads * 16] = '\0';
++ break;
++#endif
++ case 'C':
++ /* Current thread id */
++ remcomOutBuffer[0] = 'Q';
++ remcomOutBuffer[1] = 'C';
++ threadid = current->pid;
++ if (!threadid) {
++ /*
++ * idle thread
++ */
++ for (threadid = PID_MAX;
++ threadid < PID_MAX + MAX_NO_CPUS;
++ threadid++) {
++ if (current ==
++ idle_task(threadid -
++ PID_MAX))
++ break;
++ }
++ }
++ int_to_threadref(&thref, threadid);
++ pack_threadid(remcomOutBuffer + 2, &thref);
++ remcomOutBuffer[18] = '\0';
++ break;
++
++ case 'E':
++ /* Print exception info */
++ printexceptioninfo(exceptionVector,
++ err_code, remcomOutBuffer);
++ break;
++ case 'T':{
++ char * nptr;
++ /* Thread extra info */
++ if (!cmp_str(&remcomInBuffer[2],
++ "hreadExtraInfo,", 15)) {
++ break;
++ }
++ ptr = &remcomInBuffer[17];
++ hexToInt(&ptr, &threadid);
++ thread = getthread(threadid);
++ nptr = &thread->comm[0];
++ length = 0;
++ ptr = &remcomOutBuffer[0];
++ do {
++ length++;
++ ptr = pack_hex_byte(ptr, *nptr++);
++ } while (*nptr && length < 16);
++ /*
++ * would like that 16 to be the size of
++ * task_struct.comm but don't know the
++ * syntax..
++ */
++ *ptr = 0;
++ }
++ }
++ break;
++
++ /* task related */
++ case 'H':
++ switch (remcomInBuffer[1]) {
++ case 'g':
++ ptr = &remcomInBuffer[2];
++ hexToInt(&ptr, &threadid);
++ thread = getthread(threadid);
++ if (!thread) {
++ remcomOutBuffer[0] = 'E';
++ remcomOutBuffer[1] = '\0';
++ break;
++ }
++ /*
++ * Just in case I forget what this is all about,
++ * the "thread info" command to gdb causes it
++ * to ask for a thread list. It then switches
++ * to each thread and asks for the registers.
++ * For this (and only this) usage, we want to
++ * fudge the registers of tasks not on the run
++ * list (i.e. waiting) to show the routine that
++ * called schedule. Also, gdb, is a minimalist
++ * in that if the current thread is the last
++ * it will not re-read the info when done.
++ * This means that in this case we must show
++ * the real registers. So here is how we do it:
++ * Each entry we keep track of the min
++ * thread in the list (the last that gdb will)
++ * get info for. We also keep track of the
++ * starting thread.
++ * "thread_list" is cleared when switching back
++ * to the min thread if it is was current, or
++ * if it was not current, thread_list is set
++ * to 1. When the switch to current comes,
++ * if thread_list is 1, clear it, else do
++ * nothing.
++ */
++ usethread = thread;
++ if ((thread_list == 1) &&
++ (thread == thread_list_start)) {
++ thread_list = 0;
++ }
++ if (thread_list && (threadid == thread_min)) {
++ if (thread == thread_list_start) {
++ thread_list = 0;
++ } else {
++ thread_list = 1;
++ }
++ }
++ /* follow through */
++ case 'c':
++ remcomOutBuffer[0] = 'O';
++ remcomOutBuffer[1] = 'K';
++ remcomOutBuffer[2] = '\0';
++ break;
++ }
++ break;
++
++ /* Query thread status */
++ case 'T':
++ ptr = &remcomInBuffer[1];
++ hexToInt(&ptr, &threadid);
++ thread = getthread(threadid);
++ if (thread) {
++ remcomOutBuffer[0] = 'O';
++ remcomOutBuffer[1] = 'K';
++ remcomOutBuffer[2] = '\0';
++ if (thread_min > threadid)
++ thread_min = threadid;
++ } else {
++ remcomOutBuffer[0] = 'E';
++ remcomOutBuffer[1] = '\0';
++ }
++ break;
++
++ case 'Y': /* set up a hardware breakpoint */
++ ptr = &remcomInBuffer[1];
++ hexToInt(&ptr, &breakno);
++ ptr++;
++ hexToInt(&ptr, &breaktype);
++ ptr++;
++ hexToInt(&ptr, &length);
++ ptr++;
++ hexToInt(&ptr, &addr);
++ if (set_hw_break(breakno & 0x3,
++ breaktype & 0x3,
++ length & 0x3, addr) == 0) {
++ strcpy(remcomOutBuffer, "OK");
++ } else {
++ strcpy(remcomOutBuffer, "ERROR");
++ }
++ break;
++
++ /* Remove hardware breakpoint */
++ case 'y':
++ ptr = &remcomInBuffer[1];
++ hexToInt(&ptr, &breakno);
++ if (remove_hw_break(breakno & 0x3) == 0) {
++ strcpy(remcomOutBuffer, "OK");
++ } else {
++ strcpy(remcomOutBuffer, "ERROR");
++ }
++ break;
++
++ case 'r': /* reboot */
++ strcpy(remcomOutBuffer, "OK");
++ putpacket(remcomOutBuffer);
++ /*to_gdb("Rebooting\n"); */
++ /* triplefault no return from here */
++ {
++ static long no_idt[2];
++ __asm__ __volatile__("lidt %0"::"m"(no_idt[0]));
++ BREAKPOINT;
++ }
++
++ } /* switch */
++
++ /* reply to the request */
++ putpacket(remcomOutBuffer);
++ } /* while(1==1) */
++ /*
++ * reached by goto only.
++ */
++ exit_kgdb:
++ /*
++ * Here is where we set up to trap a gdb function call. NEW_esp
++ * will be changed if we are trying to do this. We handle both
++ * adding and subtracting, thus allowing gdb to put grung on
++ * the stack which it removes later.
++ */
++ if (NEW_esp != OLD_esp) {
++ int *ptr = END_OF_LOOKASIDE;
++ if (NEW_esp < OLD_esp)
++ ptr -= (OLD_esp - NEW_esp) / sizeof (int);
++ *--ptr = linux_regs->eflags;
++ *--ptr = linux_regs->xcs;
++ *--ptr = linux_regs->eip;
++ *--ptr = linux_regs->ecx;
++ *--ptr = linux_regs->ebx;
++ *--ptr = linux_regs->eax;
++ linux_regs->ecx = NEW_esp - (sizeof (int) * 6);
++ linux_regs->ebx = (unsigned int) END_OF_LOOKASIDE;
++ if (NEW_esp < OLD_esp) {
++ linux_regs->eip = (unsigned int) fn_call_stub;
++ } else {
++ linux_regs->eip = (unsigned int) fn_rtn_stub;
++ linux_regs->eax = NEW_esp;
++ }
++ linux_regs->eflags &= ~(IF_BIT | TF_BIT);
++ }
++#ifdef CONFIG_SMP
++ /*
++ * Release gdb wait locks
++ * Sanity check time. Must have at least one cpu to run. Also single
++ * step must not be done if the current cpu is on hold.
++ */
++ if (spinlock_count == 1) {
++ int ss_hold = (regs.eflags & 0x100) && kgdb_info.hold_on_sstep;
++ int cpu_avail = 0;
++ int i;
++
++ for (i = 0; i < MAX_NO_CPUS; i++) {
++ if (!cpu_online(i))
++ break;
++ if (!hold_cpu(i)) {
++ cpu_avail = 1;
++ }
++ }
++ /*
++ * Early in the bring up there will be NO cpus on line...
++ */
++ if (!cpu_avail && !cpus_empty(cpu_online_map)) {
++ to_gdb("No cpus unblocked, see 'kgdb_info.hold_cpu'\n");
++ goto once_again;
++ }
++ if (hold_cpu(smp_processor_id()) && (regs.eflags & 0x100)) {
++ to_gdb
++ ("Current cpu must be unblocked to single step\n");
++ goto once_again;
++ }
++ if (!(ss_hold)) {
++ int i;
++ for (i = 0; i < MAX_NO_CPUS; i++) {
++ if (!hold_cpu(i)) {
++ spin_unlock(&waitlocks[i]);
++ }
++ }
++ } else {
++ spin_unlock(&waitlocks[smp_processor_id()]);
++ }
++ /* Release kgdb spinlock */
++ KGDB_SPIN_UNLOCK(&kgdb_spinlock);
++ /*
++ * If this cpu is on hold, this is where we
++ * do it. Note, the NMI will pull us out of here,
++ * but will return as the above lock is not held.
++ * We will stay here till another cpu releases the lock for us.
++ */
++ spin_unlock_wait(waitlocks + smp_processor_id());
++ kgdb_local_irq_restore(flags);
++ return (0);
++ }
++#if 0
++exit_just_unlock:
++#endif
++#endif
++ /* Release kgdb spinlock */
++ KGDB_SPIN_UNLOCK(&kgdb_spinlock);
++ kgdb_local_irq_restore(flags);
++ return (0);
++}
++
++/* this function is used to set up exception handlers for tracing and
++ * breakpoints.
++ * This function is not needed as the above line does all that is needed.
++ * We leave it for backward compatitability...
++ */
++void
++set_debug_traps(void)
++{
++ /*
++ * linux_debug_hook is defined in traps.c. We store a pointer
++ * to our own exception handler into it.
++
++ * But really folks, every hear of labeled common, an old Fortran
++ * concept. Lots of folks can reference it and it is define if
++ * anyone does. Only one can initialize it at link time. We do
++ * this with the hook. See the statement above. No need for any
++ * executable code and it is ready as soon as the kernel is
++ * loaded. Very desirable in kernel debugging.
++
++ linux_debug_hook = handle_exception ;
++ */
++
++ /* In case GDB is started before us, ack any packets (presumably
++ "$?#xx") sitting there.
++ putDebugChar ('+');
++
++ initialized = 1;
++ */
++}
++
++/* This function will generate a breakpoint exception. It is used at the
++ beginning of a program to sync up with a debugger and can be used
++ otherwise as a quick means to stop program execution and "break" into
++ the debugger. */
++/* But really, just use the BREAKPOINT macro. We will handle the int stuff
++ */
++
++#ifdef later
++/*
++ * possibly we should not go thru the traps.c code at all? Someday.
++ */
++void
++do_kgdb_int3(struct pt_regs *regs, long error_code)
++{
++ kgdb_handle_exception(3, 5, error_code, regs);
++ return;
++}
++#endif
++#undef regs
++#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS
++asmlinkage void
++bad_sys_call_exit(int stuff)
++{
++ struct pt_regs *regs = (struct pt_regs *) &stuff;
++ printk("Sys call %d return with %x preempt_count\n",
++ (int) regs->orig_eax, preempt_count());
++}
++#endif
++#ifdef CONFIG_STACK_OVERFLOW_TEST
++#include <asm/kgdb.h>
++asmlinkage void
++stack_overflow(void)
++{
++#ifdef BREAKPOINT
++ BREAKPOINT;
++#else
++ printk("Kernel stack overflow, looping forever\n");
++#endif
++ while (1) {
++ }
++}
++#endif
++
++#if defined(CONFIG_SMP) || defined(CONFIG_KGDB_CONSOLE)
++char gdbconbuf[BUFMAX];
++
++static void
++kgdb_gdb_message(const char *s, unsigned count)
++{
++ int i;
++ int wcount;
++ char *bufptr;
++ /*
++ * This takes care of NMI while spining out chars to gdb
++ */
++ IF_SMP(in_kgdb_console = 1);
++ gdbconbuf[0] = 'O';
++ bufptr = gdbconbuf + 1;
++ while (count > 0) {
++ if ((count << 1) > (BUFMAX - 2)) {
++ wcount = (BUFMAX - 2) >> 1;
++ } else {
++ wcount = count;
++ }
++ count -= wcount;
++ for (i = 0; i < wcount; i++) {
++ bufptr = pack_hex_byte(bufptr, s[i]);
++ }
++ *bufptr = '\0';
++ s += wcount;
++
++ putpacket(gdbconbuf);
++
++ }
++ IF_SMP(in_kgdb_console = 0);
++}
++#endif
++#ifdef CONFIG_SMP
++static void
++to_gdb(const char *s)
++{
++ int count = 0;
++ while (s[count] && (count++ < BUFMAX)) ;
++ kgdb_gdb_message(s, count);
++}
++#endif
++#ifdef CONFIG_KGDB_CONSOLE
++#include <linux/console.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++#include <asm/semaphore.h>
++
++void
++kgdb_console_write(struct console *co, const char *s, unsigned count)
++{
++
++ if (gdb_i386vector == -1) {
++ /*
++ * We have not yet talked to gdb. What to do...
++ * lets break, on continue we can do the write.
++ * But first tell him whats up. Uh, well no can do,
++ * as this IS the console. Oh well...
++ * We do need to wait or the messages will be lost.
++ * Other option would be to tell the above code to
++ * ignore this breakpoint and do an auto return,
++ * but that might confuse gdb. Also this happens
++ * early enough in boot up that we don't have the traps
++ * set up yet, so...
++ */
++ breakpoint();
++ }
++ kgdb_gdb_message(s, count);
++}
++
++/*
++ * ------------------------------------------------------------
++ * Serial KGDB driver
++ * ------------------------------------------------------------
++ */
++
++static struct console kgdbcons = {
++ name:"kgdb",
++ write:kgdb_console_write,
++#ifdef CONFIG_KGDB_USER_CONSOLE
++ device:kgdb_console_device,
++#endif
++ flags:CON_PRINTBUFFER | CON_ENABLED,
++ index:-1,
++};
++
++/*
++ * The trick here is that this file gets linked before printk.o
++ * That means we get to peer at the console info in the command
++ * line before it does. If we are up, we register, otherwise,
++ * do nothing. By returning 0, we allow printk to look also.
++ */
++static int kgdb_console_enabled;
++
++int __init
++kgdb_console_init(char *str)
++{
++ if ((strncmp(str, "kgdb", 4) == 0) || (strncmp(str, "gdb", 3) == 0)) {
++ register_console(&kgdbcons);
++ kgdb_console_enabled = 1;
++ }
++ return 0; /* let others look at the string */
++}
++
++__setup("console=", kgdb_console_init);
++
++#ifdef CONFIG_KGDB_USER_CONSOLE
++static kdev_t kgdb_console_device(struct console *c);
++/* This stuff sort of works, but it knocks out telnet devices
++ * we are leaving it here in case we (or you) find time to figure it out
++ * better..
++ */
++
++/*
++ * We need a real char device as well for when the console is opened for user
++ * space activities.
++ */
++
++static int
++kgdb_consdev_open(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static ssize_t
++kgdb_consdev_write(struct file *file, const char *buf,
++ size_t count, loff_t * ppos)
++{
++ int size, ret = 0;
++ static char kbuf[128];
++ static DECLARE_MUTEX(sem);
++
++ /* We are not reentrant... */
++ if (down_interruptible(&sem))
++ return -ERESTARTSYS;
++
++ while (count > 0) {
++ /* need to copy the data from user space */
++ size = count;
++ if (size > sizeof (kbuf))
++ size = sizeof (kbuf);
++ if (copy_from_user(kbuf, buf, size)) {
++ ret = -EFAULT;
++ break;;
++ }
++ kgdb_console_write(&kgdbcons, kbuf, size);
++ count -= size;
++ ret += size;
++ buf += size;
++ }
++
++ up(&sem);
++
++ return ret;
++}
++
++struct file_operations kgdb_consdev_fops = {
++ open:kgdb_consdev_open,
++ write:kgdb_consdev_write
++};
++static kdev_t
++kgdb_console_device(struct console *c)
++{
++ return MKDEV(TTYAUX_MAJOR, 1);
++}
++
++/*
++ * This routine gets called from the serial stub in the i386/lib
++ * This is so it is done late in bring up (just before the console open).
++ */
++void
++kgdb_console_finit(void)
++{
++ if (kgdb_console_enabled) {
++ char *cptr = cdevname(MKDEV(TTYAUX_MAJOR, 1));
++ char *cp = cptr;
++ while (*cptr && *cptr != '(')
++ cptr++;
++ *cptr = 0;
++ unregister_chrdev(TTYAUX_MAJOR, cp);
++ register_chrdev(TTYAUX_MAJOR, "kgdb", &kgdb_consdev_fops);
++ }
++}
++#endif
++#endif
++#ifdef CONFIG_KGDB_TS
++#include <asm/msr.h> /* time stamp code */
++#include <asm/hardirq.h> /* in_interrupt */
++#ifdef CONFIG_KGDB_TS_64
++#define DATA_POINTS 64
++#endif
++#ifdef CONFIG_KGDB_TS_128
++#define DATA_POINTS 128
++#endif
++#ifdef CONFIG_KGDB_TS_256
++#define DATA_POINTS 256
++#endif
++#ifdef CONFIG_KGDB_TS_512
++#define DATA_POINTS 512
++#endif
++#ifdef CONFIG_KGDB_TS_1024
++#define DATA_POINTS 1024
++#endif
++#ifndef DATA_POINTS
++#define DATA_POINTS 128 /* must be a power of two */
++#endif
++#define INDEX_MASK (DATA_POINTS - 1)
++#if (INDEX_MASK & DATA_POINTS)
++#error "CONFIG_KGDB_TS_COUNT must be a power of 2"
++#endif
++struct kgdb_and_then_struct {
++#ifdef CONFIG_SMP
++ int on_cpu;
++#endif
++ struct task_struct *task;
++ long long at_time;
++ int from_ln;
++ char *in_src;
++ void *from;
++ int *with_shpf;
++ int data0;
++ int data1;
++};
++struct kgdb_and_then_struct2 {
++#ifdef CONFIG_SMP
++ int on_cpu;
++#endif
++ struct task_struct *task;
++ long long at_time;
++ int from_ln;
++ char *in_src;
++ void *from;
++ int *with_shpf;
++ struct task_struct *t1;
++ struct task_struct *t2;
++};
++struct kgdb_and_then_struct kgdb_data[DATA_POINTS];
++
++struct kgdb_and_then_struct *kgdb_and_then = &kgdb_data[0];
++int kgdb_and_then_count;
++
++void
++kgdb_tstamp(int line, char *source, int data0, int data1)
++{
++ static spinlock_t ts_spin = SPIN_LOCK_UNLOCKED;
++ int flags;
++ kgdb_local_irq_save(flags);
++ spin_lock(&ts_spin);
++ rdtscll(kgdb_and_then->at_time);
++#ifdef CONFIG_SMP
++ kgdb_and_then->on_cpu = smp_processor_id();
++#endif
++ kgdb_and_then->task = current;
++ kgdb_and_then->from_ln = line;
++ kgdb_and_then->in_src = source;
++ kgdb_and_then->from = __builtin_return_address(0);
++ kgdb_and_then->with_shpf = (int *) (((flags & IF_BIT) >> 9) |
++ (preempt_count() << 8));
++ kgdb_and_then->data0 = data0;
++ kgdb_and_then->data1 = data1;
++ kgdb_and_then = &kgdb_data[++kgdb_and_then_count & INDEX_MASK];
++ spin_unlock(&ts_spin);
++ kgdb_local_irq_restore(flags);
++#ifdef CONFIG_PREEMPT
++
++#endif
++ return;
++}
++#endif
++typedef int gdb_debug_hook(int exceptionVector,
++ int signo, int err_code, struct pt_regs *linux_regs);
++gdb_debug_hook *linux_debug_hook = &kgdb_handle_exception; /* histerical reasons... */
++
++static int __init kgdb_opt_kgdbeth(char *str)
++{
++ kgdb_eth = simple_strtoul(str, NULL, 10);
++ return 1;
++}
++
++static int __init kgdb_opt_kgdbeth_remoteip(char *str)
++{
++ kgdb_remoteip = in_aton(str);
++ return 1;
++}
++
++static int __init kgdb_opt_kgdbeth_listenport(char *str)
++{
++ kgdb_listenport = simple_strtoul(str, NULL, 10);
++ kgdb_sendport = kgdb_listenport - 1;
++ return 1;
++}
++
++static int __init parse_hw_addr(char *str, unsigned char *addr)
++{
++ int i;
++ char *p;
++
++ p = str;
++ i = 0;
++ while(1)
++ {
++ unsigned int c;
++
++ sscanf(p, "%x:", &c);
++ addr[i++] = c;
++ while((*p != 0) && (*p != ':')) {
++ p++;
++ }
++ if (*p == 0) {
++ break;
++ }
++ p++;
++ }
++
++ return 1;
++}
++
++static int __init kgdb_opt_kgdbeth_remotemac(char *str)
++{
++ return parse_hw_addr(str, kgdb_remotemac);
++}
++static int __init kgdb_opt_kgdbeth_localmac(char *str)
++{
++ return parse_hw_addr(str, kgdb_localmac);
++}
++
++
++__setup("gdbeth=", kgdb_opt_kgdbeth);
++__setup("gdbeth_remoteip=", kgdb_opt_kgdbeth_remoteip);
++__setup("gdbeth_listenport=", kgdb_opt_kgdbeth_listenport);
++__setup("gdbeth_remotemac=", kgdb_opt_kgdbeth_remotemac);
++__setup("gdbeth_localmac=", kgdb_opt_kgdbeth_localmac);
++
+--- linux-2.6.0-test6/arch/i386/kernel/ldt.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/ldt.c 2003-10-05 00:36:48.000000000 -0700
+@@ -2,7 +2,7 @@
+ * linux/kernel/ldt.c
+ *
+ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+- * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
++ * Copyright (C) 1999, 2003 Ingo Molnar <mingo@redhat.com>
+ */
+
+ #include <linux/errno.h>
+@@ -18,6 +18,8 @@
+ #include <asm/system.h>
+ #include <asm/ldt.h>
+ #include <asm/desc.h>
++#include <linux/highmem.h>
++#include <asm/atomic_kmap.h>
+
+ #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
+ static void flush_ldt(void *null)
+@@ -29,34 +31,31 @@ static void flush_ldt(void *null)
+
+ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+ {
+- void *oldldt;
+- void *newldt;
+- int oldsize;
++ int oldsize, newsize, i;
+
+ if (mincount <= pc->size)
+ return 0;
++ /*
++ * LDT got larger - reallocate if necessary.
++ */
+ oldsize = pc->size;
+ mincount = (mincount+511)&(~511);
+- if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
+- newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
+- else
+- newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
+-
+- if (!newldt)
+- return -ENOMEM;
+-
+- if (oldsize)
+- memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
+- oldldt = pc->ldt;
+- memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
+- pc->ldt = newldt;
+- wmb();
++ newsize = mincount*LDT_ENTRY_SIZE;
++ for (i = 0; i < newsize; i += PAGE_SIZE) {
++ int nr = i/PAGE_SIZE;
++ BUG_ON(i >= 64*1024);
++ if (!pc->ldt_pages[nr]) {
++ pc->ldt_pages[nr] = alloc_page(GFP_HIGHUSER);
++ if (!pc->ldt_pages[nr])
++ return -ENOMEM;
++ clear_highpage(pc->ldt_pages[nr]);
++ }
++ }
+ pc->size = mincount;
+- wmb();
+-
+ if (reload) {
+ #ifdef CONFIG_SMP
+ cpumask_t mask;
++
+ preempt_disable();
+ load_LDT(pc);
+ mask = cpumask_of_cpu(smp_processor_id());
+@@ -67,21 +66,20 @@ static int alloc_ldt(mm_context_t *pc, i
+ load_LDT(pc);
+ #endif
+ }
+- if (oldsize) {
+- if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
+- vfree(oldldt);
+- else
+- kfree(oldldt);
+- }
+ return 0;
+ }
+
+ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+ {
+- int err = alloc_ldt(new, old->size, 0);
+- if (err < 0)
++ int i, err, size = old->size, nr_pages = (size*LDT_ENTRY_SIZE + PAGE_SIZE-1)/PAGE_SIZE;
++
++ err = alloc_ldt(new, size, 0);
++ if (err < 0) {
++ new->size = 0;
+ return err;
+- memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
++ }
++ for (i = 0; i < nr_pages; i++)
++ copy_user_highpage(new->ldt_pages[i], old->ldt_pages[i], 0);
+ return 0;
+ }
+
+@@ -96,6 +94,7 @@ int init_new_context(struct task_struct
+
+ init_MUTEX(&mm->context.sem);
+ mm->context.size = 0;
++ memset(mm->context.ldt_pages, 0, sizeof(struct page *) * MAX_LDT_PAGES);
+ old_mm = current->mm;
+ if (old_mm && old_mm->context.size > 0) {
+ down(&old_mm->context.sem);
+@@ -107,23 +106,21 @@ int init_new_context(struct task_struct
+
+ /*
+ * No need to lock the MM as we are the last user
++ * Do not touch the ldt register, we are already
++ * in the next thread.
+ */
+ void destroy_context(struct mm_struct *mm)
+ {
+- if (mm->context.size) {
+- if (mm == current->active_mm)
+- clear_LDT();
+- if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
+- vfree(mm->context.ldt);
+- else
+- kfree(mm->context.ldt);
+- mm->context.size = 0;
+- }
++ int i, nr_pages = (mm->context.size*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
++
++ for (i = 0; i < nr_pages; i++)
++ __free_page(mm->context.ldt_pages[i]);
++ mm->context.size = 0;
+ }
+
+ static int read_ldt(void __user * ptr, unsigned long bytecount)
+ {
+- int err;
++ int err, i;
+ unsigned long size;
+ struct mm_struct * mm = current->mm;
+
+@@ -138,8 +135,25 @@ static int read_ldt(void __user * ptr, u
+ size = bytecount;
+
+ err = 0;
+- if (copy_to_user(ptr, mm->context.ldt, size))
+- err = -EFAULT;
++ /*
++ * This is necessary just in case we got here straight from a
++ * context-switch where the ptes were set but no tlb flush
++ * was done yet. We rather avoid doing a TLB flush in the
++ * context-switch path and do it here instead.
++ */
++ __flush_tlb_global();
++
++ for (i = 0; i < size; i += PAGE_SIZE) {
++ int nr = i / PAGE_SIZE, bytes;
++ char *kaddr = kmap(mm->context.ldt_pages[nr]);
++
++ bytes = size - i;
++ if (bytes > PAGE_SIZE)
++ bytes = PAGE_SIZE;
++ if (copy_to_user(ptr + i, kaddr, size - i))
++ err = -EFAULT;
++ kunmap(mm->context.ldt_pages[nr]);
++ }
+ up(&mm->context.sem);
+ if (err < 0)
+ return err;
+@@ -158,7 +172,7 @@ static int read_default_ldt(void __user
+
+ err = 0;
+ address = &default_ldt[0];
+- size = 5*sizeof(struct desc_struct);
++ size = 5*LDT_ENTRY_SIZE;
+ if (size > bytecount)
+ size = bytecount;
+
+@@ -200,7 +214,15 @@ static int write_ldt(void __user * ptr,
+ goto out_unlock;
+ }
+
+- lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
++ /*
++ * No rescheduling allowed from this point to the install.
++ *
++ * We do a TLB flush for the same reason as in the read_ldt() path.
++ */
++ preempt_disable();
++ __flush_tlb_global();
++ lp = (__u32 *) ((ldt_info.entry_number << 3) +
++ (char *) __kmap_atomic_vaddr(KM_LDT_PAGE0));
+
+ /* Allow LDTs to be cleared by the user. */
+ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+@@ -221,6 +243,7 @@ install:
+ *lp = entry_1;
+ *(lp+1) = entry_2;
+ error = 0;
++ preempt_enable();
+
+ out_unlock:
+ up(&mm->context.sem);
+@@ -248,3 +271,26 @@ asmlinkage int sys_modify_ldt(int func,
+ }
+ return ret;
+ }
++
++/*
++ * load one particular LDT into the current CPU
++ */
++void load_LDT_nolock(mm_context_t *pc, int cpu)
++{
++ struct page **pages = pc->ldt_pages;
++ int count = pc->size;
++ int nr_pages, i;
++
++ if (likely(!count)) {
++ pages = &default_ldt_page;
++ count = 5;
++ }
++ nr_pages = (count*LDT_ENTRY_SIZE + PAGE_SIZE-1) / PAGE_SIZE;
++
++ for (i = 0; i < nr_pages; i++) {
++ __kunmap_atomic_type(KM_LDT_PAGE0 - i);
++ __kmap_atomic(pages[i], KM_LDT_PAGE0 - i);
++ }
++ set_ldt_desc(cpu, (void *)__kmap_atomic_vaddr(KM_LDT_PAGE0), count);
++ load_LDT_desc();
++}
+--- linux-2.6.0-test6/arch/i386/kernel/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/Makefile 2003-10-05 00:36:48.000000000 -0700
+@@ -7,13 +7,14 @@ extra-y := head.o init_task.o vmlinux.ld
+ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
+ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
+ pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
+- doublefault.o
++ doublefault.o efi.o efi_stub.o entry_trampoline.o
+
+ obj-y += cpu/
+ obj-y += timers/
+ obj-$(CONFIG_ACPI_BOOT) += acpi/
+ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o
+ obj-$(CONFIG_MCA) += mca.o
++obj-$(CONFIG_KGDB) += kgdb_stub.o
+ obj-$(CONFIG_X86_MSR) += msr.o
+ obj-$(CONFIG_X86_CPUID) += cpuid.o
+ obj-$(CONFIG_MICROCODE) += microcode.o
+--- linux-2.6.0-test6/arch/i386/kernel/mca.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/mca.c 2003-10-05 00:36:10.000000000 -0700
+@@ -132,7 +132,9 @@ struct resource mca_standard_resources[]
+ #define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource))
+
+ /**
+- * mca_read_pos - read the POS registers into a memory buffer
++ * mca_read_and_store_pos - read the POS registers into a memory buffer
++ * @pos: a char pointer to 8 bytes, contains the POS register value on
++ * successful return
+ *
+ * Returns 1 if a card actually exists (i.e. the pos isn't
+ * all 0xff) or 0 otherwise
+--- linux-2.6.0-test6/arch/i386/kernel/mpparse.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/mpparse.c 2003-10-05 00:36:48.000000000 -0700
+@@ -169,7 +169,7 @@ void __init MP_processor_info (struct mp
+
+ if (num_processors >= NR_CPUS) {
+ printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot "
+- "boot CPU(apicid 0x%d).\n", NR_CPUS, m->mpc_apicid);
++ "boot CPU(apicid 0x%x).\n", NR_CPUS, m->mpc_apicid);
+ return;
+ }
+ num_processors++;
+@@ -616,6 +616,31 @@ static inline void __init construct_defa
+ }
+ }
+
++#ifdef CONFIG_X86_IO_APIC
++/* irq_vector must be have an entry for all RTEs of all I/O APICs. */
++void __init alloc_irq_vector_array(void)
++{
++ int total = 0;
++ int idx;
++ union IO_APIC_reg_01 reg_01;
++
++ /* The I/O APIC fixmaps aren't inited yet, so use the first one. */
++ for (idx = 0; idx < nr_ioapics; idx++) {
++ set_fixmap_nocache(FIX_IO_APIC_BASE_0, mp_ioapics[idx].mpc_apicaddr);
++ reg_01.raw = io_apic_read(0, 1);
++ total += reg_01.bits.entries + 1;
++ }
++
++ /* Always alloc at least NR_IRQS vectors. */
++ nr_irqs = max(total, NR_IRQS);
++ irq_vector = (u8 *) alloc_bootmem(nr_irqs);
++ memset(irq_vector, 0, nr_irqs);
++ irq_vector[0] = FIRST_DEVICE_VECTOR;
++}
++#else
++void __init alloc_irq_vector_array(void) { }
++#endif /* CONFIG_X86_IO_APIC */
++
+ static struct intel_mp_floating *mpf_found;
+
+ /*
+@@ -633,6 +658,7 @@ void __init get_smp_config (void)
+ */
+ if (acpi_lapic && acpi_ioapic) {
+ printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
++ alloc_irq_vector_array();
+ return;
+ }
+ else if (acpi_lapic)
+@@ -661,10 +687,11 @@ void __init get_smp_config (void)
+ * Read the physical hardware table. Anything here will
+ * override the defaults.
+ */
+- if (!smp_read_mpc((void *)mpf->mpf_physptr)) {
++ if (!smp_read_mpc((void *)phys_to_virt(mpf->mpf_physptr))) {
+ smp_found_config = 0;
+ printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
+ printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
++ alloc_irq_vector_array();
+ return;
+ }
+ /*
+@@ -688,6 +715,7 @@ void __init get_smp_config (void)
+ } else
+ BUG();
+
++ alloc_irq_vector_array();
+ printk(KERN_INFO "Processors: %d\n", num_processors);
+ /*
+ * Only use the first configuration found.
+@@ -830,7 +858,7 @@ void __init mp_register_lapic (
+ MP_processor_info(&processor);
+ }
+
+-#ifdef CONFIG_X86_IO_APIC
++#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
+
+ #define MP_ISA_BUS 0
+ #define MP_MAX_IOAPIC_PIN 127
+@@ -1019,10 +1047,6 @@ void __init mp_config_acpi_legacy_irqs (
+ }
+ }
+
+-#ifdef CONFIG_ACPI
+-
+-/* Ensure the ACPI SCI interrupt level is active low, edge-triggered */
+-
+ extern FADT_DESCRIPTOR acpi_fadt;
+
+ void __init mp_config_ioapic_for_sci(int irq)
+@@ -1031,6 +1055,7 @@ void __init mp_config_ioapic_for_sci(int
+ int ioapic_pin;
+ struct acpi_table_madt *madt;
+ struct acpi_table_int_src_ovr *entry = NULL;
++ acpi_interrupt_flags flags;
+ void *madt_end;
+ acpi_status status;
+
+@@ -1049,32 +1074,37 @@ void __init mp_config_ioapic_for_sci(int
+
+ while ((void *) entry < madt_end) {
+ if (entry->header.type == ACPI_MADT_INT_SRC_OVR &&
+- acpi_fadt.sci_int == entry->bus_irq) {
+- /*
+- * See the note at the end of ACPI 2.0b section
+- * 5.2.10.8 for what this is about.
+- */
+- if (entry->bus_irq != entry->global_irq) {
+- acpi_fadt.sci_int = entry->global_irq;
+- irq = entry->global_irq;
+- break;
+- }
+- else
+- return;
+- }
+-
++ acpi_fadt.sci_int == entry->bus_irq)
++ goto found;
++
+ entry = (struct acpi_table_int_src_ovr *)
+ ((unsigned long) entry + entry->header.length);
+ }
+ }
++ /*
++ * Although the ACPI spec says that the SCI should be level/low
++ * don't reprogram it unless there is an explicit MADT OVR entry
++ * instructing us to do so -- otherwise we break Tyan boards which
++ * have the SCI wired edge/high but no MADT OVR.
++ */
++ return;
++
++found:
++ /*
++ * See the note at the end of ACPI 2.0b section
++ * 5.2.10.8 for what this is about.
++ */
++ flags = entry->flags;
++ acpi_fadt.sci_int = entry->global_irq;
++ irq = entry->global_irq;
+
+ ioapic = mp_find_ioapic(irq);
+
+ ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
+
+- io_apic_set_pci_routing(ioapic, ioapic_pin, irq, 1, 1); // Active low, level triggered
++ io_apic_set_pci_routing(ioapic, ioapic_pin, irq,
++ (flags.trigger >> 1) , (flags.polarity >> 1));
+ }
+-#endif /* CONFIG_ACPI */
+
+ #ifdef CONFIG_ACPI_PCI
+
+@@ -1110,8 +1140,10 @@ void __init mp_parse_prt (void)
+ }
+
+ /* Don't set up the ACPI SCI because it's already set up */
+- if (acpi_fadt.sci_int == irq)
++ if (acpi_fadt.sci_int == irq) {
++ entry->irq = irq; /*we still need to set entry's irq*/
+ continue;
++ }
+
+ ioapic = mp_find_ioapic(irq);
+ if (ioapic < 0)
+@@ -1136,15 +1168,19 @@ void __init mp_parse_prt (void)
+ if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
+ printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+ mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+- entry->irq = irq;
++ if (use_pci_vector() && !platform_legacy_irq(irq))
++ irq = IO_APIC_VECTOR(irq);
++ entry->irq = irq;
+ continue;
+ }
+
+ mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+
+- if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low))
+- entry->irq = irq;
+-
++ if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low)) {
++ if (use_pci_vector() && !platform_legacy_irq(irq))
++ irq = IO_APIC_VECTOR(irq);
++ entry->irq = irq;
++ }
+ printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
+ entry->id.segment, entry->id.bus,
+ entry->id.device, ('A' + entry->pin),
+@@ -1154,5 +1190,5 @@ void __init mp_parse_prt (void)
+ }
+
+ #endif /*CONFIG_ACPI_PCI*/
+-#endif /* CONFIG_X86_IO_APIC */
++#endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
+ #endif /*CONFIG_ACPI_BOOT*/
+--- linux-2.6.0-test6/arch/i386/kernel/nmi.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/kernel/nmi.c 2003-10-05 00:33:38.000000000 -0700
+@@ -31,7 +31,16 @@
+ #include <asm/mpspec.h>
+ #include <asm/nmi.h>
+
++#ifdef CONFIG_KGDB
++#include <asm/kgdb.h>
++#ifdef CONFIG_SMP
++unsigned int nmi_watchdog = NMI_IO_APIC;
++#else
++unsigned int nmi_watchdog = NMI_LOCAL_APIC;
++#endif
++#else
+ unsigned int nmi_watchdog = NMI_NONE;
++#endif
+ static unsigned int nmi_hz = HZ;
+ unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
+ extern void show_registers(struct pt_regs *regs);
+@@ -408,6 +417,9 @@ void touch_nmi_watchdog (void)
+ for (i = 0; i < NR_CPUS; i++)
+ alert_counter[i] = 0;
+ }
++#ifdef CONFIG_KGDB
++int tune_watchdog = 5*HZ;
++#endif
+
+ void nmi_watchdog_tick (struct pt_regs * regs)
+ {
+@@ -421,12 +433,24 @@ void nmi_watchdog_tick (struct pt_regs *
+
+ sum = irq_stat[cpu].apic_timer_irqs;
+
++#ifdef CONFIG_KGDB
++ if (! in_kgdb(regs) && last_irq_sums[cpu] == sum ) {
++
++#else
+ if (last_irq_sums[cpu] == sum) {
++#endif
+ /*
+ * Ayiee, looks like this CPU is stuck ...
+ * wait a few IRQs (5 seconds) before doing the oops ...
+ */
+ alert_counter[cpu]++;
++#ifdef CONFIG_KGDB
++ if (alert_counter[cpu] == tune_watchdog) {
++ kgdb_handle_exception(2, SIGPWR, 0, regs);
++ last_irq_sums[cpu] = sum;
++ alert_counter[cpu] = 0;
++ }
++#endif
+ if (alert_counter[cpu] == 5*nmi_hz) {
+ spin_lock(&nmi_print_lock);
+ /*
+--- linux-2.6.0-test6/arch/i386/kernel/process.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/process.c 2003-10-05 00:36:48.000000000 -0700
+@@ -47,6 +47,7 @@
+ #include <asm/i387.h>
+ #include <asm/irq.h>
+ #include <asm/desc.h>
++#include <asm/atomic_kmap.h>
+ #ifdef CONFIG_MATH_EMULATION
+ #include <asm/math_emu.h>
+ #endif
+@@ -298,6 +299,9 @@ void flush_thread(void)
+ struct task_struct *tsk = current;
+
+ memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
++#ifdef CONFIG_X86_HIGH_ENTRY
++ clear_thread_flag(TIF_DB7);
++#endif
+ memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+ /*
+ * Forget coprocessor state..
+@@ -311,9 +315,8 @@ void release_thread(struct task_struct *
+ if (dead_task->mm) {
+ // temporary debugging check
+ if (dead_task->mm->context.size) {
+- printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
++ printk("WARNING: dead process %8s still has LDT? <%d>\n",
+ dead_task->comm,
+- dead_task->mm->context.ldt,
+ dead_task->mm->context.size);
+ BUG();
+ }
+@@ -348,7 +351,17 @@ int copy_thread(int nr, unsigned long cl
+ p->thread.esp = (unsigned long) childregs;
+ p->thread.esp0 = (unsigned long) (childregs+1);
+
++ /*
++ * get the two stack pages, for the virtual stack.
++ *
++ * IMPORTANT: this code relies on the fact that the task
++ * structure is an 8K aligned piece of physical memory.
++ */
++ p->thread.stack_page0 = virt_to_page((unsigned long)p->thread_info);
++ p->thread.stack_page1 = virt_to_page((unsigned long)p->thread_info + PAGE_SIZE);
++
+ p->thread.eip = (unsigned long) ret_from_fork;
++ p->thread_info->real_stack = p->thread_info;
+
+ savesegment(fs,p->thread.fs);
+ savesegment(gs,p->thread.gs);
+@@ -500,10 +513,40 @@ struct task_struct * __switch_to(struct
+
+ __unlazy_fpu(prev_p);
+
++#ifdef CONFIG_X86_HIGH_ENTRY
++ /*
++ * Set the ptes of the virtual stack. (NOTE: a one-page TLB flush is
++ * needed because otherwise NMIs could interrupt the
++ * user-return code with a virtual stack and stale TLBs.)
++ */
++ __kunmap_atomic_type(KM_VSTACK0);
++ __kunmap_atomic_type(KM_VSTACK1);
++ __kmap_atomic(next->stack_page0, KM_VSTACK0);
++ __kmap_atomic(next->stack_page1, KM_VSTACK1);
++
++ /*
++ * NOTE: here we rely on the task being the stack as well
++ */
++ next_p->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK0);
++
++#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
++ /*
++ * If next was preempted on entry from userspace to kernel,
++ * and now it's on a different cpu, we need to adjust %esp.
++ * This assumes that entry.S does not copy %esp while on the
++ * virtual stack (with interrupts enabled): which is so,
++ * except within __SWITCH_KERNELSPACE itself.
++ */
++ if (unlikely(next->esp >= TASK_SIZE)) {
++ next->esp &= THREAD_SIZE - 1;
++ next->esp |= (unsigned long) next_p->thread_info->virtual_stack;
++ }
++#endif
++#endif
+ /*
+- * Reload esp0, LDT and the page table pointer:
++ * Reload esp0:
+ */
+- load_esp0(tss, next->esp0);
++ load_esp0(tss, virtual_esp0(next_p));
+
+ /*
+ * Load the per-thread Thread-Local Storage descriptor.
+--- linux-2.6.0-test6/arch/i386/kernel/reboot.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/reboot.c 2003-10-05 00:36:48.000000000 -0700
+@@ -7,6 +7,7 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/mc146818rtc.h>
++#include <linux/efi.h>
+ #include <asm/uaccess.h>
+ #include <asm/apic.h>
+ #include "mach_reboot.h"
+@@ -153,12 +154,11 @@ void machine_real_restart(unsigned char
+ CMOS_WRITE(0x00, 0x8f);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+- /* Remap the kernel at virtual address zero, as well as offset zero
+- from the kernel segment. This assumes the kernel segment starts at
+- virtual address PAGE_OFFSET. */
+-
+- memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+- sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
++ /*
++ * Remap the first 16 MB of RAM (which includes the kernel image)
++ * at virtual address zero:
++ */
++ setup_identity_mappings(swapper_pg_dir, 0, 16*1024*1024);
+
+ /*
+ * Use `swapper_pg_dir' as our page directory.
+@@ -262,7 +262,12 @@ void machine_restart(char * __unused)
+ disable_IO_APIC();
+ #endif
+
+- if(!reboot_thru_bios) {
++ if (!reboot_thru_bios) {
++ if (efi_enabled) {
++ efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, 0);
++ __asm__ __volatile__("lidt %0": :"m" (no_idt));
++ __asm__ __volatile__("int3");
++ }
+ /* rebooting needs to touch the page at absolute addr 0 */
+ *((unsigned short *)__va(0x472)) = reboot_mode;
+ for (;;) {
+@@ -272,6 +277,8 @@ void machine_restart(char * __unused)
+ __asm__ __volatile__("int3");
+ }
+ }
++ if (efi_enabled)
++ efi.reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, 0);
+
+ machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+ }
+@@ -282,6 +289,8 @@ void machine_halt(void)
+
+ void machine_power_off(void)
+ {
++ if (efi_enabled)
++ efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, 0);
+ if (pm_power_off)
+ pm_power_off();
+ }
+--- linux-2.6.0-test6/arch/i386/kernel/setup.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/setup.c 2003-10-05 00:36:22.000000000 -0700
+@@ -36,6 +36,8 @@
+ #include <linux/root_dev.h>
+ #include <linux/highmem.h>
+ #include <linux/module.h>
++#include <linux/efi.h>
++#include <linux/init.h>
+ #include <video/edid.h>
+ #include <asm/e820.h>
+ #include <asm/mpspec.h>
+@@ -56,6 +58,8 @@ static inline char * __init machine_spec
+ * Machine setup..
+ */
+
++int efi_enabled = 0;
++
+ /* cpu data as detected by the assembly code in head.S */
+ struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+ /* common cpu data for all cpus */
+@@ -64,10 +68,10 @@ struct cpuinfo_x86 boot_cpu_data = { 0,
+ unsigned long mmu_cr4_features;
+ EXPORT_SYMBOL_GPL(mmu_cr4_features);
+
+-#ifdef CONFIG_ACPI
+- int acpi_disabled __initdata = 0;
++#ifdef CONFIG_ACPI_INTERPRETER
++ int acpi_disabled = 0;
+ #else
+- int acpi_disabled __initdata = 1;
++ int acpi_disabled = 1;
+ #endif
+ EXPORT_SYMBOL(acpi_disabled);
+
+@@ -144,6 +148,20 @@ static void __init limit_regions (unsign
+ int i;
+ unsigned long long current_size = 0;
+
++ if (efi_enabled) {
++ for (i = 0; i < memmap.nr_map; i++) {
++ current_size = memmap.map[i].phys_addr +
++ (memmap.map[i].num_pages << 12);
++ if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) {
++ if (current_size > size) {
++ memmap.map[i].num_pages -=
++ (((current_size-size) + PAGE_SIZE-1) >> PAGE_SHIFT);
++ memmap.nr_map = i + 1;
++ return;
++ }
++ }
++ }
++ }
+ for (i = 0; i < e820.nr_map; i++) {
+ if (e820.map[i].type == E820_RAM) {
+ current_size += e820.map[i].size;
+@@ -158,17 +176,21 @@ static void __init limit_regions (unsign
+ static void __init add_memory_region(unsigned long long start,
+ unsigned long long size, int type)
+ {
+- int x = e820.nr_map;
++ int x;
+
+- if (x == E820MAX) {
+- printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+- return;
+- }
++ if (!efi_enabled) {
++ x = e820.nr_map;
+
+- e820.map[x].addr = start;
+- e820.map[x].size = size;
+- e820.map[x].type = type;
+- e820.nr_map++;
++ if (x == E820MAX) {
++ printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
++ return;
++ }
++
++ e820.map[x].addr = start;
++ e820.map[x].size = size;
++ e820.map[x].type = type;
++ e820.nr_map++;
++ }
+ } /* add_memory_region */
+
+ #define E820_DEBUG 1
+@@ -445,7 +467,6 @@ static inline void copy_edd(void)
+ static void __init setup_memory_region(void)
+ {
+ char *who = machine_specific_memory_setup();
+-
+ printk(KERN_INFO "BIOS-provided physical RAM map:\n");
+ print_memory_map(who);
+ } /* setup_memory_region */
+@@ -583,6 +604,23 @@ static void __init parse_cmdline_early (
+ }
+
+ /*
++ * Callback for efi_memory_walk.
++ */
++static int __init
++efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
++{
++ unsigned long *max_pfn = arg, pfn;
++
++ if (start < end) {
++ pfn = PFN_UP(end -1);
++ if (pfn > *max_pfn)
++ *max_pfn = pfn;
++ }
++ return 0;
++}
++
++
++/*
+ * Find the highest page frame number we have available
+ */
+ void __init find_max_pfn(void)
+@@ -590,6 +628,11 @@ void __init find_max_pfn(void)
+ int i;
+
+ max_pfn = 0;
++ if (efi_enabled) {
++ efi_memmap_walk(efi_find_max_pfn, &max_pfn);
++ return;
++ }
++
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long start, end;
+ /* RAM? */
+@@ -664,6 +707,25 @@ unsigned long __init find_max_low_pfn(vo
+ }
+
+ #ifndef CONFIG_DISCONTIGMEM
++
++/*
++ * Free all available memory for boot time allocation. Used
++ * as a callback function by efi_memory_walk()
++ */
++
++static int __init
++free_available_memory(unsigned long start, unsigned long end, void *arg)
++{
++ /* check max_low_pfn */
++ if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
++ return 0;
++ if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
++ end = (max_low_pfn + 1) << PAGE_SHIFT;
++ if (start < end)
++ free_bootmem(start, end - start);
++
++ return 0;
++}
+ /*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+@@ -671,6 +733,10 @@ static void __init register_bootmem_low_
+ {
+ int i;
+
++ if (efi_enabled) {
++ efi_memmap_walk(free_available_memory, NULL);
++ return;
++ }
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long curr_pfn, last_pfn, size;
+ /*
+@@ -798,9 +864,9 @@ extern unsigned long setup_memory(void);
+ * Request address space for all standard RAM and ROM resources
+ * and also for regions reported as reserved by the e820.
+ */
+-static void __init register_memory(unsigned long max_low_pfn)
++static void __init
++legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource)
+ {
+- unsigned long low_mem_size;
+ int i;
+
+ probe_roms();
+@@ -825,11 +891,26 @@ static void __init register_memory(unsig
+ * so we try it repeatedly and let the resource manager
+ * test it.
+ */
+- request_resource(res, &code_resource);
+- request_resource(res, &data_resource);
++ request_resource(res, code_resource);
++ request_resource(res, data_resource);
+ }
+ }
++}
++
++/*
++ * Request address space for all standard resources
++ */
++static void __init register_memory(unsigned long max_low_pfn)
++{
++ unsigned long low_mem_size;
++ int i;
+
++ if (efi_enabled)
++ efi_initialize_iomem_resources(&code_resource, &data_resource);
++ else
++ legacy_init_iomem_resources(&code_resource, &data_resource);
++
++ /* EFI systems may still have VGA */
+ request_graphics_resource();
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+@@ -949,6 +1030,13 @@ static int __init noreplacement_setup(ch
+
+ __setup("noreplacement", noreplacement_setup);
+
++/*
++ * Determine if we were loaded by an EFI loader. If so, then we have also been
++ * passed the efi memmap, systab, etc., so we should use these data structures
++ * for initialization. Note, the efi init code path is determined by the
++ * global efi_enabled. This allows the same kernel image to be used on existing
++ * systems (with a traditional BIOS) as well as on EFI systems.
++ */
+ void __init setup_arch(char **cmdline_p)
+ {
+ unsigned long max_low_pfn;
+@@ -957,6 +1045,12 @@ void __init setup_arch(char **cmdline_p)
+ pre_setup_arch_hook();
+ early_cpu_init();
+
++ /* FIXME: This isn't an official loader_type right
++ * now but does currently work with elilo.
++ */
++ if ((LOADER_TYPE == 0x50) && EFI_SYSTAB)
++ efi_enabled = 1;
++
+ ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+ drive_info = DRIVE_INFO;
+ screen_info = SCREEN_INFO;
+@@ -979,7 +1073,11 @@ void __init setup_arch(char **cmdline_p)
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+ #endif
+ ARCH_SETUP
+- setup_memory_region();
++ if (efi_enabled)
++ efi_init();
++ else
++ setup_memory_region();
++
+ copy_edd();
+
+ if (!MOUNT_ROOT_RDONLY)
+@@ -1013,6 +1111,8 @@ void __init setup_arch(char **cmdline_p)
+ #ifdef CONFIG_X86_GENERICARCH
+ generic_apic_probe(*cmdline_p);
+ #endif
++ if (efi_enabled)
++ efi_map_memmap();
+
+ /*
+ * Parse the ACPI tables for possible boot-time SMP configuration.
+@@ -1028,7 +1128,8 @@ void __init setup_arch(char **cmdline_p)
+
+ #ifdef CONFIG_VT
+ #if defined(CONFIG_VGA_CONSOLE)
+- conswitchp = &vga_con;
++ if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
++ conswitchp = &vga_con;
+ #elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+ #endif
+--- linux-2.6.0-test6/arch/i386/kernel/signal.c 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/i386/kernel/signal.c 2003-10-05 00:36:48.000000000 -0700
+@@ -128,25 +128,25 @@ sys_sigaltstack(const stack_t __user *us
+ */
+
+ static int
+-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
++restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *__sc, int *peax)
+ {
+- unsigned int err = 0;
++ struct sigcontext scratch; /* 88 bytes of scratch area */
+
+-#define COPY(x) err |= __get_user(regs->x, &sc->x)
++ if (copy_from_user(&scratch, __sc, sizeof(scratch)))
++ return -EFAULT;
++
++#define COPY(x) regs->x = scratch.x
+
+ #define COPY_SEG(seg) \
+- { unsigned short tmp; \
+- err |= __get_user(tmp, &sc->seg); \
++ { unsigned short tmp = scratch.seg; \
+ regs->x##seg = tmp; }
+
+ #define COPY_SEG_STRICT(seg) \
+- { unsigned short tmp; \
+- err |= __get_user(tmp, &sc->seg); \
++ { unsigned short tmp = scratch.seg; \
+ regs->x##seg = tmp|3; }
+
+ #define GET_SEG(seg) \
+- { unsigned short tmp; \
+- err |= __get_user(tmp, &sc->seg); \
++ { unsigned short tmp = scratch.seg; \
+ loadsegment(seg,tmp); }
+
+ GET_SEG(gs);
+@@ -165,27 +165,23 @@ restore_sigcontext(struct pt_regs *regs,
+ COPY_SEG_STRICT(ss);
+
+ {
+- unsigned int tmpflags;
+- err |= __get_user(tmpflags, &sc->eflags);
++ unsigned int tmpflags = scratch.eflags;
+ regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
+ regs->orig_eax = -1; /* disable syscall checks */
+ }
+
+ {
+- struct _fpstate __user * buf;
+- err |= __get_user(buf, &sc->fpstate);
++ struct _fpstate * buf = scratch.fpstate;
+ if (buf) {
+ if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+- goto badframe;
+- err |= restore_i387(buf);
++ return -EFAULT;
++ if (restore_i387(buf))
++ return -EFAULT;
+ }
+ }
+
+- err |= __get_user(*peax, &sc->eax);
+- return err;
+-
+-badframe:
+- return 1;
++ *peax = scratch.eax;
++ return 0;
+ }
+
+ asmlinkage int sys_sigreturn(unsigned long __unused)
+@@ -263,46 +259,47 @@ badframe:
+ */
+
+ static int
+-setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
++setup_sigcontext(struct sigcontext __user *__sc, struct _fpstate __user *fpstate,
+ struct pt_regs *regs, unsigned long mask)
+ {
+- int tmp, err = 0;
++ struct sigcontext sc; /* 88 bytes of scratch area */
++ int tmp;
+
+ tmp = 0;
+ __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
+- err |= __put_user(tmp, (unsigned int *)&sc->gs);
++ *(unsigned int *)&sc.gs = tmp;
+ __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
+- err |= __put_user(tmp, (unsigned int *)&sc->fs);
+-
+- err |= __put_user(regs->xes, (unsigned int *)&sc->es);
+- err |= __put_user(regs->xds, (unsigned int *)&sc->ds);
+- err |= __put_user(regs->edi, &sc->edi);
+- err |= __put_user(regs->esi, &sc->esi);
+- err |= __put_user(regs->ebp, &sc->ebp);
+- err |= __put_user(regs->esp, &sc->esp);
+- err |= __put_user(regs->ebx, &sc->ebx);
+- err |= __put_user(regs->edx, &sc->edx);
+- err |= __put_user(regs->ecx, &sc->ecx);
+- err |= __put_user(regs->eax, &sc->eax);
+- err |= __put_user(current->thread.trap_no, &sc->trapno);
+- err |= __put_user(current->thread.error_code, &sc->err);
+- err |= __put_user(regs->eip, &sc->eip);
+- err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);
+- err |= __put_user(regs->eflags, &sc->eflags);
+- err |= __put_user(regs->esp, &sc->esp_at_signal);
+- err |= __put_user(regs->xss, (unsigned int *)&sc->ss);
++ *(unsigned int *)&sc.fs = tmp;
++ *(unsigned int *)&sc.es = regs->xes;
++ *(unsigned int *)&sc.ds = regs->xds;
++ sc.edi = regs->edi;
++ sc.esi = regs->esi;
++ sc.ebp = regs->ebp;
++ sc.esp = regs->esp;
++ sc.ebx = regs->ebx;
++ sc.edx = regs->edx;
++ sc.ecx = regs->ecx;
++ sc.eax = regs->eax;
++ sc.trapno = current->thread.trap_no;
++ sc.err = current->thread.error_code;
++ sc.eip = regs->eip;
++ *(unsigned int *)&sc.cs = regs->xcs;
++ sc.eflags = regs->eflags;
++ sc.esp_at_signal = regs->esp;
++ *(unsigned int *)&sc.ss = regs->xss;
+
+ tmp = save_i387(fpstate);
+ if (tmp < 0)
+- err = 1;
+- else
+- err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
++ return 1;
++ sc.fpstate = tmp ? fpstate : NULL;
+
+ /* non-iBCS2 extensions.. */
+- err |= __put_user(mask, &sc->oldmask);
+- err |= __put_user(current->thread.cr2, &sc->cr2);
++ sc.oldmask = mask;
++ sc.cr2 = current->thread.cr2;
+
+- return err;
++ if (copy_to_user(__sc, &sc, sizeof(sc)))
++ return 1;
++ return 0;
+ }
+
+ /*
+@@ -440,7 +437,7 @@ static void setup_rt_frame(int sig, stru
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+- err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
++ err |= __put_user(current->sas_ss_sp, (unsigned long *)&frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->esp),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+--- linux-2.6.0-test6/arch/i386/kernel/smpboot.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/smpboot.c 2003-10-05 00:34:39.000000000 -0700
+@@ -499,8 +499,8 @@ static struct task_struct * __init fork_
+ #ifdef CONFIG_NUMA
+
+ /* which logical CPUs are on which nodes */
+-cpumask_t node_2_cpu_mask[MAX_NR_NODES] =
+- { [0 ... MAX_NR_NODES-1] = CPU_MASK_NONE };
++cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
++ { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
+ /* which node each logical CPU is on */
+ int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
+
+@@ -518,7 +518,7 @@ static inline void unmap_cpu_to_node(int
+ int node;
+
+ printk("Unmapping cpu %d from all nodes\n", cpu);
+- for (node = 0; node < MAX_NR_NODES; node ++)
++ for (node = 0; node < MAX_NUMNODES; node ++)
+ cpu_clear(cpu, node_2_cpu_mask[node]);
+ cpu_2_node[cpu] = -1;
+ }
+@@ -937,6 +937,7 @@ int cpu_sibling_map[NR_CPUS] __cacheline
+ static void __init smp_boot_cpus(unsigned int max_cpus)
+ {
+ int apicid, cpu, bit, kicked;
++ unsigned long bogosum = 0;
+
+ /*
+ * Setup boot CPU information
+@@ -1048,26 +1049,25 @@ static void __init smp_boot_cpus(unsigne
+ /*
+ * Allow the user to impress friends.
+ */
+-
+ Dprintk("Before bogomips.\n");
+- if (!cpucount) {
+- printk(KERN_ERR "Error: only one processor found.\n");
+- } else {
+- unsigned long bogosum = 0;
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
+- if (cpu_isset(cpu, cpu_callout_map))
+- bogosum += cpu_data[cpu].loops_per_jiffy;
+- printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+- cpucount+1,
+- bogosum/(500000/HZ),
+- (bogosum/(5000/HZ))%100);
+- Dprintk("Before bogocount - setting activated=1.\n");
+- }
++ for (cpu = 0; cpu < NR_CPUS; cpu++)
++ if (cpu_isset(cpu, cpu_callout_map))
++ bogosum += cpu_data[cpu].loops_per_jiffy;
++ printk(KERN_INFO
++ "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
++ cpucount+1,
++ bogosum/(500000/HZ),
++ (bogosum/(5000/HZ))%100);
++
++ Dprintk("Before bogocount - setting activated=1.\n");
+
+ if (smp_b_stepping)
+ printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
+
+- /* Don't taint if we are running SMP kernel on a single non-MP approved Athlon */
++ /*
++ * Don't taint if we are running SMP kernel on a single non-MP
++ * approved Athlon
++ */
+ if (tainted & TAINT_UNSAFE_SMP) {
+ if (cpucount)
+ printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
+--- linux-2.6.0-test6/arch/i386/kernel/smp.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/smp.c 2003-10-05 00:36:48.000000000 -0700
+@@ -327,10 +327,12 @@ asmlinkage void smp_invalidate_interrupt
+
+ if (flush_mm == cpu_tlbstate[cpu].active_mm) {
+ if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
++#ifndef CONFIG_X86_SWITCH_PAGETABLES
+ if (flush_va == FLUSH_ALL)
+ local_flush_tlb();
+ else
+ __flush_tlb_one(flush_va);
++#endif
+ } else
+ leave_mm(cpu);
+ }
+@@ -396,21 +398,6 @@ static void flush_tlb_others(cpumask_t c
+ spin_unlock(&tlbstate_lock);
+ }
+
+-void flush_tlb_current_task(void)
+-{
+- struct mm_struct *mm = current->mm;
+- cpumask_t cpu_mask;
+-
+- preempt_disable();
+- cpu_mask = mm->cpu_vm_mask;
+- cpu_clear(smp_processor_id(), cpu_mask);
+-
+- local_flush_tlb();
+- if (!cpus_empty(cpu_mask))
+- flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
+- preempt_enable();
+-}
+-
+ void flush_tlb_mm (struct mm_struct * mm)
+ {
+ cpumask_t cpu_mask;
+@@ -442,7 +429,10 @@ void flush_tlb_page(struct vm_area_struc
+
+ if (current->active_mm == mm) {
+ if(current->mm)
+- __flush_tlb_one(va);
++#ifndef CONFIG_X86_SWITCH_PAGETABLES
++ __flush_tlb_one(va)
++#endif
++ ;
+ else
+ leave_mm(smp_processor_id());
+ }
+@@ -466,7 +456,17 @@ void flush_tlb_all(void)
+ {
+ on_each_cpu(do_flush_tlb_all, 0, 1, 1);
+ }
+-
++#ifdef CONFIG_KGDB
++/*
++ * By using the NMI code instead of a vector we just sneak thru the
++ * word generator coming out with just what we want. AND it does
++ * not matter if clustered_apic_mode is set or not.
++ */
++void smp_send_nmi_allbutself(void)
++{
++ send_IPI_allbutself(APIC_DM_NMI);
++}
++#endif
+ /*
+ * this function sends a 'reschedule' IPI to another CPU.
+ * it goes straight through and wastes no time serializing
+--- linux-2.6.0-test6/arch/i386/kernel/sysenter.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/kernel/sysenter.c 2003-10-05 00:36:48.000000000 -0700
+@@ -18,13 +18,18 @@
+ #include <asm/msr.h>
+ #include <asm/pgtable.h>
+ #include <asm/unistd.h>
++#include <linux/highmem.h>
+
+ extern asmlinkage void sysenter_entry(void);
+
+ void enable_sep_cpu(void *info)
+ {
+ int cpu = get_cpu();
++#ifdef CONFIG_X86_HIGH_ENTRY
++ struct tss_struct *tss = (struct tss_struct *) __fix_to_virt(FIX_TSS_0) + cpu;
++#else
+ struct tss_struct *tss = init_tss + cpu;
++#endif
+
+ tss->ss1 = __KERNEL_CS;
+ tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
+--- linux-2.6.0-test6/arch/i386/kernel/time.c 2003-09-08 13:58:55.000000000 -0700
++++ 25/arch/i386/kernel/time.c 2003-10-05 00:36:22.000000000 -0700
+@@ -44,6 +44,7 @@
+ #include <linux/module.h>
+ #include <linux/sysdev.h>
+ #include <linux/bcd.h>
++#include <linux/efi.h>
+
+ #include <asm/io.h>
+ #include <asm/smp.h>
+@@ -160,6 +161,37 @@ static int set_rtc_mmss(unsigned long no
+ return retval;
+ }
+
++static int efi_set_rtc_mmss(unsigned long nowtime)
++{
++ int real_seconds, real_minutes;
++ unsigned long flags;
++ efi_status_t status;
++ efi_time_t eft;
++ efi_time_cap_t cap;
++
++ spin_lock_irqsave(&rtc_lock, flags);
++
++ status = efi.get_time(&eft, &cap);
++ if (status != EFI_SUCCESS)
++ panic("Ooops, efitime: can't read time!\n");
++ real_seconds = nowtime % 60;
++ real_minutes = nowtime / 60;
++
++ if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
++ real_minutes += 30;
++ real_minutes %= 60;
++
++ eft.minute = real_minutes;
++ eft.second = real_seconds;
++
++ status = efi.set_time(&eft);
++ if (status != EFI_SUCCESS)
++ panic("Ooops: efitime: can't read time!\n");
++
++ spin_unlock_irqrestore(&rtc_lock, flags);
++ return 0;
++}
++
+ /* last time the cmos clock got updated */
+ static long last_rtc_update;
+
+@@ -212,7 +244,7 @@ static inline void do_timer_interrupt(in
+ >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
+ (xtime.tv_nsec / 1000)
+ <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) {
+- if (set_rtc_mmss(xtime.tv_sec) == 0)
++ if ((efi_enabled && (!efi_set_rtc_mmss(xtime.tv_sec) )) || (set_rtc_mmss(xtime.tv_sec) == 0))
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+@@ -277,6 +309,27 @@ static struct sysdev_class pit_sysclass
+ set_kset_name("pit"),
+ };
+
++/*
++ * This is called before the RT mappings are in place, so we
++ * need to be able to get the time in physical mode.
++ */
++unsigned long efi_get_time(void)
++{
++ efi_status_t status;
++ unsigned long flags;
++ efi_time_t eft;
++ efi_time_cap_t cap;
++
++ spin_lock_irqsave(&rtc_lock, flags);
++ status = phys_efi_get_time(&eft, &cap);
++ if (status != EFI_SUCCESS)
++ printk("Oops: efitime: can't read time status: 0x%lx\n", status);
++
++ spin_unlock_irqrestore(&rtc_lock, flags);
++
++ return mktime(eft.year, eft.month, eft.day, eft.hour, eft.minute, eft.second);
++}
++
+ /* XXX this driverfs stuff should probably go elsewhere later -john */
+ static struct sys_device device_i8253 = {
+ .id = 0,
+@@ -298,7 +351,10 @@ extern void (*late_time_init)(void);
+ /* Duplicate of time_init() below, with hpet_enable part added */
+ void __init hpet_time_init(void)
+ {
+- xtime.tv_sec = get_cmos_time();
++ if (efi_enabled)
++ xtime.tv_sec = efi_get_time();
++ else
++ xtime.tv_sec = get_cmos_time();
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
+ xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+ wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+@@ -324,8 +380,10 @@ void __init time_init(void)
+ return;
+ }
+ #endif
+-
+- xtime.tv_sec = get_cmos_time();
++ if (efi_enabled)
++ xtime.tv_sec = efi_get_time();
++ else
++ xtime.tv_sec = get_cmos_time();
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
+ xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+ wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+--- linux-2.6.0-test6/arch/i386/kernel/traps.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/kernel/traps.c 2003-10-05 00:36:48.000000000 -0700
+@@ -54,12 +54,8 @@
+
+ #include "mach_traps.h"
+
+-asmlinkage int system_call(void);
+-asmlinkage void lcall7(void);
+-asmlinkage void lcall27(void);
+-
+-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+- { 0, 0 }, { 0, 0 } };
++struct desc_struct default_ldt[] __attribute__((__section__(".data.default_ldt"))) = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
++struct page *default_ldt_page;
+
+ /* Do we ignore FPU interrupts ? */
+ char ignore_fpu_irq = 0;
+@@ -91,6 +87,43 @@ asmlinkage void alignment_check(void);
+ asmlinkage void spurious_interrupt_bug(void);
+ asmlinkage void machine_check(void);
+
++#ifdef CONFIG_KGDB
++extern void sysenter_entry(void);
++#include <asm/kgdb.h>
++#include <linux/init.h>
++extern void int3(void);
++extern void debug(void);
++void set_intr_gate(unsigned int n, void *addr);
++static void set_intr_usr_gate(unsigned int n, void *addr);
++/*
++ * Should be able to call this breakpoint() very early in
++ * bring up. Just hard code the call where needed.
++ * The breakpoint() code is here because set_?_gate() functions
++ * are local (static) to trap.c. They need be done only once,
++ * but it does not hurt to do them over.
++ */
++void breakpoint(void)
++{
++ init_entry_mappings();
++ set_intr_usr_gate(3,&int3); /* disable ints on trap */
++ set_intr_gate(1,&debug);
++ set_intr_gate(14,&page_fault);
++
++ BREAKPOINT;
++}
++#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \
++ { \
++ if (!user_mode(regs) ) \
++ { \
++ kgdb_handle_exception(trapnr, signr, error_code, regs); \
++ after; \
++ } else if ((trapnr == 3) && (regs->eflags &0x200)) local_irq_enable(); \
++ }
++#else
++#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after)
++#endif
++
++
+ static int kstack_depth_to_print = 24;
+
+ void show_trace(struct task_struct *task, unsigned long * stack)
+@@ -173,8 +206,9 @@ void show_registers(struct pt_regs *regs
+ ss = regs->xss & 0xffff;
+ }
+ print_modules();
+- printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n",
+- smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
++ printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx\n",
++ smp_processor_id(), 0xffff & regs->xcs,
++ regs->eip, print_tainted(), regs->eflags);
+
+ print_symbol("EIP is at %s\n", regs->eip);
+ printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
+@@ -190,23 +224,27 @@ void show_registers(struct pt_regs *regs
+ * time of the fault..
+ */
+ if (in_kernel) {
++ u8 *eip;
+
+ printk("\nStack: ");
+ show_stack(NULL, (unsigned long*)esp);
+
+ printk("Code: ");
+- if(regs->eip < PAGE_OFFSET)
+- goto bad;
+
+- for(i=0;i<20;i++)
+- {
+- unsigned char c;
+- if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
+-bad:
++ eip = (u8 *)regs->eip - 43;
++ for (i = 0; i < 64; i++, eip++) {
++ unsigned char c = 0xff;
++
++ if ((user_mode(regs) && get_user(c, eip)) ||
++ (!user_mode(regs) && __direct_get_user(c, eip))) {
++
+ printk(" Bad EIP value.");
+ break;
+ }
+- printk("%02x ", c);
++ if (eip == (u8 *)regs->eip)
++ printk("<%02x> ", c);
++ else
++ printk("%02x ", c);
+ }
+ }
+ printk("\n");
+@@ -253,12 +291,36 @@ spinlock_t die_lock = SPIN_LOCK_UNLOCKED
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+ static int die_counter;
++ int nl = 0;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+ handle_BUG(regs);
+ printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
++#ifdef CONFIG_PREEMPT
++ printk("PREEMPT ");
++ nl = 1;
++#endif
++#ifdef CONFIG_SMP
++ printk("SMP ");
++ nl = 1;
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++ printk("DEBUG_PAGEALLOC");
++ nl = 1;
++#endif
++ if (nl)
++ printk("\n");
++#ifdef CONFIG_KGDB
++ /* This is about the only place we want to go to kgdb even if in
++ * user mode. But we must go in via a trap so within kgdb we will
++ * always be in kernel mode.
++ */
++ if (user_mode(regs))
++ BREAKPOINT;
++#endif
++ CHK_REMOTE_DEBUG(0,SIGTRAP,err,regs,)
+ show_registers(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+@@ -328,6 +390,7 @@ static inline void do_trap(int trapnr, i
+ #define DO_ERROR(trapnr, signr, str, name) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
++ CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\
+ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
+ }
+
+@@ -345,7 +408,9 @@ asmlinkage void do_##name(struct pt_regs
+ #define DO_VM86_ERROR(trapnr, signr, str, name) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
++ CHK_REMOTE_DEBUG(trapnr, signr, error_code,regs, return)\
+ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
++ return; \
+ }
+
+ #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+@@ -388,8 +453,10 @@ gp_in_vm86:
+ return;
+
+ gp_in_kernel:
+- if (!fixup_exception(regs))
++ if (!fixup_exception(regs)){
++ CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,)
+ die("general protection fault", regs, error_code);
++ }
+ }
+
+ static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+@@ -528,10 +595,18 @@ asmlinkage void do_debug(struct pt_regs
+ if (regs->eflags & X86_EFLAGS_IF)
+ local_irq_enable();
+
+- /* Mask out spurious debug traps due to lazy DR7 setting */
++ /*
++ * Mask out spurious debug traps due to lazy DR7 setting or
++ * due to 4G/4G kernel mode:
++ */
+ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+ if (!tsk->thread.debugreg[7])
+ goto clear_dr7;
++ if (!user_mode(regs)) {
++ // restore upon return-to-userspace:
++ set_thread_flag(TIF_DB7);
++ goto clear_dr7;
++ }
+ }
+
+ if (regs->eflags & VM_MASK)
+@@ -551,8 +626,18 @@ asmlinkage void do_debug(struct pt_regs
+ * allowing programs to debug themselves without the ptrace()
+ * interface.
+ */
++#ifdef CONFIG_KGDB
++ /*
++ * I think this is the only "real" case of a TF in the kernel
++ * that really belongs to user space. Others are
++ * "Ours all ours!"
++ */
++ if (((regs->xcs & 3) == 0) && ((void *)regs->eip == sysenter_entry))
++ goto clear_TF_reenable;
++#else
+ if ((regs->xcs & 3) == 0)
+ goto clear_TF_reenable;
++#endif
+ if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
+ goto clear_TF;
+ }
+@@ -564,6 +649,17 @@ asmlinkage void do_debug(struct pt_regs
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+
++#ifdef CONFIG_KGDB
++ /*
++ * If this is a kernel mode trap, we need to reset db7 to allow us
++ * to continue sanely ALSO skip the signal delivery
++ */
++ if ((regs->xcs & 3) == 0)
++ goto clear_dr7;
++
++ /* if not kernel, allow ints but only if they were on */
++ if ( regs->eflags & 0x200) local_irq_enable();
++#endif
+ /* If this is a kernel mode trap, save the user PC on entry to
+ * the kernel, that's what the debugger can make sense of.
+ */
+@@ -578,6 +674,7 @@ clear_dr7:
+ __asm__("movl %0,%%db7"
+ : /* no output */
+ : "r" (0));
++ CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,)
+ return;
+
+ debug_vm86:
+@@ -773,19 +870,53 @@ asmlinkage void math_emulate(long arg)
+
+ #endif /* CONFIG_MATH_EMULATION */
+
+-#ifdef CONFIG_X86_F00F_BUG
+-void __init trap_init_f00f_bug(void)
++void __init trap_init_virtual_IDT(void)
+ {
+- __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+-
+ /*
+- * Update the IDT descriptor and reload the IDT so that
+- * it uses the read-only mapped virtual address.
++ * "idt" is magic - it overlaps the idt_descr
++ * variable so that updating idt will automatically
++ * update the idt descriptor..
+ */
+- idt_descr.address = fix_to_virt(FIX_F00F_IDT);
++ __set_fixmap(FIX_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
++ idt_descr.address = __fix_to_virt(FIX_IDT);
++
+ __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ }
++
++void __init trap_init_virtual_GDT(void)
++{
++ int cpu = smp_processor_id();
++ struct Xgt_desc_struct *gdt_desc = cpu_gdt_descr + cpu;
++ struct Xgt_desc_struct tmp_desc = {0, 0};
++ struct tss_struct * t;
++
++ __asm__ __volatile__("sgdt %0": "=m" (tmp_desc): :"memory");
++
++#ifdef CONFIG_X86_HIGH_ENTRY
++ if (!cpu) {
++ __set_fixmap(FIX_GDT_0, __pa(cpu_gdt_table), PAGE_KERNEL);
++ __set_fixmap(FIX_GDT_1, __pa(cpu_gdt_table) + PAGE_SIZE, PAGE_KERNEL);
++ __set_fixmap(FIX_TSS_0, __pa(init_tss), PAGE_KERNEL);
++ __set_fixmap(FIX_TSS_1, __pa(init_tss) + 1*PAGE_SIZE, PAGE_KERNEL);
++ __set_fixmap(FIX_TSS_2, __pa(init_tss) + 2*PAGE_SIZE, PAGE_KERNEL);
++ __set_fixmap(FIX_TSS_3, __pa(init_tss) + 3*PAGE_SIZE, PAGE_KERNEL);
++ }
++
++ gdt_desc->address = __fix_to_virt(FIX_GDT_0) + sizeof(cpu_gdt_table[0]) * cpu;
++#else
++ gdt_desc->address = (unsigned long)cpu_gdt_table[cpu];
++#endif
++ __asm__ __volatile__("lgdt %0": "=m" (*gdt_desc));
++
++#ifdef CONFIG_X86_HIGH_ENTRY
++ t = (struct tss_struct *) __fix_to_virt(FIX_TSS_0) + cpu;
++#else
++ t = init_tss + cpu;
+ #endif
++ set_tss_desc(cpu, t);
++ cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
++ load_TR_desc();
++}
+
+ #define _set_gate(gate_addr,type,dpl,addr,seg) \
+ do { \
+@@ -812,20 +943,26 @@ void set_intr_gate(unsigned int n, void
+ _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
+ }
+
+-static void __init set_trap_gate(unsigned int n, void *addr)
++void __init set_trap_gate(unsigned int n, void *addr)
+ {
+ _set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
+ }
+
+-static void __init set_system_gate(unsigned int n, void *addr)
++void __init set_system_gate(unsigned int n, void *addr)
+ {
+ _set_gate(idt_table+n,15,3,addr,__KERNEL_CS);
+ }
+
+-static void __init set_call_gate(void *a, void *addr)
++void __init set_call_gate(void *a, void *addr)
+ {
+ _set_gate(a,12,3,addr,__KERNEL_CS);
+ }
++#ifdef CONFIG_KGDB
++void set_intr_usr_gate(unsigned int n, void *addr)
++{
++ _set_gate(idt_table+n,14,3,addr,__KERNEL_CS);
++}
++#endif
+
+ static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
+ {
+@@ -844,11 +981,16 @@ void __init trap_init(void)
+ #ifdef CONFIG_X86_LOCAL_APIC
+ init_apic_mappings();
+ #endif
++ init_entry_mappings();
+
+ set_trap_gate(0,÷_error);
+ set_intr_gate(1,&debug);
+ set_intr_gate(2,&nmi);
++#ifndef CONFIG_KGDB
+ set_system_gate(3,&int3); /* int3-5 can be called from all */
++#else
++ set_intr_usr_gate(3,&int3); /* int3-5 can be called from all */
++#endif
+ set_system_gate(4,&overflow);
+ set_system_gate(5,&bounds);
+ set_trap_gate(6,&invalid_op);
+--- linux-2.6.0-test6/arch/i386/kernel/vm86.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/i386/kernel/vm86.c 2003-10-05 00:36:48.000000000 -0700
+@@ -117,7 +117,7 @@ struct pt_regs * save_v86_state(struct k
+
+ tss = init_tss + get_cpu();
+ current->thread.esp0 = current->thread.saved_esp0;
+- load_esp0(tss, current->thread.esp0);
++ load_esp0(tss, virtual_esp0(current));
+ current->thread.saved_esp0 = 0;
+ put_cpu();
+
+@@ -294,7 +294,8 @@ static void do_sys_vm86(struct kernel_vm
+ asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
+
+ tss = init_tss + get_cpu();
+- tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
++ tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
++ tss->esp0 = virtual_esp0(tsk);
+ disable_sysenter(tss);
+ put_cpu();
+
+--- linux-2.6.0-test6/arch/i386/kernel/vmlinux.lds.S 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/kernel/vmlinux.lds.S 2003-10-05 00:36:48.000000000 -0700
+@@ -3,6 +3,9 @@
+ */
+
+ #include <asm-generic/vmlinux.lds.h>
++#include <linux/config.h>
++#include <asm/page.h>
++#include <asm/asm_offsets.h>
+
+ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+ OUTPUT_ARCH(i386)
+@@ -10,7 +13,7 @@ ENTRY(startup_32)
+ jiffies = jiffies_64;
+ SECTIONS
+ {
+- . = 0xC0000000 + 0x100000;
++ . = __PAGE_OFFSET + 0x100000;
+ /* read-only */
+ _text = .; /* Text and read-only data */
+ .text : {
+@@ -19,6 +22,19 @@ SECTIONS
+ *(.gnu.warning)
+ } = 0x9090
+
++#ifdef CONFIG_X86_4G
++ . = ALIGN(PAGE_SIZE_asm);
++ __entry_tramp_start = .;
++ . = FIX_ENTRY_TRAMPOLINE_0_addr;
++ __start___entry_text = .;
++ .entry.text : AT (__entry_tramp_start) { *(.entry.text) }
++ __entry_tramp_end = __entry_tramp_start + SIZEOF(.entry.text);
++ . = __entry_tramp_end;
++ . = ALIGN(PAGE_SIZE_asm);
++#else
++ .entry.text : { *(.entry.text) }
++#endif
++
+ _etext = .; /* End of text section */
+
+ . = ALIGN(16); /* Exception table */
+@@ -34,15 +50,12 @@ SECTIONS
+ CONSTRUCTORS
+ }
+
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE_asm);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE_asm);
+ __nosave_end = .;
+
+- . = ALIGN(4096);
+- .data.page_aligned : { *(.data.idt) }
+-
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+@@ -52,7 +65,7 @@ SECTIONS
+ .data.init_task : { *(.data.init_task) }
+
+ /* will be freed after init */
+- . = ALIGN(4096); /* Init code and data */
++ . = ALIGN(PAGE_SIZE_asm); /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+@@ -91,7 +104,7 @@ SECTIONS
+ from .altinstructions and .eh_frame */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE_asm);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+@@ -99,10 +112,22 @@ SECTIONS
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+- . = ALIGN(4096);
++ . = ALIGN(PAGE_SIZE_asm);
+ __init_end = .;
+ /* freed after init ends here */
+-
++
++ . = ALIGN(PAGE_SIZE_asm);
++ .data.page_aligned_tss : { *(.data.tss) }
++
++ . = ALIGN(PAGE_SIZE_asm);
++ .data.page_aligned_default_ldt : { *(.data.default_ldt) }
++
++ . = ALIGN(PAGE_SIZE_asm);
++ .data.page_aligned_idt : { *(.data.idt) }
++
++ . = ALIGN(PAGE_SIZE_asm);
++ .data.page_aligned_gdt : { *(.data.gdt) }
++
+ __bss_start = .; /* BSS */
+ .bss : { *(.bss) }
+ __bss_stop = .;
+@@ -122,4 +147,6 @@ SECTIONS
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
++
++
+ }
+--- linux-2.6.0-test6/arch/i386/kernel/vsyscall.lds 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/i386/kernel/vsyscall.lds 2003-10-05 00:36:48.000000000 -0700
+@@ -5,7 +5,7 @@
+ */
+
+ /* This must match <asm/fixmap.h>. */
+-VSYSCALL_BASE = 0xffffe000;
++VSYSCALL_BASE = 0xffffd000;
+
+ SECTIONS
+ {
+--- linux-2.6.0-test6/arch/i386/kernel/vsyscall-sysenter.S 2003-06-14 12:18:08.000000000 -0700
++++ 25/arch/i386/kernel/vsyscall-sysenter.S 2003-10-05 00:36:48.000000000 -0700
+@@ -7,6 +7,11 @@
+ .type __kernel_vsyscall,@function
+ __kernel_vsyscall:
+ .LSTART_vsyscall:
++ cmpl $192, %eax
++ jne 1f
++ int $0x80
++ ret
++1:
+ push %ecx
+ .Lpush_ecx:
+ push %edx
+--- linux-2.6.0-test6/arch/i386/lib/checksum.S 2003-06-14 12:18:30.000000000 -0700
++++ 25/arch/i386/lib/checksum.S 2003-10-05 00:36:48.000000000 -0700
+@@ -280,14 +280,14 @@ unsigned int csum_partial_copy_generic (
+ .previous
+
+ .align 4
+-.globl csum_partial_copy_generic
++.globl direct_csum_partial_copy_generic
+
+ #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+ #define ARGBASE 16
+ #define FP 12
+
+-csum_partial_copy_generic:
++direct_csum_partial_copy_generic:
+ subl $4,%esp
+ pushl %edi
+ pushl %esi
+@@ -422,7 +422,7 @@ DST( movb %cl, (%edi) )
+
+ #define ARGBASE 12
+
+-csum_partial_copy_generic:
++direct_csum_partial_copy_generic:
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+--- linux-2.6.0-test6/arch/i386/lib/dec_and_lock.c 2003-06-26 22:07:23.000000000 -0700
++++ 25/arch/i386/lib/dec_and_lock.c 2003-10-05 00:36:40.000000000 -0700
+@@ -10,6 +10,7 @@
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
+
++#ifndef ATOMIC_DEC_AND_LOCK
+ int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+ {
+ int counter;
+@@ -38,3 +39,5 @@ slow_path:
+ spin_unlock(lock);
+ return 0;
+ }
++#endif
++
+--- linux-2.6.0-test6/arch/i386/lib/getuser.S 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/i386/lib/getuser.S 2003-10-05 00:36:48.000000000 -0700
+@@ -9,6 +9,7 @@
+ * return value.
+ */
+ #include <asm/thread_info.h>
++#include <asm/asm_offsets.h>
+
+
+ /*
+@@ -28,7 +29,7 @@
+ .globl __get_user_1
+ __get_user_1:
+ GET_THREAD_INFO(%edx)
+- cmpl TI_ADDR_LIMIT(%edx),%eax
++ cmpl TI_addr_limit(%edx),%eax
+ jae bad_get_user
+ 1: movzbl (%eax),%edx
+ xorl %eax,%eax
+@@ -40,7 +41,7 @@ __get_user_2:
+ addl $1,%eax
+ jc bad_get_user
+ GET_THREAD_INFO(%edx)
+- cmpl TI_ADDR_LIMIT(%edx),%eax
++ cmpl TI_addr_limit(%edx),%eax
+ jae bad_get_user
+ 2: movzwl -1(%eax),%edx
+ xorl %eax,%eax
+@@ -52,7 +53,7 @@ __get_user_4:
+ addl $3,%eax
+ jc bad_get_user
+ GET_THREAD_INFO(%edx)
+- cmpl TI_ADDR_LIMIT(%edx),%eax
++ cmpl TI_addr_limit(%edx),%eax
+ jae bad_get_user
+ 3: movl -3(%eax),%edx
+ xorl %eax,%eax
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/i386/lib/kgdb_serial.c 2003-10-05 00:33:44.000000000 -0700
+@@ -0,0 +1,499 @@
++/*
++ * Serial interface GDB stub
++ *
++ * Written (hacked together) by David Grothe (dave@gcom.com)
++ * Modified to allow invokation early in boot see also
++ * kgdb.h for instructions by George Anzinger(george@mvista.com)
++ * Modified to handle debugging over ethernet by Robert Walsh
++ * <rjwalsh@durables.org> and wangdi <wangdi@clusterfs.com>, based on
++ * code by San Mehat.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/serial_reg.h>
++#include <linux/config.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/highmem.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/segment.h>
++#include <asm/bitops.h>
++#include <asm/system.h>
++#include <asm/kgdb_local.h>
++#ifdef CONFIG_KGDB_USER_CONSOLE
++extern void kgdb_console_finit(void);
++#endif
++#define PRNT_off
++#define TEST_EXISTANCE
++#ifdef PRNT
++#define dbprintk(s) printk s
++#else
++#define dbprintk(s)
++#endif
++#define TEST_INTERRUPT_off
++#ifdef TEST_INTERRUPT
++#define intprintk(s) printk s
++#else
++#define intprintk(s)
++#endif
++
++#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
++
++#define GDB_BUF_SIZE 512 /* power of 2, please */
++
++static char gdb_buf[GDB_BUF_SIZE];
++static int gdb_buf_in_inx;
++static atomic_t gdb_buf_in_cnt;
++static int gdb_buf_out_inx;
++
++struct async_struct *gdb_async_info;
++static int gdb_async_irq;
++
++#define outb_px(a,b) outb_p(b,a)
++
++static void program_uart(struct async_struct *info);
++static void write_char(struct async_struct *info, int chr);
++/*
++ * Get a byte from the hardware data buffer and return it
++ */
++static int
++read_data_bfr(struct async_struct *info)
++{
++ char it = inb_p(info->port + UART_LSR);
++
++ if (it & UART_LSR_DR)
++ return (inb_p(info->port + UART_RX));
++ /*
++ * If we have a framing error assume somebody messed with
++ * our uart. Reprogram it and send '-' both ways...
++ */
++ if (it & 0xc) {
++ program_uart(info);
++ write_char(info, '-');
++ return ('-');
++ }
++ return (-1);
++
++} /* read_data_bfr */
++
++/*
++ * Get a char if available, return -1 if nothing available.
++ * Empty the receive buffer first, then look at the interface hardware.
++
++ * Locking here is a bit of a problem. We MUST not lock out communication
++ * if we are trying to talk to gdb about a kgdb entry. ON the other hand
++ * we can loose chars in the console pass thru if we don't lock. It is also
++ * possible that we could hold the lock or be waiting for it when kgdb
++ * NEEDS to talk. Since kgdb locks down the world, it does not need locks.
++ * We do, of course have possible issues with interrupting a uart operation,
++ * but we will just depend on the uart status to help keep that straight.
++
++ */
++static spinlock_t uart_interrupt_lock = SPIN_LOCK_UNLOCKED;
++#ifdef CONFIG_SMP
++extern spinlock_t kgdb_spinlock;
++#endif
++
++static int
++read_char(struct async_struct *info)
++{
++ int chr;
++ unsigned long flags;
++ local_irq_save(flags);
++#ifdef CONFIG_SMP
++ if (!spin_is_locked(&kgdb_spinlock)) {
++ spin_lock(&uart_interrupt_lock);
++ }
++#endif
++ if (atomic_read(&gdb_buf_in_cnt) != 0) { /* intr routine has q'd chars */
++ chr = gdb_buf[gdb_buf_out_inx++];
++ gdb_buf_out_inx &= (GDB_BUF_SIZE - 1);
++ atomic_dec(&gdb_buf_in_cnt);
++ } else {
++ chr = read_data_bfr(info);
++ }
++#ifdef CONFIG_SMP
++ if (!spin_is_locked(&kgdb_spinlock)) {
++ spin_unlock(&uart_interrupt_lock);
++ }
++#endif
++ local_irq_restore(flags);
++ return (chr);
++}
++
++/*
++ * Wait until the interface can accept a char, then write it.
++ */
++static void
++write_char(struct async_struct *info, int chr)
++{
++ while (!(inb_p(info->port + UART_LSR) & UART_LSR_THRE)) ;
++
++ outb_p(chr, info->port + UART_TX);
++
++} /* write_char */
++
++/*
++ * Mostly we don't need a spinlock, but since the console goes
++ * thru here with interrutps on, well, we need to catch those
++ * chars.
++ */
++/*
++ * This is the receiver interrupt routine for the GDB stub.
++ * It will receive a limited number of characters of input
++ * from the gdb host machine and save them up in a buffer.
++ *
++ * When the gdb stub routine tty_getDebugChar() is called it
++ * draws characters out of the buffer until it is empty and
++ * then reads directly from the serial port.
++ *
++ * We do not attempt to write chars from the interrupt routine
++ * since the stubs do all of that via tty_putDebugChar() which
++ * writes one byte after waiting for the interface to become
++ * ready.
++ *
++ * The debug stubs like to run with interrupts disabled since,
++ * after all, they run as a consequence of a breakpoint in
++ * the kernel.
++ *
++ * Perhaps someone who knows more about the tty driver than I
++ * care to learn can make this work for any low level serial
++ * driver.
++ */
++static irqreturn_t
++gdb_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct async_struct *info;
++ unsigned long flags;
++
++ info = gdb_async_info;
++ if (!info || !info->tty || irq != gdb_async_irq)
++ return IRQ_NONE;
++
++ local_irq_save(flags);
++ spin_lock(&uart_interrupt_lock);
++ do {
++ int chr = read_data_bfr(info);
++ intprintk(("Debug char on int: %x hex\n", chr));
++ if (chr < 0)
++ continue;
++
++ if (chr == 3) { /* Ctrl-C means remote interrupt */
++ BREAKPOINT;
++ continue;
++ }
++
++ if (atomic_read(&gdb_buf_in_cnt) >= GDB_BUF_SIZE) {
++ /* buffer overflow tosses early char */
++ read_char(info);
++ }
++ gdb_buf[gdb_buf_in_inx++] = chr;
++ gdb_buf_in_inx &= (GDB_BUF_SIZE - 1);
++ } while (inb_p(info->port + UART_IIR) & UART_IIR_RDI);
++ spin_unlock(&uart_interrupt_lock);
++ local_irq_restore(flags);
++ return IRQ_HANDLED;
++} /* gdb_interrupt */
++
++/*
++ * Just a NULL routine for testing.
++ */
++void
++gdb_null(void)
++{
++} /* gdb_null */
++
++/* These structure are filled in with values defined in asm/kgdb_local.h
++ */
++static struct serial_state state = SB_STATE;
++static struct async_struct local_info = SB_INFO;
++static int ok_to_enable_ints = 0;
++static void kgdb_enable_ints_now(void);
++
++extern char *kgdb_version;
++/*
++ * Hook an IRQ for KGDB.
++ *
++ * This routine is called from tty_putDebugChar, below.
++ */
++static int ints_disabled = 1;
++int
++gdb_hook_interrupt(struct async_struct *info, int verb)
++{
++ struct serial_state *state = info->state;
++ unsigned long flags;
++ int port;
++#ifdef TEST_EXISTANCE
++ int scratch, scratch2;
++#endif
++
++ /* The above fails if memory managment is not set up yet.
++ * Rather than fail the set up, just keep track of the fact
++ * and pick up the interrupt thing later.
++ */
++ gdb_async_info = info;
++ port = gdb_async_info->port;
++ gdb_async_irq = state->irq;
++ if (verb) {
++ printk("kgdb %s : port =%x, IRQ=%d, divisor =%d\n",
++ kgdb_version,
++ port,
++ gdb_async_irq, gdb_async_info->state->custom_divisor);
++ }
++ local_irq_save(flags);
++#ifdef TEST_EXISTANCE
++ /* Existance test */
++ /* Should not need all this, but just in case.... */
++
++ scratch = inb_p(port + UART_IER);
++ outb_px(port + UART_IER, 0);
++ outb_px(0xff, 0x080);
++ scratch2 = inb_p(port + UART_IER);
++ outb_px(port + UART_IER, scratch);
++ if (scratch2) {
++ printk
++ ("gdb_hook_interrupt: Could not clear IER, not a UART!\n");
++ local_irq_restore(flags);
++ return 1; /* We failed; there's nothing here */
++ }
++ scratch2 = inb_p(port + UART_LCR);
++ outb_px(port + UART_LCR, 0xBF); /* set up for StarTech test */
++ outb_px(port + UART_EFR, 0); /* EFR is the same as FCR */
++ outb_px(port + UART_LCR, 0);
++ outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO);
++ scratch = inb_p(port + UART_IIR) >> 6;
++ if (scratch == 1) {
++ printk("gdb_hook_interrupt: Undefined UART type!"
++ " Not a UART! \n");
++ local_irq_restore(flags);
++ return 1;
++ } else {
++ dbprintk(("gdb_hook_interrupt: UART type "
++ "is %d where 0=16450, 2=16550 3=16550A\n", scratch));
++ }
++ scratch = inb_p(port + UART_MCR);
++ outb_px(port + UART_MCR, UART_MCR_LOOP | scratch);
++ outb_px(port + UART_MCR, UART_MCR_LOOP | 0x0A);
++ scratch2 = inb_p(port + UART_MSR) & 0xF0;
++ outb_px(port + UART_MCR, scratch);
++ if (scratch2 != 0x90) {
++ printk("gdb_hook_interrupt: "
++ "Loop back test failed! Not a UART!\n");
++ local_irq_restore(flags);
++ return scratch2 + 1000; /* force 0 to fail */
++ }
++#endif /* test existance */
++ program_uart(info);
++ local_irq_restore(flags);
++
++ return (0);
++
++} /* gdb_hook_interrupt */
++
++static void
++program_uart(struct async_struct *info)
++{
++ int port = info->port;
++
++ (void) inb_p(port + UART_RX);
++ outb_px(port + UART_IER, 0);
++
++ (void) inb_p(port + UART_RX); /* serial driver comments say */
++ (void) inb_p(port + UART_IIR); /* this clears the interrupt regs */
++ (void) inb_p(port + UART_MSR);
++ outb_px(port + UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
++ outb_px(port + UART_DLL, info->state->custom_divisor & 0xff); /* LS */
++ outb_px(port + UART_DLM, info->state->custom_divisor >> 8); /* MS */
++ outb_px(port + UART_MCR, info->MCR);
++
++ outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1 | UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); /* set fcr */
++ outb_px(port + UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
++ outb_px(port + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1); /* set fcr */
++ if (!ints_disabled) {
++ intprintk(("KGDB: Sending %d to port %x offset %d\n",
++ gdb_async_info->IER,
++ (int) gdb_async_info->port, UART_IER));
++ outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
++ }
++ return;
++}
++
++/*
++ * tty_getDebugChar
++ *
++ * This is a GDB stub routine. It waits for a character from the
++ * serial interface and then returns it. If there is no serial
++ * interface connection then it returns a bogus value which will
++ * almost certainly cause the system to hang. In the
++ */
++int kgdb_in_isr = 0;
++int kgdb_in_lsr = 0;
++extern spinlock_t kgdb_spinlock;
++
++/* Caller takes needed protections */
++
++int
++tty_getDebugChar(void)
++{
++ volatile int chr, dum, time, end_time;
++
++ dbprintk(("tty_getDebugChar(port %x): ", gdb_async_info->port));
++
++ if (gdb_async_info == NULL) {
++ gdb_hook_interrupt(&local_info, 0);
++ }
++ /*
++ * This trick says if we wait a very long time and get
++ * no char, return the -1 and let the upper level deal
++ * with it.
++ */
++ rdtsc(dum, time);
++ end_time = time + 2;
++ while (((chr = read_char(gdb_async_info)) == -1) &&
++ (end_time - time) > 0) {
++ rdtsc(dum, time);
++ };
++ /*
++ * This covers our butts if some other code messes with
++ * our uart, hay, it happens :o)
++ */
++ if (chr == -1)
++ program_uart(gdb_async_info);
++
++ dbprintk(("%c\n", chr > ' ' && chr < 0x7F ? chr : ' '));
++ return (chr);
++
++} /* tty_getDebugChar */
++
++static int count = 3;
++static spinlock_t one_at_atime = SPIN_LOCK_UNLOCKED;
++
++static int __init
++kgdb_enable_ints(void)
++{
++ if (kgdb_eth != -1) {
++ return 0;
++ }
++ if (gdb_async_info == NULL) {
++ gdb_hook_interrupt(&local_info, 1);
++ }
++ ok_to_enable_ints = 1;
++ kgdb_enable_ints_now();
++#ifdef CONFIG_KGDB_USER_CONSOLE
++ kgdb_console_finit();
++#endif
++ return 0;
++}
++
++#ifdef CONFIG_SERIAL_8250
++void shutdown_for_kgdb(struct async_struct *gdb_async_info);
++#endif
++
++#ifdef CONFIG_DISCONTIGMEM
++static inline int kgdb_mem_init_done(void)
++{
++ return highmem_start_page != NULL;
++}
++#else
++static inline int kgdb_mem_init_done(void)
++{
++ return max_mapnr != 0;
++}
++#endif
++
++static void
++kgdb_enable_ints_now(void)
++{
++ if (!spin_trylock(&one_at_atime))
++ return;
++ if (!ints_disabled)
++ goto exit;
++ if (kgdb_mem_init_done() &&
++ ints_disabled) { /* don't try till mem init */
++#ifdef CONFIG_SERIAL_8250
++ /*
++ * The ifdef here allows the system to be configured
++ * without the serial driver.
++ * Don't make it a module, however, it will steal the port
++ */
++ shutdown_for_kgdb(gdb_async_info);
++#endif
++ ints_disabled = request_irq(gdb_async_info->state->irq,
++ gdb_interrupt,
++ IRQ_T(gdb_async_info),
++ "KGDB-stub", NULL);
++ intprintk(("KGDB: request_irq returned %d\n", ints_disabled));
++ }
++ if (!ints_disabled) {
++ intprintk(("KGDB: Sending %d to port %x offset %d\n",
++ gdb_async_info->IER,
++ (int) gdb_async_info->port, UART_IER));
++ outb_px(gdb_async_info->port + UART_IER, gdb_async_info->IER);
++ }
++ exit:
++ spin_unlock(&one_at_atime);
++}
++
++/*
++ * tty_putDebugChar
++ *
++ * This is a GDB stub routine. It waits until the interface is ready
++ * to transmit a char and then sends it. If there is no serial
++ * interface connection then it simply returns to its caller, having
++ * pretended to send the char. Caller takes needed protections.
++ */
++void
++tty_putDebugChar(int chr)
++{
++ dbprintk(("tty_putDebugChar(port %x): chr=%02x '%c', ints_on=%d\n",
++ gdb_async_info->port,
++ chr,
++ chr > ' ' && chr < 0x7F ? chr : ' ', ints_disabled ? 0 : 1));
++
++ if (gdb_async_info == NULL) {
++ gdb_hook_interrupt(&local_info, 0);
++ }
++
++ write_char(gdb_async_info, chr); /* this routine will wait */
++ count = (chr == '#') ? 0 : count + 1;
++ if ((count == 2)) { /* try to enable after */
++ if (ints_disabled & ok_to_enable_ints)
++ kgdb_enable_ints_now(); /* try to enable after */
++
++ /* We do this a lot because, well we really want to get these
++ * interrupts. The serial driver will clear these bits when it
++ * initializes the chip. Every thing else it does is ok,
++ * but this.
++ */
++ if (!ints_disabled) {
++ outb_px(gdb_async_info->port + UART_IER,
++ gdb_async_info->IER);
++ }
++ }
++
++} /* tty_putDebugChar */
++
++/*
++ * This does nothing for the serial port, since it doesn't buffer.
++ */
++
++void tty_flushDebugChar(void)
++{
++}
++
++module_init(kgdb_enable_ints);
+--- linux-2.6.0-test6/arch/i386/lib/Makefile 2003-06-26 22:07:23.000000000 -0700
++++ 25/arch/i386/lib/Makefile 2003-10-05 00:33:38.000000000 -0700
+@@ -9,4 +9,5 @@ lib-y = checksum.o delay.o \
+
+ lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
+ lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
++lib-$(CONFIG_KGDB) += kgdb_serial.o
+ lib-$(CONFIG_DEBUG_IOVIRT) += iodebug.o
+--- linux-2.6.0-test6/arch/i386/lib/usercopy.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/lib/usercopy.c 2003-10-05 00:36:48.000000000 -0700
+@@ -76,7 +76,7 @@ do { \
+ * and returns @count.
+ */
+ long
+-__strncpy_from_user(char *dst, const char __user *src, long count)
++__direct_strncpy_from_user(char *dst, const char __user *src, long count)
+ {
+ long res;
+ __do_strncpy_from_user(dst, src, count, res);
+@@ -102,7 +102,7 @@ __strncpy_from_user(char *dst, const cha
+ * and returns @count.
+ */
+ long
+-strncpy_from_user(char *dst, const char __user *src, long count)
++direct_strncpy_from_user(char *dst, const char __user *src, long count)
+ {
+ long res = -EFAULT;
+ if (access_ok(VERIFY_READ, src, 1))
+@@ -147,7 +147,7 @@ do { \
+ * On success, this will be zero.
+ */
+ unsigned long
+-clear_user(void __user *to, unsigned long n)
++direct_clear_user(void __user *to, unsigned long n)
+ {
+ might_sleep();
+ if (access_ok(VERIFY_WRITE, to, n))
+@@ -167,7 +167,7 @@ clear_user(void __user *to, unsigned lon
+ * On success, this will be zero.
+ */
+ unsigned long
+-__clear_user(void __user *to, unsigned long n)
++__direct_clear_user(void __user *to, unsigned long n)
+ {
+ __do_clear_user(to, n);
+ return n;
+@@ -184,7 +184,7 @@ __clear_user(void __user *to, unsigned l
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+-long strnlen_user(const char __user *s, long n)
++long direct_strnlen_user(const char __user *s, long n)
+ {
+ unsigned long mask = -__addr_ok(s);
+ unsigned long res, tmp;
+@@ -573,3 +573,4 @@ unsigned long __copy_from_user_ll(void *
+ n = __copy_user_zeroing_intel(to, (const void *) from, n);
+ return n;
+ }
++
+--- linux-2.6.0-test6/arch/i386/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/i386/Makefile 2003-10-05 00:33:38.000000000 -0700
+@@ -84,6 +84,9 @@ mcore-$(CONFIG_X86_ES7000) := mach-es700
+ # default subarch .h files
+ mflags-y += -Iinclude/asm-i386/mach-default
+
++mflags-$(CONFIG_KGDB) += -gdwarf-2
++mflags-$(CONFIG_KGDB_MORE) += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g')
++
+ head-y := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
+
+ libs-y += arch/i386/lib/
+--- linux-2.6.0-test6/arch/i386/math-emu/fpu_system.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/arch/i386/math-emu/fpu_system.h 2003-10-05 00:36:48.000000000 -0700
+@@ -15,6 +15,7 @@
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
++#include <asm/atomic_kmap.h>
+
+ /* This sets the pointer FPU_info to point to the argument part
+ of the stack frame of math_emulate() */
+@@ -22,7 +23,7 @@
+
+ /* s is always from a cpu register, and the cpu does bounds checking
+ * during register load --> no further bounds checks needed */
+-#define LDT_DESCRIPTOR(s) (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
++#define LDT_DESCRIPTOR(s) (((struct desc_struct *)__kmap_atomic_vaddr(KM_LDT_PAGE0))[(s) >> 3])
+ #define SEG_D_SIZE(x) ((x).b & (3 << 21))
+ #define SEG_G_BIT(x) ((x).b & (1 << 23))
+ #define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
+--- linux-2.6.0-test6/arch/i386/mm/extable.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/i386/mm/extable.c 2003-10-05 00:36:48.000000000 -0700
+@@ -6,6 +6,52 @@
+ #include <linux/module.h>
+ #include <linux/spinlock.h>
+ #include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++extern struct exception_table_entry __start___ex_table[];
++extern struct exception_table_entry __stop___ex_table[];
++
++/*
++ * The exception table needs to be sorted because we use the macros
++ * which put things into the exception table in a variety of sections
++ * as well as the init section and the main kernel text section.
++ */
++static inline void
++sort_ex_table(struct exception_table_entry *start,
++ struct exception_table_entry *finish)
++{
++ struct exception_table_entry el, *p, *q;
++
++ /* insertion sort */
++ for (p = start + 1; p < finish; ++p) {
++ /* start .. p-1 is sorted */
++ if (p[0].insn < p[-1].insn) {
++ /* move element p down to its right place */
++ el = *p;
++ q = p;
++ do {
++ /* el comes before q[-1], move q[-1] up one */
++ q[0] = q[-1];
++ --q;
++ } while (q > start && el.insn < q[-1].insn);
++ *q = el;
++ }
++ }
++}
++
++void fixup_sort_exception_table(void)
++{
++ struct exception_table_entry *p;
++
++ /*
++ * Fix up the trampoline exception addresses:
++ */
++ for (p = __start___ex_table; p < __stop___ex_table; p++) {
++ p->insn = (unsigned long)(void *)p->insn;
++ p->fixup = (unsigned long)(void *)p->fixup;
++ }
++ sort_ex_table(__start___ex_table, __stop___ex_table);
++}
+
+ /* Simple binary search */
+ const struct exception_table_entry *
+@@ -15,13 +61,15 @@ search_extable(const struct exception_ta
+ {
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+- long diff;
+
+ mid = (last - first) / 2 + first;
+- diff = mid->insn - value;
+- if (diff == 0)
++ /*
++ * careful, the distance between entries can be
++ * larger than 2GB:
++ */
++ if (mid->insn == value)
+ return mid;
+- else if (diff < 0)
++ else if (mid->insn < value)
+ first = mid+1;
+ else
+ last = mid-1;
+--- linux-2.6.0-test6/arch/i386/mm/fault.c 2003-06-26 22:07:23.000000000 -0700
++++ 25/arch/i386/mm/fault.c 2003-10-05 00:36:50.000000000 -0700
+@@ -19,6 +19,7 @@
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h> /* For unblank_screen() */
++#include <linux/highmem.h>
+ #include <linux/module.h>
+
+ #include <asm/system.h>
+@@ -26,6 +27,7 @@
+ #include <asm/pgalloc.h>
+ #include <asm/hardirq.h>
+ #include <asm/desc.h>
++#include <asm/tlbflush.h>
+
+ extern void die(const char *,struct pt_regs *,long);
+
+@@ -55,6 +57,161 @@ void bust_spinlocks(int yes)
+ console_loglevel = loglevel_save;
+ }
+
++/*
++ * Return EIP plus the CS segment base. The segment limit is also
++ * adjusted, clamped to the kernel/user address space (whichever is
++ * appropriate), and returned in *eip_limit.
++ *
++ * The segment is checked, because it might have been changed by another
++ * task between the original faulting instruction and here.
++ *
++ * If CS is no longer a valid code segment, or if EIP is beyond the
++ * limit, or if it is a kernel address when CS is not a kernel segment,
++ * then the returned value will be greater than *eip_limit.
++ */
++static inline unsigned long get_segment_eip(struct pt_regs *regs,
++ unsigned long *eip_limit)
++{
++ unsigned long eip = regs->eip;
++ unsigned seg = regs->xcs & 0xffff;
++ u32 seg_ar, seg_limit, base, *desc;
++
++ /* The standard kernel/user address space limit. */
++ *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
++
++ /* Unlikely, but must come before segment checks. */
++ if (unlikely((regs->eflags & VM_MASK) != 0))
++ return eip + (seg << 4);
++
++ /* By far the commonest cases. */
++ if (likely(seg == __USER_CS || seg == __KERNEL_CS))
++ return eip;
++
++ /* Check the segment exists, is within the current LDT/GDT size,
++ that kernel/user (ring 0..3) has the appropriate privilege,
++ that it's a code segment, and get the limit. */
++ __asm__ ("larl %3,%0; lsll %3,%1"
++ : "=&r" (seg_ar), "=r" (seg_limit) : "0" (0), "rm" (seg));
++ if ((~seg_ar & 0x9800) || eip > seg_limit) {
++ *eip_limit = 0;
++ return 1; /* So that returned eip > *eip_limit. */
++ }
++
++ /* Get the GDT/LDT descriptor base.
++ When you look for races in this code remember that
++ LDT and other horrors are only used in user space. */
++ if (seg & (1<<2)) {
++ /* Must lock the LDT while reading it. */
++ down(¤t->mm->context.sem);
++#if 1
++ /* horrible hack for 4/4 disabled kernels.
++ I'm not quite sure what the TLB flush is good for,
++ it's mindlessly copied from the read_ldt code */
++ __flush_tlb_global();
++ desc = kmap(current->mm->context.ldt_pages[(seg & ~7)/PAGE_SIZE]);
++ desc = (void *)desc + ((seg & ~7) % PAGE_SIZE);
++#else
++ desc = current->mm->context.ldt;
++ desc = (void *)desc + (seg & ~7);
++#endif
++ } else {
++ /* Must disable preemption while reading the GDT. */
++ desc = (u32 *)&cpu_gdt_table[get_cpu()];
++ desc = (void *)desc + (seg & ~7);
++ }
++ base = (desc[0] >> 16) |
++ ((desc[1] & 0xff) << 16) |
++ (desc[1] & 0xff000000);
++ if (seg & (1<<2)) {
++#if 1
++ kunmap((void *)((unsigned long)desc & PAGE_MASK));
++#endif
++ up(¤t->mm->context.sem);
++ } else
++ put_cpu();
++
++ /* Adjust EIP and segment limit, and clamp at the kernel limit.
++ It's legitimate for segments to wrap at 0xffffffff. */
++ seg_limit += base;
++ if (seg_limit < *eip_limit && seg_limit >= base)
++ *eip_limit = seg_limit;
++ return eip + base;
++}
++
++/*
++ * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
++ * Check that here and ignore it.
++ */
++static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
++{
++ unsigned long limit;
++ unsigned long instr = get_segment_eip (regs, &limit);
++ int scan_more = 1;
++ int prefetch = 0;
++ int i;
++
++ for (i = 0; scan_more && i < 15; i++) {
++ unsigned char opcode;
++ unsigned char instr_hi;
++ unsigned char instr_lo;
++
++ if (instr > limit)
++ break;
++ if (__get_user(opcode, (unsigned char *) instr))
++ break;
++
++ instr_hi = opcode & 0xf0;
++ instr_lo = opcode & 0x0f;
++ instr++;
++
++ switch (instr_hi) {
++ case 0x20:
++ case 0x30:
++ /* Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. */
++ scan_more = ((instr_lo & 7) == 0x6);
++ break;
++
++ case 0x60:
++ /* 0x64 thru 0x67 are valid prefixes in all modes. */
++ scan_more = (instr_lo & 0xC) == 0x4;
++ break;
++ case 0xF0:
++ /* 0xF0, 0xF2, and 0xF3 are valid prefixes in all modes. */
++ scan_more = !instr_lo || (instr_lo>>1) == 1;
++ break;
++ case 0x00:
++ /* Prefetch instruction is 0x0F0D or 0x0F18 */
++ scan_more = 0;
++ if (instr > limit)
++ break;
++ if (__get_user(opcode, (unsigned char *) instr))
++ break;
++ prefetch = (instr_lo == 0xF) &&
++ (opcode == 0x0D || opcode == 0x18);
++ break;
++ default:
++ scan_more = 0;
++ break;
++ }
++ }
++
++#if 1
++ if (prefetch)
++ printk("prefetch handled at %lx eip %lx instr %lx cs %x\n",
++ addr, regs->eip, instr, regs->xcs);
++#endif
++
++ return prefetch;
++}
++
++static inline int is_prefetch(struct pt_regs *regs, unsigned long addr)
++{
++ if (unlikely(boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
++ boot_cpu_data.x86 >= 6))
++ return __is_prefetch(regs, addr);
++ return 0;
++}
++
+ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
+
+ /*
+@@ -86,6 +243,8 @@ asmlinkage void do_page_fault(struct pt_
+
+ tsk = current;
+
++ info.si_code = SEGV_MAPERR;
++
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+@@ -99,18 +258,26 @@ asmlinkage void do_page_fault(struct pt_
+ * (error_code & 4) == 0, and that the fault was not a
+ * protection error (error_code & 1) == 0.
+ */
+- if (address >= TASK_SIZE && !(error_code & 5))
++#ifdef CONFIG_X86_4G
++ /* On 4/4 all kernels faults are either bugs, vmalloc or prefetch */
++ if (unlikely((regs->xcs & 3) == 0))
+ goto vmalloc_fault;
++#else
++ if (unlikely(address >= TASK_SIZE)) {
++ if (!(error_code & 5))
++ goto vmalloc_fault;
++ goto bad_area_nosemaphore;
++ }
++#endif
+
+ mm = tsk->mm;
+- info.si_code = SEGV_MAPERR;
+
+ /*
+ * If we're in an interrupt, have no user context or are running in an
+ * atomic region then we must not take the fault..
+ */
+ if (in_atomic() || !mm)
+- goto no_context;
++ goto bad_area_nosemaphore;
+
+ down_read(&mm->mmap_sem);
+
+@@ -198,8 +365,16 @@ good_area:
+ bad_area:
+ up_read(&mm->mmap_sem);
+
++bad_area_nosemaphore:
+ /* User mode accesses just cause a SIGSEGV */
+ if (error_code & 4) {
++ /*
++ * Valid to do another page fault here because this one came
++ * from user space.
++ */
++ if (is_prefetch(regs, address))
++ return;
++
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
+@@ -232,10 +407,24 @@ no_context:
+ if (fixup_exception(regs))
+ return;
+
++ /*
++ * Valid to do another page fault here, because if this fault
++ * had been triggered by is_prefetch fixup_exception would have
++ * handled it.
++ */
++ if (is_prefetch(regs, address))
++ return;
++
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
++#ifdef CONFIG_KGDB
++ if (!user_mode(regs)){
++ kgdb_handle_exception(14,SIGBUS, error_code, regs);
++ return;
++ }
++#endif
+
+ bust_spinlocks(1);
+
+@@ -286,10 +475,14 @@ out_of_memory:
+ do_sigbus:
+ up_read(&mm->mmap_sem);
+
+- /*
+- * Send a sigbus, regardless of whether we were in kernel
+- * or user mode.
+- */
++ /* Kernel mode? Handle exceptions or die */
++ if (!(error_code & 4))
++ goto no_context;
++
++ /* User space => ok to do another page fault */
++ if (is_prefetch(regs, address))
++ return;
++
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
+@@ -298,10 +491,6 @@ do_sigbus:
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, tsk);
+-
+- /* Kernel mode? Handle exceptions or die */
+- if (!(error_code & 4))
+- goto no_context;
+ return;
+
+ vmalloc_fault:
+--- linux-2.6.0-test6/arch/i386/mm/init.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/mm/init.c 2003-10-05 00:36:48.000000000 -0700
+@@ -25,6 +25,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
++#include <linux/efi.h>
+
+ #include <asm/processor.h>
+ #include <asm/system.h>
+@@ -38,125 +39,13 @@
+ #include <asm/tlb.h>
+ #include <asm/tlbflush.h>
+ #include <asm/sections.h>
++#include <asm/desc.h>
+
+ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ unsigned long highstart_pfn, highend_pfn;
+
+ static int do_test_wp_bit(void);
+
+-/*
+- * Creates a middle page table and puts a pointer to it in the
+- * given global directory entry. This only returns the gd entry
+- * in non-PAE compilation mode, since the middle layer is folded.
+- */
+-static pmd_t * __init one_md_table_init(pgd_t *pgd)
+-{
+- pmd_t *pmd_table;
+-
+-#ifdef CONFIG_X86_PAE
+- pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
+- if (pmd_table != pmd_offset(pgd, 0))
+- BUG();
+-#else
+- pmd_table = pmd_offset(pgd, 0);
+-#endif
+-
+- return pmd_table;
+-}
+-
+-/*
+- * Create a page table and place a pointer to it in a middle page
+- * directory entry.
+- */
+-static pte_t * __init one_page_table_init(pmd_t *pmd)
+-{
+- if (pmd_none(*pmd)) {
+- pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+- set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
+- if (page_table != pte_offset_kernel(pmd, 0))
+- BUG();
+-
+- return page_table;
+- }
+-
+- return pte_offset_kernel(pmd, 0);
+-}
+-
+-/*
+- * This function initializes a certain range of kernel virtual memory
+- * with new bootmem page tables, everywhere page tables are missing in
+- * the given range.
+- */
+-
+-/*
+- * NOTE: The pagetables are allocated contiguous on the physical space
+- * so we can cache the place of the first one and move around without
+- * checking the pgd every time.
+- */
+-static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
+-{
+- pgd_t *pgd;
+- pmd_t *pmd;
+- int pgd_idx, pmd_idx;
+- unsigned long vaddr;
+-
+- vaddr = start;
+- pgd_idx = pgd_index(vaddr);
+- pmd_idx = pmd_index(vaddr);
+- pgd = pgd_base + pgd_idx;
+-
+- for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
+- if (pgd_none(*pgd))
+- one_md_table_init(pgd);
+-
+- pmd = pmd_offset(pgd, vaddr);
+- for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
+- if (pmd_none(*pmd))
+- one_page_table_init(pmd);
+-
+- vaddr += PMD_SIZE;
+- }
+- pmd_idx = 0;
+- }
+-}
+-
+-/*
+- * This maps the physical memory to kernel virtual address space, a total
+- * of max_low_pfn pages, by creating page tables starting from address
+- * PAGE_OFFSET.
+- */
+-static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+-{
+- unsigned long pfn;
+- pgd_t *pgd;
+- pmd_t *pmd;
+- pte_t *pte;
+- int pgd_idx, pmd_idx, pte_ofs;
+-
+- pgd_idx = pgd_index(PAGE_OFFSET);
+- pgd = pgd_base + pgd_idx;
+- pfn = 0;
+-
+- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+- pmd = one_md_table_init(pgd);
+- if (pfn >= max_low_pfn)
+- continue;
+- for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
+- /* Map with big pages if possible, otherwise create normal page tables. */
+- if (cpu_has_pse) {
+- set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
+- pfn += PTRS_PER_PTE;
+- } else {
+- pte = one_page_table_init(pmd);
+-
+- for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++)
+- set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
+- }
+- }
+- }
+-}
+-
+ static inline int page_kills_ppro(unsigned long pagenr)
+ {
+ if (pagenr >= 0x70000 && pagenr <= 0x7003F)
+@@ -164,12 +53,30 @@ static inline int page_kills_ppro(unsign
+ return 0;
+ }
+
++extern int is_available_memory(efi_memory_desc_t *);
++
+ static inline int page_is_ram(unsigned long pagenr)
+ {
+ int i;
++ unsigned long addr, end;
++
++ if (efi_enabled) {
++ efi_memory_desc_t *md;
++
++ for (i = 0; i < memmap.nr_map; i++) {
++ md = &memmap.map[i];
++ if (!is_available_memory(md))
++ continue;
++ addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT;
++ end = (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT;
++
++ if ((pagenr >= addr) && (pagenr < end))
++ return 1;
++ }
++ return 0;
++ }
+
+ for (i = 0; i < e820.nr_map; i++) {
+- unsigned long addr, end;
+
+ if (e820.map[i].type != E820_RAM) /* not usable memory */
+ continue;
+@@ -186,38 +93,14 @@ static inline int page_is_ram(unsigned l
+ return 0;
+ }
+
+-#ifdef CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+-pgprot_t kmap_prot;
+
+ #define kmap_get_fixmap_pte(vaddr) \
+ pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+ void __init kmap_init(void)
+ {
+- unsigned long kmap_vstart;
+-
+- /* cache the first kmap pte */
+- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+- kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+-
+- kmap_prot = PAGE_KERNEL;
+-}
+-
+-void __init permanent_kmaps_init(pgd_t *pgd_base)
+-{
+- pgd_t *pgd;
+- pmd_t *pmd;
+- pte_t *pte;
+- unsigned long vaddr;
+-
+- vaddr = PKMAP_BASE;
+- page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+-
+- pgd = swapper_pg_dir + pgd_index(vaddr);
+- pmd = pmd_offset(pgd, vaddr);
+- pte = pte_offset_kernel(pmd, vaddr);
+- pkmap_page_table = pte;
++ kmap_pte = kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
+ }
+
+ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
+@@ -232,6 +115,8 @@ void __init one_highpage_init(struct pag
+ SetPageReserved(page);
+ }
+
++#ifdef CONFIG_HIGHMEM
++
+ #ifndef CONFIG_DISCONTIGMEM
+ void __init set_highmem_pages_init(int bad_ppro)
+ {
+@@ -243,12 +128,9 @@ void __init set_highmem_pages_init(int b
+ #else
+ extern void set_highmem_pages_init(int);
+ #endif /* !CONFIG_DISCONTIGMEM */
+-
+ #else
+-#define kmap_init() do { } while (0)
+-#define permanent_kmaps_init(pgd_base) do { } while (0)
+-#define set_highmem_pages_init(bad_ppro) do { } while (0)
+-#endif /* CONFIG_HIGHMEM */
++# define set_highmem_pages_init(bad_ppro) do { } while (0)
++#endif
+
+ unsigned long __PAGE_KERNEL = _PAGE_KERNEL;
+
+@@ -258,30 +140,125 @@ unsigned long __PAGE_KERNEL = _PAGE_KERN
+ extern void __init remap_numa_kva(void);
+ #endif
+
+-static void __init pagetable_init (void)
++static __init void prepare_pagetables(pgd_t *pgd_base, unsigned long address)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++
++ pgd = pgd_base + pgd_index(address);
++ pmd = pmd_offset(pgd, address);
++ if (!pmd_present(*pmd)) {
++ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)));
++ }
++}
++
++static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
++{
++ unsigned long vaddr;
++
++ for (vaddr = start; vaddr != end; vaddr += PAGE_SIZE)
++ prepare_pagetables(pgd_base, vaddr);
++}
++
++void setup_identity_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end)
+ {
+ unsigned long vaddr;
+- pgd_t *pgd_base = swapper_pg_dir;
++ pgd_t *pgd;
++ int i, j, k;
++ pmd_t *pmd;
++ pte_t *pte, *pte_base;
++
++ pgd = pgd_base;
++
++ for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
++ vaddr = i*PGDIR_SIZE;
++ if (end && (vaddr >= end))
++ break;
++ pmd = pmd_offset(pgd, 0);
++ for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
++ vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
++ if (end && (vaddr >= end))
++ break;
++ if (vaddr < start)
++ continue;
++ if (cpu_has_pse) {
++ unsigned long __pe;
++
++ set_in_cr4(X86_CR4_PSE);
++ boot_cpu_data.wp_works_ok = 1;
++ __pe = _KERNPG_TABLE + _PAGE_PSE + vaddr - start;
++ /* Make it "global" too if supported */
++ if (cpu_has_pge) {
++ set_in_cr4(X86_CR4_PGE);
++#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
++ __pe += _PAGE_GLOBAL;
++ __PAGE_KERNEL |= _PAGE_GLOBAL;
++#endif
++ }
++ set_pmd(pmd, __pmd(__pe));
++ continue;
++ }
++ if (!pmd_present(*pmd))
++ pte_base = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ else
++ pte_base = (pte_t *) page_address(pmd_page(*pmd));
++ pte = pte_base;
++ for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
++ vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
++ if (end && (vaddr >= end))
++ break;
++ if (vaddr < start)
++ continue;
++ *pte = mk_pte_phys(vaddr-start, PAGE_KERNEL);
++ }
++ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base)));
++ }
++ }
++}
+
++static void __init pagetable_init (void)
++{
++ unsigned long vaddr, end;
++ pgd_t *pgd_base;
+ #ifdef CONFIG_X86_PAE
+ int i;
+- /* Init entries of the first-level page table to the zero page */
+- for (i = 0; i < PTRS_PER_PGD; i++)
+- set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
+ #endif
+
+- /* Enable PSE if available */
+- if (cpu_has_pse) {
+- set_in_cr4(X86_CR4_PSE);
+- }
++ /*
++ * This can be zero as well - no problem, in that case we exit
++ * the loops anyway due to the PTRS_PER_* conditions.
++ */
++ end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
+
+- /* Enable PGE if available */
+- if (cpu_has_pge) {
+- set_in_cr4(X86_CR4_PGE);
+- __PAGE_KERNEL |= _PAGE_GLOBAL;
++ pgd_base = swapper_pg_dir;
++#ifdef CONFIG_X86_PAE
++ /*
++ * It causes too many problems if there's no proper pmd set up
++ * for all 4 entries of the PGD - so we allocate all of them.
++ * PAE systems will not miss this extra 4-8K anyway ...
++ */
++ for (i = 0; i < PTRS_PER_PGD; i++) {
++ pmd_t *pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ set_pgd(pgd_base + i, __pgd(__pa(pmd) + 0x1));
+ }
++#endif
++ /*
++ * Set up lowmem-sized identity mappings at PAGE_OFFSET:
++ */
++ setup_identity_mappings(pgd_base, PAGE_OFFSET, end);
+
+- kernel_physical_mapping_init(pgd_base);
++ /*
++ * Add flat-mode identity-mappings - SMP needs it when
++ * starting up on an AP from real-mode. (In the non-PAE
++ * case we already have these mappings through head.S.)
++ * All user-space mappings are explicitly cleared after
++ * SMP startup.
++ */
++#if CONFIG_SMP && CONFIG_X86_PAE
++ setup_identity_mappings(pgd_base, 0, 16*1024*1024);
++#endif
+ remap_numa_kva();
+
+ /*
+@@ -289,38 +266,64 @@ static void __init pagetable_init (void)
+ * created - mappings will be set by set_fixmap():
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+- page_table_range_init(vaddr, 0, pgd_base);
++ fixrange_init(vaddr, 0, pgd_base);
+
+- permanent_kmaps_init(pgd_base);
++#if CONFIG_HIGHMEM
++ {
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
+
+-#ifdef CONFIG_X86_PAE
+- /*
+- * Add low memory identity-mappings - SMP needs it when
+- * starting up on an AP from real-mode. In the non-PAE
+- * case we already have these mappings through head.S.
+- * All user-space mappings are explicitly cleared after
+- * SMP startup.
+- */
+- pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
++ /*
++ * Permanent kmaps:
++ */
++ vaddr = PKMAP_BASE;
++ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
++
++ pgd = swapper_pg_dir + pgd_index(vaddr);
++ pmd = pmd_offset(pgd, vaddr);
++ pte = pte_offset_kernel(pmd, vaddr);
++ pkmap_page_table = pte;
++ }
+ #endif
+ }
+
+-void zap_low_mappings (void)
++/*
++ * Clear kernel pagetables in a PMD_SIZE-aligned range.
++ */
++static void clear_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end)
+ {
+- int i;
++ unsigned long vaddr;
++ pgd_t *pgd;
++ pmd_t *pmd;
++ int i, j;
++
++ pgd = pgd_base;
++
++ for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
++ vaddr = i*PGDIR_SIZE;
++ if (end && (vaddr >= end))
++ break;
++ pmd = pmd_offset(pgd, 0);
++ for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
++ vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
++ if (end && (vaddr >= end))
++ break;
++ if (vaddr < start)
++ continue;
++ pmd_clear(pmd);
++ }
++ }
++ flush_tlb_all();
++}
++
++void __init zap_low_mappings(void)
++{
++ printk("zapping low mappings.\n");
+ /*
+ * Zap initial low-memory mappings.
+- *
+- * Note that "pgd_clear()" doesn't do it for
+- * us, because pgd_clear() is a no-op on i386.
+ */
+- for (i = 0; i < USER_PTRS_PER_PGD; i++)
+-#ifdef CONFIG_X86_PAE
+- set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
+-#else
+- set_pgd(swapper_pg_dir+i, __pgd(0));
+-#endif
+- flush_tlb_all();
++ clear_mappings(swapper_pg_dir, 0, 16*1024*1024);
+ }
+
+ #ifndef CONFIG_DISCONTIGMEM
+@@ -424,6 +427,7 @@ extern void set_max_mapnr_init(void);
+ #endif /* !CONFIG_DISCONTIGMEM */
+
+ static struct kcore_list kcore_mem, kcore_vmalloc;
++extern void fixup_sort_exception_table(void);
+
+ void __init mem_init(void)
+ {
+@@ -432,6 +436,8 @@ void __init mem_init(void)
+ int tmp;
+ int bad_ppro;
+
++ fixup_sort_exception_table();
++
+ #ifndef CONFIG_DISCONTIGMEM
+ if (!mem_map)
+ BUG();
+@@ -507,13 +513,18 @@ void __init mem_init(void)
+ #ifndef CONFIG_SMP
+ zap_low_mappings();
+ #endif
++ entry_trampoline_setup();
++ default_ldt_page = virt_to_page(default_ldt);
++ load_LDT(&init_mm.context);
+ }
+
+-kmem_cache_t *pgd_cache;
+-kmem_cache_t *pmd_cache;
++kmem_cache_t *pgd_cache, *pmd_cache, *kpmd_cache;
+
+ void __init pgtable_cache_init(void)
+ {
++ void (*ctor)(void *, kmem_cache_t *, unsigned long);
++ void (*dtor)(void *, kmem_cache_t *, unsigned long);
++
+ if (PTRS_PER_PMD > 1) {
+ pmd_cache = kmem_cache_create("pmd",
+ PTRS_PER_PMD*sizeof(pmd_t),
+@@ -523,13 +534,36 @@ void __init pgtable_cache_init(void)
+ NULL);
+ if (!pmd_cache)
+ panic("pgtable_cache_init(): cannot create pmd cache");
++
++ if (TASK_SIZE > PAGE_OFFSET) {
++ kpmd_cache = kmem_cache_create("kpmd",
++ PTRS_PER_PMD*sizeof(pmd_t),
++ 0,
++ SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,
++ kpmd_ctor,
++ NULL);
++ if (!kpmd_cache)
++ panic("pgtable_cache_init(): "
++ "cannot create kpmd cache");
++ }
+ }
++
++ if (PTRS_PER_PMD == 1 || TASK_SIZE <= PAGE_OFFSET)
++ ctor = pgd_ctor;
++ else
++ ctor = NULL;
++
++ if (PTRS_PER_PMD == 1 && TASK_SIZE <= PAGE_OFFSET)
++ dtor = pgd_dtor;
++ else
++ dtor = NULL;
++
+ pgd_cache = kmem_cache_create("pgd",
+ PTRS_PER_PGD*sizeof(pgd_t),
+ 0,
+ SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN,
+- pgd_ctor,
+- PTRS_PER_PMD == 1 ? pgd_dtor : NULL);
++ ctor,
++ dtor);
+ if (!pgd_cache)
+ panic("pgtable_cache_init(): Cannot create pgd cache");
+ }
+--- linux-2.6.0-test6/arch/i386/mm/ioremap.c 2003-06-14 12:18:04.000000000 -0700
++++ 25/arch/i386/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -158,7 +158,7 @@ void * __ioremap(unsigned long phys_addr
+ return NULL;
+ area->phys_addr = phys_addr;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vunmap(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/i386/mm/pgtable.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/mm/pgtable.c 2003-10-05 00:36:48.000000000 -0700
+@@ -21,6 +21,7 @@
+ #include <asm/e820.h>
+ #include <asm/tlb.h>
+ #include <asm/tlbflush.h>
++#include <asm/atomic_kmap.h>
+
+ void show_mem(void)
+ {
+@@ -157,11 +158,20 @@ void pmd_ctor(void *pmd, kmem_cache_t *c
+ memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+ }
+
++void kpmd_ctor(void *__pmd, kmem_cache_t *cache, unsigned long flags)
++{
++ pmd_t *kpmd, *pmd;
++ kpmd = pmd_offset(&swapper_pg_dir[PTRS_PER_PGD-1],
++ (PTRS_PER_PMD - NR_SHARED_PMDS)*PMD_SIZE);
++ pmd = (pmd_t *)__pmd + (PTRS_PER_PMD - NR_SHARED_PMDS);
++
++ memset(__pmd, 0, (PTRS_PER_PMD - NR_SHARED_PMDS)*sizeof(pmd_t));
++ memcpy(pmd, kpmd, NR_SHARED_PMDS*sizeof(pmd_t));
++}
++
+ /*
+- * List of all pgd's needed for non-PAE so it can invalidate entries
+- * in both cached and uncached pgd's; not needed for PAE since the
+- * kernel pmd is shared. If PAE were not to share the pmd a similar
+- * tactic would be needed. This is essentially codepath-based locking
++ * List of all pgd's needed so it can invalidate entries in both cached
++ * and uncached pgd's. This is essentially codepath-based locking
+ * against pageattr.c; it is the unique case in which a valid change
+ * of kernel pagetables can't be lazily synchronized by vmalloc faults.
+ * vmalloc faults work because attached pagetables are never freed.
+@@ -170,30 +180,60 @@ void pmd_ctor(void *pmd, kmem_cache_t *c
+ * could be used. The locking scheme was chosen on the basis of
+ * manfred's recommendations and having no core impact whatsoever.
+ * -- wli
++ *
++ * The entire issue goes away when XKVA is configured.
+ */
+ spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED;
+ LIST_HEAD(pgd_list);
+
+-void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
++/*
++ * This is not that hard to figure out.
++ * (a) PTRS_PER_PMD == 1 means non-PAE.
++ * (b) PTRS_PER_PMD > 1 means PAE.
++ * (c) TASK_SIZE > PAGE_OFFSET means XKVA.
++ * (d) TASK_SIZE <= PAGE_OFFSET means non-XKVA.
++ *
++ * Do *NOT* back out the preconstruction like the patch I'm cleaning
++ * up after this very instant did, or at all, for that matter.
++ * This is never called when PTRS_PER_PMD > 1 && TASK_SIZE > PAGE_OFFSET.
++ * -- wli
++ */
++void pgd_ctor(void *__pgd, kmem_cache_t *cache, unsigned long unused)
+ {
++ pgd_t *pgd = (pgd_t *)__pgd;
+ unsigned long flags;
+
+- if (PTRS_PER_PMD == 1)
+- spin_lock_irqsave(&pgd_lock, flags);
++ if (PTRS_PER_PMD == 1) {
++ if (TASK_SIZE <= PAGE_OFFSET)
++ spin_lock_irqsave(&pgd_lock, flags);
++ else
++ memcpy(&pgd[PTRS_PER_PGD - NR_SHARED_PMDS],
++ &swapper_pg_dir[PTRS_PER_PGD - NR_SHARED_PMDS],
++ NR_SHARED_PMDS * sizeof(pgd_t));
++ }
+
+- memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
+- swapper_pg_dir + USER_PTRS_PER_PGD,
+- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
++ if (TASK_SIZE <= PAGE_OFFSET)
++ memcpy(pgd + USER_PTRS_PER_PGD,
++ swapper_pg_dir + USER_PTRS_PER_PGD,
++ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+
+ if (PTRS_PER_PMD > 1)
+ return;
+
+- list_add(&virt_to_page(pgd)->lru, &pgd_list);
+- spin_unlock_irqrestore(&pgd_lock, flags);
+- memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++ if (TASK_SIZE > PAGE_OFFSET)
++ memset(pgd, 0, (PTRS_PER_PGD - NR_SHARED_PMDS)*sizeof(pgd_t));
++ else {
++ list_add(&virt_to_page(pgd)->lru, &pgd_list);
++ spin_unlock_irqrestore(&pgd_lock, flags);
++ memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
++ }
+ }
+
+-/* never called when PTRS_PER_PMD > 1 */
++/*
++ * Never called when PTRS_PER_PMD > 1 || TASK_SIZE > PAGE_OFFSET
++ * for with PAE we would list_del() multiple times, and for non-PAE
++ * with XKVA all the AGP pgd shootdown code is unnecessary.
++ */
+ void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused)
+ {
+ unsigned long flags; /* can be called from interrupt context */
+@@ -203,6 +243,12 @@ void pgd_dtor(void *pgd, kmem_cache_t *c
+ spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+
++/*
++ * See the comments above pgd_ctor() wrt. preconstruction.
++ * Do *NOT* memcpy() here. If you do, you back out important
++ * anti- cache pollution code.
++ *
++ */
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ int i;
+@@ -211,15 +257,33 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ if (PTRS_PER_PMD == 1 || !pgd)
+ return pgd;
+
++ /*
++ * In the 4G userspace case alias the top 16 MB virtual
++ * memory range into the user mappings as well (these
++ * include the trampoline and CPU data structures).
++ */
+ for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+- pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++ kmem_cache_t *cache;
++ pmd_t *pmd;
++
++ if (TASK_SIZE > PAGE_OFFSET && i == USER_PTRS_PER_PGD - 1)
++ cache = kpmd_cache;
++ else
++ cache = pmd_cache;
++
++ pmd = kmem_cache_alloc(cache, GFP_KERNEL);
+ if (!pmd)
+ goto out_oom;
+ set_pgd(&pgd[i], __pgd(1 + __pa((u64)((u32)pmd))));
+ }
+- return pgd;
+
++ return pgd;
+ out_oom:
++ /*
++ * we don't have to handle the kpmd_cache here, since it's the
++ * last allocation, and has either nothing to free or when it
++ * succeeds the whole operation succeeds.
++ */
+ for (i--; i >= 0; i--)
+ kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+ kmem_cache_free(pgd_cache, pgd);
+@@ -230,10 +294,29 @@ void pgd_free(pgd_t *pgd)
+ {
+ int i;
+
+- /* in the PAE case user pgd entries are overwritten before usage */
+- if (PTRS_PER_PMD > 1)
+- for (i = 0; i < USER_PTRS_PER_PGD; ++i)
+- kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+ /* in the non-PAE case, clear_page_tables() clears user pgd entries */
++ if (PTRS_PER_PMD == 1)
++ goto out_free;
++
++ /* in the PAE case user pgd entries are overwritten before usage */
++ for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
++ kmem_cache_t *cache;
++ pmd_t *pmd = __va(pgd_val(pgd[i]) - 1);
++
++ /*
++ * only userspace pmd's are cleared for us
++ * by mm/memory.c; it's a slab cache invariant
++ * that we must separate the kernel pmd slab
++ * all times, else we'll have bad pmd's.
++ */
++ if (TASK_SIZE > PAGE_OFFSET && i == USER_PTRS_PER_PGD - 1)
++ cache = kpmd_cache;
++ else
++ cache = pmd_cache;
++
++ kmem_cache_free(cache, pmd);
++ }
++out_free:
+ kmem_cache_free(pgd_cache, pgd);
+ }
++
+--- linux-2.6.0-test6/arch/i386/pci/acpi.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/i386/pci/acpi.c 2003-10-05 00:34:16.000000000 -0700
+@@ -15,10 +15,11 @@ struct pci_bus * __devinit pci_acpi_scan
+
+ static int __init pci_acpi_init(void)
+ {
++ extern int acpi_disabled;
+ if (pcibios_scanned)
+ return 0;
+
+- if (!(pci_probe & PCI_NO_ACPI_ROUTING)) {
++ if (!(pci_probe & PCI_NO_ACPI_ROUTING) && !acpi_disabled) {
+ if (!acpi_pci_irq_init()) {
+ printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+ printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n");
+--- linux-2.6.0-test6/arch/i386/pci/irq.c 2003-08-08 22:55:10.000000000 -0700
++++ 25/arch/i386/pci/irq.c 2003-10-05 00:36:20.000000000 -0700
+@@ -680,8 +680,10 @@ static int pcibios_lookup_irq(struct pci
+ if ( dev2->irq && dev2->irq != irq && \
+ (!(pci_probe & PCI_USE_PIRQ_MASK) || \
+ ((1 << dev2->irq) & mask)) ) {
++#ifndef CONFIG_PCI_USE_VECTOR
+ printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
+ pci_name(dev2), dev2->irq, irq);
++#endif
+ continue;
+ }
+ dev2->irq = irq;
+@@ -745,6 +747,10 @@ static void __init pcibios_fixup_irqs(vo
+ bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
+ }
+ if (irq >= 0) {
++ if (use_pci_vector() &&
++ !platform_legacy_irq(irq))
++ irq = IO_APIC_VECTOR(irq);
++
+ printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+ dev->irq = irq;
+--- linux-2.6.0-test6/arch/ia64/ia32/ia32_ioctl.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/ia64/ia32/ia32_ioctl.c 2003-10-05 00:34:44.000000000 -0700
+@@ -26,43 +26,11 @@
+ _ret; \
+ })
+
+-#define P(i) ((void *)(unsigned long)(i))
+-
+ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+ #define CODE
+ #include "compat_ioctl.c"
+
+-#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct linux32_dirent[2])
+-#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct linux32_dirent[2])
+-
+-static long
+-put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
+-{
+- size_t namelen = strlen(d->d_name);
+-
+- return (put_user(d->d_ino, &d32->d_ino)
+- || put_user(d->d_off, &d32->d_off)
+- || put_user(d->d_reclen, &d32->d_reclen)
+- || copy_to_user(d32->d_name, d->d_name, namelen + 1));
+-}
+-
+-static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr)
+-{
+- int ret;
+- mm_segment_t oldfs = get_fs();
+- struct dirent d[2];
+-
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd,cmd,(unsigned long)&d);
+- set_fs(oldfs);
+- if (!ret) {
+- ret |= put_dirent32(&d[0], (struct linux32_dirent *)ptr);
+- ret |= put_dirent32(&d[1], ((struct linux32_dirent *)ptr) + 1);
+- }
+- return ret;
+-}
+-
+ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+
+ #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
+@@ -73,8 +41,6 @@ typedef int (* ioctl32_handler_t)(unsign
+ };
+
+ IOCTL_TABLE_START
+-HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
+-HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
+ #define DECLARES
+ #include "compat_ioctl.c"
+ #include <linux/compat_ioctl.h>
+--- linux-2.6.0-test6/arch/ia64/ia32/ia32priv.h 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/ia32/ia32priv.h 2003-10-05 00:34:44.000000000 -0700
+@@ -249,13 +249,6 @@ typedef struct siginfo32 {
+ } _sifields;
+ } siginfo_t32;
+
+-struct linux32_dirent {
+- u32 d_ino;
+- u32 d_off;
+- u16 d_reclen;
+- char d_name[256];
+-};
+-
+ struct old_linux32_dirent {
+ u32 d_ino;
+ u32 d_offset;
+--- linux-2.6.0-test6/arch/ia64/ia32/sys_ia32.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/ia32/sys_ia32.c 2003-10-05 00:34:44.000000000 -0700
+@@ -707,8 +707,8 @@ sys32_settimeofday (struct compat_timeva
+ }
+
+ struct getdents32_callback {
+- struct linux32_dirent * current_dir;
+- struct linux32_dirent * previous;
++ struct compat_dirent * current_dir;
++ struct compat_dirent * previous;
+ int count;
+ int error;
+ };
+@@ -722,7 +722,7 @@ static int
+ filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
+ unsigned int d_type)
+ {
+- struct linux32_dirent * dirent;
++ struct compat_dirent * dirent;
+ struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+
+@@ -748,10 +748,10 @@ filldir32 (void *__buf, const char *name
+ }
+
+ asmlinkage long
+-sys32_getdents (unsigned int fd, struct linux32_dirent *dirent, unsigned int count)
++sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count)
+ {
+ struct file * file;
+- struct linux32_dirent * lastdirent;
++ struct compat_dirent * lastdirent;
+ struct getdents32_callback buf;
+ int error;
+
+--- linux-2.6.0-test6/arch/ia64/kernel/acpi.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/kernel/acpi.c 2003-10-05 00:34:41.000000000 -0700
+@@ -41,6 +41,7 @@
+ #include <linux/irq.h>
+ #include <linux/acpi.h>
+ #include <linux/efi.h>
++#include <linux/mmzone.h>
+ #include <asm/io.h>
+ #include <asm/iosapic.h>
+ #include <asm/machvec.h>
+@@ -56,7 +57,7 @@ void (*pm_power_off) (void);
+
+ unsigned char acpi_kbd_controller_present = 1;
+
+-int acpi_disabled __initdata; /* XXX this shouldn't be needed---we can't boot without ACPI! */
++int acpi_disabled; /* XXX this shouldn't be needed---we can't boot without ACPI! */
+
+ const char *
+ acpi_get_sysname (void)
+@@ -341,7 +342,7 @@ static u32 __initdata pxm_flag[PXM_FLAG_
+ #define pxm_bit_test(bit) (test_bit(bit,(void *)pxm_flag))
+ /* maps to convert between proximity domain and logical node ID */
+ int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+-int __initdata nid_to_pxm_map[NR_NODES];
++int __initdata nid_to_pxm_map[MAX_NUMNODES];
+ static struct acpi_table_slit __initdata *slit_table;
+
+ /*
+--- linux-2.6.0-test6/arch/ia64/kernel/perfmon.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/kernel/perfmon.c 2003-10-05 00:34:03.000000000 -0700
+@@ -2165,6 +2165,7 @@ pfm_alloc_fd(struct file **cfile)
+
+ d_add(file->f_dentry, inode);
+ file->f_vfsmnt = mntget(pfmfs_mnt);
++ file->f_mapping = inode->i_mapping;
+
+ file->f_op = &pfm_file_ops;
+ file->f_mode = FMODE_READ;
+--- linux-2.6.0-test6/arch/ia64/kernel/unaligned.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/ia64/kernel/unaligned.c 2003-10-05 00:36:18.000000000 -0700
+@@ -1347,7 +1347,7 @@ ia64_handle_unaligned (unsigned long ifa
+ * be holding locks...
+ */
+ if (user_mode(regs))
+- tty_write_message(current->tty, buf);
++ tty_write_message(process_tty(current), buf);
+ buf[len-1] = '\0'; /* drop '\r' */
+ printk(KERN_WARNING "%s", buf); /* watch for command names containing %s */
+ }
+--- linux-2.6.0-test6/arch/ia64/mm/discontig.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/mm/discontig.c 2003-10-05 00:34:41.000000000 -0700
+@@ -14,7 +14,6 @@
+ #include <linux/mm.h>
+ #include <linux/swap.h>
+ #include <linux/bootmem.h>
+-#include <linux/mmzone.h>
+ #include <linux/acpi.h>
+ #include <linux/efi.h>
+ #include <asm/pgalloc.h>
+@@ -26,10 +25,10 @@
+ */
+ #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
+
+-static struct ia64_node_data *node_data[NR_NODES];
+-static long boot_pg_data[8*NR_NODES+sizeof(pg_data_t)] __initdata;
+-static pg_data_t *pg_data_ptr[NR_NODES] __initdata;
+-static bootmem_data_t bdata[NR_NODES][NR_BANKS_PER_NODE+1] __initdata;
++static struct ia64_node_data *node_data[MAX_NUMNODES];
++static long boot_pg_data[8*MAX_NUMNODES+sizeof(pg_data_t)] __initdata;
++static pg_data_t *pg_data_ptr[MAX_NUMNODES] __initdata;
++static bootmem_data_t bdata[MAX_NUMNODES][NR_BANKS_PER_NODE+1] __initdata;
+ /*
+ * Return the compact node number of this cpu. Used prior to
+ * setting up the cpu_data area.
+--- linux-2.6.0-test6/arch/ia64/mm/numa.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/ia64/mm/numa.c 2003-10-05 00:34:41.000000000 -0700
+@@ -15,7 +15,6 @@
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <linux/bootmem.h>
+-#include <linux/mmzone.h>
+ #include <asm/numa.h>
+
+ /*
+@@ -29,7 +28,7 @@ struct node_cpuid_s node_cpuid[NR_CPUS];
+ * This is a matrix with "distances" between nodes, they should be
+ * proportional to the memory access latency ratios.
+ */
+-u8 numa_slit[NR_NODES * NR_NODES];
++u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
+
+ /* Identify which cnode a physical address resides on */
+ int
+--- linux-2.6.0-test6/arch/ia64/sn/io/sn2/module.c 2003-07-10 18:50:30.000000000 -0700
++++ 25/arch/ia64/sn/io/sn2/module.c 2003-10-05 00:33:23.000000000 -0700
+@@ -166,7 +166,6 @@ int module_probe_snum(module_t *m, nasid
+ {
+ lboard_t *board;
+ klmod_serial_num_t *comp;
+- char * bcopy(const char * src, char * dest, int count);
+ char serial_number[16];
+
+ /*
+@@ -215,9 +214,9 @@ int module_probe_snum(module_t *m, nasid
+ #endif
+
+ if (comp->snum.snum_str[0] != '\0') {
+- bcopy(comp->snum.snum_str,
+- m->sys_snum,
+- MAX_SERIAL_NUM_SIZE);
++ memcpy(m->sys_snum,
++ comp->snum.snum_str,
++ MAX_SERIAL_NUM_SIZE);
+ m->sys_snum_valid = 1;
+ }
+ }
+--- linux-2.6.0-test6/arch/ia64/sn/io/sn2/pic.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ia64/sn/io/sn2/pic.c 2003-10-05 00:33:23.000000000 -0700
+@@ -29,8 +29,6 @@
+ #include <asm/sn/io.h>
+ #include <asm/sn/sn_private.h>
+
+-extern char *bcopy(const char * src, char * dest, int count);
+-
+
+ #define PCI_BUS_NO_1 1
+
+@@ -51,7 +49,7 @@ pic_bus1_inventory_dup(vertex_hdl_t conn
+ (arbitrary_info_t *)&pinv) == GRAPH_SUCCESS)
+ {
+ NEW(peer_pinv);
+- bcopy((const char *)pinv, (char *)peer_pinv, sizeof(inventory_t));
++ memcpy(peer_pinv, pinv, sizeof(inventory_t));
+ if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT,
+ (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) {
+ DEL(peer_pinv);
+--- linux-2.6.0-test6/arch/m68k/atari/stram.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/m68k/atari/stram.c 2003-10-05 00:33:23.000000000 -0700
+@@ -22,6 +22,7 @@
+ #include <linux/shm.h>
+ #include <linux/bootmem.h>
+ #include <linux/mount.h>
++#include <linux/blkdev.h>
+
+ #include <asm/setup.h>
+ #include <asm/machdep.h>
+--- linux-2.6.0-test6/arch/m68k/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/m68k/Kconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -87,7 +87,7 @@ config ATARI
+
+ config HADES
+ bool "Hades support"
+- depends on ATARI
++ depends on ATARI && BROKEN
+ help
+ This option enables support for the Hades Atari clone. If you plan
+ to use this kernel on a Hades, say Y here; otherwise say N.
+@@ -361,7 +361,7 @@ config AMIGA_PCMCIA
+
+ config STRAM_SWAP
+ bool "Support for ST-RAM as swap space"
+- depends on ATARI
++ depends on ATARI && BROKEN
+ ---help---
+ Some Atari 68k macines (including the 520STF and 1020STE) divide
+ their addressible memory into ST and TT sections. The TT section
+@@ -961,7 +961,7 @@ config MVME147_SCC
+
+ config SERIAL167
+ bool "CD2401 support for MVME166/7 serial ports"
+- depends on MVME16x
++ depends on MVME16x && BROKEN
+ help
+ This is the driver for the serial ports on the Motorola MVME166,
+ 167, and 172 boards. Everyone using one of these boards should say
+--- linux-2.6.0-test6/arch/m68k/kernel/time.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/arch/m68k/kernel/time.c 2003-10-05 00:33:23.000000000 -0700
+@@ -171,3 +171,12 @@ int do_settimeofday(struct timespec *tv)
+ write_sequnlock_irq(&xtime_lock);
+ return 0;
+ }
++
++/*
++ * Scheduler clock - returns current time in ns units.
++ */
++unsigned long long sched_clock(void)
++{
++ return (unsigned long long)jiffies*(1000000000/HZ);
++}
++
+--- linux-2.6.0-test6/arch/m68k/Makefile 2003-07-27 12:14:38.000000000 -0700
++++ 25/arch/m68k/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -76,6 +76,8 @@ core-$(CONFIG_M68040) += arch/m68k/fpsp
+ core-$(CONFIG_M68060) += arch/m68k/ifpsp060/
+ core-$(CONFIG_M68KFPU_EMU) += arch/m68k/math-emu/
+
++all: zImage
++
+ lilo: vmlinux
+ if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
+ if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+--- linux-2.6.0-test6/arch/m68k/q40/q40ints.c 2003-07-27 12:14:38.000000000 -0700
++++ 25/arch/m68k/q40/q40ints.c 2003-10-05 00:33:23.000000000 -0700
+@@ -200,7 +200,9 @@ void q40_free_irq(unsigned int irq, void
+
+ irqreturn_t q40_process_int (int level, struct pt_regs *fp)
+ {
+- printk("unexpected interrupt %x\n",level);
++ printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",
++ level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);
++ printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));
+ return IRQ_HANDLED;
+ }
+
+@@ -378,7 +380,7 @@ irqreturn_t q40_irq2_handler (int vec, v
+ /*printk("reenabling irq %d\n",irq); */
+ #endif
+ }
+-// used to do 'goto repeat;' her, this delayed bh processing too long
++// used to do 'goto repeat;' here, this delayed bh processing too long
+ return IRQ_HANDLED;
+ }
+ }
+@@ -387,6 +389,7 @@ irqreturn_t q40_irq2_handler (int vec, v
+ }
+ iirq:
+ mir=master_inb(IIRQ_REG);
++ /* should test whether keyboard irq is really enabled, doing it in defhand */
+ if (mir&Q40_IRQ_KEYB_MASK) {
+ irq_tab[Q40_IRQ_KEYBOARD].count++;
+ irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
+@@ -413,7 +416,9 @@ int show_q40_interrupts (struct seq_file
+
+ static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+ {
+- printk ("Unknown q40 interrupt 0x%02x\n", irq);
++ if (irq!=Q40_IRQ_KEYBOARD)
++ printk ("Unknown q40 interrupt %d\n", irq);
++ else master_outb(-1,KEYBOARD_UNLOCK_REG);
+ return IRQ_NONE;
+ }
+ static irqreturn_t sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
+--- linux-2.6.0-test6/arch/m68k/sun3/config.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/arch/m68k/sun3/config.c 2003-10-05 00:33:23.000000000 -0700
+@@ -129,7 +129,7 @@ void __init sun3_bootmem_alloc(unsigned
+ high_memory = (void *)memory_end;
+ availmem = memory_start;
+
+- availmem += init_bootmem(start_page, num_pages);
++ availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
+ availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
+
+ free_bootmem(__pa(availmem), memory_end - (availmem));
+--- linux-2.6.0-test6/arch/mips/mm/ioremap.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/arch/mips/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -162,7 +162,7 @@ void * __ioremap(phys_t phys_addr, phys_
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vunmap(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/parisc/Kconfig 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/Kconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -150,6 +150,7 @@ config COMPAT
+
+ config HPUX
+ bool "Support for HP-UX binaries"
++ depends on !PARISC64
+
+ config NR_CPUS
+ int "Maximum number of CPUs (2-32)"
+@@ -190,6 +191,8 @@ source drivers/message/fusion/Kconfig
+
+ #source drivers/message/i2o/Kconfig
+
++source "net/Kconfig"
++
+ #source "drivers/isdn/Kconfig"
+
+ #source "drivers/telephony/Kconfig"
+--- linux-2.6.0-test6/arch/parisc/kernel/asm-offsets.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/parisc/kernel/asm-offsets.c 2003-10-05 00:33:23.000000000 -0700
+@@ -8,6 +8,7 @@
+ #include <linux/sched.h>
+ #include <linux/thread_info.h>
+ #include <linux/version.h>
++#include <linux/ptrace.h>
+
+ #include <asm/ptrace.h>
+ #include <asm/processor.h>
+@@ -249,5 +250,8 @@ int main(void)
+ DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count));
+ DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop));
+ BLANK();
++ DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT);
++ DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT);
++ BLANK();
+ return 0;
+ }
+--- linux-2.6.0-test6/arch/parisc/kernel/binfmt_elf32.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/parisc/kernel/binfmt_elf32.c 2003-10-05 00:33:23.000000000 -0700
+@@ -88,7 +88,9 @@ struct elf_prpsinfo32
+ */
+
+ #define SET_PERSONALITY(ex, ibcs2) \
+- current->personality = PER_LINUX_32BIT
++ current->personality = PER_LINUX32; \
++ current->thread.map_base = DEFAULT_MAP_BASE32; \
++ current->thread.task_size = DEFAULT_TASK_SIZE32 \
+
+ #define jiffies_to_timeval jiffies_to_compat_timeval
+ static __inline__ void
+@@ -99,3 +101,25 @@ jiffies_to_compat_timeval(unsigned long
+ }
+
+ #include "../../../fs/binfmt_elf.c"
++
++/* Set up a separate execution domain for ELF32 binaries running
++ * on an ELF64 kernel */
++
++static struct exec_domain parisc32_exec_domain = {
++ .name = "Linux/ELF32",
++ .pers_low = PER_LINUX32,
++ .pers_high = PER_LINUX32,
++};
++
++static int __init parisc32_exec_init(void)
++{
++ /* steal the identity signal mappings from the default domain */
++ parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
++ parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
++
++ register_exec_domain(&parisc32_exec_domain);
++
++ return 0;
++}
++
++__initcall(parisc32_exec_init);
+--- linux-2.6.0-test6/arch/parisc/kernel/drivers.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/drivers.c 2003-10-05 00:33:23.000000000 -0700
+@@ -28,6 +28,7 @@
+
+ /* See comments in include/asm-parisc/pci.h */
+ struct hppa_dma_ops *hppa_dma_ops;
++EXPORT_SYMBOL(hppa_dma_ops);
+
+ static struct parisc_device root;
+
+@@ -155,6 +156,7 @@ int register_parisc_driver(struct parisc
+
+ return driver_register(&driver->drv);
+ }
++EXPORT_SYMBOL(register_parisc_driver);
+
+ /**
+ * count_parisc_driver - count # of devices this driver would match
+@@ -187,6 +189,7 @@ int unregister_parisc_driver(struct pari
+ driver_unregister(&driver->drv);
+ return 0;
+ }
++EXPORT_SYMBOL(unregister_parisc_driver);
+
+ static struct parisc_device *find_device_by_addr(unsigned long hpa)
+ {
+@@ -257,7 +260,7 @@ char *print_pa_hwpath(struct parisc_devi
+ path.mod = dev->hw_path;
+ return print_hwpath(&path, output);
+ }
+-
++EXPORT_SYMBOL(print_pa_hwpath);
+
+ #if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+ /**
+@@ -289,6 +292,7 @@ void get_pci_node_path(struct pci_dev *d
+ padev = padev->parent;
+ }
+ }
++EXPORT_SYMBOL(get_pci_node_path);
+
+ /**
+ * print_pci_hwpath - Returns hardware path for PCI devices
+@@ -306,6 +310,8 @@ char *print_pci_hwpath(struct pci_dev *d
+ get_pci_node_path(dev, &path);
+ return print_hwpath(&path, output);
+ }
++EXPORT_SYMBOL(print_pci_hwpath);
++
+ #endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
+
+
+--- linux-2.6.0-test6/arch/parisc/kernel/entry.S 2003-06-16 22:32:20.000000000 -0700
++++ 25/arch/parisc/kernel/entry.S 2003-10-05 00:33:23.000000000 -0700
+@@ -2225,18 +2225,23 @@ syscall_exit:
+ LDREG TI_TASK(%r1),%r1
+ STREG %r28,TASK_PT_GR28(%r1)
+
+- /* Save other hpux returns if personality is PER_HPUX */
++#ifdef CONFIG_HPUX
+
+ /* <linux/personality.h> cannot be easily included */
+ #define PER_HPUX 0x10
+ LDREG TASK_PERSONALITY(%r1),%r19
+-#warning the ldo+CMPIB could probably be done better but 0x10 i soutside of range of CMPIB
++
++ /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
+ ldo -PER_HPUX(%r19), %r19
+ CMPIB<>,n 0,%r19,1f
++
++ /* Save other hpux returns if personality is PER_HPUX */
+ STREG %r22,TASK_PT_GR22(%r1)
+ STREG %r29,TASK_PT_GR29(%r1)
+ 1:
+
++#endif /* CONFIG_HPUX */
++
+ /* Seems to me that dp could be wrong here, if the syscall involved
+ * calling a module, and nothing got round to restoring dp on return.
+ */
+@@ -2315,18 +2320,16 @@ syscall_restore:
+ depi 3,31,2,%r31 /* ensure return to user mode. */
+
+ #ifdef __LP64__
+- /* Since we are returning to a 32 bit user process, we always
+- * clear the W bit. This means that the be (and mtsp) gets
+- * executed in narrow mode, but that is OK, since we are
+- * returning to a 32 bit process. When we support 64 bit processes
+- * we won't clear the W bit, so the be will run in wide mode.
+- */
+-
+- be 0(%sr3,%r31) /* return to user space */
++ /* decide whether to reset the wide mode bit
++ *
++ * For a syscall, the W bit is stored in the lowest bit
++ * of sp. Extract it and reset W if it is zero */
++ extrd,u,*<> %r30,63,1,%r1
+ rsm PSW_SM_W, %r0
+-#else
+- be,n 0(%sr3,%r31) /* return to user space */
++ /* now reset the lowest bit of sp if it was set */
++ xor %r30,%r1,%r30
+ #endif
++ be,n 0(%sr3,%r31) /* return to user space */
+
+ /* We have to return via an RFI, so that PSW T and R bits can be set
+ * appropriately.
+@@ -2340,12 +2343,19 @@ syscall_restore_rfi:
+ LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
+ ldi 0x0b,%r20 /* Create new PSW */
+ depi -1,13,1,%r20 /* C, Q, D, and I bits */
+- bb,>=,n %r19,15,try_tbit /* PT_SINGLESTEP */
++
++ /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
++ * set in include/linux/ptrace.h and converted to PA bitmap
++ * numbers in asm-offsets.c */
++
++ /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
++ extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
+ depi -1,27,1,%r20 /* R bit */
+-try_tbit:
+- bb,>=,n %r19,14,psw_setup /* PT_BLOCKSTEP, see ptrace.c */
++
++ /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
++ extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
+ depi -1,7,1,%r20 /* T bit */
+-psw_setup:
++
+ STREG %r20,TASK_PT_PSW(%r1)
+
+ /* Always store space registers, since sr3 can be changed (e.g. fork) */
+--- linux-2.6.0-test6/arch/parisc/kernel/firmware.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/parisc/kernel/firmware.c 2003-10-05 00:33:23.000000000 -0700
+@@ -41,19 +41,20 @@
+ * prumpf 991016
+ */
+
++#include <stdarg.h>
++
++#include <linux/delay.h>
++#include <linux/init.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/spinlock.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+
+ #include <asm/page.h>
+ #include <asm/pdc.h>
+ #include <asm/system.h>
+ #include <asm/processor.h> /* for boot_cpu_data */
+
+-#include <stdarg.h>
+-
+ static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
+ static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
+ static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
+@@ -151,6 +152,7 @@ int pdc_add_valid(unsigned long address)
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_add_valid);
+
+ /**
+ * pdc_chassis_info - Return chassis information.
+@@ -264,6 +266,7 @@ int pdc_iodc_read(unsigned long *actcnt,
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_iodc_read);
+
+ /**
+ * pdc_system_map_find_mods - Locate unarchitected modules.
+@@ -518,6 +521,7 @@ int pdc_lan_station_id(char *lan_addr, u
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_lan_station_id);
+
+
+ /**
+@@ -594,6 +598,7 @@ int pdc_get_initiator( struct hardware_p
+ spin_unlock_irq(&pdc_lock);
+ return retval >= PDC_OK;
+ }
++EXPORT_SYMBOL(pdc_get_initiator);
+
+
+ /**
+@@ -660,6 +665,7 @@ int pdc_tod_read(struct pdc_tod *tod)
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_tod_read);
+
+ /**
+ * pdc_tod_set - Set the Time-Of-Day clock.
+@@ -678,6 +684,7 @@ int pdc_tod_set(unsigned long sec, unsig
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_tod_set);
+
+ #ifdef __LP64__
+ int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
+@@ -772,20 +779,34 @@ int pdc_soft_power_button(int sw_control
+ }
+
+ /*
+- * pdc_suspend_usb - Stop USB controller
++ * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices.
++ * Primarily a problem on T600 (which parisc-linux doesn't support) but
++ * who knows what other platform firmware might do with this OS "hook".
++ */
++void pdc_io_reset(void)
++{
++ spin_lock_irq(&pdc_lock);
++ mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
++ spin_unlock_irq(&pdc_lock);
++}
++
++/*
++ * pdc_io_reset_devices - Hack to Stop USB controller
+ *
+ * If PDC used the usb controller, the usb controller
+ * is still running and will crash the machines during iommu
+ * setup, because of still running DMA. This PDC call
+- * stops the USB controller
++ * stops the USB controller.
++ * Normally called after calling pdc_io_reset().
+ */
+-void pdc_suspend_usb(void)
++void pdc_io_reset_devices(void)
+ {
+ spin_lock_irq(&pdc_lock);
+- mem_pdc_call(PDC_IO, PDC_IO_SUSPEND_USB, 0);
++ mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
+ spin_unlock_irq(&pdc_lock);
+ }
+
++
+ /**
+ * pdc_iodc_putc - Console character print using IODC.
+ * @c: the character to output.
+@@ -905,6 +926,7 @@ int pdc_sti_call(unsigned long func, uns
+
+ return retval;
+ }
++EXPORT_SYMBOL(pdc_sti_call);
+
+ #ifdef __LP64__
+ /**
+--- linux-2.6.0-test6/arch/parisc/kernel/inventory.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/parisc/kernel/inventory.c 2003-10-05 00:33:23.000000000 -0700
+@@ -526,12 +526,14 @@ static void __init system_map_inventory(
+ int i;
+ long status = PDC_OK;
+
++#if defined(CONFIG_IOMMU_SBA) && defined(CONFIG_SUPERIO)
+ /*
+- * first stop the usb controller, otherwise the machine
+- * might crash during iommu setup
++ * Stop the suckyio usb controller on Astro based systems.
++ * Otherwise the machine might crash during iommu setup.
+ */
+-#warning We still probably need to worry about USB here, but how?
+- /* pdc_suspend_usb(); */
++ pdc_io_reset();
++ pdc_io_reset_devices();
++#endif
+
+ for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) {
+ struct parisc_device *dev;
+--- linux-2.6.0-test6/arch/parisc/kernel/irq.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/irq.c 2003-10-05 00:33:23.000000000 -0700
+@@ -193,6 +193,7 @@ void disable_irq(int irq)
+ else
+ BUG();
+ }
++EXPORT_SYMBOL(disable_irq);
+
+ void enable_irq(int irq)
+ {
+@@ -208,6 +209,7 @@ void enable_irq(int irq)
+ else
+ BUG();
+ }
++EXPORT_SYMBOL(enable_irq);
+
+ int show_interrupts(struct seq_file *p, void *v)
+ {
+@@ -698,6 +700,7 @@ void synchronize_irq(unsigned int irqnum
+ {
+ while (in_irq()) ;
+ }
++EXPORT_SYMBOL(synchronize_irq);
+ #endif
+
+
+@@ -847,6 +850,7 @@ unsigned int probe_irq_mask(unsigned lon
+ {
+ return 0;
+ }
++EXPORT_SYMBOL(probe_irq_mask);
+
+ void __init init_IRQ(void)
+ {
+--- linux-2.6.0-test6/arch/parisc/kernel/module.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/module.c 2003-10-05 00:33:23.000000000 -0700
+@@ -73,10 +73,7 @@ struct got_entry {
+ Elf32_Addr addr;
+ };
+
+-struct fdesc_entry {
+- Elf32_Addr addr;
+- Elf32_Addr gp;
+-};
++#define Elf_Fdesc Elf32_Fdesc
+
+ struct stub_entry {
+ Elf32_Word insns[2]; /* each stub entry has two insns */
+@@ -86,11 +83,7 @@ struct got_entry {
+ Elf64_Addr addr;
+ };
+
+-struct fdesc_entry {
+- Elf64_Addr dummy[2];
+- Elf64_Addr addr;
+- Elf64_Addr gp;
+-};
++#define Elf_Fdesc Elf64_Fdesc
+
+ struct stub_entry {
+ Elf64_Word insns[4]; /* each stub entry has four insns */
+@@ -276,7 +269,7 @@ int module_frob_arch_sections(CONST Elf_
+
+ me->core_size = ALIGN(me->core_size, 16);
+ me->arch.fdesc_offset = me->core_size;
+- me->core_size += fdescs * sizeof(struct fdesc_entry);
++ me->core_size += fdescs * sizeof(Elf_Fdesc);
+
+ me->core_size = ALIGN(me->core_size, 16);
+ me->arch.stub_offset = me->core_size;
+@@ -322,7 +315,7 @@ static Elf64_Word get_got(struct module
+ #ifdef __LP64__
+ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
+ {
+- struct fdesc_entry *fdesc = me->module_core + me->arch.fdesc_offset;
++ Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
+
+ if (!value) {
+ printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
+@@ -664,7 +657,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs
+ *loc64 = get_fdesc(me, val+addend);
+ DEBUGP("FDESC for %s at %p points to %lx\n",
+ strtab + sym->st_name, *loc64,
+- ((struct fdesc_entry *)*loc64)->addr);
++ ((Elf_Fdesc *)*loc64)->addr);
+ } else {
+ /* if the symbol is not local to this
+ * module then val+addend is a pointer
+@@ -696,10 +689,10 @@ int module_finalize(const Elf_Ehdr *hdr,
+ Elf_Sym *newptr, *oldptr;
+ Elf_Shdr *symhdr = NULL;
+ #ifdef DEBUG
+- struct fdesc_entry *entry;
++ Elf_Fdesc *entry;
+ u32 *addr;
+
+- entry = (struct fdesc_entry *)me->init;
++ entry = (Elf_Fdesc *)me->init;
+ printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
+ entry->gp, entry->addr);
+ addr = (u32 *)entry->addr;
+--- linux-2.6.0-test6/arch/parisc/kernel/parisc_ksyms.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/parisc_ksyms.c 2003-10-05 00:33:23.000000000 -0700
+@@ -26,19 +26,6 @@ EXPORT_SYMBOL(strrchr);
+ EXPORT_SYMBOL(strstr);
+ EXPORT_SYMBOL(strpbrk);
+
+-#include <asm/hardware.h> /* struct parisc_device for asm/pci.h */
+-#include <linux/pci.h>
+-EXPORT_SYMBOL(hppa_dma_ops);
+-#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+-EXPORT_SYMBOL(get_pci_node_path);
+-#endif
+-
+-#include <linux/sched.h>
+-#include <asm/irq.h>
+-EXPORT_SYMBOL(enable_irq);
+-EXPORT_SYMBOL(disable_irq);
+-EXPORT_SYMBOL(probe_irq_mask);
+-
+ #include <asm/processor.h>
+ EXPORT_SYMBOL(kernel_thread);
+ EXPORT_SYMBOL(boot_cpu_data);
+@@ -46,10 +33,6 @@ EXPORT_SYMBOL(boot_cpu_data);
+ #include <linux/pm.h>
+ EXPORT_SYMBOL(pm_power_off);
+
+-#ifdef CONFIG_SMP
+-EXPORT_SYMBOL(synchronize_irq);
+-#endif /* CONFIG_SMP */
+-
+ #include <asm/atomic.h>
+ EXPORT_SYMBOL(__xchg8);
+ EXPORT_SYMBOL(__xchg32);
+@@ -74,14 +57,6 @@ extern int $global$;
+ EXPORT_SYMBOL($global$);
+ #endif
+
+-EXPORT_SYMBOL(register_parisc_driver);
+-EXPORT_SYMBOL(unregister_parisc_driver);
+-EXPORT_SYMBOL(print_pci_hwpath);
+-EXPORT_SYMBOL(print_pa_hwpath);
+-EXPORT_SYMBOL(pdc_iodc_read);
+-EXPORT_SYMBOL(pdc_tod_read);
+-EXPORT_SYMBOL(pdc_tod_set);
+-
+ #include <asm/io.h>
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+@@ -89,22 +64,6 @@ EXPORT_SYMBOL(__memcpy_toio);
+ EXPORT_SYMBOL(__memcpy_fromio);
+ EXPORT_SYMBOL(__memset_io);
+
+-#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+-EXPORT_SYMBOL(inb);
+-EXPORT_SYMBOL(inw);
+-EXPORT_SYMBOL(inl);
+-EXPORT_SYMBOL(outb);
+-EXPORT_SYMBOL(outw);
+-EXPORT_SYMBOL(outl);
+-
+-EXPORT_SYMBOL(insb);
+-EXPORT_SYMBOL(insw);
+-EXPORT_SYMBOL(insl);
+-EXPORT_SYMBOL(outsb);
+-EXPORT_SYMBOL(outsw);
+-EXPORT_SYMBOL(outsl);
+-#endif
+-
+ #include <asm/cache.h>
+ EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
+ EXPORT_SYMBOL(flush_kernel_dcache_page);
+@@ -130,17 +89,6 @@ EXPORT_SYMBOL(__up);
+ EXPORT_SYMBOL(__down_interruptible);
+ EXPORT_SYMBOL(__down);
+
+-#include <linux/in6.h>
+-#include <asm/checksum.h>
+-EXPORT_SYMBOL(csum_partial_copy_nocheck);
+-EXPORT_SYMBOL(csum_partial_copy_from_user);
+-
+-#include <asm/pdc.h>
+-EXPORT_SYMBOL(pdc_add_valid);
+-EXPORT_SYMBOL(pdc_lan_station_id);
+-EXPORT_SYMBOL(pdc_get_initiator);
+-EXPORT_SYMBOL(pdc_sti_call);
+-
+ extern void $$divI(void);
+ extern void $$divU(void);
+ extern void $$remI(void);
+@@ -218,6 +166,3 @@ EXPORT_SYMBOL(__moddi3);
+ extern void $$dyncall(void);
+ EXPORT_SYMBOL($$dyncall);
+ #endif
+-
+-#include <asm/pgtable.h>
+-EXPORT_SYMBOL(vmalloc_start);
+--- linux-2.6.0-test6/arch/parisc/kernel/pci.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/pci.c 2003-10-05 00:33:23.000000000 -0700
+@@ -88,7 +88,8 @@ u##size in##type (int addr) \
+ EISA_IN(size); \
+ if (!parisc_pci_hba[b]) return (u##size) -1; \
+ return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
+-}
++} \
++EXPORT_SYMBOL(in##type);
+
+ PCI_PORT_IN(b, 8)
+ PCI_PORT_IN(w, 16)
+@@ -102,7 +103,8 @@ void out##type (u##size d, int addr) \
+ EISA_OUT(size); \
+ if (!parisc_pci_hba[b]) return; \
+ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
+-}
++} \
++EXPORT_SYMBOL(out##type);
+
+ PCI_PORT_OUT(b, 8)
+ PCI_PORT_OUT(w, 16)
+--- linux-2.6.0-test6/arch/parisc/kernel/ptrace.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/parisc/kernel/ptrace.c 2003-10-05 00:33:23.000000000 -0700
+@@ -23,16 +23,6 @@
+ #include <asm/processor.h>
+ #include <asm/offsets.h>
+
+-/* These are used in entry.S, syscall_restore_rfi. We need to record the
+- * current stepping mode somewhere other than in PSW, because there is no
+- * concept of saving and restoring the users PSW over a syscall. We choose
+- * to use these two bits in task->ptrace. These bits must not clash with
+- * any PT_* defined in include/linux/sched.h, and must match with the bit
+- * tests in entry.S
+- */
+-#define PT_SINGLESTEP 0x10000
+-#define PT_BLOCKSTEP 0x20000
+-
+ /* PSW bits we allow the debugger to modify */
+ #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
+
+--- linux-2.6.0-test6/arch/parisc/kernel/setup.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/setup.c 2003-10-05 00:33:23.000000000 -0700
+@@ -43,6 +43,7 @@
+ #include <asm/led.h>
+ #include <asm/machdep.h> /* for pa7300lc_init() proto */
+ #include <asm/pdc_chassis.h>
++#include <asm/io.h>
+
+ #define COMMAND_LINE_SIZE 1024
+ char saved_command_line[COMMAND_LINE_SIZE];
+@@ -208,27 +209,32 @@ static void __init parisc_proc_mkdir(voi
+ proc_runway_root = proc_mkdir("bus/runway", 0);
+ }
+ break;
++ default:
++ /* FIXME: this was added to prevent the compiler
++ * complaining about missing pcx, pcxs and pcxt
++ * I'm assuming they have neither gsc nor runway */
++ break;
+ }
+ }
+
+ static struct resource central_bus = {
+ .name = "Central Bus",
+- .start = (unsigned long)0xfffffffffff80000,
+- .end = (unsigned long)0xfffffffffffaffff,
++ .start = F_EXTEND(0xfff80000),
++ .end = F_EXTEND(0xfffaffff),
+ .flags = IORESOURCE_MEM,
+ };
+
+ static struct resource local_broadcast = {
+ .name = "Local Broadcast",
+- .start = (unsigned long)0xfffffffffffb0000,
+- .end = (unsigned long)0xfffffffffffdffff,
++ .start = F_EXTEND(0xfffb0000),
++ .end = F_EXTEND(0xfffdffff),
+ .flags = IORESOURCE_MEM,
+ };
+
+ static struct resource global_broadcast = {
+ .name = "Global Broadcast",
+- .start = (unsigned long)0xfffffffffffe0000,
+- .end = (unsigned long)0xffffffffffffffff,
++ .start = F_EXTEND(0xfffe0000),
++ .end = F_EXTEND(0xffffffff),
+ .flags = IORESOURCE_MEM,
+ };
+
+--- linux-2.6.0-test6/arch/parisc/kernel/signal.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/signal.c 2003-10-05 00:33:23.000000000 -0700
+@@ -25,6 +25,8 @@
+ #include <linux/unistd.h>
+ #include <linux/stddef.h>
+ #include <linux/compat.h>
++#include <linux/elf.h>
++#include <linux/personality.h>
+ #include <asm/ucontext.h>
+ #include <asm/rt_sigframe.h>
+ #include <asm/uaccess.h>
+@@ -41,8 +43,11 @@
+
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+-/* Use this to get at 32-bit user passed pointers.
+- * See sys_sparc32.c for description about these. */
++/* gcc will complain if a pointer is cast to an integer of different
++ * size. If you really need to do this (and we do for an ELF32 user
++ * application in an ELF64 kernel) then you have to do a cast to an
++ * integer of the same size first. The A() macro accomplishes
++ * this. */
+ #define A(__x) ((unsigned long)(__x))
+
+ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
+@@ -166,11 +171,17 @@ sys_rt_sigreturn(struct pt_regs *regs, i
+ struct rt_sigframe *frame;
+ struct siginfo si;
+ sigset_t set;
+- unsigned long usp = regs->gr[30];
++ unsigned long usp = (regs->gr[30] & ~(0x01UL));
++ unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
++#ifdef __LP64__
++ if(personality(current->personality) == PER_LINUX32)
++ sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
++#endif
++
+
+ /* Unwind the user stack to get the rt_sigframe structure. */
+ frame = (struct rt_sigframe *)
+- (usp - PARISC_RT_SIGFRAME_SIZE);
++ (usp - sigframe_size);
+ DBG(("in sys_rt_sigreturn, frame is %p\n", frame));
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+@@ -271,11 +282,12 @@ setup_rt_frame(int sig, struct k_sigacti
+ sigset_t *set, struct pt_regs *regs, int in_syscall)
+ {
+ struct rt_sigframe *frame;
+- unsigned long rp, usp, haddr;
++ unsigned long rp, usp;
++ unsigned long haddr, sigframe_size;
+ struct siginfo si;
+ int err = 0;
+
+- usp = regs->gr[30];
++ usp = (regs->gr[30] & ~(0x01UL));
+ frame = get_sigframe(ka, usp, sizeof(*frame));
+
+ DBG(("setup_rt_frame 1: frame %p info %p\n", frame, info));
+@@ -308,64 +320,86 @@ setup_rt_frame(int sig, struct k_sigacti
+ }
+ #endif
+
+-#undef CACHE_FLUSHING_IS_NOT_BROKEN
+-#ifdef CACHE_FLUSHING_IS_NOT_BROKEN
++ flush_user_dcache_range((unsigned long) &frame->tramp[0],
++ (unsigned long) &frame->tramp[4]);
+ flush_user_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[4]);
+-#else
+- /* It should *always* be cache line-aligned, but the compiler
+- sometimes screws up. */
+- asm volatile("fdc 0(%%sr3,%0)\n\t"
+- "fdc %1(%%sr3,%0)\n\t"
+- "sync\n\t"
+- "fic 0(%%sr3,%0)\n\t"
+- "fic %1(%%sr3,%0)\n\t"
+- "sync\n\t"
+- : : "r" (frame->tramp), "r" (L1_CACHE_BYTES));
+-#endif
+
+ rp = (unsigned long) frame->tramp;
+
+ if (err)
+ goto give_sigsegv;
+
+-/* Much more has to happen with signals than this -- but it'll at least */
+-/* provide a pointer to some places which definitely need a look. */
+-#define HACK u32
+-
+- haddr = (HACK)A(ka->sa.sa_handler);
+- /* ARGH! Fucking brain damage. You don't want to know. */
+- if (haddr & 2) {
+- HACK *plabel;
+- HACK ltp;
+-
+- plabel = (HACK *) (haddr & ~3);
+- err |= __get_user(haddr, plabel);
+- err |= __get_user(ltp, plabel + 1);
++ haddr = A(ka->sa.sa_handler);
++ /* The sa_handler may be a pointer to a function descriptor */
++#ifdef __LP64__
++ if(personality(current->personality) == PER_LINUX32) {
++#endif
++ if (haddr & PA_PLABEL_FDESC) {
++ Elf32_Fdesc fdesc;
++ Elf32_Fdesc *ufdesc = (Elf32_Fdesc *)A(haddr & ~3);
++
++ err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
++
++ if (err)
++ goto give_sigsegv;
++
++ haddr = fdesc.addr;
++ regs->gr[19] = fdesc.gp;
++ }
++#ifdef __LP64__
++ } else {
++ Elf64_Fdesc fdesc;
++ Elf64_Fdesc *ufdesc = (Elf64_Fdesc *)A(haddr & ~3);
++
++ err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
++
+ if (err)
+ goto give_sigsegv;
+- regs->gr[19] = ltp;
++
++ haddr = fdesc.addr;
++ regs->gr[19] = fdesc.gp;
++ DBG(("64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
++ haddr, regs->gr[19], in_syscall));
+ }
++#endif
+
+ /* The syscall return path will create IAOQ values from r31.
+ */
+- if (in_syscall)
+- regs->gr[31] = (HACK) haddr;
+- else {
+- regs->gr[0] = USER_PSW;
+- regs->iaoq[0] = (HACK) haddr | 3;
++ sigframe_size = PARISC_RT_SIGFRAME_SIZE;
++#ifdef __LP64__
++ if(personality(current->personality) == PER_LINUX32)
++ sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
++#endif
++ if (in_syscall) {
++ regs->gr[31] = haddr;
++#ifdef __LP64__
++ if(personality(current->personality) == PER_LINUX)
++ sigframe_size |= 1;
++#endif
++ } else {
++ unsigned long psw = USER_PSW;
++#ifdef __LP64__
++ if(personality(current->personality) == PER_LINUX)
++ psw |= PSW_W;
++#endif
++
++ regs->gr[0] = psw;
++ regs->iaoq[0] = haddr | 3;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ }
+
+ regs->gr[2] = rp; /* userland return pointer */
+ regs->gr[26] = sig; /* signal number */
+- regs->gr[25] = (HACK)A(&frame->info); /* siginfo pointer */
+- regs->gr[24] = (HACK)A(&frame->uc); /* ucontext pointer */
++ regs->gr[25] = A(&frame->info); /* siginfo pointer */
++ regs->gr[24] = A(&frame->uc); /* ucontext pointer */
++
+ DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",
+- regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
+- regs->gr[30] + PARISC_RT_SIGFRAME_SIZE));
++ regs->gr[30], sigframe_size,
++ regs->gr[30] + sigframe_size));
+ /* Raise the user stack pointer to make a proper call frame. */
+- regs->gr[30] = ((HACK)A(frame) + PARISC_RT_SIGFRAME_SIZE);
++ regs->gr[30] = (A(frame) + sigframe_size);
++
+
+ DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+ current->comm, current->pid, frame, regs->gr[30],
+--- linux-2.6.0-test6/arch/parisc/kernel/syscall.S 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/syscall.S 2003-10-05 00:33:23.000000000 -0700
+@@ -69,9 +69,14 @@ linux_gateway_entry:
+ * exit from the syscall, and also use that value to know
+ * whether to do narrow or wide syscalls. -PB
+ */
+- ssm PSW_SM_W, %r0
++ ssm PSW_SM_W, %r1
++ extrd,u %r1,PSW_W_BIT,1,%r1
++ /* sp must be aligned on 4, so deposit the W bit setting into
++ * the bottom of sp temporarily */
++ or,ev %r1,%r30,%r30
++ b,n 1f
+ /* The top halves of argument registers must be cleared on syscall
+- * entry.
++ * entry from narrow executable.
+ */
+ depdi 0, 31, 32, %r26
+ depdi 0, 31, 32, %r25
+@@ -79,11 +84,13 @@ linux_gateway_entry:
+ depdi 0, 31, 32, %r23
+ depdi 0, 31, 32, %r22
+ depdi 0, 31, 32, %r21
++1:
+ #endif
+ mfctl %cr30,%r1
+ xor %r1,%r30,%r30 /* ye olde xor trick */
+ xor %r1,%r30,%r1
+ xor %r1,%r30,%r30
++
+ ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
+
+ /* N.B.: It is critical that we don't set sr7 to 0 until r30
+@@ -104,9 +111,19 @@ linux_gateway_entry:
+ PSW value is stored. This is needed for gdb and sys_ptrace. */
+ STREG %r0, TASK_PT_PSW(%r1)
+ STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
++ STREG %r19, TASK_PT_GR19(%r1)
++
+ LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */
++#ifdef __LP64__
++ extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */
++#if 0
++ xor %r19,%r2,%r2 /* clear bottom bit */
++ depd,z %r19,1,1,%r19
++ std %r19,TASK_PT_PSW(%r1)
++#endif
++#endif
+ STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
+- STREG %r19, TASK_PT_GR19(%r1)
++
+ STREG %r20, TASK_PT_GR20(%r1)
+ STREG %r21, TASK_PT_GR21(%r1)
+ STREG %r22, TASK_PT_GR22(%r1)
+@@ -130,6 +147,7 @@ linux_gateway_entry:
+
+ #ifdef __LP64__
+ ldo -16(%r30),%r29 /* Reference param save area */
++ copy %r19,%r2 /* W bit back to r2 */
+ #else
+ /* no need to save these on stack in wide mode because the first 8
+ * args are passed in registers */
+@@ -144,9 +162,17 @@ linux_gateway_entry:
+ /* Note! We cannot use the syscall table that is mapped
+ nearby since the gateway page is mapped execute-only. */
+
++#ifdef __LP64__
++ ldil L%sys_call_table, %r1
++ or,= %r2,%r2,%r2
++ addil L%(sys_call_table64-sys_call_table), %r1
++ ldo R%sys_call_table(%r1), %r19
++ or,= %r2,%r2,%r2
++ ldo R%sys_call_table64(%r1), %r19
++#else
+ ldil L%sys_call_table, %r1
+ ldo R%sys_call_table(%r1), %r19
+-
++#endif
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+@@ -317,304 +343,21 @@ tracesys_sigexit:
+ ldil L%syscall_exit_rfi,%r1
+ be,n R%syscall_exit_rfi(%sr7,%r1)
+
+-#ifdef __LP64__
+-/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
+- * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
+- * implementation is required on wide palinux. Use ENTRY_COMP where
+- * the compatability layer has a useful 32-bit implementation.
+- */
+-#define ENTRY_SAME(_name_) .dword sys_##_name_
+-#define ENTRY_DIFF(_name_) .dword sys32_##_name_
+-#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
+-#define ENTRY_OURS(_name_) .dword parisc_##_name_
+-#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
+-#else
+-#define ENTRY_SAME(_name_) .word sys_##_name_
+-#define ENTRY_DIFF(_name_) .word sys_##_name_
+-#define ENTRY_UHOH(_name_) .word sys_##_name_
+-#define ENTRY_OURS(_name_) .word parisc_##_name_
+-#define ENTRY_COMP(_name_) .word sys_##_name_
+-#endif
+-
+- .align 8
++ .align 4096
+ .export sys_call_table
+ .Lsys_call_table:
+ sys_call_table:
+- ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
+- ENTRY_SAME(exit)
+- ENTRY_SAME(fork_wrapper)
+- ENTRY_SAME(read)
+- ENTRY_SAME(write)
+- ENTRY_SAME(open) /* 5 */
+- ENTRY_SAME(close)
+- ENTRY_SAME(waitpid)
+- ENTRY_SAME(creat)
+- ENTRY_SAME(link)
+- ENTRY_SAME(unlink) /* 10 */
+- ENTRY_DIFF(execve_wrapper)
+- ENTRY_SAME(chdir)
+- /* See comments in kernel/time.c!!! Maybe we don't need this? */
+- ENTRY_DIFF(time)
+- ENTRY_SAME(mknod)
+- ENTRY_SAME(chmod) /* 15 */
+- ENTRY_SAME(lchown)
+- ENTRY_SAME(socket)
+- /* struct stat is MAYBE identical wide and narrow ?? */
+- ENTRY_COMP(newstat)
+- ENTRY_DIFF(lseek)
+- ENTRY_SAME(getpid) /* 20 */
+- /* the 'void * data' parameter may need re-packing in wide */
+- ENTRY_DIFF(mount)
+- /* concerned about struct sockaddr in wide/narrow */
+- /* ---> I think sockaddr is OK unless the compiler packs the struct */
+- /* differently to align the char array */
+- ENTRY_SAME(bind)
+- ENTRY_SAME(setuid)
+- ENTRY_SAME(getuid)
+- ENTRY_SAME(stime) /* 25 */
+- ENTRY_SAME(ptrace)
+- ENTRY_SAME(alarm)
+- /* see stat comment */
+- ENTRY_COMP(newfstat)
+- ENTRY_SAME(pause)
+- /* struct utimbuf uses time_t which might vary */
+- ENTRY_COMP(utime) /* 30 */
+- /* struct sockaddr... */
+- ENTRY_SAME(connect)
+- ENTRY_SAME(listen)
+- ENTRY_SAME(access)
+- ENTRY_SAME(nice)
+- /* struct sockaddr... */
+- ENTRY_SAME(accept) /* 35 */
+- ENTRY_SAME(sync)
+- ENTRY_SAME(kill)
+- ENTRY_SAME(rename)
+- ENTRY_SAME(mkdir)
+- ENTRY_SAME(rmdir) /* 40 */
+- ENTRY_SAME(dup)
+- ENTRY_SAME(pipe)
+- ENTRY_COMP(times)
+- /* struct sockaddr... */
+- ENTRY_SAME(getsockname)
+- /* it seems possible brk() could return a >4G pointer... */
+- ENTRY_SAME(brk) /* 45 */
+- ENTRY_SAME(setgid)
+- ENTRY_SAME(getgid)
+- ENTRY_SAME(signal)
+- ENTRY_SAME(geteuid)
+- ENTRY_SAME(getegid) /* 50 */
+- ENTRY_SAME(acct)
+- ENTRY_SAME(umount)
+- /* struct sockaddr... */
+- ENTRY_SAME(getpeername)
+- ENTRY_COMP(ioctl)
+- ENTRY_COMP(fcntl) /* 55 */
+- ENTRY_SAME(socketpair)
+- ENTRY_SAME(setpgid)
+- ENTRY_SAME(send)
+- ENTRY_SAME(newuname)
+- ENTRY_SAME(umask) /* 60 */
+- ENTRY_SAME(chroot)
+- ENTRY_SAME(ustat)
+- ENTRY_SAME(dup2)
+- ENTRY_SAME(getppid)
+- ENTRY_SAME(getpgrp) /* 65 */
+- ENTRY_SAME(setsid)
+- ENTRY_SAME(pivot_root)
+- /* I don't like this */
+- ENTRY_UHOH(sgetmask)
+- ENTRY_UHOH(ssetmask)
+- ENTRY_SAME(setreuid) /* 70 */
+- ENTRY_SAME(setregid)
+- ENTRY_SAME(mincore)
+- ENTRY_COMP(sigpending)
+- ENTRY_SAME(sethostname)
+- /* Following 3 have linux-common-code structs containing longs -( */
+- ENTRY_COMP(setrlimit) /* 75 */
+- ENTRY_COMP(getrlimit)
+- ENTRY_COMP(getrusage)
+- /* struct timeval and timezone are maybe?? consistent wide and narrow */
+- ENTRY_DIFF(gettimeofday)
+- ENTRY_DIFF(settimeofday)
+- ENTRY_SAME(getgroups) /* 80 */
+- ENTRY_SAME(setgroups)
+- /* struct socketaddr... */
+- ENTRY_SAME(sendto)
+- ENTRY_SAME(symlink)
+- /* see stat comment */
+- ENTRY_COMP(newlstat)
+- ENTRY_SAME(readlink) /* 85 */
+- ENTRY_SAME(ni_syscall) /* was uselib */
+- ENTRY_SAME(swapon)
+- ENTRY_SAME(reboot)
+- ENTRY_SAME(mmap2)
+- ENTRY_SAME(mmap) /* 90 */
+- ENTRY_SAME(munmap)
+- ENTRY_SAME(truncate)
+- ENTRY_SAME(ftruncate)
+- ENTRY_SAME(fchmod)
+- ENTRY_SAME(fchown) /* 95 */
+- ENTRY_SAME(getpriority)
+- ENTRY_SAME(setpriority)
+- ENTRY_SAME(recv)
+- ENTRY_COMP(statfs)
+- ENTRY_COMP(fstatfs) /* 100 */
+- ENTRY_SAME(stat64)
+- ENTRY_SAME(ni_syscall) /* was socketcall */
+- ENTRY_SAME(syslog)
+- /* even though manpage says struct timeval contains longs, ours has
+- * time_t and suseconds_t -- both of which are safe wide/narrow */
+- ENTRY_COMP(setitimer)
+- ENTRY_COMP(getitimer) /* 105 */
+- ENTRY_SAME(capget)
+- ENTRY_SAME(capset)
+- ENTRY_OURS(pread64)
+- ENTRY_OURS(pwrite64)
+- ENTRY_SAME(getcwd) /* 110 */
+- ENTRY_SAME(vhangup)
+- ENTRY_SAME(fstat64)
+- ENTRY_SAME(vfork_wrapper)
+- /* struct rusage contains longs... */
+- ENTRY_COMP(wait4)
+- ENTRY_SAME(swapoff) /* 115 */
+- ENTRY_DIFF(sysinfo)
+- ENTRY_SAME(shutdown)
+- ENTRY_SAME(fsync)
+- ENTRY_SAME(madvise)
+- ENTRY_SAME(clone_wrapper) /* 120 */
+- ENTRY_SAME(setdomainname)
+- ENTRY_DIFF(sendfile)
+- /* struct sockaddr... */
+- ENTRY_SAME(recvfrom)
+- /* struct timex contains longs */
+- ENTRY_DIFF(adjtimex)
+- ENTRY_SAME(mprotect) /* 125 */
+- /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
+- ENTRY_COMP(sigprocmask)
+- ENTRY_SAME(ni_syscall) /* create_module */
+- ENTRY_SAME(init_module)
+- ENTRY_SAME(delete_module)
+- ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
+- /* time_t inside struct dqblk */
+- ENTRY_SAME(quotactl)
+- ENTRY_SAME(getpgid)
+- ENTRY_SAME(fchdir)
+- ENTRY_SAME(bdflush)
+- ENTRY_SAME(sysfs) /* 135 */
+- ENTRY_SAME(personality)
+- ENTRY_SAME(ni_syscall) /* for afs_syscall */
+- ENTRY_SAME(setfsuid)
+- ENTRY_SAME(setfsgid)
+- /* I think this might work */
+- ENTRY_SAME(llseek) /* 140 */
+- /* struct linux_dirent has longs, like 'unsigned long d_ino' which
+- * almost definitely should be 'ino_t d_ino' but it's too late now */
+- ENTRY_DIFF(getdents)
+- /* it is POSSIBLE that select will be OK because even though fd_set
+- * contains longs, the macros and sizes are clever. */
+- ENTRY_DIFF(select)
+- ENTRY_SAME(flock)
+- ENTRY_SAME(msync)
+- /* struct iovec contains pointers */
+- ENTRY_DIFF(readv) /* 145 */
+- ENTRY_DIFF(writev)
+- ENTRY_SAME(getsid)
+- ENTRY_SAME(fdatasync)
+- /* struct __sysctl_args is a mess */
+- ENTRY_DIFF(sysctl)
+- ENTRY_SAME(mlock) /* 150 */
+- ENTRY_SAME(munlock)
+- ENTRY_SAME(mlockall)
+- ENTRY_SAME(munlockall)
+- /* struct sched_param is ok for now */
+- ENTRY_SAME(sched_setparam)
+- ENTRY_SAME(sched_getparam) /* 155 */
+- ENTRY_SAME(sched_setscheduler)
+- ENTRY_SAME(sched_getscheduler)
+- ENTRY_SAME(sched_yield)
+- ENTRY_SAME(sched_get_priority_max)
+- ENTRY_SAME(sched_get_priority_min) /* 160 */
+- /* These 2 would've worked if someone had defined struct timespec
+- * carefully, like timeval for example (which is about the same).
+- * Unfortunately it contains a long :-( */
+- ENTRY_DIFF(sched_rr_get_interval)
+- ENTRY_COMP(nanosleep)
+- ENTRY_SAME(mremap)
+- ENTRY_SAME(setresuid)
+- ENTRY_SAME(getresuid) /* 165 */
+- ENTRY_DIFF(sigaltstack_wrapper)
+- ENTRY_SAME(ni_syscall) /* query_module */
+- ENTRY_SAME(poll)
+- /* structs contain pointers and an in_addr... */
+- ENTRY_DIFF(nfsservctl)
+- ENTRY_SAME(setresgid) /* 170 */
+- ENTRY_SAME(getresgid)
+- ENTRY_SAME(prctl)
+- /* signals need a careful review */
+- ENTRY_SAME(rt_sigreturn_wrapper)
+- ENTRY_DIFF(rt_sigaction)
+- ENTRY_DIFF(rt_sigprocmask) /* 175 */
+- ENTRY_DIFF(rt_sigpending)
+- ENTRY_UHOH(rt_sigtimedwait)
+- /* even though the struct siginfo_t is different, it appears like
+- * all the paths use values which should be same wide and narrow.
+- * Also the struct is padded to 128 bytes which means we don't have
+- * to worry about faulting trying to copy in a larger 64-bit
+- * struct from a 32-bit user-space app.
+- */
+- ENTRY_SAME(rt_sigqueueinfo)
+- ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+- ENTRY_SAME(chown) /* 180 */
+- /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
+- ENTRY_COMP(setsockopt)
+- ENTRY_SAME(getsockopt)
+- ENTRY_COMP(sendmsg)
+- ENTRY_COMP(recvmsg)
+- ENTRY_SAME(semop) /* 185 */
+- ENTRY_SAME(semget)
+- ENTRY_DIFF(semctl_broken)
+- ENTRY_DIFF(msgsnd)
+- ENTRY_DIFF(msgrcv)
+- ENTRY_SAME(msgget) /* 190 */
+- ENTRY_SAME(msgctl_broken)
+- ENTRY_SAME(shmat_wrapper)
+- ENTRY_SAME(shmdt)
+- ENTRY_SAME(shmget)
+- ENTRY_SAME(shmctl_broken) /* 195 */
+- ENTRY_SAME(ni_syscall) /* streams1 */
+- ENTRY_SAME(ni_syscall) /* streams2 */
+- ENTRY_SAME(lstat64)
+- ENTRY_OURS(truncate64)
+- ENTRY_OURS(ftruncate64) /* 200 */
+- ENTRY_SAME(getdents64)
+- ENTRY_COMP(fcntl64)
+- ENTRY_SAME(ni_syscall)
+- ENTRY_SAME(ni_syscall)
+- ENTRY_SAME(ni_syscall) /* 205 */
+- ENTRY_SAME(gettid)
+- ENTRY_OURS(readahead)
+- ENTRY_SAME(ni_syscall) /* tkill */
+-
+- ENTRY_SAME(sendfile64)
+- ENTRY_COMP(futex) /* 210 */
+- ENTRY_COMP(sched_setaffinity)
+- ENTRY_COMP(sched_getaffinity)
+- ENTRY_SAME(ni_syscall)
+- ENTRY_SAME(ni_syscall)
+- ENTRY_SAME(io_setup) /* 215 */
+- ENTRY_SAME(io_destroy)
+- ENTRY_SAME(io_getevents)
+- ENTRY_SAME(io_submit)
+- ENTRY_SAME(io_cancel)
+- ENTRY_SAME(alloc_hugepages) /* 220 */
+- ENTRY_SAME(free_hugepages)
+- ENTRY_SAME(exit_group)
+- ENTRY_DIFF(lookup_dcookie)
+- ENTRY_SAME(epoll_create)
+- ENTRY_SAME(epoll_ctl) /* 225 */
+- ENTRY_SAME(epoll_wait)
+- ENTRY_SAME(remap_file_pages)
++#include "syscall_table.S"
+ .end
++#ifdef __LP64__
++ .align 4096
++ .export sys_call_table64
++.Lsys_call_table64:
++sys_call_table64:
++#define SYSCALL_TABLE_64BIT
++#include "syscall_table.S"
++#endif
++
+
+ /* Make sure nothing else is placed on this page */
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/parisc/kernel/syscall_table.S 2003-10-05 00:33:23.000000000 -0700
+@@ -0,0 +1,304 @@
++#undef ENTRY_SAME
++#undef ENTRY_DIFF
++#undef ENTRY_UHOH
++#undef ENTRY_COMP
++#undef ENTRY_OURS
++#if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT)
++/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
++ * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
++ * implementation is required on wide palinux. Use ENTRY_COMP where
++ * the compatability layer has a useful 32-bit implementation.
++ */
++#define ENTRY_SAME(_name_) .dword sys_##_name_
++#define ENTRY_DIFF(_name_) .dword sys32_##_name_
++#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
++#define ENTRY_OURS(_name_) .dword parisc_##_name_
++#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
++#elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT)
++#define ENTRY_SAME(_name_) .dword sys_##_name_
++#define ENTRY_DIFF(_name_) .dword sys_##_name_
++#define ENTRY_UHOH(_name_) .dword sys_##_name_
++#define ENTRY_OURS(_name_) .dword sys_##_name_
++#define ENTRY_COMP(_name_) .dword sys_##_name_
++#else
++#define ENTRY_SAME(_name_) .word sys_##_name_
++#define ENTRY_DIFF(_name_) .word sys_##_name_
++#define ENTRY_UHOH(_name_) .word sys_##_name_
++#define ENTRY_OURS(_name_) .word parisc_##_name_
++#define ENTRY_COMP(_name_) .word sys_##_name_
++#endif
++
++ ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
++ ENTRY_SAME(exit)
++ ENTRY_SAME(fork_wrapper)
++ ENTRY_SAME(read)
++ ENTRY_SAME(write)
++ ENTRY_SAME(open) /* 5 */
++ ENTRY_SAME(close)
++ ENTRY_SAME(waitpid)
++ ENTRY_SAME(creat)
++ ENTRY_SAME(link)
++ ENTRY_SAME(unlink) /* 10 */
++ ENTRY_DIFF(execve_wrapper)
++ ENTRY_SAME(chdir)
++ /* See comments in kernel/time.c!!! Maybe we don't need this? */
++ ENTRY_DIFF(time)
++ ENTRY_SAME(mknod)
++ ENTRY_SAME(chmod) /* 15 */
++ ENTRY_SAME(lchown)
++ ENTRY_SAME(socket)
++ /* struct stat is MAYBE identical wide and narrow ?? */
++ ENTRY_COMP(newstat)
++ ENTRY_DIFF(lseek)
++ ENTRY_SAME(getpid) /* 20 */
++ /* the 'void * data' parameter may need re-packing in wide */
++ ENTRY_DIFF(mount)
++ /* concerned about struct sockaddr in wide/narrow */
++ /* ---> I think sockaddr is OK unless the compiler packs the struct */
++ /* differently to align the char array */
++ ENTRY_SAME(bind)
++ ENTRY_SAME(setuid)
++ ENTRY_SAME(getuid)
++ ENTRY_SAME(stime) /* 25 */
++ ENTRY_SAME(ptrace)
++ ENTRY_SAME(alarm)
++ /* see stat comment */
++ ENTRY_COMP(newfstat)
++ ENTRY_SAME(pause)
++ /* struct utimbuf uses time_t which might vary */
++ ENTRY_COMP(utime) /* 30 */
++ /* struct sockaddr... */
++ ENTRY_SAME(connect)
++ ENTRY_SAME(listen)
++ ENTRY_SAME(access)
++ ENTRY_SAME(nice)
++ /* struct sockaddr... */
++ ENTRY_SAME(accept) /* 35 */
++ ENTRY_SAME(sync)
++ ENTRY_SAME(kill)
++ ENTRY_SAME(rename)
++ ENTRY_SAME(mkdir)
++ ENTRY_SAME(rmdir) /* 40 */
++ ENTRY_SAME(dup)
++ ENTRY_SAME(pipe)
++ ENTRY_COMP(times)
++ /* struct sockaddr... */
++ ENTRY_SAME(getsockname)
++ /* it seems possible brk() could return a >4G pointer... */
++ ENTRY_SAME(brk) /* 45 */
++ ENTRY_SAME(setgid)
++ ENTRY_SAME(getgid)
++ ENTRY_SAME(signal)
++ ENTRY_SAME(geteuid)
++ ENTRY_SAME(getegid) /* 50 */
++ ENTRY_SAME(acct)
++ ENTRY_SAME(umount)
++ /* struct sockaddr... */
++ ENTRY_SAME(getpeername)
++ ENTRY_COMP(ioctl)
++ ENTRY_COMP(fcntl) /* 55 */
++ ENTRY_SAME(socketpair)
++ ENTRY_SAME(setpgid)
++ ENTRY_SAME(send)
++ ENTRY_SAME(newuname)
++ ENTRY_SAME(umask) /* 60 */
++ ENTRY_SAME(chroot)
++ ENTRY_SAME(ustat)
++ ENTRY_SAME(dup2)
++ ENTRY_SAME(getppid)
++ ENTRY_SAME(getpgrp) /* 65 */
++ ENTRY_SAME(setsid)
++ ENTRY_SAME(pivot_root)
++ /* I don't like this */
++ ENTRY_UHOH(sgetmask)
++ ENTRY_UHOH(ssetmask)
++ ENTRY_SAME(setreuid) /* 70 */
++ ENTRY_SAME(setregid)
++ ENTRY_SAME(mincore)
++ ENTRY_COMP(sigpending)
++ ENTRY_SAME(sethostname)
++ /* Following 3 have linux-common-code structs containing longs -( */
++ ENTRY_COMP(setrlimit) /* 75 */
++ ENTRY_COMP(getrlimit)
++ ENTRY_COMP(getrusage)
++ /* struct timeval and timezone are maybe?? consistent wide and narrow */
++ ENTRY_DIFF(gettimeofday)
++ ENTRY_DIFF(settimeofday)
++ ENTRY_SAME(getgroups) /* 80 */
++ ENTRY_SAME(setgroups)
++ /* struct socketaddr... */
++ ENTRY_SAME(sendto)
++ ENTRY_SAME(symlink)
++ /* see stat comment */
++ ENTRY_COMP(newlstat)
++ ENTRY_SAME(readlink) /* 85 */
++ ENTRY_SAME(ni_syscall) /* was uselib */
++ ENTRY_SAME(swapon)
++ ENTRY_SAME(reboot)
++ ENTRY_SAME(mmap2)
++ ENTRY_SAME(mmap) /* 90 */
++ ENTRY_SAME(munmap)
++ ENTRY_SAME(truncate)
++ ENTRY_SAME(ftruncate)
++ ENTRY_SAME(fchmod)
++ ENTRY_SAME(fchown) /* 95 */
++ ENTRY_SAME(getpriority)
++ ENTRY_SAME(setpriority)
++ ENTRY_SAME(recv)
++ ENTRY_COMP(statfs)
++ ENTRY_COMP(fstatfs) /* 100 */
++ ENTRY_SAME(stat64)
++ ENTRY_SAME(ni_syscall) /* was socketcall */
++ ENTRY_SAME(syslog)
++ /* even though manpage says struct timeval contains longs, ours has
++ * time_t and suseconds_t -- both of which are safe wide/narrow */
++ ENTRY_COMP(setitimer)
++ ENTRY_COMP(getitimer) /* 105 */
++ ENTRY_SAME(capget)
++ ENTRY_SAME(capset)
++ ENTRY_OURS(pread64)
++ ENTRY_OURS(pwrite64)
++ ENTRY_SAME(getcwd) /* 110 */
++ ENTRY_SAME(vhangup)
++ ENTRY_SAME(fstat64)
++ ENTRY_SAME(vfork_wrapper)
++ /* struct rusage contains longs... */
++ ENTRY_COMP(wait4)
++ ENTRY_SAME(swapoff) /* 115 */
++ ENTRY_DIFF(sysinfo)
++ ENTRY_SAME(shutdown)
++ ENTRY_SAME(fsync)
++ ENTRY_SAME(madvise)
++ ENTRY_SAME(clone_wrapper) /* 120 */
++ ENTRY_SAME(setdomainname)
++ ENTRY_DIFF(sendfile)
++ /* struct sockaddr... */
++ ENTRY_SAME(recvfrom)
++ /* struct timex contains longs */
++ ENTRY_DIFF(adjtimex)
++ ENTRY_SAME(mprotect) /* 125 */
++ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
++ ENTRY_COMP(sigprocmask)
++ ENTRY_SAME(ni_syscall) /* create_module */
++ ENTRY_SAME(init_module)
++ ENTRY_SAME(delete_module)
++ ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
++ /* time_t inside struct dqblk */
++ ENTRY_SAME(quotactl)
++ ENTRY_SAME(getpgid)
++ ENTRY_SAME(fchdir)
++ ENTRY_SAME(bdflush)
++ ENTRY_SAME(sysfs) /* 135 */
++ ENTRY_SAME(personality)
++ ENTRY_SAME(ni_syscall) /* for afs_syscall */
++ ENTRY_SAME(setfsuid)
++ ENTRY_SAME(setfsgid)
++ /* I think this might work */
++ ENTRY_SAME(llseek) /* 140 */
++ /* struct linux_dirent has longs, like 'unsigned long d_ino' which
++ * almost definitely should be 'ino_t d_ino' but it's too late now */
++ ENTRY_DIFF(getdents)
++ /* it is POSSIBLE that select will be OK because even though fd_set
++ * contains longs, the macros and sizes are clever. */
++ ENTRY_DIFF(select)
++ ENTRY_SAME(flock)
++ ENTRY_SAME(msync)
++ /* struct iovec contains pointers */
++ ENTRY_DIFF(readv) /* 145 */
++ ENTRY_DIFF(writev)
++ ENTRY_SAME(getsid)
++ ENTRY_SAME(fdatasync)
++ /* struct __sysctl_args is a mess */
++ ENTRY_DIFF(sysctl)
++ ENTRY_SAME(mlock) /* 150 */
++ ENTRY_SAME(munlock)
++ ENTRY_SAME(mlockall)
++ ENTRY_SAME(munlockall)
++ /* struct sched_param is ok for now */
++ ENTRY_SAME(sched_setparam)
++ ENTRY_SAME(sched_getparam) /* 155 */
++ ENTRY_SAME(sched_setscheduler)
++ ENTRY_SAME(sched_getscheduler)
++ ENTRY_SAME(sched_yield)
++ ENTRY_SAME(sched_get_priority_max)
++ ENTRY_SAME(sched_get_priority_min) /* 160 */
++ /* These 2 would've worked if someone had defined struct timespec
++ * carefully, like timeval for example (which is about the same).
++ * Unfortunately it contains a long :-( */
++ ENTRY_DIFF(sched_rr_get_interval)
++ ENTRY_COMP(nanosleep)
++ ENTRY_SAME(mremap)
++ ENTRY_SAME(setresuid)
++ ENTRY_SAME(getresuid) /* 165 */
++ ENTRY_DIFF(sigaltstack_wrapper)
++ ENTRY_SAME(ni_syscall) /* query_module */
++ ENTRY_SAME(poll)
++ /* structs contain pointers and an in_addr... */
++ ENTRY_DIFF(nfsservctl)
++ ENTRY_SAME(setresgid) /* 170 */
++ ENTRY_SAME(getresgid)
++ ENTRY_SAME(prctl)
++ /* signals need a careful review */
++ ENTRY_SAME(rt_sigreturn_wrapper)
++ ENTRY_DIFF(rt_sigaction)
++ ENTRY_DIFF(rt_sigprocmask) /* 175 */
++ ENTRY_DIFF(rt_sigpending)
++ ENTRY_UHOH(rt_sigtimedwait)
++ /* even though the struct siginfo_t is different, it appears like
++ * all the paths use values which should be same wide and narrow.
++ * Also the struct is padded to 128 bytes which means we don't have
++ * to worry about faulting trying to copy in a larger 64-bit
++ * struct from a 32-bit user-space app.
++ */
++ ENTRY_SAME(rt_sigqueueinfo)
++ ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
++ ENTRY_SAME(chown) /* 180 */
++ /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
++ ENTRY_COMP(setsockopt)
++ ENTRY_SAME(getsockopt)
++ ENTRY_COMP(sendmsg)
++ ENTRY_COMP(recvmsg)
++ ENTRY_SAME(semop) /* 185 */
++ ENTRY_SAME(semget)
++ ENTRY_DIFF(semctl_broken)
++ ENTRY_DIFF(msgsnd)
++ ENTRY_DIFF(msgrcv)
++ ENTRY_SAME(msgget) /* 190 */
++ ENTRY_SAME(msgctl_broken)
++ ENTRY_SAME(shmat_wrapper)
++ ENTRY_SAME(shmdt)
++ ENTRY_SAME(shmget)
++ ENTRY_SAME(shmctl_broken) /* 195 */
++ ENTRY_SAME(ni_syscall) /* streams1 */
++ ENTRY_SAME(ni_syscall) /* streams2 */
++ ENTRY_SAME(lstat64)
++ ENTRY_OURS(truncate64)
++ ENTRY_OURS(ftruncate64) /* 200 */
++ ENTRY_SAME(getdents64)
++ ENTRY_COMP(fcntl64)
++ ENTRY_SAME(ni_syscall)
++ ENTRY_SAME(ni_syscall)
++ ENTRY_SAME(ni_syscall) /* 205 */
++ ENTRY_SAME(gettid)
++ ENTRY_OURS(readahead)
++ ENTRY_SAME(ni_syscall) /* tkill */
++
++ ENTRY_SAME(sendfile64)
++ ENTRY_COMP(futex) /* 210 */
++ ENTRY_COMP(sched_setaffinity)
++ ENTRY_COMP(sched_getaffinity)
++ ENTRY_SAME(ni_syscall)
++ ENTRY_SAME(ni_syscall)
++ ENTRY_SAME(io_setup) /* 215 */
++ ENTRY_SAME(io_destroy)
++ ENTRY_SAME(io_getevents)
++ ENTRY_SAME(io_submit)
++ ENTRY_SAME(io_cancel)
++ ENTRY_SAME(alloc_hugepages) /* 220 */
++ ENTRY_SAME(free_hugepages)
++ ENTRY_SAME(exit_group)
++ ENTRY_DIFF(lookup_dcookie)
++ ENTRY_SAME(epoll_create)
++ ENTRY_SAME(epoll_ctl) /* 225 */
++ ENTRY_SAME(epoll_wait)
++ ENTRY_SAME(remap_file_pages)
+--- linux-2.6.0-test6/arch/parisc/kernel/sys_parisc.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/sys_parisc.c 2003-10-05 00:34:08.000000000 -0700
+@@ -65,7 +65,7 @@ static int get_offset(struct address_spa
+ */
+ static int get_offset(struct address_space *mapping)
+ {
+- int offset = (int) mapping << (PAGE_SHIFT - 8);
++ int offset = (unsigned long) mapping << (PAGE_SHIFT - 8);
+ return offset & 0x3FF000;
+ }
+ #endif
+@@ -93,17 +93,13 @@ static unsigned long get_shared_area(str
+ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff, unsigned long flags)
+ {
+- struct inode *inode;
+-
+ if (len > TASK_SIZE)
+ return -ENOMEM;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+
+- inode = filp ? filp->f_dentry->d_inode : NULL;
+-
+- if (inode && (flags & MAP_SHARED)) {
+- addr = get_shared_area(inode->i_mapping, addr, len, pgoff);
++ if (filp && (flags & MAP_SHARED)) {
++ addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
+ } else {
+ addr = get_unshared_area(addr, len);
+ }
+@@ -165,12 +161,13 @@ long sys_shmat_wrapper(int shmid, char *
+ return raddr;
+ }
+
+-
+ /* Fucking broken ABI */
+
+ #ifdef CONFIG_PARISC64
+ extern asmlinkage long sys_truncate(const char *, unsigned long);
+ extern asmlinkage long sys_ftruncate(unsigned int, unsigned long);
++extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
++
+ asmlinkage long parisc_truncate64(const char * path,
+ unsigned int high, unsigned int low)
+ {
+@@ -182,6 +179,21 @@ asmlinkage long parisc_ftruncate64(unsig
+ {
+ return sys_ftruncate(fd, (long)high << 32 | low);
+ }
++
++/* stubs for the benefit of the syscall_table since truncate64 and truncate
++ * are identical on LP64 */
++asmlinkage long sys_truncate64(const char * path, unsigned long length)
++{
++ return sys_truncate(path, length);
++}
++asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
++{
++ return sys_ftruncate(fd, length);
++}
++asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ return sys_fcntl(fd, cmd, arg);
++}
+ #else
+
+ extern asmlinkage long sys_truncate64(const char *, loff_t);
+--- linux-2.6.0-test6/arch/parisc/kernel/time.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/arch/parisc/kernel/time.c 2003-10-05 00:33:23.000000000 -0700
+@@ -48,7 +48,9 @@ static inline void
+ parisc_do_profile(struct pt_regs *regs)
+ {
+ unsigned long pc = regs->iaoq[0];
++#if 0
+ extern unsigned long prof_cpu_mask;
++#endif
+ extern char _stext;
+
+ profile_hook(regs);
+@@ -60,6 +62,10 @@ parisc_do_profile(struct pt_regs *regs)
+ return;
+
+ #if 0
++ /* FIXME: when we have irq affinity to cpu, we need to
++ * only look at the cpus specified in this mask
++ */
++
+ if (!((1 << smp_processor_id()) & prof_cpu_mask))
+ return;
+ #endif
+@@ -206,7 +212,6 @@ do_settimeofday (struct timespec *tv)
+ * done, and then undo it!
+ */
+ nsec -= gettimeoffset() * 1000;
+- nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+@@ -223,6 +228,16 @@ do_settimeofday (struct timespec *tv)
+ return 0;
+ }
+
++/*
++ * XXX: We can do better than this.
++ * Returns nanoseconds
++ */
++
++unsigned long long sched_clock(void)
++{
++ return (unsigned long long)jiffies * (1000000000 / HZ);
++}
++
+
+ void __init time_init(void)
+ {
+--- linux-2.6.0-test6/arch/parisc/kernel/traps.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/parisc/kernel/traps.c 2003-10-05 00:33:23.000000000 -0700
+@@ -678,12 +678,13 @@ void handle_interruption(int code, struc
+ }
+
+ if (user_mode(regs)) {
+- if (fault_space != regs->sr[7]) {
++ if ((fault_space>>SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
+ #ifdef PRINT_USER_FAULTS
+ if (fault_space == 0)
+ printk(KERN_DEBUG "User Fault on Kernel Space ");
+ else
+- printk(KERN_DEBUG "User Fault (long pointer) ");
++ printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
++ code);
+ printk("pid=%d command='%s'\n", current->pid, current->comm);
+ show_regs(regs);
+ #endif
+--- linux-2.6.0-test6/arch/parisc/kernel/unaligned.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/arch/parisc/kernel/unaligned.c 2003-10-05 00:33:23.000000000 -0700
+@@ -369,8 +369,8 @@ static int emulate_std(struct pt_regs *r
+
+ void handle_unaligned(struct pt_regs *regs)
+ {
+- unsigned long unaligned_count = 0;
+- unsigned long last_time = 0;
++ static unsigned long unaligned_count = 0;
++ static unsigned long last_time = 0;
+ unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
+ int modify = 0;
+ int ret = -1;
+@@ -380,7 +380,6 @@ void handle_unaligned(struct pt_regs *re
+ /* if the unaligned access is inside the kernel:
+ * if the access is caused by a syscall, then we fault the calling
+ * user process
+- * otherwise we halt the kernel
+ */
+ if (!user_mode(regs))
+ {
+@@ -427,10 +426,10 @@ void handle_unaligned(struct pt_regs *re
+ show_regs(regs);
+ #endif
+ }
+- }
+
+- if (!unaligned_enabled)
+- goto force_sigbus;
++ if (!unaligned_enabled)
++ goto force_sigbus;
++ }
+
+ /* handle modification - OK, it's ugly, see the instruction manual */
+ switch (MAJOR_OP(regs->iir))
+--- linux-2.6.0-test6/arch/parisc/lib/checksum.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/parisc/lib/checksum.c 2003-10-05 00:33:23.000000000 -0700
+@@ -16,8 +16,10 @@
+ *
+ * $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ */
+-#include <net/checksum.h>
++#include <linux/module.h>
+ #include <linux/types.h>
++
++#include <net/checksum.h>
+ #include <asm/byteorder.h>
+ #include <asm/string.h>
+ #include <asm/uaccess.h>
+@@ -109,6 +111,7 @@ unsigned int csum_partial_copy_nocheck(c
+
+ return sum;
+ }
++EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+ /*
+ * Copy from userspace and compute checksum. If we catch an exception
+@@ -128,3 +131,4 @@ unsigned int csum_partial_copy_from_user
+
+ return csum_partial(dst, len, sum);
+ }
++EXPORT_SYMBOL(csum_partial_copy_from_user);
+--- linux-2.6.0-test6/arch/parisc/lib/io.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/parisc/lib/io.c 2003-10-05 00:33:23.000000000 -0700
+@@ -8,6 +8,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <asm/io.h>
+
+ /* Copies a block of memory to a device in an efficient manner.
+@@ -457,3 +458,10 @@ void outsl (unsigned long port, const vo
+ break;
+ }
+ }
++
++EXPORT_SYMBOL(insb);
++EXPORT_SYMBOL(insw);
++EXPORT_SYMBOL(insl);
++EXPORT_SYMBOL(outsb);
++EXPORT_SYMBOL(outsw);
++EXPORT_SYMBOL(outsl);
+--- linux-2.6.0-test6/arch/parisc/math-emu/denormal.c 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/parisc/math-emu/denormal.c 2003-10-05 00:33:23.000000000 -0700
+@@ -47,7 +47,7 @@
+ #include "sgl_float.h"
+ #include "dbl_float.h"
+ #include "hppa.h"
+-#include "types.h"
++#include <linux/kernel.h>
+ /* #include <machine/sys/mdep_private.h> */
+
+ #undef Fpustatus_register
+--- linux-2.6.0-test6/arch/parisc/math-emu/fpudispatch.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/parisc/math-emu/fpudispatch.c 2003-10-05 00:33:23.000000000 -0700
+@@ -50,7 +50,7 @@
+ #define FPUDEBUG 0
+
+ #include "float.h"
+-#include "types.h"
++#include <linux/kernel.h>
+ #include <asm/processor.h>
+ /* #include <sys/debug.h> */
+ /* #include <machine/sys/mdep_private.h> */
+--- linux-2.6.0-test6/arch/parisc/math-emu/Makefile 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/parisc/math-emu/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -2,6 +2,11 @@
+ # Makefile for the linux/parisc floating point code
+ #
+
++# See arch/parisc/math-emu/README
++CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \
++ -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \
++ -Wno-implicit-int
++
+ obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
+ dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \
+ sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \
+--- linux-2.6.0-test6/arch/parisc/math-emu/types.h 2003-06-14 12:18:00.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,25 +0,0 @@
+-/*
+- * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+- *
+- * Floating-point emulation code
+- * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2, or (at your option)
+- * any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#include <linux/kernel.h>
+-#define BUG() do { \
+- printk(KERN_ERR "floating-pt emulation BUG at %s:%d!\n", __FILE__, __LINE__); \
+-} while (0)
+--- linux-2.6.0-test6/arch/parisc/mm/init.c 2003-06-16 22:32:20.000000000 -0700
++++ 25/arch/parisc/mm/init.c 2003-10-05 00:33:23.000000000 -0700
+@@ -430,6 +430,8 @@ void free_initmem(void)
+ & ~(VM_MAP_OFFSET-1)))
+
+ void *vmalloc_start;
++EXPORT_SYMBOL(vmalloc_start);
++
+ #ifdef CONFIG_PA11
+ unsigned long pcxl_dma_start;
+ #endif
+@@ -618,8 +620,6 @@ static void __init pagetable_init(void)
+ {
+ int range;
+
+- printk("pagetable_init\n");
+-
+ /* Map each physical memory range to its kernel vaddr */
+
+ for (range = 0; range < npmem_ranges; range++) {
+--- linux-2.6.0-test6/arch/parisc/mm/ioremap.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/parisc/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -159,7 +159,7 @@ void * __ioremap(unsigned long phys_addr
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/ppc64/kernel/ioctl32.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/ppc64/kernel/ioctl32.c 2003-10-05 00:34:44.000000000 -0700
+@@ -328,396 +328,6 @@ static int do_ncp_setprivatedata(unsigne
+ return err;
+ }
+
+-struct usbdevfs_ctrltransfer32 {
+- __u8 bRequestType;
+- __u8 bRequest;
+- __u16 wValue;
+- __u16 wIndex;
+- __u16 wLength;
+- __u32 timeout; /* in milliseconds */
+- __u32 data;
+-};
+-
+-#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+-
+-static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_ctrltransfer kctrl;
+- struct usbdevfs_ctrltransfer32 *uctrl;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- int err;
+-
+- uctrl = (struct usbdevfs_ctrltransfer32 *) arg;
+-
+- if (copy_from_user(&kctrl, uctrl,
+- (sizeof(struct usbdevfs_ctrltransfer) -
+- sizeof(void *))))
+- return -EFAULT;
+-
+- if (get_user(udata, &uctrl->data))
+- return -EFAULT;
+- uptr = (void *) A(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kctrl.wLength > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *)__get_free_page(GFP_KERNEL);
+-
+- if ((kctrl.bRequestType & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kctrl.wLength))
+- goto out;
+- }
+-
+- kctrl.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kctrl.bRequestType & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kctrl.wLength))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-struct usbdevfs_bulktransfer32 {
+- unsigned int ep;
+- unsigned int len;
+- unsigned int timeout; /* in milliseconds */
+- __u32 data;
+-};
+-
+-#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
+-
+-static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_bulktransfer kbulk;
+- struct usbdevfs_bulktransfer32 *ubulk;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- int err;
+-
+- ubulk = (struct usbdevfs_bulktransfer32 *) arg;
+-
+- if (get_user(kbulk.ep, &ubulk->ep) ||
+- get_user(kbulk.len, &ubulk->len) ||
+- get_user(kbulk.timeout, &ubulk->timeout) ||
+- get_user(udata, &ubulk->data))
+- return -EFAULT;
+-
+- uptr = (void *) A(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kbulk.len > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *) __get_free_page(GFP_KERNEL);
+-
+- if ((kbulk.ep & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kbulk.len))
+- goto out;
+- }
+-
+- kbulk.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kbulk.ep & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kbulk.len))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-/* This needs more work before we can enable it. Unfortunately
+- * because of the fancy asynchronous way URB status/error is written
+- * back to userspace, we'll need to fiddle with USB devio internals
+- * and/or reimplement entirely the frontend of it ourselves. -DaveM
+- *
+- * The issue is:
+- *
+- * When an URB is submitted via usbdevicefs it is put onto an
+- * asynchronous queue. When the URB completes, it may be reaped
+- * via another ioctl. During this reaping the status is written
+- * back to userspace along with the length of the transfer.
+- *
+- * We must translate into 64-bit kernel types so we pass in a kernel
+- * space copy of the usbdevfs_urb structure. This would mean that we
+- * must do something to deal with the async entry reaping. First we
+- * have to deal somehow with this transitory memory we've allocated.
+- * This is problematic since there are many call sites from which the
+- * async entries can be destroyed (and thus when we'd need to free up
+- * this kernel memory). One of which is the close() op of usbdevicefs.
+- * To handle that we'd need to make our own file_operations struct which
+- * overrides usbdevicefs's release op with our own which runs usbdevicefs's
+- * real release op then frees up the kernel memory.
+- *
+- * But how to keep track of these kernel buffers? We'd need to either
+- * keep track of them in some table _or_ know about usbdevicefs internals
+- * (ie. the exact layout of its file private, which is actually defined
+- * in linux/usbdevice_fs.h, the layout of the async queues are private to
+- * devio.c)
+- *
+- * There is one possible other solution I considered, also involving knowledge
+- * of usbdevicefs internals:
+- *
+- * After an URB is submitted, we "fix up" the address back to the user
+- * space one. This would work if the status/length fields written back
+- * by the async URB completion lines up perfectly in the 32-bit type with
+- * the 64-bit kernel type. Unfortunately, it does not because the iso
+- * frame descriptors, at the end of the struct, can be written back.
+- *
+- * I think we'll just need to simply duplicate the devio URB engine here.
+- */
+-#if 0
+-struct usbdevfs_urb32 {
+- __u8 type;
+- __u8 endpoint;
+- __s32 status;
+- __u32 flags;
+- __u32 buffer;
+- __s32 buffer_length;
+- __s32 actual_length;
+- __s32 start_frame;
+- __s32 number_of_packets;
+- __s32 error_count;
+- __u32 signr;
+- __u32 usercontext; /* unused */
+- struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+-};
+-
+-#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
+-
+-static int get_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (get_user(kurb->type, &uurb->type) ||
+- __get_user(kurb->endpoint, &uurb->endpoint) ||
+- __get_user(kurb->status, &uurb->status) ||
+- __get_user(kurb->flags, &uurb->flags) ||
+- __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+- __get_user(kurb->actual_length, &uurb->actual_length) ||
+- __get_user(kurb->start_frame, &uurb->start_frame) ||
+- __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+- __get_user(kurb->error_count, &uurb->error_count) ||
+- __get_user(kurb->signr, &uurb->signr))
+- return -EFAULT;
+-
+- kurb->usercontext = 0; /* unused currently */
+-
+- return 0;
+-}
+-
+-/* Just put back the values which usbdevfs actually changes. */
+-static int put_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (put_user(kurb->status, &uurb->status) ||
+- __put_user(kurb->actual_length, &uurb->actual_length) ||
+- __put_user(kurb->error_count, &uurb->error_count))
+- return -EFAULT;
+-
+- if (kurb->number_of_packets != 0) {
+- int i;
+-
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- if (__put_user(kurb->iso_frame_desc[i].actual_length,
+- &uurb->iso_frame_desc[i].actual_length) ||
+- __put_user(kurb->iso_frame_desc[i].status,
+- &uurb->iso_frame_desc[i].status))
+- return -EFAULT;
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- unsigned int totlen;
+- int i;
+-
+- if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
+- kurb->number_of_packets = 0;
+- return 0;
+- }
+-
+- if (kurb->number_of_packets < 1 ||
+- kurb->number_of_packets > 128)
+- return -EINVAL;
+-
+- if (copy_from_user(&kurb->iso_frame_desc[0],
+- &uurb->iso_frame_desc[0],
+- sizeof(struct usbdevfs_iso_packet_desc) *
+- kurb->number_of_packets))
+- return -EFAULT;
+-
+- totlen = 0;
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- unsigned int this_len;
+-
+- this_len = kurb->iso_frame_desc[i].length;
+- if (this_len > 1023)
+- return -EINVAL;
+-
+- totlen += this_len;
+- }
+-
+- if (totlen > 32768)
+- return -EINVAL;
+-
+- kurb->buffer_length = totlen;
+-
+- return 0;
+-}
+-
+-static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_urb *kurb;
+- struct usbdevfs_urb32 *uurb;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- unsigned int buflen;
+- int err;
+-
+- uurb = (struct usbdevfs_urb32 *) arg;
+-
+- err = -ENOMEM;
+- kurb = kmalloc(sizeof(struct usbdevfs_urb) +
+- (sizeof(struct usbdevfs_iso_packet_desc) * 128),
+- GFP_KERNEL);
+- if (!kurb)
+- goto out;
+-
+- err = -EFAULT;
+- if (get_urb32(kurb, uurb))
+- goto out;
+-
+- err = get_urb32_isoframes(kurb, uurb);
+- if (err)
+- goto out;
+-
+- err = -EFAULT;
+- if (__get_user(udata, &uurb->buffer))
+- goto out;
+- uptr = (void *) A(udata);
+-
+- err = -ENOMEM;
+- buflen = kurb->buffer_length;
+- kptr = kmalloc(buflen, GFP_KERNEL);
+- if (!kptr)
+- goto out;
+-
+- kurb->buffer = kptr;
+-
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, buflen))
+- goto out_kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
+- set_fs(old_fs);
+-
+- if (err >= 0) {
+- /* XXX Shit, this doesn't work for async URBs :-( XXX */
+- if (put_urb32(kurb, uurb)) {
+- err = -EFAULT;
+- } else if ((kurb->endpoint & USB_DIR_IN) != 0) {
+- if (copy_to_user(uptr, kptr, buflen))
+- err = -EFAULT;
+- }
+- }
+-
+-out_kptr:
+- kfree(kptr);
+-
+-out:
+- kfree(kurb);
+- return err;
+-}
+-#endif
+-
+-#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
+-#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
+-
+-static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- mm_segment_t old_fs;
+- void *kptr;
+- int err;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd,
+- (cmd == USBDEVFS_REAPURB32 ?
+- USBDEVFS_REAPURB :
+- USBDEVFS_REAPURBNDELAY),
+- (unsigned long) &kptr);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- put_user(((u32)(long)kptr), (u32 *) A(arg)))
+- err = -EFAULT;
+-
+- return err;
+-}
+-
+-struct usbdevfs_disconnectsignal32 {
+- unsigned int signr;
+- u32 context;
+-};
+-
+-#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
+-
+-static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_disconnectsignal kdis;
+- struct usbdevfs_disconnectsignal32 *udis;
+- mm_segment_t old_fs;
+- u32 uctx;
+- int err;
+-
+- udis = (struct usbdevfs_disconnectsignal32 *) arg;
+-
+- if (get_user(kdis.signr, &udis->signr) ||
+- __get_user(uctx, &udis->context))
+- return -EFAULT;
+-
+- kdis.context = (void *) (long)uctx;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
+- set_fs(old_fs);
+-
+- return err;
+-}
+
+ #define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 },
+ #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
+@@ -734,8 +344,6 @@ IOCTL_TABLE_START
+ COMPATIBLE_IOCTL(TCSBRKP)
+ COMPATIBLE_IOCTL(TIOCSTART)
+ COMPATIBLE_IOCTL(TIOCSTOP)
+-COMPATIBLE_IOCTL(TIOCGSERIAL)
+-COMPATIBLE_IOCTL(TIOCSSERIAL)
+ COMPATIBLE_IOCTL(TIOCSLTC)
+ #if 0
+ COMPATIBLE_IOCTL(FBIOBLANK)
+@@ -755,13 +363,6 @@ HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, d
+ HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
+ HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
+
+-/* USB devfs */
+-HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
+-HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
+-/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
+-HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+ IOCTL_TABLE_END
+
+ int ioctl_table_size = ARRAY_SIZE(ioctl_start);
+--- linux-2.6.0-test6/arch/ppc64/kernel/process.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/ppc64/kernel/process.c 2003-10-05 00:33:23.000000000 -0700
+@@ -70,23 +70,6 @@ enable_kernel_fp(void)
+ #endif /* CONFIG_SMP */
+ }
+
+-#ifdef CONFIG_SMP
+-static void smp_unlazy_onefpu(void *arg)
+-{
+- struct pt_regs *regs = current->thread.regs;
+-
+- if (!regs)
+- return;
+- if (regs->msr & MSR_FP)
+- giveup_fpu(current);
+-}
+-
+-void dump_smp_unlazy_fpu(void)
+-{
+- smp_call_function(smp_unlazy_onefpu, NULL, 1, 1);
+-}
+-#endif
+-
+ int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
+ {
+ struct pt_regs *regs = tsk->thread.regs;
+--- linux-2.6.0-test6/arch/ppc64/kernel/semaphore.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/ppc64/kernel/semaphore.c 2003-10-05 00:34:19.000000000 -0700
+@@ -21,6 +21,7 @@
+ #include <asm/semaphore.h>
+ #include <asm/errno.h>
+
++#if 0
+ /*
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
+@@ -128,3 +129,140 @@ int __down_interruptible(struct semaphor
+ wake_up(&sem->wait);
+ return retval;
+ }
++#else
++
++static __inline__ int atomic_add_negative(int i, atomic_t *v)
++{
++ if (atomic_add_return(i, v) < 0)
++ return 1;
++ else
++ return 0;
++}
++
++void __up(struct semaphore *sem)
++{
++ wake_up(&sem->wait);
++}
++
++void __down(struct semaphore * sem)
++{
++ struct task_struct *tsk = current;
++ DECLARE_WAITQUEUE(wait, tsk);
++ unsigned long flags;
++
++ tsk->state = TASK_UNINTERRUPTIBLE;
++ spin_lock_irqsave(&sem->wait.lock, flags);
++ add_wait_queue_exclusive_locked(&sem->wait, &wait);
++
++ sem->sleepers++;
++ for (;;) {
++ int sleepers = sem->sleepers;
++
++ /*
++ * Add "everybody else" into it. They aren't
++ * playing, because we own the spinlock in
++ * the wait_queue_head.
++ */
++ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
++ sem->sleepers = 0;
++ break;
++ }
++ sem->sleepers = 1; /* us - see -1 above */
++ spin_unlock_irqrestore(&sem->wait.lock, flags);
++
++ schedule();
++
++ spin_lock_irqsave(&sem->wait.lock, flags);
++ tsk->state = TASK_UNINTERRUPTIBLE;
++ }
++ remove_wait_queue_locked(&sem->wait, &wait);
++ wake_up_locked(&sem->wait);
++ spin_unlock_irqrestore(&sem->wait.lock, flags);
++ tsk->state = TASK_RUNNING;
++}
++
++int __down_interruptible(struct semaphore * sem)
++{
++ int retval = 0;
++ struct task_struct *tsk = current;
++ DECLARE_WAITQUEUE(wait, tsk);
++ unsigned long flags;
++
++ tsk->state = TASK_INTERRUPTIBLE;
++ spin_lock_irqsave(&sem->wait.lock, flags);
++ add_wait_queue_exclusive_locked(&sem->wait, &wait);
++
++ sem->sleepers++;
++ for (;;) {
++ int sleepers = sem->sleepers;
++
++ /*
++ * With signals pending, this turns into
++ * the trylock failure case - we won't be
++ * sleeping, and we* can't get the lock as
++ * it has contention. Just correct the count
++ * and exit.
++ */
++ if (signal_pending(current)) {
++ retval = -EINTR;
++ sem->sleepers = 0;
++ atomic_add(sleepers, &sem->count);
++ break;
++ }
++
++ /*
++ * Add "everybody else" into it. They aren't
++ * playing, because we own the spinlock in
++ * wait_queue_head. The "-1" is because we're
++ * still hoping to get the semaphore.
++ */
++ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
++ sem->sleepers = 0;
++ break;
++ }
++ sem->sleepers = 1; /* us - see -1 above */
++ spin_unlock_irqrestore(&sem->wait.lock, flags);
++
++ schedule();
++
++ spin_lock_irqsave(&sem->wait.lock, flags);
++ tsk->state = TASK_INTERRUPTIBLE;
++ }
++ remove_wait_queue_locked(&sem->wait, &wait);
++ wake_up_locked(&sem->wait);
++ spin_unlock_irqrestore(&sem->wait.lock, flags);
++
++ tsk->state = TASK_RUNNING;
++ return retval;
++}
++
++/*
++ * Trylock failed - make sure we correct for
++ * having decremented the count.
++ *
++ * We could have done the trylock with a
++ * single "cmpxchg" without failure cases,
++ * but then it wouldn't work on a 386.
++ */
++int __down_trylock(struct semaphore * sem)
++{
++ int sleepers;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sem->wait.lock, flags);
++ sleepers = sem->sleepers + 1;
++ sem->sleepers = 0;
++
++ /*
++ * Add "everybody else" and us into it. They aren't
++ * playing, because we own the spinlock in the
++ * wait_queue_head.
++ */
++ if (!atomic_add_negative(sleepers, &sem->count)) {
++ wake_up_locked(&sem->wait);
++ }
++
++ spin_unlock_irqrestore(&sem->wait.lock, flags);
++ return 1;
++}
++#endif
+--- linux-2.6.0-test6/arch/ppc/boot/ld.script 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/ppc/boot/ld.script 2003-10-05 00:36:51.000000000 -0700
+@@ -82,6 +82,7 @@ SECTIONS
+ *(__ksymtab)
+ *(__ksymtab_strings)
+ *(__bug_table)
++ *(__kcrctab)
+ }
+
+ }
+--- linux-2.6.0-test6/arch/ppc/mm/cachemap.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/ppc/mm/cachemap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -101,7 +101,7 @@ void *consistent_alloc(int gfp, size_t s
+ if (! area)
+ goto out;
+
+- va = VMALLOC_VMADDR(area->addr);
++ va = (unsigned long) area->addr;
+
+ flags = _PAGE_KERNEL | _PAGE_NO_CACHE;
+
+--- linux-2.6.0-test6/arch/ppc/mm/pgtable.c 2003-09-27 18:57:43.000000000 -0700
++++ 25/arch/ppc/mm/pgtable.c 2003-10-05 00:33:23.000000000 -0700
+@@ -195,7 +195,7 @@ __ioremap(phys_addr_t addr, unsigned lon
+ area = get_vm_area(size, VM_IOREMAP);
+ if (area == 0)
+ return NULL;
+- v = VMALLOC_VMADDR(area->addr);
++ v = (unsigned long) area->addr;
+ } else {
+ v = (ioremap_bot -= size);
+ }
+--- linux-2.6.0-test6/arch/s390/mm/ioremap.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/s390/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -124,7 +124,7 @@ void * __ioremap(unsigned long phys_addr
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/sh/mm/init.c 2003-07-27 12:14:38.000000000 -0700
++++ 25/arch/sh/mm/init.c 2003-10-05 00:34:40.000000000 -0700
+@@ -51,8 +51,8 @@ unsigned long mmu_context_cache = NO_CON
+ #endif
+
+ #ifdef CONFIG_DISCONTIGMEM
+-pg_data_t discontig_page_data[NR_NODES];
+-bootmem_data_t discontig_node_bdata[NR_NODES];
++pg_data_t discontig_page_data[MAX_NUMNODES];
++bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
+ #endif
+
+ void show_mem(void)
+--- linux-2.6.0-test6/arch/sh/mm/ioremap.c 2003-07-02 14:53:14.000000000 -0700
++++ 25/arch/sh/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -149,7 +149,7 @@ void * p3_ioremap(unsigned long phys_add
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/arch/sparc64/defconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/sparc64/defconfig 2003-10-05 00:33:23.000000000 -0700
+@@ -571,6 +571,7 @@ CONFIG_BRIDGE_EBT_T_NAT=m
+ CONFIG_BRIDGE_EBT_802_3=m
+ CONFIG_BRIDGE_EBT_ARP=m
+ CONFIG_BRIDGE_EBT_IP=m
++CONFIG_BRIDGE_EBT_LIMIT=m
+ CONFIG_BRIDGE_EBT_MARK=m
+ CONFIG_BRIDGE_EBT_PKTTYPE=m
+ CONFIG_BRIDGE_EBT_STP=m
+@@ -665,7 +666,7 @@ CONFIG_TUN=m
+ # Ethernet (10 or 100Mbit)
+ #
+ CONFIG_NET_ETHERNET=y
+-# CONFIG_MII is not set
++CONFIG_MII=m
+ CONFIG_SUNLANCE=y
+ CONFIG_HAPPYMEAL=y
+ CONFIG_SUNBMAC=m
+@@ -729,15 +730,6 @@ CONFIG_YELLOWFIN=m
+ CONFIG_R8169=m
+ # CONFIG_SIS190 is not set
+ CONFIG_SK98LIN=m
+-CONFIG_CONFIG_SK98LIN_T1=y
+-CONFIG_CONFIG_SK98LIN_T2=y
+-CONFIG_CONFIG_SK98LIN_T3=y
+-CONFIG_CONFIG_SK98LIN_T4=y
+-CONFIG_CONFIG_SK98LIN_T5=y
+-CONFIG_CONFIG_SK98LIN_T6=y
+-CONFIG_CONFIG_SK98LIN_T7=y
+-CONFIG_CONFIG_SK98LIN_T8=y
+-CONFIG_CONFIG_SK98LIN_T9=y
+ CONFIG_TIGON3=m
+
+ #
+@@ -895,6 +887,30 @@ CONFIG_IRDA_FAST_RR=y
+ # CONFIG_VLSI_FIR is not set
+
+ #
++# Bluetooth support
++#
++CONFIG_BT=m
++CONFIG_BT_L2CAP=m
++CONFIG_BT_SCO=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++
++#
++# Bluetooth device drivers
++#
++CONFIG_BT_HCIUSB=m
++CONFIG_BT_USB_SCO=y
++# CONFIG_BT_USB_ZERO_PACKET is not set
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_H4=y
++CONFIG_BT_HCIUART_BCSP=y
++CONFIG_BT_HCIUART_BCSP_TXCRC=y
++CONFIG_BT_HCIVHCI=m
++
++#
+ # ISDN subsystem
+ #
+ CONFIG_ISDN_BOOL=y
+@@ -1517,30 +1533,6 @@ CONFIG_USB_TEST=m
+ # CONFIG_USB_GADGET is not set
+
+ #
+-# Bluetooth support
+-#
+-CONFIG_BT=m
+-CONFIG_BT_L2CAP=m
+-CONFIG_BT_SCO=m
+-CONFIG_BT_RFCOMM=m
+-CONFIG_BT_RFCOMM_TTY=y
+-CONFIG_BT_BNEP=m
+-CONFIG_BT_BNEP_MC_FILTER=y
+-CONFIG_BT_BNEP_PROTO_FILTER=y
+-
+-#
+-# Bluetooth device drivers
+-#
+-CONFIG_BT_HCIUSB=m
+-CONFIG_BT_USB_SCO=y
+-# CONFIG_BT_USB_ZERO_PACKET is not set
+-CONFIG_BT_HCIUART=m
+-CONFIG_BT_HCIUART_H4=y
+-CONFIG_BT_HCIUART_BCSP=y
+-CONFIG_BT_HCIUART_BCSP_TXCRC=y
+-CONFIG_BT_HCIVHCI=m
+-
+-#
+ # Watchdog
+ #
+ # CONFIG_SOFT_WATCHDOG is not set
+--- linux-2.6.0-test6/arch/sparc64/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/sparc64/Kconfig 2003-10-05 00:36:40.000000000 -0700
+@@ -787,12 +787,19 @@ config DEBUG_SPINLOCK
+ best used in conjunction with the NMI watchdog so that spinlock
+ deadlocks are also debuggable.
+
++config LOCKMETER
++ bool "Kernel lock metering"
++ depends on SMP && !PREEMPT
++ help
++ Say Y to enable kernel lock metering, which adds overhead to SMP locks,
++ but allows you to see various statistics using the lockstat command.
++
+ # We have a custom atomic_dec_and_lock() implementation but it's not
+ # compatible with spinlock debugging so we need to fall back on
+ # the generic version in that case.
+ config HAVE_DEC_LOCK
+ bool
+- depends on !DEBUG_SPINLOCK
++ depends on !DEBUG_SPINLOCK && !LOCKMETER
+ default y
+
+ config DEBUG_SPINLOCK_SLEEP
+--- linux-2.6.0-test6/arch/sparc64/kernel/entry.S 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/sparc64/kernel/entry.S 2003-10-05 00:33:23.000000000 -0700
+@@ -26,7 +26,7 @@
+
+ #define curptr g6
+
+-#define NR_SYSCALLS 267 /* Each OS is different... */
++#define NR_SYSCALLS 268 /* Each OS is different... */
+
+ .text
+ .align 32
+--- linux-2.6.0-test6/arch/sparc64/kernel/ioctl32.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/sparc64/kernel/ioctl32.c 2003-10-05 00:34:44.000000000 -0700
+@@ -985,402 +985,6 @@ static int drm32_res_ctx(unsigned int fd
+
+ #endif
+
+-/* HERE! */
+-
+-struct usbdevfs_ctrltransfer32 {
+- __u8 bRequestType;
+- __u8 bRequest;
+- __u16 wValue;
+- __u16 wIndex;
+- __u16 wLength;
+- __u32 timeout; /* in milliseconds */
+- __u32 data;
+-};
+-
+-#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+-
+-static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_ctrltransfer kctrl;
+- struct usbdevfs_ctrltransfer32 *uctrl;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void __user *uptr;
+- void *kptr;
+- int err;
+-
+- uctrl = (struct usbdevfs_ctrltransfer32 *) arg;
+-
+- if (copy_from_user(&kctrl, uctrl,
+- (sizeof(struct usbdevfs_ctrltransfer) -
+- sizeof(void *))))
+- return -EFAULT;
+-
+- if (get_user(udata, &uctrl->data))
+- return -EFAULT;
+- uptr = A(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kctrl.wLength > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *)__get_free_page(GFP_KERNEL);
+-
+- if ((kctrl.bRequestType & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kctrl.wLength))
+- goto out;
+- }
+-
+- kctrl.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kctrl.bRequestType & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kctrl.wLength))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-struct usbdevfs_bulktransfer32 {
+- unsigned int ep;
+- unsigned int len;
+- unsigned int timeout; /* in milliseconds */
+- __u32 data;
+-};
+-
+-#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
+-
+-static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_bulktransfer kbulk;
+- struct usbdevfs_bulktransfer32 *ubulk;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void __user *uptr;
+- void *kptr;
+- int err;
+-
+- ubulk = (struct usbdevfs_bulktransfer32 *) arg;
+-
+- if (get_user(kbulk.ep, &ubulk->ep) ||
+- get_user(kbulk.len, &ubulk->len) ||
+- get_user(kbulk.timeout, &ubulk->timeout) ||
+- get_user(udata, &ubulk->data))
+- return -EFAULT;
+-
+- uptr = A(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kbulk.len > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *) __get_free_page(GFP_KERNEL);
+-
+- if ((kbulk.ep & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kbulk.len))
+- goto out;
+- }
+-
+- kbulk.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kbulk.ep & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kbulk.len))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-/* This needs more work before we can enable it. Unfortunately
+- * because of the fancy asynchronous way URB status/error is written
+- * back to userspace, we'll need to fiddle with USB devio internals
+- * and/or reimplement entirely the frontend of it ourselves. -DaveM
+- *
+- * The issue is:
+- *
+- * When an URB is submitted via usbdevicefs it is put onto an
+- * asynchronous queue. When the URB completes, it may be reaped
+- * via another ioctl. During this reaping the status is written
+- * back to userspace along with the length of the transfer.
+- *
+- * We must translate into 64-bit kernel types so we pass in a kernel
+- * space copy of the usbdevfs_urb structure. This would mean that we
+- * must do something to deal with the async entry reaping. First we
+- * have to deal somehow with this transitory memory we've allocated.
+- * This is problematic since there are many call sites from which the
+- * async entries can be destroyed (and thus when we'd need to free up
+- * this kernel memory). One of which is the close() op of usbdevicefs.
+- * To handle that we'd need to make our own file_operations struct which
+- * overrides usbdevicefs's release op with our own which runs usbdevicefs's
+- * real release op then frees up the kernel memory.
+- *
+- * But how to keep track of these kernel buffers? We'd need to either
+- * keep track of them in some table _or_ know about usbdevicefs internals
+- * (ie. the exact layout of its file private, which is actually defined
+- * in linux/usbdevice_fs.h, the layout of the async queues are private to
+- * devio.c)
+- *
+- * There is one possible other solution I considered, also involving knowledge
+- * of usbdevicefs internals:
+- *
+- * After an URB is submitted, we "fix up" the address back to the user
+- * space one. This would work if the status/length fields written back
+- * by the async URB completion lines up perfectly in the 32-bit type with
+- * the 64-bit kernel type. Unfortunately, it does not because the iso
+- * frame descriptors, at the end of the struct, can be written back.
+- *
+- * I think we'll just need to simply duplicate the devio URB engine here.
+- */
+-#if 0
+-struct usbdevfs_urb32 {
+- __u8 type;
+- __u8 endpoint;
+- __s32 status;
+- __u32 flags;
+- __u32 buffer;
+- __s32 buffer_length;
+- __s32 actual_length;
+- __s32 start_frame;
+- __s32 number_of_packets;
+- __s32 error_count;
+- __u32 signr;
+- __u32 usercontext; /* unused */
+- struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+-};
+-
+-#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
+-
+-static int get_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (get_user(kurb->type, &uurb->type) ||
+- __get_user(kurb->endpoint, &uurb->endpoint) ||
+- __get_user(kurb->status, &uurb->status) ||
+- __get_user(kurb->flags, &uurb->flags) ||
+- __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+- __get_user(kurb->actual_length, &uurb->actual_length) ||
+- __get_user(kurb->start_frame, &uurb->start_frame) ||
+- __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+- __get_user(kurb->error_count, &uurb->error_count) ||
+- __get_user(kurb->signr, &uurb->signr))
+- return -EFAULT;
+-
+- kurb->usercontext = 0; /* unused currently */
+-
+- return 0;
+-}
+-
+-/* Just put back the values which usbdevfs actually changes. */
+-static int put_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (put_user(kurb->status, &uurb->status) ||
+- __put_user(kurb->actual_length, &uurb->actual_length) ||
+- __put_user(kurb->error_count, &uurb->error_count))
+- return -EFAULT;
+-
+- if (kurb->number_of_packets != 0) {
+- int i;
+-
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- if (__put_user(kurb->iso_frame_desc[i].actual_length,
+- &uurb->iso_frame_desc[i].actual_length) ||
+- __put_user(kurb->iso_frame_desc[i].status,
+- &uurb->iso_frame_desc[i].status))
+- return -EFAULT;
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- unsigned int totlen;
+- int i;
+-
+- if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
+- kurb->number_of_packets = 0;
+- return 0;
+- }
+-
+- if (kurb->number_of_packets < 1 ||
+- kurb->number_of_packets > 128)
+- return -EINVAL;
+-
+- if (copy_from_user(&kurb->iso_frame_desc[0],
+- &uurb->iso_frame_desc[0],
+- sizeof(struct usbdevfs_iso_packet_desc) *
+- kurb->number_of_packets))
+- return -EFAULT;
+-
+- totlen = 0;
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- unsigned int this_len;
+-
+- this_len = kurb->iso_frame_desc[i].length;
+- if (this_len > 1023)
+- return -EINVAL;
+-
+- totlen += this_len;
+- }
+-
+- if (totlen > 32768)
+- return -EINVAL;
+-
+- kurb->buffer_length = totlen;
+-
+- return 0;
+-}
+-
+-static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_urb *kurb;
+- struct usbdevfs_urb32 *uurb;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void __user *uptr;
+- void *kptr;
+- unsigned int buflen;
+- int err;
+-
+- uurb = (struct usbdevfs_urb32 *) arg;
+-
+- err = -ENOMEM;
+- kurb = kmalloc(sizeof(struct usbdevfs_urb) +
+- (sizeof(struct usbdevfs_iso_packet_desc) * 128),
+- GFP_KERNEL);
+- if (!kurb)
+- goto out;
+-
+- err = -EFAULT;
+- if (get_urb32(kurb, uurb))
+- goto out;
+-
+- err = get_urb32_isoframes(kurb, uurb);
+- if (err)
+- goto out;
+-
+- err = -EFAULT;
+- if (__get_user(udata, &uurb->buffer))
+- goto out;
+- uptr = A(udata);
+-
+- err = -ENOMEM;
+- buflen = kurb->buffer_length;
+- kptr = kmalloc(buflen, GFP_KERNEL);
+- if (!kptr)
+- goto out;
+-
+- kurb->buffer = kptr;
+-
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, buflen))
+- goto out_kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
+- set_fs(old_fs);
+-
+- if (err >= 0) {
+- /* XXX Shit, this doesn't work for async URBs :-( XXX */
+- if (put_urb32(kurb, uurb)) {
+- err = -EFAULT;
+- } else if ((kurb->endpoint & USB_DIR_IN) != 0) {
+- if (copy_to_user(uptr, kptr, buflen))
+- err = -EFAULT;
+- }
+- }
+-
+-out_kptr:
+- kfree(kptr);
+-
+-out:
+- kfree(kurb);
+- return err;
+-}
+-#endif
+-
+-#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
+-#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
+-
+-static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- mm_segment_t old_fs;
+- void *kptr;
+- int err;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd,
+- (cmd == USBDEVFS_REAPURB32 ?
+- USBDEVFS_REAPURB :
+- USBDEVFS_REAPURBNDELAY),
+- (unsigned long) &kptr);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- put_user(((u32)(long)kptr), (u32 __user *) A(arg)))
+- err = -EFAULT;
+-
+- return err;
+-}
+-
+-struct usbdevfs_disconnectsignal32 {
+- unsigned int signr;
+- u32 context;
+-};
+-
+-#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
+-
+-static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_disconnectsignal kdis;
+- struct usbdevfs_disconnectsignal32 *udis;
+- mm_segment_t old_fs;
+- u32 uctx;
+- int err;
+-
+- udis = (struct usbdevfs_disconnectsignal32 *) arg;
+-
+- if (get_user(kdis.signr, &udis->signr) ||
+- __get_user(uctx, &udis->context))
+- return -EFAULT;
+-
+- kdis.context = (void *) (long)uctx;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
+- set_fs(old_fs);
+-
+- return err;
+-}
+-
+ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+
+ #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
+@@ -1397,8 +1001,6 @@ IOCTL_TABLE_START
+ COMPATIBLE_IOCTL(TCSBRKP)
+ COMPATIBLE_IOCTL(TIOCSTART)
+ COMPATIBLE_IOCTL(TIOCSTOP)
+-COMPATIBLE_IOCTL(TIOCGSERIAL)
+-COMPATIBLE_IOCTL(TIOCSSERIAL)
+ COMPATIBLE_IOCTL(TIOCSLTC)
+ COMPATIBLE_IOCTL(FBIOGTYPE)
+ COMPATIBLE_IOCTL(FBIOSATTR)
+@@ -1467,9 +1069,6 @@ COMPATIBLE_IOCTL(AUDIO_GETDEV)
+ COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS)
+ COMPATIBLE_IOCTL(AUDIO_FLUSH)
+ COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
+-/* Raw devices */
+-COMPATIBLE_IOCTL(RAW_SETBIND)
+-COMPATIBLE_IOCTL(RAW_GETBIND)
+ /* NCP ioctls which do not need any translations */
+ COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
+ COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
+@@ -1575,12 +1174,6 @@ HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioct
+ HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl)
+ HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl)
+ #endif
+-HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
+-HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
+-/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
+-HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+ /* take care of sizeof(sizeof()) breakage */
+ IOCTL_TABLE_END
+
+--- linux-2.6.0-test6/arch/sparc64/kernel/module.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/sparc64/kernel/module.c 2003-10-05 00:33:23.000000000 -0700
+@@ -14,6 +14,9 @@
+ #include <linux/vmalloc.h>
+ #include <linux/mm.h>
+
++#include <asm/processor.h>
++#include <asm/spitfire.h>
++
+ static struct vm_struct * modvmlist = NULL;
+
+ static void module_unmap(void * addr)
+@@ -279,6 +282,16 @@ int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+ {
++ /* Cheetah's I-cache is fully coherent. */
++ if (tlb_type == spitfire) {
++ unsigned long va;
++
++ flushw_all();
++ for (va = 0; va < (PAGE_SIZE << 1); va += 32)
++ spitfire_put_icache_tag(va, 0x0);
++ __asm__ __volatile__("flush %g6");
++ }
++
+ return 0;
+ }
+
+--- linux-2.6.0-test6/arch/sparc64/kernel/smp.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/sparc64/kernel/smp.c 2003-10-05 00:33:23.000000000 -0700
+@@ -118,7 +118,6 @@ void __init smp_callin(void)
+
+ inherit_locked_prom_mappings(0);
+
+- __flush_cache_all();
+ __flush_tlb_all();
+
+ smp_setup_percpu_timer();
+@@ -661,7 +660,6 @@ extern unsigned long xcall_flush_tlb_ran
+ extern unsigned long xcall_flush_tlb_kernel_range;
+ extern unsigned long xcall_flush_tlb_all_spitfire;
+ extern unsigned long xcall_flush_tlb_all_cheetah;
+-extern unsigned long xcall_flush_cache_all_spitfire;
+ extern unsigned long xcall_report_regs;
+ extern unsigned long xcall_receive_signal;
+ extern unsigned long xcall_flush_dcache_page_cheetah;
+@@ -776,15 +774,6 @@ void smp_report_regs(void)
+ smp_cross_call(&xcall_report_regs, 0, 0, 0);
+ }
+
+-void smp_flush_cache_all(void)
+-{
+- /* Cheetah need do nothing. */
+- if (tlb_type == spitfire) {
+- smp_cross_call(&xcall_flush_cache_all_spitfire, 0, 0, 0);
+- __flush_cache_all();
+- }
+-}
+-
+ void smp_flush_tlb_all(void)
+ {
+ if (tlb_type == spitfire)
+--- linux-2.6.0-test6/arch/sparc64/kernel/systbls.S 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/sparc64/kernel/systbls.S 2003-10-05 00:33:23.000000000 -0700
+@@ -72,7 +72,7 @@ sys_call_table32:
+ /*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
+ .word sys_ni_syscall, compat_clock_settime, compat_clock_gettime, compat_clock_getres, compat_clock_nanosleep
+ /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, compat_timer_settime, compat_timer_gettime, sys_timer_getoverrun
+- .word sys_timer_delete, sys32_timer_create, sys_ni_syscall
++ .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, sys_ni_syscall
+
+ /* Now the 64-bit native Linux syscall table. */
+
+@@ -133,7 +133,7 @@ sys_call_table:
+ /*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+ .word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+ /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+- .word sys_timer_delete, sys_timer_create, sys_ni_syscall
++ .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_ni_syscall
+
+ #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+ defined(CONFIG_SOLARIS_EMUL_MODULE)
+@@ -233,5 +233,6 @@ sunos_sys_table:
+ .word sunos_nosys, sunos_nosys, sunos_nosys
+ .word sunos_nosys, sunos_nosys, sunos_nosys
+ .word sunos_nosys, sunos_nosys, sunos_nosys
++ .word sunos_nosys
+
+ #endif
+--- linux-2.6.0-test6/arch/sparc64/lib/rwlock.S 2003-06-26 22:07:24.000000000 -0700
++++ 25/arch/sparc64/lib/rwlock.S 2003-10-05 00:36:40.000000000 -0700
+@@ -63,5 +63,33 @@ __write_lock: /* %o0 = lock_ptr */
+ be,pt %icc, 99b
+ membar #StoreLoad | #StoreStore
+ ba,a,pt %xcc, 1b
++
++ .globl __read_trylock
++__read_trylock: /* %o0 = lock_ptr */
++ ldsw [%o0], %g5
++ brlz,pn %g5, 100f
++ add %g5, 1, %g7
++ cas [%o0], %g5, %g7
++ cmp %g5, %g7
++ bne,pn %icc, __read_trylock
++ membar #StoreLoad | #StoreStore
++ retl
++ mov 1, %o0
++
++ .globl __write_trylock
++__write_trylock: /* %o0 = lock_ptr */
++ sethi %hi(0x80000000), %g2
++1: lduw [%o0], %g5
++4: brnz,pn %g5, 100f
++ or %g5, %g2, %g7
++ cas [%o0], %g5, %g7
++ cmp %g5, %g7
++ bne,pn %icc, 1b
++ membar #StoreLoad | #StoreStore
++ retl
++ mov 1, %o0
++100: retl
++ mov 0, %o0
++
+ rwlock_impl_end:
+
+--- linux-2.6.0-test6/arch/sparc64/mm/init.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/sparc64/mm/init.c 2003-10-05 00:33:23.000000000 -0700
+@@ -1025,19 +1025,6 @@ void __flush_dcache_range(unsigned long
+ }
+ }
+
+-void __flush_cache_all(void)
+-{
+- /* Cheetah should be fine here too. */
+- if (tlb_type == spitfire) {
+- unsigned long va;
+-
+- flushw_all();
+- for (va = 0; va < (PAGE_SIZE << 1); va += 32)
+- spitfire_put_icache_tag(va, 0x0);
+- __asm__ __volatile__("flush %g6");
+- }
+-}
+-
+ /* If not locked, zap it. */
+ void __flush_tlb_all(void)
+ {
+--- linux-2.6.0-test6/arch/sparc64/mm/ultra.S 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/sparc64/mm/ultra.S 2003-10-05 00:33:23.000000000 -0700
+@@ -721,20 +721,6 @@ xcall_flush_tlb_all_cheetah:
+ stxa %g0, [%g2] ASI_IMMU_DEMAP
+ retry
+
+- .globl xcall_flush_cache_all_spitfire
+-xcall_flush_cache_all_spitfire:
+- sethi %hi(16383), %g2
+- or %g2, %lo(16383), %g2
+- clr %g3
+-1: stxa %g0, [%g3] ASI_IC_TAG
+- membar #Sync
+- add %g3, 32, %g3
+- cmp %g3, %g2
+- bleu,pt %xcc, 1b
+- nop
+- flush %g6
+- retry
+-
+ /* These just get rescheduled to PIL vectors. */
+ .globl xcall_call_function
+ xcall_call_function:
+--- linux-2.6.0-test6/arch/sparc/kernel/entry.S 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/sparc/kernel/entry.S 2003-10-05 00:33:23.000000000 -0700
+@@ -38,7 +38,7 @@
+
+ #define curptr g6
+
+-#define NR_SYSCALLS 267 /* Each OS is different... */
++#define NR_SYSCALLS 268 /* Each OS is different... */
+
+ /* These are just handy. */
+ #define _SV save %sp, -STACKFRAME_SZ, %sp
+--- linux-2.6.0-test6/arch/sparc/kernel/systbls.S 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/sparc/kernel/systbls.S 2003-10-05 00:33:23.000000000 -0700
+@@ -72,7 +72,7 @@ sys_call_table:
+ /*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+ /*255*/ .long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
+ /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
+-/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall
++/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_nis_syscall
+
+ #ifdef CONFIG_SUNOS_EMUL
+ /* Now the SunOS syscall table. */
+@@ -171,6 +171,6 @@ sunos_sys_table:
+ .long sunos_nosys
+ /*260*/ .long sunos_nosys, sunos_nosys, sunos_nosys
+ .long sunos_nosys, sunos_nosys, sunos_nosys
+- .long sunos_nosys, sunos_nosys
++ .long sunos_nosys, sunos_nosys, sunos_nosys
+
+ #endif
+--- linux-2.6.0-test6/arch/sparc/kernel/time.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/arch/sparc/kernel/time.c 2003-10-05 00:36:33.000000000 -0700
+@@ -617,3 +617,12 @@ static int set_rtc_mmss(unsigned long no
+ return -1;
+ }
+ }
++
++/*
++ * Returns nanoseconds
++ */
++
++unsigned long long sched_clock(void)
++{
++ return (unsigned long long)jiffies * (1000000000 / HZ);
++}
+--- linux-2.6.0-test6/arch/um/config.release 2003-08-08 22:55:11.000000000 -0700
++++ 25/arch/um/config.release 2003-10-05 00:34:32.000000000 -0700
+@@ -228,7 +228,6 @@ CONFIG_ROMFS_FS=m
+ CONFIG_EXT2_FS=y
+ CONFIG_SYSV_FS=m
+ CONFIG_UDF_FS=m
+-# CONFIG_UDF_RW is not set
+ CONFIG_UFS_FS=m
+ # CONFIG_UFS_FS_WRITE is not set
+
+--- linux-2.6.0-test6/arch/um/defconfig 2003-08-08 22:55:11.000000000 -0700
++++ 25/arch/um/defconfig 2003-10-05 00:34:32.000000000 -0700
+@@ -3,29 +3,19 @@
+ #
+ CONFIG_USERMODE=y
+ CONFIG_MMU=y
+-CONFIG_SWAP=y
+ CONFIG_UID16=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
+-CONFIG_CONFIG_LOG_BUF_SHIFT=14
+-
+-#
+-# Code maturity level options
+-#
+-CONFIG_EXPERIMENTAL=y
+
+ #
+-# General Setup
++# UML-specific options
+ #
+ CONFIG_MODE_TT=y
+ CONFIG_MODE_SKAS=y
+ CONFIG_NET=y
+-CONFIG_SYSVIPC=y
+-CONFIG_BSD_PROCESS_ACCT=y
+-CONFIG_SYSCTL=y
+-CONFIG_BINFMT_AOUT=y
+ CONFIG_BINFMT_ELF=y
+ CONFIG_BINFMT_MISC=y
+ CONFIG_HOSTFS=y
++CONFIG_HPPFS=y
+ CONFIG_MCONSOLE=y
+ CONFIG_MAGIC_SYSRQ=y
+ # CONFIG_HOST_2G_2G is not set
+@@ -38,10 +28,38 @@ CONFIG_PROC_MM=y
+ CONFIG_KERNEL_STACK_ORDER=2
+
+ #
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_STANDALONE=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_SYSCTL=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_IKCONFIG is not set
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++
++#
+ # Loadable module support
+ #
+-CONFIG_MODULES=y
+-# CONFIG_KMOD is not set
++# CONFIG_MODULES is not set
++
++#
++# Generic Driver Options
++#
+
+ #
+ # Character Devices
+@@ -69,6 +87,7 @@ CONFIG_HOSTAUDIO=y
+ #
+ CONFIG_BLK_DEV_UBD=y
+ # CONFIG_BLK_DEV_UBD_SYNC is not set
++CONFIG_BLK_DEV_COW_COMMON=y
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_NBD=y
+ CONFIG_BLK_DEV_RAM=y
+@@ -78,7 +97,7 @@ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_NETDEVICES=y
+
+ #
+-# Network Devices
++# UML Network Devices
+ #
+ CONFIG_UML_NET=y
+ CONFIG_UML_NET_ETHERTAP=y
+@@ -88,22 +107,6 @@ CONFIG_UML_NET_DAEMON=y
+ CONFIG_UML_NET_MCAST=y
+ # CONFIG_UML_NET_PCAP is not set
+ CONFIG_UML_NET_SLIRP=y
+-CONFIG_DUMMY=y
+-# CONFIG_BONDING is not set
+-# CONFIG_EQUALIZER is not set
+-CONFIG_TUN=y
+-# CONFIG_ETHERTAP is not set
+-CONFIG_PPP=y
+-# CONFIG_PPP_MULTILINK is not set
+-# CONFIG_PPP_ASYNC is not set
+-# CONFIG_PPP_SYNC_TTY is not set
+-# CONFIG_PPP_DEFLATE is not set
+-# CONFIG_PPP_BSDCOMP is not set
+-# CONFIG_PPPOE is not set
+-CONFIG_SLIP=y
+-# CONFIG_SLIP_COMPRESSED is not set
+-# CONFIG_SLIP_SMART is not set
+-# CONFIG_SLIP_MODE_SLIP6 is not set
+
+ #
+ # Networking support
+@@ -115,8 +118,6 @@ CONFIG_SLIP=y
+ CONFIG_PACKET=y
+ CONFIG_PACKET_MMAP=y
+ # CONFIG_NETLINK_DEV is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_FILTER is not set
+ CONFIG_UNIX=y
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+@@ -130,8 +131,11 @@ CONFIG_INET=y
+ # CONFIG_SYN_COOKIES is not set
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+-# CONFIG_XFRM_USER is not set
++# CONFIG_INET_IPCOMP is not set
+ # CONFIG_IPV6 is not set
++# CONFIG_DECNET is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NETFILTER is not set
+
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+@@ -141,8 +145,6 @@ CONFIG_IPV6_SCTP__=y
+ # CONFIG_ATM is not set
+ # CONFIG_VLAN_8021Q is not set
+ # CONFIG_LLC is not set
+-# CONFIG_DECNET is not set
+-# CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_NET_DIVERT is not set
+@@ -160,6 +162,10 @@ CONFIG_IPV6_SCTP__=y
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
++CONFIG_DUMMY=y
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_TUN=y
+
+ #
+ # Ethernet (10 or 100Mbit)
+@@ -171,6 +177,22 @@ CONFIG_IPV6_SCTP__=y
+ #
+
+ #
++# Ethernet (10000 Mbit)
++#
++CONFIG_PPP=y
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++# CONFIG_PPP_ASYNC is not set
++# CONFIG_PPP_SYNC_TTY is not set
++# CONFIG_PPP_DEFLATE is not set
++# CONFIG_PPP_BSDCOMP is not set
++# CONFIG_PPPOE is not set
++CONFIG_SLIP=y
++# CONFIG_SLIP_COMPRESSED is not set
++# CONFIG_SLIP_SMART is not set
++# CONFIG_SLIP_MODE_SLIP6 is not set
++
++#
+ # Wireless LAN (non-hamradio)
+ #
+ # CONFIG_NET_RADIO is not set
+@@ -188,66 +210,82 @@ CONFIG_IPV6_SCTP__=y
+ #
+ # File systems
+ #
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++CONFIG_MINIX_FS=y
++# CONFIG_ROMFS_FS is not set
+ CONFIG_QUOTA=y
+ # CONFIG_QFMT_V1 is not set
+ # CONFIG_QFMT_V2 is not set
+ CONFIG_QUOTACTL=y
+-CONFIG_AUTOFS_FS=m
+-CONFIG_AUTOFS4_FS=m
+-CONFIG_REISERFS_FS=m
+-# CONFIG_REISERFS_CHECK is not set
+-# CONFIG_REISERFS_PROC_INFO is not set
++CONFIG_AUTOFS_FS=y
++CONFIG_AUTOFS4_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_DEVFS_FS=y
++CONFIG_DEVFS_MOUNT=y
++# CONFIG_DEVFS_DEBUG is not set
++CONFIG_DEVPTS_FS=y
++# CONFIG_DEVPTS_FS_XATTR is not set
++# CONFIG_TMPFS is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_AFFS_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+-# CONFIG_EXT3_FS is not set
+-# CONFIG_JBD is not set
+-CONFIG_FAT_FS=m
+-CONFIG_MSDOS_FS=m
+-CONFIG_VFAT_FS=m
+ # CONFIG_EFS_FS is not set
+ CONFIG_JFFS_FS=y
+ CONFIG_JFFS_FS_VERBOSE=0
+-CONFIG_JFFS_PROC_FS=y
+ # CONFIG_JFFS2_FS is not set
+ # CONFIG_CRAMFS is not set
+-# CONFIG_TMPFS is not set
+-CONFIG_RAMFS=y
+-CONFIG_ISO9660_FS=m
+-# CONFIG_JOLIET is not set
+-# CONFIG_ZISOFS is not set
+-# CONFIG_JFS_FS is not set
+-CONFIG_MINIX_FS=m
+ # CONFIG_VXFS_FS is not set
+-# CONFIG_NTFS_FS is not set
+ # CONFIG_HPFS_FS is not set
+-CONFIG_PROC_FS=y
+-CONFIG_DEVFS_FS=y
+-CONFIG_DEVFS_MOUNT=y
+-# CONFIG_DEVFS_DEBUG is not set
+-CONFIG_DEVPTS_FS=y
+ # CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-CONFIG_EXT2_FS=y
+-# CONFIG_EXT2_FS_XATTR is not set
+ # CONFIG_SYSV_FS is not set
+-# CONFIG_UDF_FS is not set
+ # CONFIG_UFS_FS is not set
+-# CONFIG_XFS_FS is not set
+
+ #
+ # Network File Systems
+ #
+-# CONFIG_CODA_FS is not set
+-# CONFIG_INTERMEZZO_FS is not set
+ # CONFIG_NFS_FS is not set
+ # CONFIG_NFSD is not set
+ # CONFIG_EXPORTFS is not set
+-# CONFIG_CIFS is not set
+ # CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
+ # CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_INTERMEZZO_FS is not set
+ # CONFIG_AFS_FS is not set
+
+ #
+@@ -317,28 +355,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
+ #
+ # SCSI support
+ #
+-CONFIG_SCSI=y
+-CONFIG_GENERIC_ISA_DMA=y
+-
+-#
+-# SCSI support type (disk, tape, CD-ROM)
+-#
+-CONFIG_BLK_DEV_SD=y
+-CONFIG_SD_EXTRA_DEVS=40
+-CONFIG_CHR_DEV_ST=y
+-CONFIG_BLK_DEV_SR=y
+-CONFIG_BLK_DEV_SR_VENDOR=y
+-CONFIG_SR_EXTRA_DEVS=2
+-CONFIG_CHR_DEV_SG=y
+-
+-#
+-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+-#
+-CONFIG_SCSI_DEBUG_QUEUES=y
+-CONFIG_SCSI_MULTI_LUN=y
+-CONFIG_SCSI_CONSTANTS=y
+-CONFIG_SCSI_LOGGING=y
+-CONFIG_SCSI_DEBUG=y
++# CONFIG_SCSI is not set
+
+ #
+ # Multi-device support (RAID and LVM)
+@@ -360,6 +377,7 @@ CONFIG_MTD_CHAR=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
+
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -374,20 +392,21 @@ CONFIG_MTD_BLOCK=y
+ #
+ # Mapping drivers for chip access
+ #
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+
+ #
+ # Self-contained MTD device drivers
+ #
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-CONFIG_MTD_BLKMTD=m
++CONFIG_MTD_BLKMTD=y
+
+ #
+ # Disk-On-Chip Device Drivers
+ #
+-# CONFIG_MTD_DOC1000 is not set
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
+
+ #
+ # NAND Flash Device Drivers
+--- linux-2.6.0-test6/arch/um/drivers/chan_kern.c 2003-06-14 12:18:35.000000000 -0700
++++ 25/arch/um/drivers/chan_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -8,6 +8,7 @@
+ #include <linux/list.h>
+ #include <linux/slab.h>
+ #include <linux/tty.h>
++#include <linux/string.h>
+ #include <linux/tty_flip.h>
+ #include <asm/irq.h>
+ #include "chan_kern.h"
+--- linux-2.6.0-test6/arch/um/drivers/chan_user.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/um/drivers/chan_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -188,8 +188,8 @@ void register_winch(int fd, void *device
+ if(!isatty(fd)) return;
+
+ pid = tcgetpgrp(fd);
+- if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) &&
+- (pid == -1)){
++ if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
++ device_data) && (pid == -1)){
+ thread = winch_tramp(fd, device_data, &thread_fd);
+ if(fd != -1){
+ register_winch_irq(thread_fd, fd, thread, device_data);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/um/drivers/cow.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,40 @@
++#ifndef __COW_H__
++#define __COW_H__
++
++#include <asm/types.h>
++
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define ntohll(x) (x)
++# define htonll(x) (x)
++#elif __BYTE_ORDER == __LITTLE_ENDIAN
++# define ntohll(x) bswap_64(x)
++# define htonll(x) bswap_64(x)
++#else
++#error "__BYTE_ORDER not defined"
++#endif
++
++extern int init_cow_file(int fd, char *cow_file, char *backing_file,
++ int sectorsize, int *bitmap_offset_out,
++ unsigned long *bitmap_len_out, int *data_offset_out);
++
++extern int file_reader(__u64 offset, char *buf, int len, void *arg);
++extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
++ void *arg, __u32 *magic_out,
++ char **backing_file_out, time_t *mtime_out,
++ __u64 *size_out, int *sectorsize_out,
++ int *bitmap_offset_out);
++
++extern int write_cow_header(char *cow_file, int fd, char *backing_file,
++ int sectorsize, long long *size);
++
++extern void cow_sizes(__u64 size, int sectorsize, int bitmap_offset,
++ unsigned long *bitmap_len_out, int *data_offset_out);
++
++#endif
++
++/*
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/um/drivers/cow_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,628 @@
++#define COW_MAJOR 60
++#define MAJOR_NR COW_MAJOR
++
++#include <linux/stddef.h>
++#include <linux/kernel.h>
++#include <linux/ctype.h>
++#include <linux/stat.h>
++#include <linux/vmalloc.h>
++#include <linux/blkdev.h>
++#include <linux/blk.h>
++#include <linux/fs.h>
++#include <linux/genhd.h>
++#include <linux/devfs_fs.h>
++#include <asm/uaccess.h>
++#include "2_5compat.h"
++#include "cow.h"
++#include "ubd_user.h"
++
++#define COW_SHIFT 4
++
++struct cow {
++ int count;
++ char *cow_path;
++ dev_t cow_dev;
++ struct block_device *cow_bdev;
++ char *backing_path;
++ dev_t backing_dev;
++ struct block_device *backing_bdev;
++ int sectorsize;
++ unsigned long *bitmap;
++ unsigned long bitmap_len;
++ int bitmap_offset;
++ int data_offset;
++ devfs_handle_t devfs;
++ struct semaphore sem;
++ struct semaphore io_sem;
++ atomic_t working;
++ spinlock_t io_lock;
++ struct buffer_head *bh;
++ struct buffer_head *bhtail;
++ void *end_io;
++};
++
++#define DEFAULT_COW { \
++ .count = 0, \
++ .cow_path = NULL, \
++ .cow_dev = 0, \
++ .backing_path = NULL, \
++ .backing_dev = 0, \
++ .bitmap = NULL, \
++ .bitmap_len = 0, \
++ .bitmap_offset = 0, \
++ .data_offset = 0, \
++ .devfs = NULL, \
++ .working = ATOMIC_INIT(0), \
++ .io_lock = SPIN_LOCK_UNLOCKED, \
++}
++
++#define MAX_DEV (8)
++#define MAX_MINOR (MAX_DEV << COW_SHIFT)
++
++struct cow cow_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_COW };
++
++/* Not modified by this driver */
++static int blk_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = BLOCK_SIZE };
++static int hardsect_sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 512 };
++
++/* Protected by cow_lock */
++static int sizes[MAX_MINOR] = { [ 0 ... MAX_MINOR - 1 ] = 0 };
++
++static struct hd_struct cow_part[MAX_MINOR] =
++ { [ 0 ... MAX_MINOR - 1 ] = { 0, 0, 0 } };
++
++/* Protected by io_request_lock */
++static request_queue_t *cow_queue;
++
++static int cow_open(struct inode *inode, struct file *filp);
++static int cow_release(struct inode * inode, struct file * file);
++static int cow_ioctl(struct inode * inode, struct file * file,
++ unsigned int cmd, unsigned long arg);
++static int cow_revalidate(kdev_t rdev);
++
++static struct block_device_operations cow_blops = {
++ .open = cow_open,
++ .release = cow_release,
++ .ioctl = cow_ioctl,
++ .revalidate = cow_revalidate,
++};
++
++/* Initialized in an initcall, and unchanged thereafter */
++devfs_handle_t cow_dir_handle;
++
++#define INIT_GENDISK(maj, name, parts, shift, bsizes, max, blops) \
++{ \
++ .major = maj, \
++ .major_name = name, \
++ .minor_shift = shift, \
++ .max_p = 1 << shift, \
++ .part = parts, \
++ .sizes = bsizes, \
++ .nr_real = max, \
++ .real_devices = NULL, \
++ .next = NULL, \
++ .fops = blops, \
++ .de_arr = NULL, \
++ .flags = 0 \
++}
++
++static spinlock_t cow_lock = SPIN_LOCK_UNLOCKED;
++
++static struct gendisk cow_gendisk = INIT_GENDISK(MAJOR_NR, "cow", cow_part,
++ COW_SHIFT, sizes, MAX_DEV,
++ &cow_blops);
++
++static int cow_add(int n)
++{
++ struct cow *dev = &cow_dev[n];
++ char name[sizeof("nnnnnn\0")];
++ int err = -ENODEV;
++
++ if(dev->cow_path == NULL)
++ goto out;
++
++ sprintf(name, "%d", n);
++ dev->devfs = devfs_register(cow_dir_handle, name, DEVFS_FL_REMOVABLE,
++ MAJOR_NR, n << COW_SHIFT, S_IFBLK |
++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
++ &cow_blops, NULL);
++
++ init_MUTEX_LOCKED(&dev->sem);
++ init_MUTEX(&dev->io_sem);
++
++ return(0);
++
++out:
++ return(err);
++}
++
++/*
++* Add buffer_head to back of pending list
++*/
++static void cow_add_bh(struct cow *cow, struct buffer_head *bh)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&cow->io_lock, flags);
++ if(cow->bhtail != NULL){
++ cow->bhtail->b_reqnext = bh;
++ cow->bhtail = bh;
++ }
++ else {
++ cow->bh = bh;
++ cow->bhtail = bh;
++ }
++ spin_unlock_irqrestore(&cow->io_lock, flags);
++}
++
++/*
++* Grab first pending buffer
++*/
++static struct buffer_head *cow_get_bh(struct cow *cow)
++{
++ struct buffer_head *bh;
++
++ spin_lock_irq(&cow->io_lock);
++ bh = cow->bh;
++ if(bh != NULL){
++ if(bh == cow->bhtail)
++ cow->bhtail = NULL;
++ cow->bh = bh->b_reqnext;
++ bh->b_reqnext = NULL;
++ }
++ spin_unlock_irq(&cow->io_lock);
++
++ return(bh);
++}
++
++static void cow_handle_bh(struct cow *cow, struct buffer_head *bh,
++ struct buffer_head **cow_bh, int ncow_bh)
++{
++ int i;
++
++ if(ncow_bh > 0)
++ ll_rw_block(WRITE, ncow_bh, cow_bh);
++
++ for(i = 0; i < ncow_bh ; i++){
++ wait_on_buffer(cow_bh[i]);
++ brelse(cow_bh[i]);
++ }
++
++ ll_rw_block(WRITE, 1, &bh);
++ brelse(bh);
++}
++
++static struct buffer_head *cow_new_bh(struct cow *dev, int sector)
++{
++ struct buffer_head *bh;
++
++ sector = (dev->bitmap_offset + sector / 8) / dev->sectorsize;
++ bh = getblk(dev->cow_dev, sector, dev->sectorsize);
++ memcpy(bh->b_data, dev->bitmap + sector / (8 * sizeof(dev->bitmap[0])),
++ dev->sectorsize);
++ return(bh);
++}
++
++/* Copied from loop.c, needed to avoid deadlocking in make_request. */
++
++static int cow_thread(void *data)
++{
++ struct cow *dev = data;
++ struct buffer_head *bh;
++
++ daemonize();
++ exit_files(current);
++
++ sprintf(current->comm, "cow%d", dev - cow_dev);
++
++ spin_lock_irq(¤t->sigmask_lock);
++ sigfillset(¤t->blocked);
++ flush_signals(current);
++ spin_unlock_irq(¤t->sigmask_lock);
++
++ atomic_inc(&dev->working);
++
++ current->policy = SCHED_OTHER;
++ current->nice = -20;
++
++ current->flags |= PF_NOIO;
++
++ /*
++ * up sem, we are running
++ */
++ up(&dev->sem);
++
++ for(;;){
++ int start, len, nbh, i, update_bitmap = 0;
++ struct buffer_head *cow_bh[2];
++
++ down_interruptible(&dev->io_sem);
++ /*
++ * could be upped because of tear-down, not because of
++ * pending work
++ */
++ if(!atomic_read(&dev->working))
++ break;
++
++ bh = cow_get_bh(dev);
++ if(bh == NULL){
++ printk(KERN_ERR "cow: missing bh\n");
++ continue;
++ }
++
++ start = bh->b_blocknr * bh->b_size / dev->sectorsize;
++ len = bh->b_size / dev->sectorsize;
++ for(i = 0; i < len ; i++){
++ if(ubd_test_bit(start +ni,
++ (unsigned char *) dev->bitmap))
++ continue;
++
++ update_bitmap = 1;
++ ubd_set_bit(start + i, (unsigned char *) dev->bitmap);
++ }
++
++ cow_bh[0] = NULL;
++ cow_bh[1] = NULL;
++ nbh = 0;
++ if(update_bitmap){
++ cow_bh[0] = cow_new_bh(dev, start);
++ nbh++;
++ if(start / dev->sectorsize !=
++ (start + len) / dev->sectorsize){
++ cow_bh[1] = cow_new_bh(dev, start + len);
++ nbh++;
++ }
++ }
++
++ bh->b_dev = dev->cow_dev;
++ bh->b_blocknr += dev->data_offset / dev->sectorsize;
++
++ cow_handle_bh(dev, bh, cow_bh, nbh);
++
++ /*
++ * upped both for pending work and tear-down, lo_pending
++ * will hit zero then
++ */
++ if(atomic_dec_and_test(&dev->working))
++ break;
++ }
++
++ up(&dev->sem);
++ return(0);
++}
++
++static int cow_make_request(request_queue_t *q, int rw, struct buffer_head *bh)
++{
++ struct cow *dev;
++ int n, minor;
++
++ minor = MINOR(bh->b_rdev);
++ n = minor >> COW_SHIFT;
++ dev = &cow_dev[n];
++
++ dev->end_io = NULL;
++ if(ubd_test_bit(bh->b_rsector, (unsigned char *) dev->bitmap)){
++ bh->b_rdev = dev->cow_dev;
++ bh->b_rsector += dev->data_offset / dev->sectorsize;
++ }
++ else if(rw == WRITE){
++ bh->b_dev = dev->cow_dev;
++ bh->b_blocknr += dev->data_offset / dev->sectorsize;
++
++ cow_add_bh(dev, bh);
++ up(&dev->io_sem);
++ return(0);
++ }
++ else {
++ bh->b_rdev = dev->backing_dev;
++ }
++
++ return(1);
++}
++
++int cow_init(void)
++{
++ int i;
++
++ cow_dir_handle = devfs_mk_dir (NULL, "cow", NULL);
++ if (devfs_register_blkdev(MAJOR_NR, "cow", &cow_blops)) {
++ printk(KERN_ERR "cow: unable to get major %d\n", MAJOR_NR);
++ return -1;
++ }
++ read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
++ blksize_size[MAJOR_NR] = blk_sizes;
++ blk_size[MAJOR_NR] = sizes;
++ INIT_HARDSECT(hardsect_size, MAJOR_NR, hardsect_sizes);
++
++ cow_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
++ blk_init_queue(cow_queue, NULL);
++ INIT_ELV(cow_queue, &cow_queue->elevator);
++ blk_queue_make_request(cow_queue, cow_make_request);
++
++ add_gendisk(&cow_gendisk);
++
++ for(i=0;i<MAX_DEV;i++)
++ cow_add(i);
++
++ return(0);
++}
++
++__initcall(cow_init);
++
++static int reader(__u64 start, char *buf, int count, void *arg)
++{
++ dev_t dev = *((dev_t *) arg);
++ struct buffer_head *bh;
++ __u64 block;
++ int cur, offset, left, n, blocksize = get_hardsect_size(dev);
++
++ if(blocksize == 0)
++ panic("Zero blocksize");
++
++ block = start / blocksize;
++ offset = start % blocksize;
++ left = count;
++ cur = 0;
++ while(left > 0){
++ n = (left > blocksize) ? blocksize : left;
++
++ bh = bread(dev, block, (n < 512) ? 512 : n);
++ if(bh == NULL)
++ return(-EIO);
++
++ n -= offset;
++ memcpy(&buf[cur], bh->b_data + offset, n);
++ block++;
++ left -= n;
++ cur += n;
++ offset = 0;
++ brelse(bh);
++ }
++
++ return(count);
++}
++
++static int cow_open(struct inode *inode, struct file *filp)
++{
++ int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
++ unsigned long);
++ mm_segment_t fs;
++ struct cow *dev;
++ __u64 size;
++ __u32 magic;
++ time_t mtime;
++ char *backing_file;
++ int n, offset, err = 0;
++
++ n = DEVICE_NR(inode->i_rdev);
++ if(n >= MAX_DEV)
++ return(-ENODEV);
++ dev = &cow_dev[n];
++ offset = n << COW_SHIFT;
++
++ spin_lock(&cow_lock);
++
++ if(dev->count == 0){
++ dev->cow_dev = name_to_kdev_t(dev->cow_path);
++ if(dev->cow_dev == 0){
++ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
++ "failed\n", dev->cow_path);
++ err = -ENODEV;
++ }
++
++ dev->backing_dev = name_to_kdev_t(dev->backing_path);
++ if(dev->backing_dev == 0){
++ printk(KERN_ERR "cow_open - name_to_kdev_t(\"%s\") "
++ "failed\n", dev->backing_path);
++ err = -ENODEV;
++ }
++
++ if(err)
++ goto out;
++
++ dev->cow_bdev = bdget(dev->cow_dev);
++ if(dev->cow_bdev == NULL){
++ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
++ dev->cow_path);
++ err = -ENOMEM;
++ }
++ dev->backing_bdev = bdget(dev->backing_dev);
++ if(dev->backing_bdev == NULL){
++ printk(KERN_ERR "cow_open - bdget(\"%s\") failed\n",
++ dev->backing_path);
++ err = -ENOMEM;
++ }
++
++ if(err)
++ goto out;
++
++ err = blkdev_get(dev->cow_bdev, FMODE_READ|FMODE_WRITE, 0,
++ BDEV_RAW);
++ if(err){
++ printk("cow_open - blkdev_get of COW device failed, "
++ "error = %d\n", err);
++ goto out;
++ }
++
++ err = blkdev_get(dev->backing_bdev, FMODE_READ, 0, BDEV_RAW);
++ if(err){
++ printk("cow_open - blkdev_get of backing device "
++ "failed, error = %d\n", err);
++ goto out;
++ }
++
++ err = read_cow_header(reader, &dev->cow_dev, &magic,
++ &backing_file, &mtime, &size,
++ &dev->sectorsize, &dev->bitmap_offset);
++ if(err){
++ printk(KERN_ERR "cow_open - read_cow_header failed, "
++ "err = %d\n", err);
++ goto out;
++ }
++
++ cow_sizes(size, dev->sectorsize, dev->bitmap_offset,
++ &dev->bitmap_len, &dev->data_offset);
++ dev->bitmap = (void *) vmalloc(dev->bitmap_len);
++ if(dev->bitmap == NULL){
++ err = -ENOMEM;
++ printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
++ goto out;
++ }
++ flush_tlb_kernel_vm();
++
++ err = reader(dev->bitmap_offset, (char *) dev->bitmap,
++ dev->bitmap_len, &dev->cow_dev);
++ if(err < 0){
++ printk(KERN_ERR "Failed to read COW bitmap\n");
++ vfree(dev->bitmap);
++ goto out;
++ }
++
++ dev_ioctl = dev->backing_bdev->bd_op->ioctl;
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = (*dev_ioctl)(inode, filp, BLKGETSIZE,
++ (unsigned long) &sizes[offset]);
++ set_fs(fs);
++ if(err){
++ printk(KERN_ERR "cow_open - BLKGETSIZE failed, "
++ "error = %d\n", err);
++ goto out;
++ }
++
++ kernel_thread(cow_thread, dev,
++ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
++ down(&dev->sem);
++ }
++ dev->count++;
++out:
++ spin_unlock(&cow_lock);
++ return(err);
++}
++
++static int cow_release(struct inode * inode, struct file * file)
++{
++ struct cow *dev;
++ int n, err;
++
++ n = DEVICE_NR(inode->i_rdev);
++ if(n >= MAX_DEV)
++ return(-ENODEV);
++ dev = &cow_dev[n];
++
++ spin_lock(&cow_lock);
++
++ if(--dev->count > 0)
++ goto out;
++
++ err = blkdev_put(dev->cow_bdev, BDEV_RAW);
++ if(err)
++ printk("cow_release - blkdev_put of cow device failed, "
++ "error = %d\n", err);
++ bdput(dev->cow_bdev);
++ dev->cow_bdev = 0;
++
++ err = blkdev_put(dev->backing_bdev, BDEV_RAW);
++ if(err)
++ printk("cow_release - blkdev_put of backing device failed, "
++ "error = %d\n", err);
++ bdput(dev->backing_bdev);
++ dev->backing_bdev = 0;
++
++out:
++ spin_unlock(&cow_lock);
++ return(0);
++}
++
++static int cow_ioctl(struct inode * inode, struct file * file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct cow *dev;
++ int (*dev_ioctl)(struct inode *, struct file *, unsigned int,
++ unsigned long);
++ int n;
++
++ n = DEVICE_NR(inode->i_rdev);
++ if(n >= MAX_DEV)
++ return(-ENODEV);
++ dev = &cow_dev[n];
++
++ dev_ioctl = dev->backing_bdev->bd_op->ioctl;
++ return((*dev_ioctl)(inode, file, cmd, arg));
++}
++
++static int cow_revalidate(kdev_t rdev)
++{
++ printk(KERN_ERR "Need to implement cow_revalidate\n");
++ return(0);
++}
++
++static int parse_unit(char **ptr)
++{
++ char *str = *ptr, *end;
++ int n = -1;
++
++ if(isdigit(*str)) {
++ n = simple_strtoul(str, &end, 0);
++ if(end == str)
++ return(-1);
++ *ptr = end;
++ }
++ else if (('a' <= *str) && (*str <= 'h')) {
++ n = *str - 'a';
++ str++;
++ *ptr = str;
++ }
++ return(n);
++}
++
++static int cow_setup(char *str)
++{
++ struct cow *dev;
++ char *cow_name, *backing_name;
++ int unit;
++
++ unit = parse_unit(&str);
++ if(unit < 0){
++ printk(KERN_ERR "cow_setup - Couldn't parse unit number\n");
++ return(1);
++ }
++
++ if(*str != '='){
++ printk(KERN_ERR "cow_setup - Missing '=' after unit "
++ "number\n");
++ return(1);
++ }
++ str++;
++
++ cow_name = str;
++ backing_name = strchr(str, ',');
++ if(backing_name == NULL){
++ printk(KERN_ERR "cow_setup - missing backing device name\n");
++ return(0);
++ }
++ *backing_name = '\0';
++ backing_name++;
++
++ spin_lock(&cow_lock);
++
++ dev = &cow_dev[unit];
++ dev->cow_path = cow_name;
++ dev->backing_path = backing_name;
++
++ spin_unlock(&cow_lock);
++ return(0);
++}
++
++__setup("cow", cow_setup);
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/um/drivers/cow_sys.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,48 @@
++#ifndef __COW_SYS_H__
++#define __COW_SYS_H__
++
++#include "kern_util.h"
++#include "user_util.h"
++#include "os.h"
++#include "user.h"
++
++static inline void *cow_malloc(int size)
++{
++ return(um_kmalloc(size));
++}
++
++static inline void cow_free(void *ptr)
++{
++ kfree(ptr);
++}
++
++#define cow_printf printk
++
++static inline char *cow_strdup(char *str)
++{
++ return(uml_strdup(str));
++}
++
++static inline int cow_seek_file(int fd, __u64 offset)
++{
++ return(os_seek_file(fd, offset));
++}
++
++static inline int cow_file_size(char *file, __u64 *size_out)
++{
++ return(os_file_size(file, size_out));
++}
++
++static inline int cow_write_file(int fd, char *buf, int size)
++{
++ return(os_write_file(fd, buf, size));
++}
++
++#endif
++
++/*
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/um/drivers/cow_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,296 @@
++#include <stddef.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <byteswap.h>
++#include <sys/stat.h>
++#include <sys/time.h>
++#include <sys/param.h>
++#include <netinet/in.h>
++
++#include "cow.h"
++#include "cow_sys.h"
++
++#define PATH_LEN_V1 256
++
++struct cow_header_v1 {
++ int magic;
++ int version;
++ char backing_file[PATH_LEN_V1];
++ time_t mtime;
++ __u64 size;
++ int sectorsize;
++};
++
++#define PATH_LEN_V2 MAXPATHLEN
++
++struct cow_header_v2 {
++ unsigned long magic;
++ unsigned long version;
++ char backing_file[PATH_LEN_V2];
++ time_t mtime;
++ __u64 size;
++ int sectorsize;
++};
++
++union cow_header {
++ struct cow_header_v1 v1;
++ struct cow_header_v2 v2;
++};
++
++#define COW_MAGIC 0x4f4f4f4d /* MOOO */
++#define COW_VERSION 2
++
++void cow_sizes(__u64 size, int sectorsize, int bitmap_offset,
++ unsigned long *bitmap_len_out, int *data_offset_out)
++{
++ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
++
++ *data_offset_out = bitmap_offset + *bitmap_len_out;
++ *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
++ *data_offset_out *= sectorsize;
++}
++
++static int absolutize(char *to, int size, char *from)
++{
++ char save_cwd[256], *slash;
++ int remaining;
++
++ if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
++ cow_printf("absolutize : unable to get cwd - errno = %d\n",
++ errno);
++ return(-1);
++ }
++ slash = strrchr(from, '/');
++ if(slash != NULL){
++ *slash = '\0';
++ if(chdir(from)){
++ *slash = '/';
++ cow_printf("absolutize : Can't cd to '%s' - "
++ "errno = %d\n", from, errno);
++ return(-1);
++ }
++ *slash = '/';
++ if(getcwd(to, size) == NULL){
++ cow_printf("absolutize : unable to get cwd of '%s' - "
++ "errno = %d\n", from, errno);
++ return(-1);
++ }
++ remaining = size - strlen(to);
++ if(strlen(slash) + 1 > remaining){
++ cow_printf("absolutize : unable to fit '%s' into %d "
++ "chars\n", from, size);
++ return(-1);
++ }
++ strcat(to, slash);
++ }
++ else {
++ if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
++ cow_printf("absolutize : unable to fit '%s' into %d "
++ "chars\n", from, size);
++ return(-1);
++ }
++ strcpy(to, save_cwd);
++ strcat(to, "/");
++ strcat(to, from);
++ }
++ chdir(save_cwd);
++ return(0);
++}
++
++int write_cow_header(char *cow_file, int fd, char *backing_file,
++ int sectorsize, long long *size)
++{
++ struct cow_header_v2 *header;
++ struct stat64 buf;
++ int err;
++
++ err = cow_seek_file(fd, 0);
++ if(err != 0){
++ cow_printf("write_cow_header - lseek failed, errno = %d\n",
++ errno);
++ return(-errno);
++ }
++
++ err = -ENOMEM;
++ header = cow_malloc(sizeof(*header));
++ if(header == NULL){
++ cow_printf("Failed to allocate COW V2 header\n");
++ goto out;
++ }
++ header->magic = htonl(COW_MAGIC);
++ header->version = htonl(COW_VERSION);
++
++ err = -EINVAL;
++ if(strlen(backing_file) > sizeof(header->backing_file) - 1){
++ cow_printf("Backing file name \"%s\" is too long - names are "
++ "limited to %d characters\n", backing_file,
++ sizeof(header->backing_file) - 1);
++ goto out_free;
++ }
++
++ if(absolutize(header->backing_file, sizeof(header->backing_file),
++ backing_file))
++ goto out_free;
++
++ err = stat64(header->backing_file, &buf);
++ if(err < 0){
++ cow_printf("Stat of backing file '%s' failed, errno = %d\n",
++ header->backing_file, errno);
++ err = -errno;
++ goto out_free;
++ }
++
++ err = cow_file_size(header->backing_file, size);
++ if(err){
++ cow_printf("Couldn't get size of backing file '%s', "
++ "errno = %d\n", header->backing_file, -*size);
++ goto out_free;
++ }
++
++ header->mtime = htonl(buf.st_mtime);
++ header->size = htonll(*size);
++ header->sectorsize = htonl(sectorsize);
++
++ err = write(fd, header, sizeof(*header));
++ if(err != sizeof(*header)){
++ cow_printf("Write of header to new COW file '%s' failed, "
++ "errno = %d\n", cow_file, errno);
++ goto out_free;
++ }
++ err = 0;
++ out_free:
++ cow_free(header);
++ out:
++ return(err);
++}
++
++int file_reader(__u64 offset, char *buf, int len, void *arg)
++{
++ int fd = *((int *) arg);
++
++ return(pread(fd, buf, len, offset));
++}
++
++int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
++ __u32 *magic_out, char **backing_file_out,
++ time_t *mtime_out, __u64 *size_out,
++ int *sectorsize_out, int *bitmap_offset_out)
++{
++ union cow_header *header;
++ char *file;
++ int err, n;
++ unsigned long version, magic;
++
++ header = cow_malloc(sizeof(*header));
++ if(header == NULL){
++ cow_printf("read_cow_header - Failed to allocate header\n");
++ return(-ENOMEM);
++ }
++ err = -EINVAL;
++ n = (*reader)(0, (char *) header, sizeof(*header), arg);
++ if(n < offsetof(typeof(header->v1), backing_file)){
++ cow_printf("read_cow_header - short header\n");
++ goto out;
++ }
++
++ magic = header->v1.magic;
++ if(magic == COW_MAGIC) {
++ version = header->v1.version;
++ }
++ else if(magic == ntohl(COW_MAGIC)){
++ version = ntohl(header->v1.version);
++ }
++ /* No error printed because the non-COW case comes through here */
++ else goto out;
++
++ *magic_out = COW_MAGIC;
++
++ if(version == 1){
++ if(n < sizeof(header->v1)){
++ cow_printf("read_cow_header - failed to read V1 "
++ "header\n");
++ goto out;
++ }
++ *mtime_out = header->v1.mtime;
++ *size_out = header->v1.size;
++ *sectorsize_out = header->v1.sectorsize;
++ *bitmap_offset_out = sizeof(header->v1);
++ file = header->v1.backing_file;
++ }
++ else if(version == 2){
++ if(n < sizeof(header->v2)){
++ cow_printf("read_cow_header - failed to read V2 "
++ "header\n");
++ goto out;
++ }
++ *mtime_out = ntohl(header->v2.mtime);
++ *size_out = ntohll(header->v2.size);
++ *sectorsize_out = ntohl(header->v2.sectorsize);
++ *bitmap_offset_out = sizeof(header->v2);
++ file = header->v2.backing_file;
++ }
++ else {
++ cow_printf("read_cow_header - invalid COW version\n");
++ goto out;
++ }
++ err = -ENOMEM;
++ *backing_file_out = cow_strdup(file);
++ if(*backing_file_out == NULL){
++ cow_printf("read_cow_header - failed to allocate backing "
++ "file\n");
++ goto out;
++ }
++ err = 0;
++ out:
++ cow_free(header);
++ return(err);
++}
++
++int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
++ int *bitmap_offset_out, unsigned long *bitmap_len_out,
++ int *data_offset_out)
++{
++ __u64 size, offset;
++ char zero = 0;
++ int err;
++
++ err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
++ if(err)
++ goto out;
++
++ cow_sizes(size, sectorsize, sizeof(struct cow_header_v2),
++ bitmap_len_out, data_offset_out);
++ *bitmap_offset_out = sizeof(struct cow_header_v2);
++
++ offset = *data_offset_out + size - sizeof(zero);
++ err = cow_seek_file(fd, offset);
++ if(err != 0){
++ cow_printf("cow bitmap lseek failed : errno = %d\n", errno);
++ goto out;
++ }
++
++ /* does not really matter how much we write it is just to set EOF
++ * this also sets the entire COW bitmap
++ * to zero without having to allocate it
++ */
++ err = cow_write_file(fd, &zero, sizeof(zero));
++ if(err != sizeof(zero)){
++ err = -EINVAL;
++ cow_printf("Write of bitmap to new COW file '%s' failed, "
++ "errno = %d\n", cow_file, errno);
++ goto out;
++ }
++
++ return(0);
++
++ out:
++ return(err);
++}
++
++/*
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+--- linux-2.6.0-test6/arch/um/drivers/hostaudio_kern.c 2003-06-14 12:18:35.000000000 -0700
++++ 25/arch/um/drivers/hostaudio_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -11,6 +11,7 @@
+ #include "linux/fs.h"
+ #include "linux/sound.h"
+ #include "linux/soundcard.h"
++#include "asm/uaccess.h"
+ #include "kern_util.h"
+ #include "init.h"
+ #include "hostaudio.h"
+@@ -22,7 +23,7 @@ char *mixer = HOSTAUDIO_DEV_MIXER;
+ #ifndef MODULE
+ static int set_dsp(char *name, int *add)
+ {
+- dsp = uml_strdup(name);
++ dsp = name;
+ return(0);
+ }
+
+@@ -34,7 +35,7 @@ __uml_setup("dsp=", set_dsp,
+
+ static int set_mixer(char *name, int *add)
+ {
+- mixer = uml_strdup(name);
++ mixer = name;
+ return(0);
+ }
+
+@@ -51,23 +52,55 @@ static ssize_t hostaudio_read(struct fil
+ loff_t *ppos)
+ {
+ struct hostaudio_state *state = file->private_data;
++ void *kbuf;
++ int err;
+
+ #ifdef DEBUG
+ printk("hostaudio: read called, count = %d\n", count);
+ #endif
+
+- return(hostaudio_read_user(state, buffer, count, ppos));
++ kbuf = kmalloc(count, GFP_KERNEL);
++ if(kbuf == NULL)
++ return(-ENOMEM);
++
++ err = hostaudio_read_user(state, kbuf, count, ppos);
++ if(err < 0)
++ goto out;
++
++ if(copy_to_user(buffer, kbuf, err))
++ err = -EFAULT;
++
++ out:
++ kfree(kbuf);
++ return(err);
+ }
+
+ static ssize_t hostaudio_write(struct file *file, const char *buffer,
+ size_t count, loff_t *ppos)
+ {
+ struct hostaudio_state *state = file->private_data;
++ void *kbuf;
++ int err;
+
+ #ifdef DEBUG
+ printk("hostaudio: write called, count = %d\n", count);
+ #endif
+- return(hostaudio_write_user(state, buffer, count, ppos));
++
++ kbuf = kmalloc(count, GFP_KERNEL);
++ if(kbuf == NULL)
++ return(-ENOMEM);
++
++ err = -EFAULT;
++ if(copy_from_user(kbuf, buffer, count))
++ goto out;
++
++ err = hostaudio_write_user(state, kbuf, count, ppos);
++ if(err < 0)
++ goto out;
++
++ out:
++ kfree(kbuf);
++ return(err);
+ }
+
+ static unsigned int hostaudio_poll(struct file *file,
+@@ -86,12 +119,43 @@ static int hostaudio_ioctl(struct inode
+ unsigned int cmd, unsigned long arg)
+ {
+ struct hostaudio_state *state = file->private_data;
++ unsigned long data = 0;
++ int err;
+
+ #ifdef DEBUG
+ printk("hostaudio: ioctl called, cmd = %u\n", cmd);
+ #endif
++ switch(cmd){
++ case SNDCTL_DSP_SPEED:
++ case SNDCTL_DSP_STEREO:
++ case SNDCTL_DSP_GETBLKSIZE:
++ case SNDCTL_DSP_CHANNELS:
++ case SNDCTL_DSP_SUBDIVIDE:
++ case SNDCTL_DSP_SETFRAGMENT:
++ if(get_user(data, (int *) arg))
++ return(-EFAULT);
++ break;
++ default:
++ break;
++ }
++
++ err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
++
++ switch(cmd){
++ case SNDCTL_DSP_SPEED:
++ case SNDCTL_DSP_STEREO:
++ case SNDCTL_DSP_GETBLKSIZE:
++ case SNDCTL_DSP_CHANNELS:
++ case SNDCTL_DSP_SUBDIVIDE:
++ case SNDCTL_DSP_SETFRAGMENT:
++ if(put_user(data, (int *) arg))
++ return(-EFAULT);
++ break;
++ default:
++ break;
++ }
+
+- return(hostaudio_ioctl_user(state, cmd, arg));
++ return(err);
+ }
+
+ static int hostaudio_open(struct inode *inode, struct file *file)
+@@ -225,7 +289,8 @@ MODULE_LICENSE("GPL");
+
+ static int __init hostaudio_init_module(void)
+ {
+- printk(KERN_INFO "UML Audio Relay\n");
++ printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
++ dsp, mixer);
+
+ module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
+ if(module_data.dev_audio < 0){
+--- linux-2.6.0-test6/arch/um/drivers/line.c 2003-06-14 12:18:33.000000000 -0700
++++ 25/arch/um/drivers/line.c 2003-10-05 00:34:32.000000000 -0700
+@@ -6,8 +6,8 @@
+ #include "linux/sched.h"
+ #include "linux/slab.h"
+ #include "linux/list.h"
++#include "linux/interrupt.h"
+ #include "linux/devfs_fs_kernel.h"
+-#include "asm/irq.h"
+ #include "asm/uaccess.h"
+ #include "chan_kern.h"
+ #include "irq_user.h"
+@@ -16,16 +16,18 @@
+ #include "user_util.h"
+ #include "kern_util.h"
+ #include "os.h"
++#include "irq_kern.h"
+
+ #define LINE_BUFSIZE 4096
+
+-void line_interrupt(int irq, void *data, struct pt_regs *unused)
++irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
+ {
+ struct line *dev = data;
+
+ if(dev->count > 0)
+ chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq,
+ dev);
++ return IRQ_HANDLED;
+ }
+
+ void line_timer_cb(void *arg)
+@@ -136,20 +138,22 @@ int line_write(struct line *lines, struc
+ return(len);
+ }
+
+-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
++irqreturn_t line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+ {
+ struct line *dev = data;
+ struct tty_struct *tty = dev->tty;
+ int err;
+
+ err = flush_buffer(dev);
+- if(err == 0) return;
++ if(err == 0)
++ return(IRQ_NONE);
+ else if(err < 0){
+ dev->head = dev->buffer;
+ dev->tail = dev->buffer;
+ }
+
+- if(tty == NULL) return;
++ if(tty == NULL)
++ return(IRQ_NONE);
+
+ if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
+ (tty->ldisc.write_wakeup != NULL))
+@@ -161,9 +165,9 @@ void line_write_interrupt(int irq, void
+ * writes.
+ */
+
+- if (waitqueue_active(&tty->write_wait))
++ if(waitqueue_active(&tty->write_wait))
+ wake_up_interruptible(&tty->write_wait);
+-
++ return(IRQ_HANDLED);
+ }
+
+ int line_write_room(struct tty_struct *tty)
+@@ -369,7 +373,7 @@ int line_get_config(char *name, struct l
+
+ dev = simple_strtoul(name, &end, 0);
+ if((*end != '\0') || (end == name)){
+- *error_out = "line_setup failed to parse device number";
++ *error_out = "line_get_config failed to parse device number";
+ return(0);
+ }
+
+@@ -379,15 +383,15 @@ int line_get_config(char *name, struct l
+ }
+
+ line = &lines[dev];
++
+ down(&line->sem);
+-
+ if(!line->valid)
+ CONFIG_CHUNK(str, size, n, "none", 1);
+ else if(line->count == 0)
+ CONFIG_CHUNK(str, size, n, line->init_str, 1);
+ else n = chan_config_string(&line->chan_list, str, size, error_out);
+-
+ up(&line->sem);
++
+ return(n);
+ }
+
+@@ -412,7 +416,8 @@ struct tty_driver *line_register_devfs(s
+ return NULL;
+
+ driver->driver_name = line_driver->name;
+- driver->name = line_driver->devfs_name;
++ driver->name = line_driver->device_name;
++ driver->devfs_name = line_driver->devfs_name;
+ driver->major = line_driver->major;
+ driver->minor_start = line_driver->minor_start;
+ driver->type = line_driver->type;
+@@ -432,7 +437,7 @@ struct tty_driver *line_register_devfs(s
+
+ for(i = 0; i < nlines; i++){
+ if(!lines[i].valid)
+- tty_unregister_devfs(driver, i);
++ tty_unregister_device(driver, i);
+ }
+
+ mconsole_register_dev(&line_driver->mc);
+@@ -465,24 +470,25 @@ struct winch {
+ struct line *line;
+ };
+
+-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
++irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
+ {
+ struct winch *winch = data;
+ struct tty_struct *tty;
+ int err;
+ char c;
+
+- err = generic_read(winch->fd, &c, NULL);
+- if(err < 0){
+- if(err != -EAGAIN){
+- printk("winch_interrupt : read failed, errno = %d\n",
+- -err);
+- printk("fd %d is losing SIGWINCH support\n",
+- winch->tty_fd);
+- free_irq(irq, data);
+- return;
++ if(winch->fd != -1){
++ err = generic_read(winch->fd, &c, NULL);
++ if(err < 0){
++ if(err != -EAGAIN){
++ printk("winch_interrupt : read failed, "
++ "errno = %d\n", -err);
++ printk("fd %d is losing SIGWINCH support\n",
++ winch->tty_fd);
++ return(IRQ_HANDLED);
++ }
++ goto out;
+ }
+- goto out;
+ }
+ tty = winch->line->tty;
+ if(tty != NULL){
+@@ -492,7 +498,9 @@ void winch_interrupt(int irq, void *data
+ kill_pg(tty->pgrp, SIGWINCH, 1);
+ }
+ out:
+- reactivate_fd(winch->fd, WINCH_IRQ);
++ if(winch->fd != -1)
++ reactivate_fd(winch->fd, WINCH_IRQ);
++ return(IRQ_HANDLED);
+ }
+
+ DECLARE_MUTEX(winch_handler_sem);
+@@ -529,7 +537,10 @@ static void winch_cleanup(void)
+
+ list_for_each(ele, &winch_handlers){
+ winch = list_entry(ele, struct winch, list);
+- close(winch->fd);
++ if(winch->fd != -1){
++ deactivate_fd(winch->fd, WINCH_IRQ);
++ close(winch->fd);
++ }
+ if(winch->pid != -1)
+ os_kill_process(winch->pid, 1);
+ }
+--- linux-2.6.0-test6/arch/um/drivers/Makefile 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/um/drivers/Makefile 2003-10-05 00:34:32.000000000 -0700
+@@ -1,5 +1,5 @@
+ #
+-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
++# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
+ # Licensed under the GPL
+ #
+
+@@ -39,6 +39,8 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
+ obj-$(CONFIG_TTY_CHAN) += tty.o
+ obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
+ obj-$(CONFIG_UML_WATCHDOG) += harddog.o
++obj-$(CONFIG_BLK_DEV_COW) += cow_kern.o
++obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
+
+ obj-y += stdio_console.o $(CHAN_OBJS)
+
+@@ -46,7 +48,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubs
+
+ USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
+ null.o pty.o tty.o xterm.o
+-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
++USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+ $(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+--- linux-2.6.0-test6/arch/um/drivers/mconsole_kern.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/um/drivers/mconsole_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -27,6 +27,7 @@
+ #include "init.h"
+ #include "os.h"
+ #include "umid.h"
++#include "irq_kern.h"
+
+ static int do_unlink_socket(struct notifier_block *notifier,
+ unsigned long what, void *data)
+@@ -67,7 +68,7 @@ void mc_work_proc(void *unused)
+
+ DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
+
+-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ int fd;
+ struct mconsole_entry *new;
+@@ -88,6 +89,7 @@ void mconsole_interrupt(int irq, void *d
+ }
+ if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
+ reactivate_fd(fd, MCONSOLE_IRQ);
++ return(IRQ_HANDLED);
+ }
+
+ void mconsole_version(struct mc_request *req)
+@@ -100,20 +102,34 @@ void mconsole_version(struct mc_request
+ mconsole_reply(req, version, 0, 0);
+ }
+
++void mconsole_log(struct mc_request *req)
++{
++ int len;
++ char *ptr = req->request.data;
++
++ ptr += strlen("log");
++ while(isspace(*ptr)) ptr++;
++
++ len = ptr - req->request.data;
++ printk("%.*s", len, ptr);
++ mconsole_reply(req, "", 0, 0);
++}
++
+ #define UML_MCONSOLE_HELPTEXT \
+-"Commands:
+- version - Get kernel version
+- help - Print this message
+- halt - Halt UML
+- reboot - Reboot UML
+- config <dev>=<config> - Add a new device to UML;
+- same syntax as command line
+- config <dev> - Query the configuration of a device
+- remove <dev> - Remove a device from UML
+- sysrq <letter> - Performs the SysRq action controlled by the letter
+- cad - invoke the Ctl-Alt-Del handler
+- stop - pause the UML; it will do nothing until it receives a 'go'
+- go - continue the UML after a 'stop'
++"Commands: \n\
++ version - Get kernel version \n\
++ help - Print this message \n\
++ halt - Halt UML \n\
++ reboot - Reboot UML \n\
++ config <dev>=<config> - Add a new device to UML; \n\
++ same syntax as command line \n\
++ config <dev> - Query the configuration of a device \n\
++ remove <dev> - Remove a device from UML \n\
++ sysrq <letter> - Performs the SysRq action controlled by the letter \n\
++ cad - invoke the Ctl-Alt-Del handler \n\
++ stop - pause the UML; it will do nothing until it receives a 'go' \n\
++ go - continue the UML after a 'stop' \n\
++ log <string> - make UML enter <string> into the kernel log\n\
+ "
+
+ void mconsole_help(struct mc_request *req)
+@@ -302,7 +318,7 @@ int mconsole_init(void)
+ if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
+ snprintf(mconsole_socket_name, sizeof(file), "%s", file);
+
+- sock = create_unix_socket(file, sizeof(file));
++ sock = create_unix_socket(file, sizeof(file), 1);
+ if (sock < 0){
+ printk("Failed to initialize management console\n");
+ return(1);
+--- linux-2.6.0-test6/arch/um/drivers/mconsole_user.c 2003-06-14 12:17:59.000000000 -0700
++++ 25/arch/um/drivers/mconsole_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -28,6 +28,7 @@ static struct mconsole_command commands[
+ { "cad", mconsole_cad, 1 },
+ { "stop", mconsole_stop, 0 },
+ { "go", mconsole_go, 1 },
++ { "log", mconsole_log, 1 },
+ };
+
+ /* Initialized in mconsole_init, which is an initcall */
+@@ -139,6 +140,7 @@ int mconsole_reply(struct mc_request *re
+ memcpy(reply.data, str, len);
+ reply.data[len] = '\0';
+ total -= len;
++ str += len;
+ reply.len = len + 1;
+
+ len = sizeof(reply) + reply.len - sizeof(reply.data);
+--- linux-2.6.0-test6/arch/um/drivers/mmapper_kern.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/um/drivers/mmapper_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -120,7 +120,10 @@ static int __init mmapper_init(void)
+ printk(KERN_INFO "Mapper v0.1\n");
+
+ v_buf = (char *) find_iomem("mmapper", &mmapper_size);
+- if(mmapper_size == 0) return(0);
++ if(mmapper_size == 0){
++ printk(KERN_ERR "mmapper_init - find_iomem failed\n");
++ return(0);
++ }
+
+ p_buf = __pa(v_buf);
+
+--- linux-2.6.0-test6/arch/um/drivers/net_kern.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/drivers/net_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -26,6 +26,7 @@
+ #include "mconsole_kern.h"
+ #include "init.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+
+ static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
+ LIST_HEAD(opened);
+@@ -61,14 +62,14 @@ static int uml_net_rx(struct net_device
+ return pkt_len;
+ }
+
+-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+ struct net_device *dev = dev_id;
+ struct uml_net_private *lp = dev->priv;
+ int err;
+
+ if(!netif_running(dev))
+- return;
++ return(IRQ_NONE);
+
+ spin_lock(&lp->lock);
+ while((err = uml_net_rx(dev)) > 0) ;
+@@ -83,6 +84,7 @@ void uml_net_interrupt(int irq, void *de
+
+ out:
+ spin_unlock(&lp->lock);
++ return(IRQ_HANDLED);
+ }
+
+ static int uml_net_open(struct net_device *dev)
+@@ -252,37 +254,6 @@ void uml_net_user_timer_expire(unsigned
+ #endif
+ }
+
+-/*
+- * default do nothing hard header packet routines for struct net_device init.
+- * real ethernet transports will overwrite with real routines.
+- */
+-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
+- unsigned short type, void *daddr, void *saddr, unsigned len)
+-{
+- return(0); /* no change */
+-}
+-
+-static int uml_net_rebuild_header(struct sk_buff *skb)
+-{
+- return(0); /* ignore */
+-}
+-
+-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+-{
+- return(-1); /* fail */
+-}
+-
+-static void uml_net_header_cache_update(struct hh_cache *hh,
+- struct net_device *dev, unsigned char * haddr)
+-{
+- /* ignore */
+-}
+-
+-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
+-{
+- return(0); /* nothing */
+-}
+-
+ static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
+ static struct list_head devices = LIST_HEAD_INIT(devices);
+
+@@ -292,7 +263,7 @@ static int eth_configure(int n, void *in
+ struct uml_net *device;
+ struct net_device *dev;
+ struct uml_net_private *lp;
+- int err, size;
++ int save, err, size;
+
+ size = transport->private_size + sizeof(struct uml_net_private) +
+ sizeof(((struct uml_net_private *) 0)->user);
+@@ -334,12 +305,6 @@ static int eth_configure(int n, void *in
+ snprintf(dev->name, sizeof(dev->name), "eth%d", n);
+ device->dev = dev;
+
+- dev->hard_header = uml_net_hard_header;
+- dev->rebuild_header = uml_net_rebuild_header;
+- dev->hard_header_cache = uml_net_header_cache;
+- dev->header_cache_update= uml_net_header_cache_update;
+- dev->hard_header_parse = uml_net_header_parse;
+-
+ (*transport->kern->init)(dev, init);
+
+ dev->mtu = transport->user->max_packet;
+@@ -362,21 +327,29 @@ static int eth_configure(int n, void *in
+ return 1;
+ lp = dev->priv;
+
+- INIT_LIST_HEAD(&lp->list);
+- spin_lock_init(&lp->lock);
+- lp->dev = dev;
+- lp->fd = -1;
+- lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
+- lp->have_mac = device->have_mac;
+- lp->protocol = transport->kern->protocol;
+- lp->open = transport->user->open;
+- lp->close = transport->user->close;
+- lp->remove = transport->user->remove;
+- lp->read = transport->kern->read;
+- lp->write = transport->kern->write;
+- lp->add_address = transport->user->add_address;
+- lp->delete_address = transport->user->delete_address;
+- lp->set_mtu = transport->user->set_mtu;
++ /* lp.user is the first four bytes of the transport data, which
++ * has already been initialized. This structure assignment will
++ * overwrite that, so we make sure that .user gets overwritten with
++ * what it already has.
++ */
++ save = lp->user[0];
++ *lp = ((struct uml_net_private)
++ { .list = LIST_HEAD_INIT(lp->list),
++ .lock = SPIN_LOCK_UNLOCKED,
++ .dev = dev,
++ .fd = -1,
++ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
++ .have_mac = device->have_mac,
++ .protocol = transport->kern->protocol,
++ .open = transport->user->open,
++ .close = transport->user->close,
++ .remove = transport->user->remove,
++ .read = transport->kern->read,
++ .write = transport->kern->write,
++ .add_address = transport->user->add_address,
++ .delete_address = transport->user->delete_address,
++ .set_mtu = transport->user->set_mtu,
++ .user = { save } });
+
+ init_timer(&lp->tl);
+ lp->tl.function = uml_net_user_timer_expire;
+@@ -609,7 +582,8 @@ static int net_remove(char *str)
+ unregister_netdev(dev);
+
+ list_del(&device->list);
+- free_netdev(device);
++ kfree(device);
++ free_netdev(dev);
+ return(0);
+ }
+
+--- linux-2.6.0-test6/arch/um/drivers/port_kern.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/um/drivers/port_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -6,6 +6,7 @@
+ #include "linux/list.h"
+ #include "linux/sched.h"
+ #include "linux/slab.h"
++#include "linux/interrupt.h"
+ #include "linux/irq.h"
+ #include "linux/spinlock.h"
+ #include "linux/errno.h"
+@@ -14,6 +15,7 @@
+ #include "kern_util.h"
+ #include "kern.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+ #include "port.h"
+ #include "init.h"
+ #include "os.h"
+@@ -44,7 +46,7 @@ struct connection {
+ struct port_list *port;
+ };
+
+-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
++static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+ {
+ struct connection *conn = data;
+ int fd;
+@@ -52,7 +54,7 @@ static void pipe_interrupt(int irq, void
+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+ if(fd < 0){
+ if(fd == -EAGAIN)
+- return;
++ return(IRQ_NONE);
+
+ printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
+ -fd);
+@@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void
+ list_add(&conn->list, &conn->port->connections);
+
+ up(&conn->port->sem);
++ return(IRQ_HANDLED);
+ }
+
+ static int port_accept(struct port_list *port)
+@@ -138,12 +141,13 @@ void port_work_proc(void *unused)
+
+ DECLARE_WORK(port_work, port_work_proc, NULL);
+
+-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
++static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
+ {
+ struct port_list *port = data;
+
+ port->has_connection = 1;
+ schedule_work(&port_work);
++ return(IRQ_HANDLED);
+ }
+
+ void *port_data(int port_num)
+--- linux-2.6.0-test6/arch/um/drivers/ssl.c 2003-06-14 12:18:21.000000000 -0700
++++ 25/arch/um/drivers/ssl.c 2003-10-05 00:34:32.000000000 -0700
+@@ -53,8 +53,9 @@ static int ssl_remove(char *str);
+
+ static struct line_driver driver = {
+ .name = "UML serial line",
+- .devfs_name = "tts/%d",
+- .major = TTYAUX_MAJOR,
++ .device_name = "ttS",
++ .devfs_name = "tts/",
++ .major = TTY_MAJOR,
+ .minor_start = 64,
+ .type = TTY_DRIVER_TYPE_SERIAL,
+ .subtype = 0,
+--- linux-2.6.0-test6/arch/um/drivers/stdio_console.c 2003-06-14 12:18:04.000000000 -0700
++++ 25/arch/um/drivers/stdio_console.c 2003-10-05 00:34:32.000000000 -0700
+@@ -83,7 +83,8 @@ static int con_remove(char *str);
+
+ static struct line_driver driver = {
+ .name = "UML console",
+- .devfs_name = "vc/%d",
++ .device_name = "tty",
++ .devfs_name = "vc/",
+ .major = TTY_MAJOR,
+ .minor_start = 0,
+ .type = TTY_DRIVER_TYPE_CONSOLE,
+@@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_st
+
+ static int con_init_done = 0;
+
++static struct tty_operations console_ops = {
++ .open = con_open,
++ .close = con_close,
++ .write = con_write,
++ .chars_in_buffer = chars_in_buffer,
++ .set_termios = set_termios,
++ .write_room = line_write_room,
++};
++
+ int stdio_init(void)
+ {
+ char *new_title;
+@@ -166,7 +176,8 @@ int stdio_init(void)
+ printk(KERN_INFO "Initializing stdio console driver\n");
+
+ console_driver = line_register_devfs(&console_lines, &driver,
+- &console_ops, vts, sizeof(vts)/sizeof(vts[0]));
++ &console_ops, vts,
++ sizeof(vts)/sizeof(vts[0]));
+
+ lines_init(vts, sizeof(vts)/sizeof(vts[0]));
+
+@@ -188,15 +199,6 @@ static void console_write(struct console
+ if(con_init_done) up(&vts[console->index].sem);
+ }
+
+-static struct tty_operations console_ops = {
+- .open = con_open,
+- .close = con_close,
+- .write = con_write,
+- .chars_in_buffer = chars_in_buffer,
+- .set_termios = set_termios,
+- .write_room = line_write_room,
+-};
+-
+ static struct tty_driver *console_device(struct console *c, int *index)
+ {
+ *index = c->index;
+@@ -212,12 +214,14 @@ static struct console stdiocons = INIT_C
+ console_device, console_setup,
+ CON_PRINTBUFFER);
+
+-static void __init stdio_console_init(void)
++static int __init stdio_console_init(void)
+ {
+ INIT_LIST_HEAD(&vts[0].chan_list);
+ list_add(&init_console_chan.list, &vts[0].chan_list);
+ register_console(&stdiocons);
++ return(0);
+ }
++
+ console_initcall(stdio_console_init);
+
+ static int console_chan_setup(char *str)
+--- linux-2.6.0-test6/arch/um/drivers/ubd_kern.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/arch/um/drivers/ubd_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -8,6 +8,13 @@
+ * old style ubd by setting UBD_SHIFT to 0
+ * 2002-09-27...2002-10-18 massive tinkering for 2.5
+ * partitions have changed in 2.5
++ * 2003-01-29 more tinkering for 2.5.59-1
++ * This should now address the sysfs problems and has
++ * the symlink for devfs to allow for booting with
++ * the common /dev/ubd/discX/... names rather than
++ * only /dev/ubdN/discN this version also has lots of
++ * clean ups preparing for ubd-many.
++ * James McMechan
+ */
+
+ #define MAJOR_NR UBD_MAJOR
+@@ -40,6 +47,7 @@
+ #include "mconsole_kern.h"
+ #include "init.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+ #include "ubd_user.h"
+ #include "2_5compat.h"
+ #include "os.h"
+@@ -49,9 +57,9 @@ static spinlock_t ubd_lock = SPIN_LOCK_U
+
+ static void (*do_ubd)(void);
+
+-static int ubd_open(struct inode * inode, struct file * filp);
+-static int ubd_release(struct inode * inode, struct file * file);
+-static int ubd_ioctl(struct inode * inode, struct file * file,
++static int ubd_open(struct block_device *bdev, struct file * filp);
++static int ubd_release(struct gendisk *disk);
++static int ubd_ioctl(struct block_device *bdev, struct file * file,
+ unsigned int cmd, unsigned long arg);
+
+ #define MAX_DEV (8)
+@@ -67,7 +75,7 @@ static struct block_device_operations ub
+ static request_queue_t *ubd_queue;
+
+ /* Protected by ubd_lock */
+-static int fake_major = 0;
++static int fake_major = MAJOR_NR;
+
+ static struct gendisk *ubd_gendisk[MAX_DEV];
+ static struct gendisk *fake_gendisk[MAX_DEV];
+@@ -96,12 +104,12 @@ struct cow {
+
+ struct ubd {
+ char *file;
+- int is_dir;
+ int count;
+ int fd;
+ __u64 size;
+ struct openflags boot_openflags;
+ struct openflags openflags;
++ int no_cow;
+ struct cow cow;
+ };
+
+@@ -115,12 +123,12 @@ struct ubd {
+
+ #define DEFAULT_UBD { \
+ .file = NULL, \
+- .is_dir = 0, \
+ .count = 0, \
+ .fd = -1, \
+ .size = -1, \
+ .boot_openflags = OPEN_FLAGS, \
+ .openflags = OPEN_FLAGS, \
++ .no_cow = 0, \
+ .cow = DEFAULT_COW, \
+ }
+
+@@ -128,8 +136,10 @@ struct ubd ubd_dev[MAX_DEV] = { [ 0 ...
+
+ static int ubd0_init(void)
+ {
+- if(ubd_dev[0].file == NULL)
+- ubd_dev[0].file = "root_fs";
++ struct ubd *dev = &ubd_dev[0];
++
++ if(dev->file == NULL)
++ dev->file = "root_fs";
+ return(0);
+ }
+
+@@ -196,19 +206,39 @@ __uml_help(fake_ide_setup,
+ " Create ide0 entries that map onto ubd devices.\n\n"
+ );
+
++static int parse_unit(char **ptr)
++{
++ char *str = *ptr, *end;
++ int n = -1;
++
++ if(isdigit(*str)) {
++ n = simple_strtoul(str, &end, 0);
++ if(end == str)
++ return(-1);
++ *ptr = end;
++ }
++ else if (('a' <= *str) && (*str <= 'h')) {
++ n = *str - 'a';
++ str++;
++ *ptr = str;
++ }
++ return(n);
++}
++
+ static int ubd_setup_common(char *str, int *index_out)
+ {
++ struct ubd *dev;
+ struct openflags flags = global_openflags;
+ char *backing_file;
+ int n, err;
+
+ if(index_out) *index_out = -1;
+- n = *str++;
++ n = *str;
+ if(n == '='){
+- static int fake_major_allowed = 1;
+ char *end;
+ int major;
+
++ str++;
+ if(!strcmp(str, "sync")){
+ global_openflags.s = 1;
+ return(0);
+@@ -220,20 +250,14 @@ static int ubd_setup_common(char *str, i
+ return(1);
+ }
+
+- if(!fake_major_allowed){
+- printk(KERN_ERR "Can't assign a fake major twice\n");
+- return(1);
+- }
+-
+ err = 1;
+ spin_lock(&ubd_lock);
+- if(!fake_major_allowed){
++ if(fake_major != MAJOR_NR){
+ printk(KERN_ERR "Can't assign a fake major twice\n");
+ goto out1;
+ }
+
+ fake_major = major;
+- fake_major_allowed = 0;
+
+ printk(KERN_INFO "Setting extra ubd major number to %d\n",
+ major);
+@@ -243,25 +267,23 @@ static int ubd_setup_common(char *str, i
+ return(err);
+ }
+
+- if(n < '0'){
+- printk(KERN_ERR "ubd_setup : index out of range\n"); }
+-
+- if((n >= '0') && (n <= '9')) n -= '0';
+- else if((n >= 'a') && (n <= 'z')) n -= 'a';
+- else {
+- printk(KERN_ERR "ubd_setup : device syntax invalid\n");
++ n = parse_unit(&str);
++ if(n < 0){
++ printk(KERN_ERR "ubd_setup : couldn't parse unit number "
++ "'%s'\n", str);
+ return(1);
+ }
+ if(n >= MAX_DEV){
+- printk(KERN_ERR "ubd_setup : index out of range "
+- "(%d devices)\n", MAX_DEV);
++ printk(KERN_ERR "ubd_setup : index %d out of range "
++ "(%d devices)\n", n, MAX_DEV);
+ return(1);
+ }
+
+ err = 1;
+ spin_lock(&ubd_lock);
+
+- if(ubd_dev[n].file != NULL){
++ dev = &ubd_dev[n];
++ if(dev->file != NULL){
+ printk(KERN_ERR "ubd_setup : device already configured\n");
+ goto out2;
+ }
+@@ -276,6 +298,11 @@ static int ubd_setup_common(char *str, i
+ flags.s = 1;
+ str++;
+ }
++ if (*str == 'd'){
++ dev->no_cow = 1;
++ str++;
++ }
++
+ if(*str++ != '='){
+ printk(KERN_ERR "ubd_setup : Expected '='\n");
+ goto out2;
+@@ -284,14 +311,17 @@ static int ubd_setup_common(char *str, i
+ err = 0;
+ backing_file = strchr(str, ',');
+ if(backing_file){
+- *backing_file = '\0';
+- backing_file++;
++ if(dev->no_cow)
++ printk(KERN_ERR "Can't specify both 'd' and a "
++ "cow file\n");
++ else {
++ *backing_file = '\0';
++ backing_file++;
++ }
+ }
+- ubd_dev[n].file = str;
+- if(ubd_is_dir(ubd_dev[n].file))
+- ubd_dev[n].is_dir = 1;
+- ubd_dev[n].cow.file = backing_file;
+- ubd_dev[n].boot_openflags = flags;
++ dev->file = str;
++ dev->cow.file = backing_file;
++ dev->boot_openflags = flags;
+ out2:
+ spin_unlock(&ubd_lock);
+ return(err);
+@@ -321,8 +351,7 @@ __uml_help(ubd_setup,
+ static int fakehd_set = 0;
+ static int fakehd(char *str)
+ {
+- printk(KERN_INFO
+- "fakehd : Changing ubd name to \"hd\".\n");
++ printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
+ fakehd_set = 1;
+ return 1;
+ }
+@@ -391,9 +420,10 @@ static void ubd_handler(void)
+ do_ubd_request(ubd_queue);
+ }
+
+-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
++static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
+ {
+ ubd_handler();
++ return(IRQ_HANDLED);
+ }
+
+ /* Only changed by ubd_init, which is an initcall. */
+@@ -429,16 +459,18 @@ static void ubd_close(struct ubd *dev)
+ static int ubd_open_dev(struct ubd *dev)
+ {
+ struct openflags flags;
+- int err, n, create_cow, *create_ptr;
++ char **back_ptr;
++ int err, create_cow, *create_ptr;
+
++ dev->openflags = dev->boot_openflags;
+ create_cow = 0;
+ create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
+- dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
++ back_ptr = dev->no_cow ? NULL : &dev->cow.file;
++ dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
+ &dev->cow.bitmap_offset, &dev->cow.bitmap_len,
+ &dev->cow.data_offset, create_ptr);
+
+ if((dev->fd == -ENOENT) && create_cow){
+- n = dev - ubd_dev;
+ dev->fd = create_cow_file(dev->file, dev->cow.file,
+ dev->openflags, 1 << 9,
+ &dev->cow.bitmap_offset,
+@@ -455,7 +487,10 @@ static int ubd_open_dev(struct ubd *dev)
+ if(dev->cow.file != NULL){
+ err = -ENOMEM;
+ dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
+- if(dev->cow.bitmap == NULL) goto error;
++ if(dev->cow.bitmap == NULL){
++ printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
++ goto error;
++ }
+ flush_tlb_kernel_vm();
+
+ err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
+@@ -481,17 +516,31 @@ static int ubd_new_disk(int major, u64 s
+
+ {
+ struct gendisk *disk;
++ char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
++ int err;
+
+ disk = alloc_disk(1 << UBD_SHIFT);
+- if (!disk)
+- return -ENOMEM;
++ if(disk == NULL)
++ return(-ENOMEM);
+
+ disk->major = major;
+ disk->first_minor = unit << UBD_SHIFT;
+ disk->fops = &ubd_blops;
+ set_capacity(disk, size / 512);
+- sprintf(disk->disk_name, "ubd");
+- sprintf(disk->devfs_name, "ubd/disc%d", unit);
++ if(major == MAJOR_NR){
++ sprintf(disk->disk_name, "ubd%d", unit);
++ sprintf(disk->devfs_name, "ubd/disc%d", unit);
++ sprintf(from, "ubd/%d", unit);
++ sprintf(to, "disc%d/disc", unit);
++ err = devfs_mk_symlink(from, to);
++ if(err)
++ printk("ubd_new_disk failed to make link from %s to "
++ "%s, error = %d\n", from, to, err);
++ }
++ else {
++ sprintf(disk->disk_name, "ubd_fake%d", unit);
++ sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
++ }
+
+ disk->private_data = &ubd_dev[unit];
+ disk->queue = ubd_queue;
+@@ -506,10 +555,7 @@ static int ubd_add(int n)
+ struct ubd *dev = &ubd_dev[n];
+ int err;
+
+- if(dev->is_dir)
+- return(-EISDIR);
+-
+- if (!dev->file)
++ if(dev->file == NULL)
+ return(-ENODEV);
+
+ if (ubd_open_dev(dev))
+@@ -523,7 +569,7 @@ static int ubd_add(int n)
+ if(err)
+ return(err);
+
+- if(fake_major)
++ if(fake_major != MAJOR_NR)
+ ubd_new_disk(fake_major, dev->size, n,
+ &fake_gendisk[n]);
+
+@@ -561,42 +607,42 @@ static int ubd_config(char *str)
+ return(err);
+ }
+
+-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
++static int ubd_get_config(char *name, char *str, int size, char **error_out)
+ {
+- struct ubd *ubd;
++ struct ubd *dev;
+ char *end;
+- int major, n = 0;
++ int n, len = 0;
+
+- major = simple_strtoul(dev, &end, 0);
+- if((*end != '\0') || (end == dev)){
+- *error_out = "ubd_get_config : didn't parse major number";
++ n = simple_strtoul(name, &end, 0);
++ if((*end != '\0') || (end == name)){
++ *error_out = "ubd_get_config : didn't parse device number";
+ return(-1);
+ }
+
+- if((major >= MAX_DEV) || (major < 0)){
+- *error_out = "ubd_get_config : major number out of range";
++ if((n >= MAX_DEV) || (n < 0)){
++ *error_out = "ubd_get_config : device number out of range";
+ return(-1);
+ }
+
+- ubd = &ubd_dev[major];
++ dev = &ubd_dev[n];
+ spin_lock(&ubd_lock);
+
+- if(ubd->file == NULL){
+- CONFIG_CHUNK(str, size, n, "", 1);
++ if(dev->file == NULL){
++ CONFIG_CHUNK(str, size, len, "", 1);
+ goto out;
+ }
+
+- CONFIG_CHUNK(str, size, n, ubd->file, 0);
++ CONFIG_CHUNK(str, size, len, dev->file, 0);
+
+- if(ubd->cow.file != NULL){
+- CONFIG_CHUNK(str, size, n, ",", 0);
+- CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
++ if(dev->cow.file != NULL){
++ CONFIG_CHUNK(str, size, len, ",", 0);
++ CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
+ }
+- else CONFIG_CHUNK(str, size, n, "", 1);
++ else CONFIG_CHUNK(str, size, len, "", 1);
+
+ out:
+ spin_unlock(&ubd_lock);
+- return(n);
++ return(len);
+ }
+
+ static int ubd_remove(char *str)
+@@ -604,11 +650,9 @@ static int ubd_remove(char *str)
+ struct ubd *dev;
+ int n, err = -ENODEV;
+
+- if(!isdigit(*str))
+- return(err); /* it should be a number 0-7/a-h */
++ n = parse_unit(&str);
+
+- n = *str - '0';
+- if(n >= MAX_DEV)
++ if((n < 0) || (n >= MAX_DEV))
+ return(err);
+
+ dev = &ubd_dev[n];
+@@ -669,7 +713,7 @@ int ubd_init(void)
+
+ elevator_init(ubd_queue, &elevator_noop);
+
+- if (fake_major != 0) {
++ if (fake_major != MAJOR_NR) {
+ char name[sizeof("ubd_nnn\0")];
+
+ snprintf(name, sizeof(name), "ubd_%d", fake_major);
+@@ -710,19 +754,13 @@ int ubd_driver_init(void){
+
+ device_initcall(ubd_driver_init);
+
+-static int ubd_open(struct inode *inode, struct file *filp)
++static int ubd_open(struct block_device *bdev, struct file *filp)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct ubd *dev = disk->private_data;
+- int err = -EISDIR;
+-
+- if(dev->is_dir == 1)
+- goto out;
++ int err = 0;
+
+- err = 0;
+ if(dev->count == 0){
+- dev->openflags = dev->boot_openflags;
+-
+ err = ubd_open_dev(dev);
+ if(err){
+ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
+@@ -739,9 +777,8 @@ static int ubd_open(struct inode *inode,
+ return(err);
+ }
+
+-static int ubd_release(struct inode * inode, struct file * file)
++static int ubd_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ubd *dev = disk->private_data;
+
+ if(--dev->count == 0)
+@@ -796,15 +833,6 @@ static int prepare_request(struct reques
+
+ if(req->rq_status == RQ_INACTIVE) return(1);
+
+- if(dev->is_dir){
+- strcpy(req->buffer, "HOSTFS:");
+- strcat(req->buffer, dev->file);
+- spin_lock(&ubd_io_lock);
+- end_request(req, 1);
+- spin_unlock(&ubd_io_lock);
+- return(1);
+- }
+-
+ if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
+ printk("Write attempted on readonly ubd device %s\n",
+ disk->disk_name);
+@@ -865,11 +893,11 @@ static void do_ubd_request(request_queue
+ }
+ }
+
+-static int ubd_ioctl(struct inode * inode, struct file * file,
++static int ubd_ioctl(struct block_device *bdev, struct file * file,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct hd_geometry *loc = (struct hd_geometry *) arg;
+- struct ubd *dev = inode->i_bdev->bd_disk->private_data;
++ struct ubd *dev = bdev->bd_disk->private_data;
+ int err;
+ struct hd_driveid ubd_id = {
+ .cyls = 0,
+@@ -890,7 +918,7 @@ static int ubd_ioctl(struct inode * inod
+
+ case HDIO_SET_UNMASKINTR:
+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
+- if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev))
++ if((arg > 1) || (bdev->bd_contains != bdev))
+ return(-EINVAL);
+ return(0);
+
+@@ -910,7 +938,7 @@ static int ubd_ioctl(struct inode * inod
+
+ case HDIO_SET_MULTCOUNT:
+ if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
+- if(inode->i_bdev->bd_contains != inode->i_bdev)
++ if(bdev->bd_contains != bdev)
+ return(-EINVAL);
+ return(0);
+
+--- linux-2.6.0-test6/arch/um/drivers/ubd_user.c 2003-06-14 12:18:04.000000000 -0700
++++ 25/arch/um/drivers/ubd_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -24,142 +24,24 @@
+ #include "user.h"
+ #include "ubd_user.h"
+ #include "os.h"
++#include "cow.h"
+
+ #include <endian.h>
+ #include <byteswap.h>
+-#if __BYTE_ORDER == __BIG_ENDIAN
+-# define ntohll(x) (x)
+-# define htonll(x) (x)
+-#elif __BYTE_ORDER == __LITTLE_ENDIAN
+-# define ntohll(x) bswap_64(x)
+-# define htonll(x) bswap_64(x)
+-#else
+-#error "__BYTE_ORDER not defined"
+-#endif
+-
+-#define PATH_LEN_V1 256
+-
+-struct cow_header_v1 {
+- int magic;
+- int version;
+- char backing_file[PATH_LEN_V1];
+- time_t mtime;
+- __u64 size;
+- int sectorsize;
+-};
+-
+-#define PATH_LEN_V2 MAXPATHLEN
+-
+-struct cow_header_v2 {
+- unsigned long magic;
+- unsigned long version;
+- char backing_file[PATH_LEN_V2];
+- time_t mtime;
+- __u64 size;
+- int sectorsize;
+-};
+-
+-union cow_header {
+- struct cow_header_v1 v1;
+- struct cow_header_v2 v2;
+-};
+-
+-#define COW_MAGIC 0x4f4f4f4d /* MOOO */
+-#define COW_VERSION 2
+-
+-static void sizes(__u64 size, int sectorsize, int bitmap_offset,
+- unsigned long *bitmap_len_out, int *data_offset_out)
+-{
+- *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
+-
+- *data_offset_out = bitmap_offset + *bitmap_len_out;
+- *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
+- *data_offset_out *= sectorsize;
+-}
+-
+-static int read_cow_header(int fd, int *magic_out, char **backing_file_out,
+- time_t *mtime_out, __u64 *size_out,
+- int *sectorsize_out, int *bitmap_offset_out)
+-{
+- union cow_header *header;
+- char *file;
+- int err, n;
+- unsigned long version, magic;
+-
+- header = um_kmalloc(sizeof(*header));
+- if(header == NULL){
+- printk("read_cow_header - Failed to allocate header\n");
+- return(-ENOMEM);
+- }
+- err = -EINVAL;
+- n = read(fd, header, sizeof(*header));
+- if(n < offsetof(typeof(header->v1), backing_file)){
+- printk("read_cow_header - short header\n");
+- goto out;
+- }
+-
+- magic = header->v1.magic;
+- if(magic == COW_MAGIC) {
+- version = header->v1.version;
+- }
+- else if(magic == ntohl(COW_MAGIC)){
+- version = ntohl(header->v1.version);
+- }
+- else goto out;
+-
+- *magic_out = COW_MAGIC;
+-
+- if(version == 1){
+- if(n < sizeof(header->v1)){
+- printk("read_cow_header - failed to read V1 header\n");
+- goto out;
+- }
+- *mtime_out = header->v1.mtime;
+- *size_out = header->v1.size;
+- *sectorsize_out = header->v1.sectorsize;
+- *bitmap_offset_out = sizeof(header->v1);
+- file = header->v1.backing_file;
+- }
+- else if(version == 2){
+- if(n < sizeof(header->v2)){
+- printk("read_cow_header - failed to read V2 header\n");
+- goto out;
+- }
+- *mtime_out = ntohl(header->v2.mtime);
+- *size_out = ntohll(header->v2.size);
+- *sectorsize_out = ntohl(header->v2.sectorsize);
+- *bitmap_offset_out = sizeof(header->v2);
+- file = header->v2.backing_file;
+- }
+- else {
+- printk("read_cow_header - invalid COW version\n");
+- goto out;
+- }
+- err = -ENOMEM;
+- *backing_file_out = uml_strdup(file);
+- if(*backing_file_out == NULL){
+- printk("read_cow_header - failed to allocate backing file\n");
+- goto out;
+- }
+- err = 0;
+- out:
+- kfree(header);
+- return(err);
+-}
+
+ static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
+ {
+- struct stat buf1, buf2;
++ struct stat64 buf1, buf2;
+
+ if(from_cmdline == NULL) return(1);
+ if(!strcmp(from_cmdline, from_cow)) return(1);
+
+- if(stat(from_cmdline, &buf1) < 0){
++ if(stat64(from_cmdline, &buf1) < 0){
+ printk("Couldn't stat '%s', errno = %d\n", from_cmdline,
+ errno);
+ return(1);
+ }
+- if(stat(from_cow, &buf2) < 0){
++ if(stat64(from_cow, &buf2) < 0){
+ printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
+ return(1);
+ }
+@@ -215,118 +97,6 @@ int read_cow_bitmap(int fd, void *buf, i
+ return(0);
+ }
+
+-static int absolutize(char *to, int size, char *from)
+-{
+- char save_cwd[256], *slash;
+- int remaining;
+-
+- if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+- printk("absolutize : unable to get cwd - errno = %d\n", errno);
+- return(-1);
+- }
+- slash = strrchr(from, '/');
+- if(slash != NULL){
+- *slash = '\0';
+- if(chdir(from)){
+- *slash = '/';
+- printk("absolutize : Can't cd to '%s' - errno = %d\n",
+- from, errno);
+- return(-1);
+- }
+- *slash = '/';
+- if(getcwd(to, size) == NULL){
+- printk("absolutize : unable to get cwd of '%s' - "
+- "errno = %d\n", from, errno);
+- return(-1);
+- }
+- remaining = size - strlen(to);
+- if(strlen(slash) + 1 > remaining){
+- printk("absolutize : unable to fit '%s' into %d "
+- "chars\n", from, size);
+- return(-1);
+- }
+- strcat(to, slash);
+- }
+- else {
+- if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+- printk("absolutize : unable to fit '%s' into %d "
+- "chars\n", from, size);
+- return(-1);
+- }
+- strcpy(to, save_cwd);
+- strcat(to, "/");
+- strcat(to, from);
+- }
+- chdir(save_cwd);
+- return(0);
+-}
+-
+-static int write_cow_header(char *cow_file, int fd, char *backing_file,
+- int sectorsize, long long *size)
+-{
+- struct cow_header_v2 *header;
+- struct stat64 buf;
+- int err;
+-
+- err = os_seek_file(fd, 0);
+- if(err != 0){
+- printk("write_cow_header - lseek failed, errno = %d\n", errno);
+- return(-errno);
+- }
+-
+- err = -ENOMEM;
+- header = um_kmalloc(sizeof(*header));
+- if(header == NULL){
+- printk("Failed to allocate COW V2 header\n");
+- goto out;
+- }
+- header->magic = htonl(COW_MAGIC);
+- header->version = htonl(COW_VERSION);
+-
+- err = -EINVAL;
+- if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+- printk("Backing file name \"%s\" is too long - names are "
+- "limited to %d characters\n", backing_file,
+- sizeof(header->backing_file) - 1);
+- goto out_free;
+- }
+-
+- if(absolutize(header->backing_file, sizeof(header->backing_file),
+- backing_file))
+- goto out_free;
+-
+- err = stat64(header->backing_file, &buf);
+- if(err < 0){
+- printk("Stat of backing file '%s' failed, errno = %d\n",
+- header->backing_file, errno);
+- err = -errno;
+- goto out_free;
+- }
+-
+- err = os_file_size(header->backing_file, size);
+- if(err){
+- printk("Couldn't get size of backing file '%s', errno = %d\n",
+- header->backing_file, -*size);
+- goto out_free;
+- }
+-
+- header->mtime = htonl(buf.st_mtime);
+- header->size = htonll(*size);
+- header->sectorsize = htonl(sectorsize);
+-
+- err = write(fd, header, sizeof(*header));
+- if(err != sizeof(*header)){
+- printk("Write of header to new COW file '%s' failed, "
+- "errno = %d\n", cow_file, errno);
+- goto out_free;
+- }
+- err = 0;
+- out_free:
+- kfree(header);
+- out:
+- return(err);
+-}
+-
+ int open_ubd_file(char *file, struct openflags *openflags,
+ char **backing_file_out, int *bitmap_offset_out,
+ unsigned long *bitmap_len_out, int *data_offset_out,
+@@ -346,10 +116,17 @@ int open_ubd_file(char *file, struct ope
+ if((fd = os_open_file(file, *openflags, mode)) < 0)
+ return(fd);
+ }
++
++ err = os_lock_file(fd, openflags->w);
++ if(err){
++ printk("Failed to lock '%s', errno = %d\n", file, -err);
++ goto error;
++ }
++
+ if(backing_file_out == NULL) return(fd);
+
+- err = read_cow_header(fd, &magic, &backing_file, &mtime, &size,
+- §orsize, bitmap_offset_out);
++ err = read_cow_header(file_reader, &fd, &magic, &backing_file, &mtime,
++ &size, §orsize, bitmap_offset_out);
+ if(err && (*backing_file_out != NULL)){
+ printk("Failed to read COW header from COW file \"%s\", "
+ "errno = %d\n", file, err);
+@@ -376,12 +153,12 @@ int open_ubd_file(char *file, struct ope
+ if(err) goto error;
+ }
+
+- sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out,
+- data_offset_out);
++ cow_sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out,
++ data_offset_out);
+
+ return(fd);
+ error:
+- close(fd);
++ os_close_file(fd);
+ return(err);
+ }
+
+@@ -389,10 +166,7 @@ int create_cow_file(char *cow_file, char
+ int sectorsize, int *bitmap_offset_out,
+ unsigned long *bitmap_len_out, int *data_offset_out)
+ {
+- __u64 blocks;
+- long zero;
+- int err, fd, i;
+- long long size;
++ int err, fd;
+
+ flags.c = 1;
+ fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
+@@ -403,29 +177,12 @@ int create_cow_file(char *cow_file, char
+ goto out;
+ }
+
+- err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
+- if(err) goto out_close;
+-
+- blocks = (size + sectorsize - 1) / sectorsize;
+- blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
+- zero = 0;
+- for(i = 0; i < blocks; i++){
+- err = write(fd, &zero, sizeof(zero));
+- if(err != sizeof(zero)){
+- printk("Write of bitmap to new COW file '%s' failed, "
+- "errno = %d\n", cow_file, errno);
+- goto out_close;
+- }
+- }
+-
+- sizes(size, sectorsize, sizeof(struct cow_header_v2),
+- bitmap_len_out, data_offset_out);
+- *bitmap_offset_out = sizeof(struct cow_header_v2);
+-
+- return(fd);
+-
+- out_close:
+- close(fd);
++ err = init_cow_file(fd, cow_file, backing_file, sectorsize,
++ bitmap_offset_out, bitmap_len_out,
++ data_offset_out);
++ if(!err)
++ return(fd);
++ os_close_file(fd);
+ out:
+ return(err);
+ }
+@@ -448,14 +205,6 @@ int write_ubd_fs(int fd, char *buffer, i
+ else return(n);
+ }
+
+-int ubd_is_dir(char *file)
+-{
+- struct stat64 buf;
+-
+- if(stat64(file, &buf) < 0) return(0);
+- return(S_ISDIR(buf.st_mode));
+-}
+-
+ void do_io(struct io_thread_req *req)
+ {
+ char *buf;
+--- linux-2.6.0-test6/arch/um/drivers/xterm.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/um/drivers/xterm.c 2003-10-05 00:34:32.000000000 -0700
+@@ -108,7 +108,7 @@ int xterm_open(int input, int output, in
+ }
+ close(fd);
+
+- fd = create_unix_socket(file, sizeof(file));
++ fd = create_unix_socket(file, sizeof(file), 1);
+ if(fd < 0){
+ printk("xterm_open : create_unix_socket failed, errno = %d\n",
+ -fd);
+--- linux-2.6.0-test6/arch/um/drivers/xterm_kern.c 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/um/drivers/xterm_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -5,9 +5,12 @@
+
+ #include "linux/errno.h"
+ #include "linux/slab.h"
++#include "linux/signal.h"
++#include "linux/interrupt.h"
+ #include "asm/semaphore.h"
+ #include "asm/irq.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+ #include "kern_util.h"
+ #include "os.h"
+ #include "xterm.h"
+@@ -19,17 +22,18 @@ struct xterm_wait {
+ int new_fd;
+ };
+
+-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
++static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+ {
+ struct xterm_wait *xterm = data;
+ int fd;
+
+ fd = os_rcv_fd(xterm->fd, &xterm->pid);
+ if(fd == -EAGAIN)
+- return;
++ return(IRQ_NONE);
+
+ xterm->new_fd = fd;
+ up(&xterm->sem);
++ return(IRQ_HANDLED);
+ }
+
+ int xterm_fd(int socket, int *pid_out)
+--- linux-2.6.0-test6/arch/um/dyn.lds.S 2003-06-14 12:18:21.000000000 -0700
++++ 25/arch/um/dyn.lds.S 2003-10-05 00:34:32.000000000 -0700
+@@ -15,7 +15,11 @@ SECTIONS
+ . = ALIGN(4096); /* Init code and data */
+ _stext = .;
+ __init_begin = .;
+- .text.init : { *(.text.init) }
++ .init.text : {
++ _sinittext = .;
++ *(.init.text)
++ _einittext = .;
++ }
+
+ . = ALIGN(4096);
+
+@@ -67,7 +71,7 @@ SECTIONS
+
+ #include "asm/common.lds.S"
+
+- .data.init : { *(.data.init) }
++ init.data : { *(.init.data) }
+
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/arch/um/include/irq_kern.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,28 @@
++/*
++ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
++ */
++
++#ifndef __IRQ_KERN_H__
++#define __IRQ_KERN_H__
++
++#include "linux/interrupt.h"
++
++extern int um_request_irq(unsigned int irq, int fd, int type,
++ irqreturn_t (*handler)(int, void *,
++ struct pt_regs *),
++ unsigned long irqflags, const char * devname,
++ void *dev_id);
++
++#endif
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+--- linux-2.6.0-test6/arch/um/include/kern_util.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/um/include/kern_util.h 2003-10-05 00:34:32.000000000 -0700
+@@ -63,10 +63,9 @@ extern void init_flush_vm(void);
+ extern void *syscall_sp(void *t);
+ extern void syscall_trace(void);
+ extern int hz(void);
+-extern void idle_timer(void);
++extern void uml_idle_timer(void);
+ extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
+ extern int external_pid(void *t);
+-extern int pid_to_processor_id(int pid);
+ extern void boot_timer_handler(int sig);
+ extern void interrupt_end(void);
+ extern void initial_thread_cb(void (*proc)(void *), void *arg);
+@@ -90,9 +89,7 @@ extern int remove_gdb(void);
+ extern char *uml_strdup(char *string);
+ extern void unprotect_kernel_mem(void);
+ extern void protect_kernel_mem(void);
+-extern void set_kmem_end(unsigned long);
+ extern void uml_cleanup(void);
+-extern int pid_to_processor_id(int pid);
+ extern void set_current(void *t);
+ extern void lock_signalled_task(void *t);
+ extern void IPI_handler(int cpu);
+@@ -101,7 +98,9 @@ extern void *get_init_task(void);
+ extern int clear_user_proc(void *buf, int size);
+ extern int copy_to_user_proc(void *to, void *from, int size);
+ extern int copy_from_user_proc(void *to, void *from, int size);
++extern int strlen_user_proc(char *str);
+ extern void bus_handler(int sig, union uml_pt_regs *regs);
++extern void winch(int sig, union uml_pt_regs *regs);
+ extern long execute_syscall(void *r);
+ extern int smp_sigio_handler(void);
+ extern void *get_current(void);
+--- linux-2.6.0-test6/arch/um/include/line.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/arch/um/include/line.h 2003-10-05 00:34:32.000000000 -0700
+@@ -9,12 +9,14 @@
+ #include "linux/list.h"
+ #include "linux/workqueue.h"
+ #include "linux/tty.h"
++#include "linux/interrupt.h"
+ #include "asm/semaphore.h"
+ #include "chan_user.h"
+ #include "mconsole_kern.h"
+
+ struct line_driver {
+ char *name;
++ char *device_name;
+ char *devfs_name;
+ short major;
+ short minor_start;
+@@ -67,8 +69,9 @@ struct lines {
+
+ #define LINES_INIT(n) { num : n }
+
+-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
+-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
++extern irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused);
++extern irqreturn_t line_write_interrupt(int irq, void *data,
++ struct pt_regs *unused);
+ extern void line_close(struct line *lines, struct tty_struct *tty);
+ extern int line_open(struct line *lines, struct tty_struct *tty,
+ struct chan_opts *opts);
+--- linux-2.6.0-test6/arch/um/include/mconsole.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/arch/um/include/mconsole.h 2003-10-05 00:34:32.000000000 -0700
+@@ -77,6 +77,7 @@ extern void mconsole_sysrq(struct mc_req
+ extern void mconsole_cad(struct mc_request *req);
+ extern void mconsole_stop(struct mc_request *req);
+ extern void mconsole_go(struct mc_request *req);
++extern void mconsole_log(struct mc_request *req);
+
+ extern int mconsole_get_request(int fd, struct mc_request *req);
+ extern int mconsole_notify(char *sock_name, int type, const void *data,
+--- linux-2.6.0-test6/arch/um/include/mem.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/um/include/mem.h 2003-10-05 00:34:32.000000000 -0700
+@@ -13,7 +13,6 @@ struct vm_reserved {
+ };
+
+ extern void set_usable_vm(unsigned long start, unsigned long end);
+-extern void set_kmem_end(unsigned long new);
+
+ #endif
+
+--- linux-2.6.0-test6/arch/um/include/mem_user.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/arch/um/include/mem_user.h 2003-10-05 00:34:32.000000000 -0700
+@@ -51,9 +51,6 @@ extern unsigned long task_size;
+
+ extern int init_mem_user(void);
+ extern int create_mem_file(unsigned long len);
+-extern void setup_range(int fd, char *driver, unsigned long start,
+- unsigned long pfn, unsigned long total, int need_vm,
+- struct mem_region *region, void *reserved);
+ extern void setup_memory(void *entry);
+ extern unsigned long find_iomem(char *driver, unsigned long *len_out);
+ extern int init_maps(struct mem_region *region);
+--- linux-2.6.0-test6/arch/um/include/os.h 2003-06-14 12:18:02.000000000 -0700
++++ 25/arch/um/include/os.h 2003-10-05 00:34:32.000000000 -0700
+@@ -103,10 +103,11 @@ extern int os_accept_connection(int fd);
+ extern int os_shutdown_socket(int fd, int r, int w);
+ extern void os_close_file(int fd);
+ extern int os_rcv_fd(int fd, int *helper_pid_out);
+-extern int create_unix_socket(char *file, int len);
++extern int create_unix_socket(char *file, int len, int close_on_exec);
+ extern int os_connect_socket(char *name);
+ extern int os_file_type(char *file);
+ extern int os_file_mode(char *file, struct openflags *mode_out);
++extern int os_lock_file(int fd, int excl);
+
+ extern unsigned long os_process_pc(int pid);
+ extern int os_process_parent(int pid);
+@@ -120,6 +121,7 @@ extern int os_map_memory(void *virt, int
+ extern int os_protect_memory(void *addr, unsigned long len,
+ int r, int w, int x);
+ extern int os_unmap_memory(void *addr, int len);
++extern void os_flush_stdout(void);
+
+ #endif
+
+--- linux-2.6.0-test6/arch/um/include/sysdep-i386/sigcontext.h 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/um/include/sysdep-i386/sigcontext.h 2003-10-05 00:34:32.000000000 -0700
+@@ -28,8 +28,8 @@
+ */
+ #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
+
+-/* These are General Protection and Page Fault */
+-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
++/* This is Page Fault */
++#define SEGV_IS_FIXABLE(trap) (trap == 14)
+
+ #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
+
+--- linux-2.6.0-test6/arch/um/include/ubd_user.h 2003-06-14 12:18:22.000000000 -0700
++++ 25/arch/um/include/ubd_user.h 2003-10-05 00:34:32.000000000 -0700
+@@ -39,7 +39,6 @@ extern int read_ubd_fs(int fd, void *buf
+ extern int write_ubd_fs(int fd, char *buffer, int len);
+ extern int start_io_thread(unsigned long sp, int *fds_out);
+ extern void do_io(struct io_thread_req *req);
+-extern int ubd_is_dir(char *file);
+
+ static inline int ubd_test_bit(__u64 bit, unsigned char *data)
+ {
+--- linux-2.6.0-test6/arch/um/include/user.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/um/include/user.h 2003-10-05 00:34:32.000000000 -0700
+@@ -14,7 +14,7 @@ extern void *um_kmalloc_atomic(int size)
+ extern void kfree(void *ptr);
+ extern int in_aton(char *str);
+ extern int open_gdb_chan(void);
+-
++extern int strlcpy(char *, const char *, int);
+ #endif
+
+ /*
+--- linux-2.6.0-test6/arch/um/include/user_util.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/um/include/user_util.h 2003-10-05 00:34:32.000000000 -0700
+@@ -59,7 +59,6 @@ extern int wait_for_stop(int pid, int si
+ extern void *add_signal_handler(int sig, void (*handler)(int));
+ extern int start_fork_tramp(void *arg, unsigned long temp_stack,
+ int clone_flags, int (*tramp)(void *));
+-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
+ extern int linux_main(int argc, char **argv);
+ extern void set_cmdline(char *cmd);
+ extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
+@@ -90,7 +89,8 @@ extern int arch_handle_signal(int sig, u
+ extern int arch_fixup(unsigned long address, void *sc_ptr);
+ extern void forward_pending_sigio(int target);
+ extern int can_do_skas(void);
+-
++extern void arch_init_thread(void);
++
+ #endif
+
+ /*
+--- linux-2.6.0-test6/arch/um/Kconfig 2003-08-08 22:55:11.000000000 -0700
++++ 25/arch/um/Kconfig 2003-10-05 00:34:32.000000000 -0700
+@@ -61,6 +61,20 @@ config MODE_SKAS
+
+ config NET
+ bool "Networking support"
++ help
++ Unless you really know what you are doing, you should say Y here.
++ The reason is that some programs need kernel networking support even
++ when running on a stand-alone machine that isn't connected to any
++ other computer. If you are upgrading from an older kernel, you
++ should consider updating your networking tools too because changes
++ in the kernel and the tools often go hand in hand. The tools are
++ contained in the package net-tools, the location and version number
++ of which are given in Documentation/Changes.
++
++ For a general introduction to Linux networking, it is highly
++ recommended to read the NET-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
+
+ source "fs/Kconfig.binfmt"
+
+@@ -105,6 +119,16 @@ config MCONSOLE
+ config MAGIC_SYSRQ
+ bool "Magic SysRq key"
+ depends on MCONSOLE
++ help
++ If you say Y here, you will have some control over the system even
++ if the system crashes for example during kernel debugging (e.g., you
++ will be able to flush the buffer cache to disk, reboot the system
++ immediately or dump some status information). This is accomplished
++ by pressing various keys while holding SysRq (Alt+PrintScreen). It
++ also works on a serial console (on PC hardware at least), if you
++ send a BREAK and then within 5 seconds a command keypress. The
++ keys are documented in Documentation/sysrq.txt. Don't say Y
++ unless you really know what this hack does.
+
+ config HOST_2G_2G
+ bool "2G/2G host address space split"
+@@ -239,6 +263,10 @@ config FRAME_POINTER
+ config PT_PROXY
+ bool "Enable ptrace proxy"
+ depends on XTERM_CHAN && DEBUG_INFO
++ help
++ This option enables a debugging interface which allows gdb to debug
++ the kernel without needing to actually attach to kernel threads.
++ If you want to do kernel debugging, say Y here; otherwise say N.
+
+ config GPROF
+ bool "Enable gprof support"
+--- linux-2.6.0-test6/arch/um/Kconfig_block 2003-06-14 12:18:25.000000000 -0700
++++ 25/arch/um/Kconfig_block 2003-10-05 00:34:32.000000000 -0700
+@@ -29,6 +29,20 @@ config BLK_DEV_UBD_SYNC
+ wise choice too. In all other cases (for example, if you're just
+ playing around with User-Mode Linux) you can choose N.
+
++# Turn this back on when the driver actually works
++#
++#config BLK_DEV_COW
++# tristate "COW block device"
++# help
++# This is a layered driver which sits above two other block devices.
++# One is read-only, and the other is a read-write layer which stores
++# all changes. This provides the illusion that the read-only layer
++# can be mounted read-write and changed.
++
++config BLK_DEV_COW_COMMON
++ bool
++ default BLK_DEV_COW || BLK_DEV_UBD
++
+ config BLK_DEV_LOOP
+ tristate "Loopback device support"
+
+--- linux-2.6.0-test6/arch/um/Kconfig_net 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/um/Kconfig_net 2003-10-05 00:34:32.000000000 -0700
+@@ -1,5 +1,5 @@
+
+-menu "Network Devices"
++menu "UML Network Devices"
+ depends on NET
+
+ # UML virtual driver
+@@ -176,73 +176,5 @@ config UML_NET_SLIRP
+
+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
+
+-
+-# Below are hardware-independent drivers mirrored from
+-# drivers/net/Config.in. It would be nice if Linux
+-# had HW independent drivers separated from the other
+-# but it does not. Until then each non-ISA/PCI arch
+-# needs to provide it's own menu of network drivers
+-config DUMMY
+- tristate "Dummy net driver support"
+-
+-config BONDING
+- tristate "Bonding driver support"
+-
+-config EQUALIZER
+- tristate "EQL (serial line load balancing) support"
+-
+-config TUN
+- tristate "Universal TUN/TAP device driver support"
+-
+-config ETHERTAP
+- tristate "Ethertap network tap (OBSOLETE)"
+- depends on EXPERIMENTAL && NETLINK
+-
+-config PPP
+- tristate "PPP (point-to-point protocol) support"
+-
+-config PPP_MULTILINK
+- bool "PPP multilink support (EXPERIMENTAL)"
+- depends on PPP && EXPERIMENTAL
+-
+-config PPP_FILTER
+- bool "PPP filtering"
+- depends on PPP && FILTER
+-
+-config PPP_ASYNC
+- tristate "PPP support for async serial ports"
+- depends on PPP
+-
+-config PPP_SYNC_TTY
+- tristate "PPP support for sync tty ports"
+- depends on PPP
+-
+-config PPP_DEFLATE
+- tristate "PPP Deflate compression"
+- depends on PPP
+-
+-config PPP_BSDCOMP
+- tristate "PPP BSD-Compress compression"
+- depends on PPP
+-
+-config PPPOE
+- tristate "PPP over Ethernet (EXPERIMENTAL)"
+- depends on PPP && EXPERIMENTAL
+-
+-config SLIP
+- tristate "SLIP (serial line) support"
+-
+-config SLIP_COMPRESSED
+- bool "CSLIP compressed headers"
+- depends on SLIP=y
+-
+-config SLIP_SMART
+- bool "Keepalive and linefill"
+- depends on SLIP=y
+-
+-config SLIP_MODE_SLIP6
+- bool "Six bit SLIP encapsulation"
+- depends on SLIP=y
+-
+ endmenu
+
+--- linux-2.6.0-test6/arch/um/kernel/config.c.in 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/um/kernel/config.c.in 2003-10-05 00:34:32.000000000 -0700
+@@ -7,9 +7,7 @@
+ #include <stdlib.h>
+ #include "init.h"
+
+-static __initdata char *config = "
+-CONFIG
+-";
++static __initdata char *config = "CONFIG";
+
+ static int __init print_config(char *line, int *add)
+ {
+--- linux-2.6.0-test6/arch/um/kernel/init_task.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/um/kernel/init_task.c 2003-10-05 00:34:32.000000000 -0700
+@@ -17,6 +17,7 @@ static struct fs_struct init_fs = INIT_F
+ struct mm_struct init_mm = INIT_MM(init_mm);
+ static struct files_struct init_files = INIT_FILES;
+ static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
++static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+ /*
+ * Initial task structure.
+@@ -38,26 +39,12 @@ union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+-struct task_struct *alloc_task_struct(void)
+-{
+- return((struct task_struct *)
+- __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
+-}
+-
+ void unprotect_stack(unsigned long stack)
+ {
+ protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
+ 1, 1, 0, 1);
+ }
+
+-void free_task_struct(struct task_struct *task)
+-{
+- /* free_pages decrements the page counter and only actually frees
+- * the pages if they are now not accessed by anything.
+- */
+- free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
+-}
+-
+ /*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+--- linux-2.6.0-test6/arch/um/kernel/irq.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/irq.c 2003-10-05 00:34:32.000000000 -0700
+@@ -28,6 +28,7 @@
+ #include "user_util.h"
+ #include "kern_util.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+
+ static void register_irq_proc (unsigned int irq);
+
+@@ -82,65 +83,52 @@ struct hw_interrupt_type no_irq_type = {
+ end_none
+ };
+
+-/* Not changed */
+-volatile unsigned long irq_err_count;
+-
+ /*
+ * Generic, controller-independent functions:
+ */
+
+-int get_irq_list(char *buf)
++int show_interrupts(struct seq_file *p, void *v)
+ {
+ int i, j;
+- unsigned long flags;
+ struct irqaction * action;
+- char *p = buf;
++ unsigned long flags;
+
+- p += sprintf(p, " ");
+- for (j=0; j<num_online_cpus(); j++)
+- p += sprintf(p, "CPU%d ",j);
+- *p++ = '\n';
++ seq_printf(p, " ");
++ for (j=0; j<NR_CPUS; j++)
++ if (cpu_online(j))
++ seq_printf(p, "CPU%d ",j);
++ seq_putc(p, '\n');
+
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+- goto end;
+- p += sprintf(p, "%3d: ",i);
++ goto skip;
++ seq_printf(p, "%3d: ",i);
+ #ifndef CONFIG_SMP
+- p += sprintf(p, "%10u ", kstat_irqs(i));
++ seq_printf(p, "%10u ", kstat_irqs(i));
+ #else
+- for (j = 0; j < num_online_cpus(); j++)
+- p += sprintf(p, "%10u ",
+- kstat_cpu(cpu_logical_map(j)).irqs[i]);
++ for (j = 0; j < NR_CPUS; j++)
++ if (cpu_online(j))
++ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ #endif
+- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+- p += sprintf(p, " %s", action->name);
++ seq_printf(p, " %14s", irq_desc[i].handler->typename);
++ seq_printf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+- p += sprintf(p, ", %s", action->name);
+- *p++ = '\n';
+- end:
++ seq_printf(p, ", %s", action->name);
++
++ seq_putc(p, '\n');
++skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+- p += sprintf(p, "\n");
+-#ifdef notdef
+-#ifdef CONFIG_SMP
+- p += sprintf(p, "LOC: ");
+- for (j = 0; j < num_online_cpus(); j++)
+- p += sprintf(p, "%10u ",
+- apic_timer_irqs[cpu_logical_map(j)]);
+- p += sprintf(p, "\n");
+-#endif
+-#endif
+- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+- return p - buf;
+-}
+-
++ seq_printf(p, "NMI: ");
++ for (j = 0; j < NR_CPUS; j++)
++ if (cpu_online(j))
++ seq_printf(p, "%10u ", nmi_count(j));
++ seq_putc(p, '\n');
+
+-int show_interrupts(struct seq_file *p, void *v)
+-{
+- return(0);
++ return 0;
+ }
+
+ /*
+@@ -281,13 +269,12 @@ unsigned int do_IRQ(int irq, union uml_p
+ * 0 return value means that this irq is already being
+ * handled by some other CPU. (or is disabled)
+ */
+- int cpu = smp_processor_id();
+ irq_desc_t *desc = irq_desc + irq;
+ struct irqaction * action;
+ unsigned int status;
+
+ irq_enter();
+- kstat_cpu(cpu).irqs[irq]++;
++ kstat_this_cpu.irqs[irq]++;
+ spin_lock(&desc->lock);
+ desc->handler->ack(irq);
+ /*
+@@ -384,7 +371,7 @@ out:
+ */
+
+ int request_irq(unsigned int irq,
+- void (*handler)(int, void *, struct pt_regs *),
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
+@@ -430,15 +417,19 @@ int request_irq(unsigned int irq,
+ }
+
+ int um_request_irq(unsigned int irq, int fd, int type,
+- void (*handler)(int, void *, struct pt_regs *),
++ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags, const char * devname,
+ void *dev_id)
+ {
+- int retval;
++ int err;
+
+- retval = request_irq(irq, handler, irqflags, devname, dev_id);
+- if(retval) return(retval);
+- return(activate_fd(irq, fd, type, dev_id));
++ err = request_irq(irq, handler, irqflags, devname, dev_id);
++ if(err)
++ return(err);
++
++ if(fd != -1)
++ err = activate_fd(irq, fd, type, dev_id);
++ return(err);
+ }
+
+ /* this was setup_x86_irq but it seems pretty generic */
+@@ -654,7 +645,7 @@ static int prof_cpu_mask_read_proc (char
+ return -EINVAL;
+ tmp = *mask;
+ for (k = 0; k < sizeof(cpumask_t)/sizeof(u16); ++k) {
+- int j = sprintf(page, "%04hx", cpus_coerce(tmp));
++ int j = sprintf(page, "%04hx", (short) cpus_coerce(tmp));
+ len += j;
+ page += j;
+ cpus_shift_right(tmp, tmp, 16);
+--- linux-2.6.0-test6/arch/um/kernel/Makefile 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/Makefile 2003-10-05 00:34:32.000000000 -0700
+@@ -21,6 +21,8 @@ obj-$(CONFIG_TTY_LOG) += tty_log.o
+ obj-$(CONFIG_MODE_TT) += tt/
+ obj-$(CONFIG_MODE_SKAS) += skas/
+
++clean-files := config.c
++
+ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
+
+ USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
+@@ -45,17 +47,13 @@ $(USER_OBJS) : %.o: %.c
+ $(obj)/frame.o: $(src)/frame.c
+ $(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
+
+-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
++QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+
+ $(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
+ $(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
+
+ $(obj)/config.o : $(obj)/config.c
+
+-clean:
+- rm -f config.c
+- for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
+-
+ modules:
+
+ fastdep:
+--- linux-2.6.0-test6/arch/um/kernel/mem.c 2003-06-14 12:18:08.000000000 -0700
++++ 25/arch/um/kernel/mem.c 2003-10-05 00:34:32.000000000 -0700
+@@ -119,11 +119,6 @@ unsigned long get_kmem_end(void)
+ return(kmem_top);
+ }
+
+-void set_kmem_end(unsigned long new)
+-{
+- kmem_top = new;
+-}
+-
+ #ifdef CONFIG_HIGHMEM
+ /* Changed during early boot */
+ pte_t *kmap_pte;
+@@ -218,7 +213,7 @@ static int setup_one_range(int fd, char
+ if(regions[i] == NULL) break;
+ }
+ if(i == NREGIONS){
+- printk("setup_range : no free regions\n");
++ printk("setup_one_range : no free regions\n");
+ i = -1;
+ goto out;
+ }
+@@ -227,7 +222,9 @@ static int setup_one_range(int fd, char
+ fd = create_mem_file(len);
+
+ if(region == NULL){
+- region = alloc_bootmem_low_pages(sizeof(*region));
++ if(kmalloc_ok)
++ region = kmalloc(sizeof(*region), GFP_KERNEL);
++ else region = alloc_bootmem_low_pages(sizeof(*region));
+ if(region == NULL)
+ panic("Failed to allocating mem_region");
+ }
+@@ -528,9 +525,9 @@ int nregions(void)
+ return(NREGIONS);
+ }
+
+-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
+- unsigned long len, int need_vm, struct mem_region *region,
+- void *reserved)
++static void setup_range(int fd, char *driver, unsigned long start,
++ unsigned long pfn, unsigned long len, int need_vm,
++ struct mem_region *region, void *reserved)
+ {
+ int i, cur;
+
+--- linux-2.6.0-test6/arch/um/kernel/mem_user.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/arch/um/kernel/mem_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -111,6 +111,11 @@ int setup_region(struct mem_region *regi
+ offset = 0;
+ }
+
++ if(offset >= region->len){
++ printf("%ld bytes of physical memory is insufficient\n",
++ region->len);
++ exit(1);
++ }
+ loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, region->fd, offset);
+ if(loc != start){
+@@ -122,26 +127,26 @@ int setup_region(struct mem_region *regi
+
+ static int __init parse_iomem(char *str, int *add)
+ {
+- struct stat buf;
++ struct stat64 buf;
+ char *file, *driver;
+ int fd;
+
+ driver = str;
+ file = strchr(str,',');
+ if(file == NULL){
+- printk("parse_iomem : failed to parse iomem\n");
++ printf("parse_iomem : failed to parse iomem\n");
+ return(1);
+ }
+ *file = '\0';
+ file++;
+ fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
+ if(fd < 0){
+- printk("parse_iomem - Couldn't open io file, errno = %d\n",
++ printf("parse_iomem - Couldn't open io file, errno = %d\n",
+ errno);
+ return(1);
+ }
+- if(fstat(fd, &buf) < 0) {
+- printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
++ if(fstat64(fd, &buf) < 0) {
++ printf("parse_iomem - cannot fstat file, errno = %d\n", errno);
+ return(1);
+ }
+ add_iomem(driver, fd, buf.st_size);
+--- linux-2.6.0-test6/arch/um/kernel/process.c 2003-06-14 12:18:32.000000000 -0700
++++ 25/arch/um/kernel/process.c 2003-10-05 00:34:32.000000000 -0700
+@@ -72,7 +72,6 @@ void init_new_thread_signals(int altstac
+ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ set_handler(SIGUSR2, (__sighandler_t) sig_handler,
+ SA_NOMASK | flags, -1);
+- (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
+ signal(SIGHUP, SIG_IGN);
+
+ init_irq_signals(altstack);
+@@ -127,7 +126,8 @@ int start_fork_tramp(void *thread_arg, u
+ if(err < 0) panic("Waiting for outer trampoline failed - errno = %d",
+ errno);
+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
+- panic("outer trampoline didn't exit with SIGKILL");
++ panic("outer trampoline didn't exit with SIGKILL, "
++ "status = %d", status);
+
+ return(arg.pid);
+ }
+--- linux-2.6.0-test6/arch/um/kernel/process_kern.c 2003-07-10 18:50:30.000000000 -0700
++++ 25/arch/um/kernel/process_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -52,17 +52,12 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [
+
+ struct task_struct *get_task(int pid, int require)
+ {
+- struct task_struct *task, *ret;
++ struct task_struct *ret;
+
+- ret = NULL;
+ read_lock(&tasklist_lock);
+- for_each_process(task){
+- if(task->pid == pid){
+- ret = task;
+- break;
+- }
+- }
++ ret = find_task_by_pid(pid);
+ read_unlock(&tasklist_lock);
++
+ if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
+ return(ret);
+ }
+@@ -103,13 +98,14 @@ unsigned long alloc_stack(int order, int
+
+ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+ {
+- struct task_struct *p;
++ int pid;
+
+ current->thread.request.u.thread.proc = fn;
+ current->thread.request.u.thread.arg = arg;
+- p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
+- if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
+- return(p->pid);
++ pid = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
++ if(pid < 0)
++ panic("do_fork failed in kernel_thread, errno = %d", pid);
++ return(pid);
+ }
+
+ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+@@ -129,7 +125,7 @@ void set_current(void *t)
+ { external_pid(task), task });
+ }
+
+-void *switch_to(void *prev, void *next, void *last)
++void *_switch_to(void *prev, void *next, void *last)
+ {
+ return(CHOOSE_MODE(switch_to_tt(prev, next),
+ switch_to_skas(prev, next)));
+@@ -149,7 +145,7 @@ void release_thread(struct task_struct *
+ void exit_thread(void)
+ {
+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
+- unprotect_stack((unsigned long) current->thread_info);
++ unprotect_stack((unsigned long) current_thread);
+ }
+
+ void *get_current(void)
+@@ -157,6 +153,10 @@ void *get_current(void)
+ return(current);
+ }
+
++void prepare_to_copy(struct task_struct *tsk)
++{
++}
++
+ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct * p,
+ struct pt_regs *regs)
+@@ -190,7 +190,7 @@ int current_pid(void)
+
+ void default_idle(void)
+ {
+- idle_timer();
++ uml_idle_timer();
+
+ atomic_inc(&init_mm.mm_count);
+ current->mm = &init_mm;
+@@ -363,10 +363,15 @@ int clear_user_proc(void *buf, int size)
+ return(clear_user(buf, size));
+ }
+
++int strlen_user_proc(char *str)
++{
++ return(strlen_user(str));
++}
++
+ int smp_sigio_handler(void)
+ {
+ #ifdef CONFIG_SMP
+- int cpu = current->thread_info->cpu;
++ int cpu = current_thread->cpu;
+ IPI_handler(cpu);
+ if(cpu != 0)
+ return(1);
+@@ -381,7 +386,7 @@ int um_in_interrupt(void)
+
+ int cpu(void)
+ {
+- return(current->thread_info->cpu);
++ return(current_thread->cpu);
+ }
+
+ /*
+--- linux-2.6.0-test6/arch/um/kernel/ptrace.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/arch/um/kernel/ptrace.c 2003-10-05 00:34:32.000000000 -0700
+@@ -311,11 +311,8 @@ void syscall_trace(void)
+
+ /* the 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
+- current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+- ? 0x80 : 0);
+- current->state = TASK_STOPPED;
+- notify_parent(current, SIGCHLD);
+- schedule();
++ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
++ ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+--- linux-2.6.0-test6/arch/um/kernel/sigio_kern.c 2003-06-14 12:18:04.000000000 -0700
++++ 25/arch/um/kernel/sigio_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -6,18 +6,21 @@
+ #include "linux/kernel.h"
+ #include "linux/list.h"
+ #include "linux/slab.h"
+-#include "asm/irq.h"
++#include "linux/signal.h"
++#include "linux/interrupt.h"
+ #include "init.h"
+ #include "sigio.h"
+ #include "irq_user.h"
++#include "irq_kern.h"
+
+ /* Protected by sigio_lock() called from write_sigio_workaround */
+ static int sigio_irq_fd = -1;
+
+-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
++irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+ {
+ read_sigio_fd(sigio_irq_fd);
+ reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
++ return(IRQ_HANDLED);
+ }
+
+ int write_sigio_irq(int fd)
+--- linux-2.6.0-test6/arch/um/kernel/signal_kern.c 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/um/kernel/signal_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -36,7 +36,7 @@ static void force_segv(int sig)
+ if(sig == SIGSEGV){
+ struct k_sigaction *ka;
+
+- ka = ¤t->sig->action[SIGSEGV - 1];
++ ka = ¤t->sighand->action[SIGSEGV - 1];
+ ka->sa.sa_handler = SIG_DFL;
+ }
+ force_sig(SIGSEGV, current);
+@@ -142,7 +142,7 @@ static int kern_do_signal(struct pt_regs
+ return(0);
+
+ /* Whee! Actually deliver the signal. */
+- ka = ¤t->sig->action[sig -1 ];
++ ka = ¤t->sighand->action[sig -1 ];
+ err = handle_signal(regs, sig, ka, &info, oldset, error);
+ if(!err) return(1);
+
+@@ -201,7 +201,7 @@ int sys_sigsuspend(int history0, int his
+ }
+ }
+
+-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
++int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+ {
+ sigset_t saveset, newset;
+
+@@ -227,6 +227,42 @@ int sys_rt_sigsuspend(sigset_t *unewset,
+ }
+ }
+
++int sys_sigaction(int sig, const struct old_sigaction __user *act,
++ struct old_sigaction __user *oact)
++{
++ struct k_sigaction new_ka, old_ka;
++ int ret;
++
++ if (act) {
++ old_sigset_t mask;
++ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
++ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
++ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
++ return -EFAULT;
++ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
++ __get_user(mask, &act->sa_mask);
++ siginitset(&new_ka.sa.sa_mask, mask);
++ }
++
++ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
++
++ if (!ret && oact) {
++ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
++ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
++ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
++ return -EFAULT;
++ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
++ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
++ }
++
++ return ret;
++}
++
++int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
++{
++ return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
++}
++
+ static int copy_sc_from_user(struct pt_regs *to, void *from,
+ struct arch_frame_data *arch)
+ {
+@@ -239,8 +275,8 @@ static int copy_sc_from_user(struct pt_r
+
+ int sys_sigreturn(struct pt_regs regs)
+ {
+- void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
+- void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
++ void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
++ void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
+ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+
+ spin_lock_irq(¤t->sighand->siglock);
+@@ -257,7 +293,8 @@ int sys_sigreturn(struct pt_regs regs)
+
+ int sys_rt_sigreturn(struct pt_regs regs)
+ {
+- struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs));
++ unsigned long sp = PT_REGS_SP(¤t->thread.regs);
++ struct ucontext __user *uc = sp_to_uc(sp);
+ void *fp;
+ int sig_size = _NSIG_WORDS * sizeof(unsigned long);
+
+--- linux-2.6.0-test6/arch/um/kernel/skas/include/mode.h 2003-06-14 12:18:22.000000000 -0700
++++ 25/arch/um/kernel/skas/include/mode.h 2003-10-05 00:34:32.000000000 -0700
+@@ -20,6 +20,7 @@ extern void sig_handler_common_skas(int
+ extern void halt_skas(void);
+ extern void reboot_skas(void);
+ extern void kill_off_processes_skas(void);
++extern int is_skas_winch(int pid, int fd, void *data);
+
+ #endif
+
+--- linux-2.6.0-test6/arch/um/kernel/skas/include/uaccess.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/arch/um/kernel/skas/include/uaccess.h 2003-10-05 00:34:32.000000000 -0700
+@@ -19,7 +19,7 @@
+ #define access_ok_skas(type, addr, size) \
+ ((segment_eq(get_fs(), KERNEL_DS)) || \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+- ((unsigned long) (addr) + (size) < TASK_SIZE)))
++ ((unsigned long) (addr) + (size) <= TASK_SIZE)))
+
+ static inline int verify_area_skas(int type, const void * addr,
+ unsigned long size)
+--- linux-2.6.0-test6/arch/um/kernel/skas/Makefile 2003-06-14 12:18:06.000000000 -0700
++++ 25/arch/um/kernel/skas/Makefile 2003-10-05 00:34:32.000000000 -0700
+@@ -7,18 +7,22 @@ obj-y = exec_kern.o exec_user.o mem.o me
+ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
+ sys-$(SUBARCH)/
+
++host-progs := util/mk_ptregs
++clean-files := include/skas_ptregs.h
++
+ USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
+ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+-include/skas_ptregs.h : util/mk_ptregs
+- util/mk_ptregs > $@
+-
+-util/mk_ptregs :
+- $(MAKE) -C util
++$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs
++ @echo -n ' Generating $@'
++ @$< > $@.tmp
++ @if [ -r $@ ] && cmp -s $@ $@.tmp; then \
++ echo ' (unchanged)'; \
++ rm -f $@.tmp; \
++ else \
++ echo ' (updated)'; \
++ mv -f $@.tmp $@; \
++ fi
+
+ $(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+-
+-clean :
+- $(MAKE) -C util clean
+- $(RM) -f include/skas_ptregs.h
+--- linux-2.6.0-test6/arch/um/kernel/skas/process.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/arch/um/kernel/skas/process.c 2003-10-05 00:34:32.000000000 -0700
+@@ -4,6 +4,7 @@
+ */
+
+ #include <stdlib.h>
++#include <unistd.h>
+ #include <errno.h>
+ #include <signal.h>
+ #include <setjmp.h>
+@@ -24,6 +25,16 @@
+ #include "os.h"
+ #include "proc_mm.h"
+ #include "skas_ptrace.h"
++#include "chan_user.h"
++
++int is_skas_winch(int pid, int fd, void *data)
++{
++ if(pid != getpid())
++ return(0);
++
++ register_winch_irq(-1, fd, -1, data);
++ return(1);
++}
+
+ unsigned long exec_regs[FRAME_SIZE];
+ unsigned long exec_fp_regs[HOST_FP_SIZE];
+@@ -48,11 +59,11 @@ static void handle_trap(int pid, union u
+ int err, syscall_nr, status;
+
+ syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
++ UPT_SYSCALL_NR(regs) = syscall_nr;
+ if(syscall_nr < 1){
+ relay_signal(SIGTRAP, regs);
+ return;
+ }
+- UPT_SYSCALL_NR(regs) = syscall_nr;
+
+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+ if(err < 0)
+@@ -72,8 +83,6 @@ static void handle_trap(int pid, union u
+ handle_syscall(regs);
+ }
+
+-int userspace_pid;
+-
+ static int userspace_tramp(void *arg)
+ {
+ init_new_thread_signals(0);
+@@ -83,6 +92,8 @@ static int userspace_tramp(void *arg)
+ return(0);
+ }
+
++int userspace_pid;
++
+ void start_userspace(void)
+ {
+ void *stack;
+@@ -149,6 +160,7 @@ void userspace(union uml_pt_regs *regs)
+ case SIGILL:
+ case SIGBUS:
+ case SIGFPE:
++ case SIGWINCH:
+ user_signal(WSTOPSIG(status), regs);
+ break;
+ default:
+@@ -328,7 +340,8 @@ void reboot_skas(void)
+ int new_mm(int from)
+ {
+ struct proc_mm_op copy;
+- int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
++ int n, fd = os_open_file("/proc/mm",
++ of_cloexec(of_write(OPENFLAGS())), 0);
+
+ if(fd < 0)
+ return(-errno);
+@@ -342,6 +355,7 @@ int new_mm(int from)
+ printk("new_mm : /proc/mm copy_segments failed, "
+ "errno = %d\n", errno);
+ }
++
+ return(fd);
+ }
+
+--- linux-2.6.0-test6/arch/um/kernel/skas/process_kern.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/skas/process_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -61,9 +61,8 @@ void new_thread_handler(int sig)
+ thread_wait(¤t->thread.mode.skas.switch_buf,
+ current->thread.mode.skas.fork_buf);
+
+-#ifdef CONFIG_SMP
+- schedule_tail(NULL);
+-#endif
++ if(current->thread.prev_sched != NULL)
++ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
+ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf);
+@@ -93,9 +92,8 @@ void fork_handler(int sig)
+ current->thread.mode.skas.fork_buf);
+
+ force_flush_all();
+-#ifdef CONFIG_SMP
+- schedule_tail(current->thread.prev_sched);
+-#endif
++ if(current->thread.prev_sched != NULL)
++ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+ unblock_signals();
+
+@@ -136,7 +134,7 @@ int copy_thread_skas(int nr, unsigned lo
+
+ void init_idle_skas(void)
+ {
+- cpu_tasks[current->thread_info->cpu].pid = os_getpid();
++ cpu_tasks[current_thread->cpu].pid = os_getpid();
+ default_idle();
+ }
+
+@@ -164,7 +162,7 @@ int start_uml_skas(void)
+ capture_signal_stack();
+
+ init_new_thread_signals(1);
+- idle_timer();
++ uml_idle_timer();
+
+ init_task.thread.request.u.thread.proc = start_kernel_proc;
+ init_task.thread.request.u.thread.arg = NULL;
+--- linux-2.6.0-test6/arch/um/kernel/skas/util/mk_ptregs.c 2003-06-14 12:18:08.000000000 -0700
++++ 25/arch/um/kernel/skas/util/mk_ptregs.c 2003-10-05 00:34:32.000000000 -0700
+@@ -1,3 +1,4 @@
++#include <stdio.h>
+ #include <asm/ptrace.h>
+ #include <asm/user.h>
+
+--- linux-2.6.0-test6/arch/um/kernel/smp.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/smp.c 2003-10-05 00:34:32.000000000 -0700
+@@ -22,7 +22,7 @@
+ #include "os.h"
+
+ /* CPU online map, set by smp_boot_cpus */
+-unsigned long cpu_online_map = cpumask_of_cpu(0);
++unsigned long cpu_online_map = CPU_MASK_NONE;
+
+ /* Per CPU bogomips and other parameters
+ * The only piece used here is the ipi pipe, which is set before SMP is
+@@ -97,15 +97,15 @@ void smp_send_stop(void)
+
+ printk(KERN_INFO "Stopping all CPUs...");
+ for(i = 0; i < num_online_cpus(); i++){
+- if(i == current->thread_info->cpu)
++ if(i == current_thread->cpu)
+ continue;
+ write(cpu_data[i].ipi_pipe[1], "S", 1);
+ }
+ printk("done\n");
+ }
+
+-static cpumask_t smp_commenced_mask;
+-static cpumask_t smp_callin_map = CPU_MASK_NONE;
++static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
++static cpumask_t cpu_callin_map = CPU_MASK_NONE;
+
+ static int idle_proc(void *cpup)
+ {
+@@ -120,12 +120,12 @@ static int idle_proc(void *cpup)
+ current->thread.mode.tt.extern_pid);
+
+ wmb();
+- if (cpu_test_and_set(cpu, &smp_callin_map)) {
++ if (cpu_test_and_set(cpu, cpu_callin_map)) {
+ printk("huh, CPU#%d already present??\n", cpu);
+ BUG();
+ }
+
+- while (!cpu_isset(cpu, &smp_commenced_mask))
++ while (!cpu_isset(cpu, smp_commenced_mask))
+ cpu_relax();
+
+ cpu_set(cpu, cpu_online_map);
+@@ -140,8 +140,11 @@ static struct task_struct *idle_thread(i
+
+ current->thread.request.u.thread.proc = idle_proc;
+ current->thread.request.u.thread.arg = (void *) cpu;
+- new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
+- if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
++ new_task = copy_process(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL,
++ NULL);
++ if(IS_ERR(new_task))
++ panic("copy_process failed in idle_thread, error = %ld",
++ PTR_ERR(new_task));
+
+ cpu_tasks[cpu] = ((struct cpu_task)
+ { .pid = new_task->thread.mode.tt.extern_pid,
+@@ -150,6 +153,7 @@ static struct task_struct *idle_thread(i
+ CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c,
+ sizeof(c)),
+ ({ panic("skas mode doesn't support SMP"); }));
++ wake_up_forked_process(new_task);
+ return(new_task);
+ }
+
+@@ -157,15 +161,16 @@ void smp_prepare_cpus(unsigned int maxcp
+ {
+ struct task_struct *idle;
+ unsigned long waittime;
+- int err, cpu;
++ int err, cpu, me = smp_processor_id();
+
+- cpu_set(0, cpu_online_map);
+- cpu_set(0, smp_callin_map);
++ cpu_clear(me, cpu_online_map);
++ cpu_set(me, cpu_online_map);
++ cpu_set(me, cpu_callin_map);
+
+- err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
++ err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
+ if(err) panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+
+- activate_ipi(cpu_data[0].ipi_pipe[0],
++ activate_ipi(cpu_data[me].ipi_pipe[0],
+ current->thread.mode.tt.extern_pid);
+
+ for(cpu = 1; cpu < ncpus; cpu++){
+@@ -177,10 +182,10 @@ void smp_prepare_cpus(unsigned int maxcp
+ unhash_process(idle);
+
+ waittime = 200000000;
+- while (waittime-- && !cpu_isset(cpu, smp_callin_map))
++ while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
+ cpu_relax();
+
+- if (cpu_isset(cpu, smp_callin_map))
++ if (cpu_isset(cpu, cpu_callin_map))
+ printk("done\n");
+ else printk("failed\n");
+ }
+@@ -270,7 +275,7 @@ int smp_call_function(void (*_func)(void
+ info = _info;
+
+ for (i=0;i<NR_CPUS;i++)
+- if((i != current->thread_info->cpu) &&
++ if((i != current_thread->cpu) &&
+ cpu_isset(i, cpu_online_map))
+ write(cpu_data[i].ipi_pipe[1], "C", 1);
+
+--- linux-2.6.0-test6/arch/um/kernel/syscall_kern.c 2003-06-14 12:18:28.000000000 -0700
++++ 25/arch/um/kernel/syscall_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -35,39 +35,40 @@ long um_mount(char * dev_name, char * di
+
+ long sys_fork(void)
+ {
+- struct task_struct *p;
++ long ret;
+
+ current->thread.forking = 1;
+- p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
++ ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+ current->thread.forking = 0;
+- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
++ return(ret);
+ }
+
+-long sys_clone(unsigned long clone_flags, unsigned long newsp)
++long sys_clone(unsigned long clone_flags, unsigned long newsp,
++ int *parent_tid, int *child_tid)
+ {
+- struct task_struct *p;
++ long ret;
+
+ current->thread.forking = 1;
+- p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
++ ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+ current->thread.forking = 0;
+- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
++ return(ret);
+ }
+
+ long sys_vfork(void)
+ {
+- struct task_struct *p;
++ long ret;
+
+ current->thread.forking = 1;
+- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
++ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
++ NULL);
+ current->thread.forking = 0;
+- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
++ return(ret);
+ }
+
+ /* common code for old and new mmaps */
+-static inline long do_mmap2(
+- unsigned long addr, unsigned long len,
+- unsigned long prot, unsigned long flags,
+- unsigned long fd, unsigned long pgoff)
++long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len,
++ unsigned long prot, unsigned long flags, unsigned long fd,
++ unsigned long pgoff)
+ {
+ int error = -EBADF;
+ struct file * file = NULL;
+@@ -93,7 +94,7 @@ long sys_mmap2(unsigned long addr, unsig
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+ {
+- return do_mmap2(addr, len, prot, flags, fd, pgoff);
++ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
+ }
+
+ /*
+@@ -120,7 +121,8 @@ int old_mmap(unsigned long addr, unsigne
+ if (offset & ~PAGE_MASK)
+ goto out;
+
+- err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
++ err = do_mmap2(current->mm, addr, len, prot, flags, fd,
++ offset >> PAGE_SHIFT);
+ out:
+ return err;
+ }
+@@ -141,37 +143,6 @@ int sys_pipe(unsigned long * fildes)
+ return error;
+ }
+
+-int sys_sigaction(int sig, const struct old_sigaction *act,
+- struct old_sigaction *oact)
+-{
+- struct k_sigaction new_ka, old_ka;
+- int ret;
+-
+- if (act) {
+- old_sigset_t mask;
+- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+- return -EFAULT;
+- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+- __get_user(mask, &act->sa_mask);
+- siginitset(&new_ka.sa.sa_mask, mask);
+- }
+-
+- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+-
+- if (!ret && oact) {
+- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+- return -EFAULT;
+- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+- }
+-
+- return ret;
+-}
+-
+ /*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+@@ -253,7 +224,7 @@ int sys_ipc (uint call, int first, int s
+ return sys_shmctl (first, second,
+ (struct shmid_ds *) ptr);
+ default:
+- return -EINVAL;
++ return -ENOSYS;
+ }
+ }
+
+@@ -302,11 +273,6 @@ int sys_olduname(struct oldold_utsname *
+ return error;
+ }
+
+-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+-{
+- return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
+-}
+-
+ long execute_syscall(void *r)
+ {
+ return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
+--- linux-2.6.0-test6/arch/um/kernel/sys_call_table.c 2003-06-14 12:18:30.000000000 -0700
++++ 25/arch/um/kernel/sys_call_table.c 2003-10-05 00:34:32.000000000 -0700
+@@ -219,15 +219,30 @@ extern syscall_handler_t sys_getdents64;
+ extern syscall_handler_t sys_gettid;
+ extern syscall_handler_t sys_readahead;
+ extern syscall_handler_t sys_tkill;
++extern syscall_handler_t sys_setxattr;
++extern syscall_handler_t sys_lsetxattr;
++extern syscall_handler_t sys_fsetxattr;
++extern syscall_handler_t sys_getxattr;
++extern syscall_handler_t sys_lgetxattr;
++extern syscall_handler_t sys_fgetxattr;
++extern syscall_handler_t sys_listxattr;
++extern syscall_handler_t sys_llistxattr;
++extern syscall_handler_t sys_flistxattr;
++extern syscall_handler_t sys_removexattr;
++extern syscall_handler_t sys_lremovexattr;
++extern syscall_handler_t sys_fremovexattr;
+ extern syscall_handler_t sys_sendfile64;
+ extern syscall_handler_t sys_futex;
+ extern syscall_handler_t sys_sched_setaffinity;
+ extern syscall_handler_t sys_sched_getaffinity;
++extern syscall_handler_t sys_set_thread_area;
++extern syscall_handler_t sys_get_thread_area;
+ extern syscall_handler_t sys_io_setup;
+ extern syscall_handler_t sys_io_destroy;
+ extern syscall_handler_t sys_io_getevents;
+ extern syscall_handler_t sys_io_submit;
+ extern syscall_handler_t sys_io_cancel;
++extern syscall_handler_t sys_fadvise64;
+ extern syscall_handler_t sys_exit_group;
+ extern syscall_handler_t sys_lookup_dcookie;
+ extern syscall_handler_t sys_epoll_create;
+@@ -235,6 +250,20 @@ extern syscall_handler_t sys_epoll_ctl;
+ extern syscall_handler_t sys_epoll_wait;
+ extern syscall_handler_t sys_remap_file_pages;
+ extern syscall_handler_t sys_set_tid_address;
++extern syscall_handler_t sys_timer_create;
++extern syscall_handler_t sys_timer_settime;
++extern syscall_handler_t sys_timer_gettime;
++extern syscall_handler_t sys_timer_getoverrun;
++extern syscall_handler_t sys_timer_delete;
++extern syscall_handler_t sys_clock_settime;
++extern syscall_handler_t sys_clock_gettime;
++extern syscall_handler_t sys_clock_getres;
++extern syscall_handler_t sys_clock_nanosleep;
++extern syscall_handler_t sys_statfs64;
++extern syscall_handler_t sys_fstatfs64;
++extern syscall_handler_t sys_tgkill;
++extern syscall_handler_t sys_utimes;
++extern syscall_handler_t sys_fadvise64_64;
+
+ #ifdef CONFIG_NFSD
+ #define NFSSERVCTL sys_nfsservctl
+@@ -246,7 +275,7 @@ extern syscall_handler_t um_mount;
+ extern syscall_handler_t um_time;
+ extern syscall_handler_t um_stime;
+
+-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
++#define LAST_GENERIC_SYSCALL __NR_fadvise64_64
+
+ #if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
+ #define LAST_SYSCALL LAST_GENERIC_SYSCALL
+@@ -455,32 +484,37 @@ syscall_handler_t *sys_call_table[] = {
+ [ __NR_stat64 ] = sys_stat64,
+ [ __NR_lstat64 ] = sys_lstat64,
+ [ __NR_fstat64 ] = sys_fstat64,
+- [ __NR_fcntl64 ] = sys_fcntl64,
+ [ __NR_getdents64 ] = sys_getdents64,
++ [ __NR_fcntl64 ] = sys_fcntl64,
++ [ 223 ] = sys_ni_syscall,
+ [ __NR_gettid ] = sys_gettid,
+ [ __NR_readahead ] = sys_readahead,
+- [ __NR_setxattr ] = sys_ni_syscall,
+- [ __NR_lsetxattr ] = sys_ni_syscall,
+- [ __NR_fsetxattr ] = sys_ni_syscall,
+- [ __NR_getxattr ] = sys_ni_syscall,
+- [ __NR_lgetxattr ] = sys_ni_syscall,
+- [ __NR_fgetxattr ] = sys_ni_syscall,
+- [ __NR_listxattr ] = sys_ni_syscall,
+- [ __NR_llistxattr ] = sys_ni_syscall,
+- [ __NR_flistxattr ] = sys_ni_syscall,
+- [ __NR_removexattr ] = sys_ni_syscall,
+- [ __NR_lremovexattr ] = sys_ni_syscall,
+- [ __NR_fremovexattr ] = sys_ni_syscall,
++ [ __NR_setxattr ] = sys_setxattr,
++ [ __NR_lsetxattr ] = sys_lsetxattr,
++ [ __NR_fsetxattr ] = sys_fsetxattr,
++ [ __NR_getxattr ] = sys_getxattr,
++ [ __NR_lgetxattr ] = sys_lgetxattr,
++ [ __NR_fgetxattr ] = sys_fgetxattr,
++ [ __NR_listxattr ] = sys_listxattr,
++ [ __NR_llistxattr ] = sys_llistxattr,
++ [ __NR_flistxattr ] = sys_flistxattr,
++ [ __NR_removexattr ] = sys_removexattr,
++ [ __NR_lremovexattr ] = sys_lremovexattr,
++ [ __NR_fremovexattr ] = sys_fremovexattr,
+ [ __NR_tkill ] = sys_tkill,
+ [ __NR_sendfile64 ] = sys_sendfile64,
+ [ __NR_futex ] = sys_futex,
+ [ __NR_sched_setaffinity ] = sys_sched_setaffinity,
+ [ __NR_sched_getaffinity ] = sys_sched_getaffinity,
++ [ __NR_set_thread_area ] = sys_ni_syscall,
++ [ __NR_get_thread_area ] = sys_ni_syscall,
+ [ __NR_io_setup ] = sys_io_setup,
+ [ __NR_io_destroy ] = sys_io_destroy,
+ [ __NR_io_getevents ] = sys_io_getevents,
+ [ __NR_io_submit ] = sys_io_submit,
+ [ __NR_io_cancel ] = sys_io_cancel,
++ [ __NR_fadvise64 ] = sys_fadvise64,
++ [ 251 ] = sys_ni_syscall,
+ [ __NR_exit_group ] = sys_exit_group,
+ [ __NR_lookup_dcookie ] = sys_lookup_dcookie,
+ [ __NR_epoll_create ] = sys_epoll_create,
+@@ -488,6 +522,20 @@ syscall_handler_t *sys_call_table[] = {
+ [ __NR_epoll_wait ] = sys_epoll_wait,
+ [ __NR_remap_file_pages ] = sys_remap_file_pages,
+ [ __NR_set_tid_address ] = sys_set_tid_address,
++ [ __NR_timer_create ] = sys_timer_create,
++ [ __NR_timer_settime ] = sys_timer_settime,
++ [ __NR_timer_gettime ] = sys_timer_gettime,
++ [ __NR_timer_getoverrun ] = sys_timer_getoverrun,
++ [ __NR_timer_delete ] = sys_timer_delete,
++ [ __NR_clock_settime ] = sys_clock_settime,
++ [ __NR_clock_gettime ] = sys_clock_gettime,
++ [ __NR_clock_getres ] = sys_clock_getres,
++ [ __NR_clock_nanosleep ] = sys_clock_nanosleep,
++ [ __NR_statfs64 ] = sys_statfs64,
++ [ __NR_fstatfs64 ] = sys_fstatfs64,
++ [ __NR_tgkill ] = sys_tgkill,
++ [ __NR_utimes ] = sys_utimes,
++ [ __NR_fadvise64_64 ] = sys_fadvise64_64,
+
+ ARCH_SYSCALLS
+ [ LAST_SYSCALL + 1 ... NR_syscalls ] =
+--- linux-2.6.0-test6/arch/um/kernel/sysrq.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/arch/um/kernel/sysrq.c 2003-10-05 00:34:32.000000000 -0700
+@@ -53,6 +53,14 @@ void show_trace_task(struct task_struct
+ show_trace((unsigned long *)esp);
+ }
+
++void show_stack(struct task_struct *task, unsigned long *sp)
++{
++ if(task)
++ show_trace_task(task);
++ else
++ show_trace(sp);
++}
++
+ /*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+--- linux-2.6.0-test6/arch/um/kernel/time.c 2003-06-16 22:32:20.000000000 -0700
++++ 25/arch/um/kernel/time.c 2003-10-05 00:34:32.000000000 -0700
+@@ -15,12 +15,16 @@
+ #include "process.h"
+ #include "signal_user.h"
+ #include "time_user.h"
++#include "kern_constants.h"
+
+ extern struct timeval xtime;
+
++struct timeval local_offset = { 0, 0 };
++
+ void timer(void)
+ {
+ gettimeofday(&xtime, NULL);
++ timeradd(&xtime, &local_offset, &xtime);
+ }
+
+ void set_interval(int timer_type)
+@@ -65,7 +69,7 @@ void switch_timers(int to_real)
+ errno);
+ }
+
+-void idle_timer(void)
++void uml_idle_timer(void)
+ {
+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
+ panic("Couldn't unset SIGVTALRM handler");
+@@ -82,8 +86,6 @@ void time_init(void)
+ set_interval(ITIMER_VIRTUAL);
+ }
+
+-struct timeval local_offset = { 0, 0 };
+-
+ void do_gettimeofday(struct timeval *tv)
+ {
+ unsigned long flags;
+@@ -100,7 +102,7 @@ int do_settimeofday(struct timespec *tv)
+ unsigned long flags;
+ struct timeval tv_in;
+
+- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
++ if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
+ return -EINVAL;
+
+ tv_in.tv_sec = tv->tv_sec;
+@@ -110,6 +112,8 @@ int do_settimeofday(struct timespec *tv)
+ gettimeofday(&now, NULL);
+ timersub(&tv_in, &now, &local_offset);
+ time_unlock(flags);
++
++ return(0);
+ }
+
+ void idle_sleep(int secs)
+--- linux-2.6.0-test6/arch/um/kernel/time_kern.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/um/kernel/time_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -38,7 +38,7 @@ int __attribute__ ((__section__ (".unpro
+
+ void timer_irq(union uml_pt_regs *regs)
+ {
+- int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
++ int cpu = current_thread->cpu, ticks = missed_ticks[cpu];
+
+ if(!timer_irq_inited) return;
+ missed_ticks[cpu] = 0;
+@@ -55,12 +55,13 @@ void boot_timer_handler(int sig)
+ do_timer(®s);
+ }
+
+-void um_timer(int irq, void *dev, struct pt_regs *regs)
++irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
+ {
+ do_timer(regs);
+- write_seqlock(&xtime_lock);
++ write_seqlock_irq(&xtime_lock);
+ timer();
+- write_sequnlock(&xtime_lock);
++ write_sequnlock_irq(&xtime_lock);
++ return(IRQ_HANDLED);
+ }
+
+ long um_time(int * tloc)
+@@ -78,12 +79,12 @@ long um_time(int * tloc)
+ long um_stime(int * tptr)
+ {
+ int value;
+- struct timeval new;
++ struct timespec new;
+
+ if (get_user(value, tptr))
+ return -EFAULT;
+ new.tv_sec = value;
+- new.tv_usec = 0;
++ new.tv_nsec = 0;
+ do_settimeofday(&new);
+ return 0;
+ }
+@@ -122,9 +123,11 @@ void __const_udelay(um_udelay_t usecs)
+ void timer_handler(int sig, union uml_pt_regs *regs)
+ {
+ #ifdef CONFIG_SMP
++ local_irq_disable();
+ update_process_times(user_context(UPT_SP(regs)));
++ local_irq_enable();
+ #endif
+- if(current->thread_info->cpu == 0)
++ if(current_thread->cpu == 0)
+ timer_irq(regs);
+ }
+
+--- linux-2.6.0-test6/arch/um/kernel/trap_kern.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/um/kernel/trap_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -16,6 +16,7 @@
+ #include "asm/tlbflush.h"
+ #include "asm/a.out.h"
+ #include "asm/current.h"
++#include "asm/irq.h"
+ #include "user_util.h"
+ #include "kern_util.h"
+ #include "kern.h"
+@@ -51,7 +52,7 @@ int handle_page_fault(unsigned long addr
+ if(is_write && !(vma->vm_flags & VM_WRITE))
+ goto out;
+ page = address & PAGE_MASK;
+- if(page == (unsigned long) current->thread_info + PAGE_SIZE)
++ if(page == (unsigned long) current_thread + PAGE_SIZE)
+ panic("Kernel stack overflow");
+ pgd = pgd_offset(mm, page);
+ pmd = pmd_offset(pgd, page);
+@@ -180,6 +181,11 @@ void bus_handler(int sig, union uml_pt_r
+ else relay_signal(sig, regs);
+ }
+
++void winch(int sig, union uml_pt_regs *regs)
++{
++ do_IRQ(WINCH_IRQ, regs);
++}
++
+ void trap_init(void)
+ {
+ }
+--- linux-2.6.0-test6/arch/um/kernel/trap_user.c 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/um/kernel/trap_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -82,6 +82,8 @@ struct signal_info sig_info[] = {
+ .is_irq = 0 },
+ [ SIGILL ] { .handler = relay_signal,
+ .is_irq = 0 },
++ [ SIGWINCH ] { .handler = winch,
++ .is_irq = 1 },
+ [ SIGBUS ] { .handler = bus_handler,
+ .is_irq = 0 },
+ [ SIGSEGV] { .handler = segv_handler,
+--- linux-2.6.0-test6/arch/um/kernel/tt/exec_kern.c 2003-06-14 12:17:59.000000000 -0700
++++ 25/arch/um/kernel/tt/exec_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -47,17 +47,17 @@ void flush_thread_tt(void)
+ do_exit(SIGKILL);
+ }
+
+- if(current->thread_info->cpu == 0)
++ if(current_thread->cpu == 0)
+ forward_interrupts(new_pid);
+ current->thread.request.op = OP_EXEC;
+ current->thread.request.u.exec.pid = new_pid;
+- unprotect_stack((unsigned long) current->thread_info);
++ unprotect_stack((unsigned long) current_thread);
+ os_usr1_process(os_getpid());
+
+ enable_timer();
+ free_page(stack);
+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
+- task_protections((unsigned long) current->thread_info);
++ task_protections((unsigned long) current_thread);
+ force_flush_all();
+ unblock_signals();
+ }
+--- linux-2.6.0-test6/arch/um/kernel/tt/include/uaccess.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/arch/um/kernel/tt/include/uaccess.h 2003-10-05 00:34:32.000000000 -0700
+@@ -46,18 +46,20 @@ extern int __do_copy_from_user(void *to,
+
+ static inline int copy_from_user_tt(void *to, const void *from, int n)
+ {
+- return(access_ok_tt(VERIFY_READ, from, n) ?
+- __do_copy_from_user(to, from, n,
+- ¤t->thread.fault_addr,
+- ¤t->thread.fault_catcher) : n);
++ if(!access_ok_tt(VERIFY_READ, from, n))
++ return(n);
++
++ return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr,
++ ¤t->thread.fault_catcher));
+ }
+
+ static inline int copy_to_user_tt(void *to, const void *from, int n)
+ {
+- return(access_ok_tt(VERIFY_WRITE, to, n) ?
+- __do_copy_to_user(to, from, n,
+- ¤t->thread.fault_addr,
+- ¤t->thread.fault_catcher) : n);
++ if(!access_ok_tt(VERIFY_WRITE, to, n))
++ return(n);
++
++ return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr,
++ ¤t->thread.fault_catcher));
+ }
+
+ extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
+@@ -67,7 +69,9 @@ static inline int strncpy_from_user_tt(c
+ {
+ int n;
+
+- if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
++ if(!access_ok_tt(VERIFY_READ, src, 1))
++ return(-EFAULT);
++
+ n = __do_strncpy_from_user(dst, src, count,
+ ¤t->thread.fault_addr,
+ ¤t->thread.fault_catcher);
+@@ -87,10 +91,11 @@ static inline int __clear_user_tt(void *
+
+ static inline int clear_user_tt(void *mem, int len)
+ {
+- return(access_ok_tt(VERIFY_WRITE, mem, len) ?
+- __do_clear_user(mem, len,
+- ¤t->thread.fault_addr,
+- ¤t->thread.fault_catcher) : len);
++ if(!access_ok_tt(VERIFY_WRITE, mem, len))
++ return(len);
++
++ return(__do_clear_user(mem, len, ¤t->thread.fault_addr,
++ ¤t->thread.fault_catcher));
+ }
+
+ extern int __do_strnlen_user(const char *str, unsigned long n,
+--- linux-2.6.0-test6/arch/um/kernel/tt/process_kern.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/tt/process_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -104,7 +104,10 @@ void *switch_to_tt(void *prev, void *nex
+
+ void release_thread_tt(struct task_struct *task)
+ {
+- os_kill_process(task->thread.mode.tt.extern_pid, 0);
++ int pid = task->thread.mode.tt.extern_pid;
++
++ if(os_getpid() != pid)
++ os_kill_process(pid, 0);
+ }
+
+ void exit_thread_tt(void)
+@@ -125,27 +128,27 @@ static void new_thread_handler(int sig)
+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
+
+- block_signals();
++ force_flush_all();
++ if(current->thread.prev_sched != NULL)
++ schedule_tail(current->thread.prev_sched);
++ current->thread.prev_sched = NULL;
++
+ init_new_thread_signals(1);
+-#ifdef CONFIG_SMP
+- schedule_tail(current->thread.prev_sched);
+-#endif
+ enable_timer();
+ free_page(current->thread.temp_stack);
+ set_cmdline("(kernel thread)");
+- force_flush_all();
+
+- current->thread.prev_sched = NULL;
+ change_sig(SIGUSR1, 1);
+ change_sig(SIGVTALRM, 1);
+ change_sig(SIGPROF, 1);
+- unblock_signals();
++ local_irq_enable();
+ if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf))
+ do_exit(0);
+ }
+
+ static int new_thread_proc(void *stack)
+ {
++ local_irq_disable();
+ init_new_thread_stack(stack, new_thread_handler);
+ os_usr1_process(os_getpid());
+ return(0);
+@@ -165,35 +168,32 @@ void finish_fork_handler(int sig)
+ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
+
+-#ifdef CONFIG_SMP
+- schedule_tail(NULL);
+-#endif
++ force_flush_all();
++ if(current->thread.prev_sched != NULL)
++ schedule_tail(current->thread.prev_sched);
++ current->thread.prev_sched = NULL;
++
+ enable_timer();
+ change_sig(SIGVTALRM, 1);
+ local_irq_enable();
+- force_flush_all();
+ if(current->mm != current->parent->mm)
+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
+ 1, 0, 1);
+- task_protections((unsigned long) current->thread_info);
+-
+- current->thread.prev_sched = NULL;
++ task_protections((unsigned long) current_thread);
+
+ free_page(current->thread.temp_stack);
++ local_irq_disable();
+ change_sig(SIGUSR1, 0);
+ set_user_mode(current);
+ }
+
+-static int sigusr1 = SIGUSR1;
+-
+ int fork_tramp(void *stack)
+ {
+- int sig = sigusr1;
+-
+ local_irq_disable();
++ arch_init_thread();
+ init_new_thread_stack(stack, finish_fork_handler);
+
+- kill(os_getpid(), sig);
++ os_usr1_process(os_getpid());
+ return(0);
+ }
+
+@@ -377,8 +377,8 @@ static void mprotect_kernel_mem(int w)
+
+ pages = (1 << CONFIG_KERNEL_STACK_ORDER);
+
+- start = (unsigned long) current->thread_info + PAGE_SIZE;
+- end = (unsigned long) current + PAGE_SIZE * pages;
++ start = (unsigned long) current_thread + PAGE_SIZE;
++ end = (unsigned long) current_thread + PAGE_SIZE * pages;
+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
+ protect_memory(end, high_physmem - end, 1, w, 1, 1);
+
+--- linux-2.6.0-test6/arch/um/kernel/tt/ptproxy/proxy.c 2003-06-14 12:18:23.000000000 -0700
++++ 25/arch/um/kernel/tt/ptproxy/proxy.c 2003-10-05 00:34:32.000000000 -0700
+@@ -293,10 +293,10 @@ void fake_child_exit(void)
+ }
+
+ char gdb_init_string[] =
+-"att 1
+-b panic
+-b stop
+-handle SIGWINCH nostop noprint pass
++"att 1 \n\
++b panic \n\
++b stop \n\
++handle SIGWINCH nostop noprint pass \n\
+ ";
+
+ int start_debugger(char *prog, int startup, int stop, int *fd_out)
+--- linux-2.6.0-test6/arch/um/kernel/tt/tracer.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/arch/um/kernel/tt/tracer.c 2003-10-05 00:34:32.000000000 -0700
+@@ -39,7 +39,7 @@ int is_tracer_winch(int pid, int fd, voi
+ return(0);
+
+ register_winch_irq(tracer_winch[0], fd, -1, data);
+- return(0);
++ return(1);
+ }
+
+ static void tracer_winch_handler(int sig)
+@@ -401,7 +401,7 @@ static int __init uml_debug_setup(char *
+
+ if(!strcmp(line, "go")) debug_stop = 0;
+ else if(!strcmp(line, "parent")) debug_parent = 1;
+- else printk("Unknown debug option : '%s'\n", line);
++ else printf("Unknown debug option : '%s'\n", line);
+
+ line = next;
+ }
+--- linux-2.6.0-test6/arch/um/kernel/tt/uaccess_user.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/arch/um/kernel/tt/uaccess_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -8,15 +8,20 @@
+ #include <string.h>
+ #include "user_util.h"
+ #include "uml_uaccess.h"
++#include "task.h"
++#include "kern_util.h"
+
+ int __do_copy_from_user(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher)
+ {
++ struct tt_regs save = TASK_REGS(get_current())->tt;
+ unsigned long fault;
+ int faulted;
+
+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
+ __do_copy, &faulted);
++ TASK_REGS(get_current())->tt = save;
++
+ if(!faulted) return(0);
+ else return(n - (fault - (unsigned long) from));
+ }
+@@ -29,11 +34,14 @@ static void __do_strncpy(void *dst, cons
+ int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
+ void **fault_addr, void **fault_catcher)
+ {
++ struct tt_regs save = TASK_REGS(get_current())->tt;
+ unsigned long fault;
+ int faulted;
+
+ fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
+ __do_strncpy, &faulted);
++ TASK_REGS(get_current())->tt = save;
++
+ if(!faulted) return(strlen(dst));
+ else return(-1);
+ }
+@@ -46,11 +54,14 @@ static void __do_clear(void *to, const v
+ int __do_clear_user(void *mem, unsigned long len,
+ void **fault_addr, void **fault_catcher)
+ {
++ struct tt_regs save = TASK_REGS(get_current())->tt;
+ unsigned long fault;
+ int faulted;
+
+ fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
+ __do_clear, &faulted);
++ TASK_REGS(get_current())->tt = save;
++
+ if(!faulted) return(0);
+ else return(len - (fault - (unsigned long) mem));
+ }
+@@ -58,6 +69,7 @@ int __do_clear_user(void *mem, unsigned
+ int __do_strnlen_user(const char *str, unsigned long n,
+ void **fault_addr, void **fault_catcher)
+ {
++ struct tt_regs save = TASK_REGS(get_current())->tt;
+ int ret;
+ unsigned long *faddrp = (unsigned long *)fault_addr;
+ jmp_buf jbuf;
+@@ -71,6 +83,8 @@ int __do_strnlen_user(const char *str, u
+ }
+ *fault_addr = NULL;
+ *fault_catcher = NULL;
++
++ TASK_REGS(get_current())->tt = save;
+ return ret;
+ }
+
+--- linux-2.6.0-test6/arch/um/kernel/um_arch.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/um/kernel/um_arch.c 2003-10-05 00:34:32.000000000 -0700
+@@ -38,13 +38,18 @@
+ #include "mode_kern.h"
+ #include "mode.h"
+
+-#define DEFAULT_COMMAND_LINE "root=6200"
++#define DEFAULT_COMMAND_LINE "root=ubd0"
+
+ struct cpuinfo_um boot_cpu_data = {
+ .loops_per_jiffy = 0,
+ .ipi_pipe = { -1, -1 }
+ };
+
++/* Placeholder to make UML link until the vsyscall stuff is actually
++ * implemented
++ */
++void *__kernel_vsyscall;
++
+ unsigned long thread_saved_pc(struct task_struct *task)
+ {
+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
+@@ -61,10 +66,14 @@ static int show_cpuinfo(struct seq_file
+ return 0;
+ #endif
+
+- seq_printf(m, "bogomips\t: %lu.%02lu\n",
++ seq_printf(m, "processor\t: %d\n", index);
++ seq_printf(m, "vendor_id\t: User Mode Linux\n");
++ seq_printf(m, "model name\t: UML\n");
++ seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
++ seq_printf(m, "host\t\t: %s\n", host_info);
++ seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
+ loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100);
+- seq_printf(m, "host\t\t: %s\n", host_info);
+
+ return(0);
+ }
+@@ -134,12 +143,12 @@ void set_cmdline(char *cmd)
+ if(umid != NULL){
+ snprintf(argv1_begin,
+ (argv1_end - argv1_begin) * sizeof(*ptr),
+- "(%s)", umid);
++ "(%s) ", umid);
+ ptr = &argv1_begin[strlen(argv1_begin)];
+ }
+ else ptr = argv1_begin;
+
+- snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
++ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
+ memset(argv1_begin + strlen(argv1_begin), '\0',
+ argv1_end - argv1_begin - strlen(argv1_begin));
+ #endif
+@@ -179,7 +188,7 @@ __uml_setup("root=", uml_root_setup,
+ static int __init uml_ncpus_setup(char *line, int *add)
+ {
+ if (!sscanf(line, "%d", &ncpus)) {
+- printk("Couldn't parse [%s]\n", line);
++ printf("Couldn't parse [%s]\n", line);
+ return -1;
+ }
+
+@@ -210,7 +219,7 @@ static int __init mode_tt_setup(char *li
+
+ static int __init mode_tt_setup(char *line, int *add)
+ {
+- printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
++ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+ return(0);
+ }
+
+@@ -221,7 +230,7 @@ static int __init mode_tt_setup(char *li
+
+ static int __init mode_tt_setup(char *line, int *add)
+ {
+- printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
++ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+ return(0);
+ }
+
+@@ -369,6 +378,7 @@ int linux_main(int argc, char **argv)
+ 2 * PAGE_SIZE;
+
+ task_protections((unsigned long) &init_thread_info);
++ os_flush_stdout();
+
+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
+ }
+--- linux-2.6.0-test6/arch/um/kernel/umid.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/arch/um/kernel/umid.c 2003-10-05 00:34:32.000000000 -0700
+@@ -33,18 +33,19 @@ static char *uml_dir = UML_DIR;
+ static int umid_is_random = 1;
+ static int umid_inited = 0;
+
+-static int make_umid(void);
++static int make_umid(int (*printer)(const char *fmt, ...));
+
+-static int __init set_umid(char *name, int is_random)
++static int __init set_umid(char *name, int is_random,
++ int (*printer)(const char *fmt, ...))
+ {
+ if(umid_inited){
+- printk("Unique machine name can't be set twice\n");
++ (*printer)("Unique machine name can't be set twice\n");
+ return(-1);
+ }
+
+ if(strlen(name) > UMID_LEN - 1)
+- printk("Unique machine name is being truncated to %s "
+- "characters\n", UMID_LEN);
++ (*printer)("Unique machine name is being truncated to %s "
++ "characters\n", UMID_LEN);
+ strlcpy(umid, name, sizeof(umid));
+
+ umid_is_random = is_random;
+@@ -54,7 +55,7 @@ static int __init set_umid(char *name, i
+
+ static int __init set_umid_arg(char *name, int *add)
+ {
+- return(set_umid(name, 0));
++ return(set_umid(name, 0, printf));
+ }
+
+ __uml_setup("umid=", set_umid_arg,
+@@ -67,7 +68,7 @@ int __init umid_file_name(char *name, ch
+ {
+ int n;
+
+- if(!umid_inited && make_umid()) return(-1);
++ if(!umid_inited && make_umid(printk)) return(-1);
+
+ n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
+ if(n > len){
+@@ -92,14 +93,14 @@ static int __init create_pid_file(void)
+ fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
+ 0644);
+ if(fd < 0){
+- printk("Open of machine pid file \"%s\" failed - "
++ printf("Open of machine pid file \"%s\" failed - "
+ "errno = %d\n", file, -fd);
+ return 0;
+ }
+
+ sprintf(pid, "%d\n", os_getpid());
+ if(write(fd, pid, strlen(pid)) != strlen(pid))
+- printk("Write of pid file failed - errno = %d\n", errno);
++ printf("Write of pid file failed - errno = %d\n", errno);
+ close(fd);
+ return 0;
+ }
+@@ -197,7 +198,7 @@ static int __init set_uml_dir(char *name
+ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
+ uml_dir = malloc(strlen(name) + 1);
+ if(uml_dir == NULL){
+- printk("Failed to malloc uml_dir - error = %d\n",
++ printf("Failed to malloc uml_dir - error = %d\n",
+ errno);
+ uml_dir = name;
+ return(0);
+@@ -217,7 +218,7 @@ static int __init make_uml_dir(void)
+ char *home = getenv("HOME");
+
+ if(home == NULL){
+- printk("make_uml_dir : no value in environment for "
++ printf("make_uml_dir : no value in environment for "
+ "$HOME\n");
+ exit(1);
+ }
+@@ -239,25 +240,25 @@ static int __init make_uml_dir(void)
+ strcpy(uml_dir, dir);
+
+ if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
+- printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
++ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+ return(-1);
+ }
+ return 0;
+ }
+
+-static int __init make_umid(void)
++static int __init make_umid(int (*printer)(const char *fmt, ...))
+ {
+ int fd, err;
+ char tmp[strlen(uml_dir) + UMID_LEN + 1];
+
+ strlcpy(tmp, uml_dir, sizeof(tmp));
+
+- if(*umid == 0){
++ if(!umid_inited){
+ strcat(tmp, "XXXXXX");
+ fd = mkstemp(tmp);
+ if(fd < 0){
+- printk("make_umid - mkstemp failed, errno = %d\n",
+- errno);
++ (*printer)("make_umid - mkstemp failed, errno = %d\n",
++ errno);
+ return(1);
+ }
+
+@@ -267,7 +268,7 @@ static int __init make_umid(void)
+ * for directories.
+ */
+ unlink(tmp);
+- set_umid(&tmp[strlen(uml_dir)], 1);
++ set_umid(&tmp[strlen(uml_dir)], 1, printer);
+ }
+
+ sprintf(tmp, "%s%s", uml_dir, umid);
+@@ -275,14 +276,14 @@ static int __init make_umid(void)
+ if((err = mkdir(tmp, 0777)) < 0){
+ if(errno == EEXIST){
+ if(not_dead_yet(tmp)){
+- printk("umid '%s' is in use\n", umid);
++ (*printer)("umid '%s' is in use\n", umid);
+ return(-1);
+ }
+ err = mkdir(tmp, 0777);
+ }
+ }
+ if(err < 0){
+- printk("Failed to create %s - errno = %d\n", umid, errno);
++ (*printer)("Failed to create %s - errno = %d\n", umid, errno);
+ return(-1);
+ }
+
+@@ -295,7 +296,13 @@ __uml_setup("uml_dir=", set_uml_dir,
+ );
+
+ __uml_postsetup(make_uml_dir);
+-__uml_postsetup(make_umid);
++
++static int __init make_umid_setup(void)
++{
++ return(make_umid(printf));
++}
++
++__uml_postsetup(make_umid_setup);
+ __uml_postsetup(create_pid_file);
+
+ /*
+--- linux-2.6.0-test6/arch/um/kernel/user_util.c 2003-06-14 12:17:59.000000000 -0700
++++ 25/arch/um/kernel/user_util.c 2003-10-05 00:34:32.000000000 -0700
+@@ -119,17 +119,6 @@ int wait_for_stop(int pid, int sig, int
+ }
+ }
+
+-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
+-{
+- int pid;
+-
+- pid = clone(fn, sp, flags, arg);
+- if(pid < 0) return(-1);
+- wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
+- ptrace(PTRACE_CONT, pid, 0, 0);
+- return(pid);
+-}
+-
+ int raw(int fd, int complain)
+ {
+ struct termios tt;
+--- linux-2.6.0-test6/arch/um/Makefile 2003-08-08 22:55:11.000000000 -0700
++++ 25/arch/um/Makefile 2003-10-05 00:34:32.000000000 -0700
+@@ -24,15 +24,17 @@ core-y += $(ARCH_DIR)/kernel/ \
+ # Have to precede the include because the included Makefiles reference them.
+ SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
+ include/asm-um/sigcontext.h include/asm-um/processor.h \
+- include/asm-um/ptrace.h include/asm-um/arch-signal.h
++ include/asm-um/ptrace.h include/asm-um/arch-signal.h \
++ include/asm-um/module.h
+
+ ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
+
+ GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
+
+-include $(ARCH_DIR)/Makefile-$(SUBARCH)
+-include $(ARCH_DIR)/Makefile-os-$(OS)
++.PHONY: sys_prepare
++sys_prepare:
++ @:
+
+ MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
+ MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
+@@ -41,6 +43,9 @@ ifneq ($(MAKEFILE-y),)
+ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
+ endif
+
++include $(ARCH_DIR)/Makefile-$(SUBARCH)
++include $(ARCH_DIR)/Makefile-os-$(OS)
++
+ EXTRAVERSION := $(EXTRAVERSION)-1um
+
+ ARCH_INCLUDE = -I$(ARCH_DIR)/include
+@@ -52,14 +57,14 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include
+
+ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
+- $(MODE_INCLUDE)
++ -Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
+
+ LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
+
+ SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
+
+ ifeq ($(CONFIG_MODE_SKAS), y)
+-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
++$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
+ endif
+
+ include/linux/version.h: arch/$(ARCH)/Makefile
+@@ -98,17 +103,17 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_
+ CONFIG_KERNEL_STACK_ORDER ?= 2
+ STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
+
+-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \
++AFLAGS_vmlinux.lds.o = $(shell echo -U$(SUBARCH) \
+ -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
+ -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
+- -DKERNEL_STACK_SIZE=$(STACK_SIZE)
++ -DKERNEL_STACK_SIZE=$(STACK_SIZE))
+
+-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
++export AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
+
+ LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
+
+-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
+- $(call if_changed_dep,as_s_S)
++#$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
++# $(call if_changed_dep,as_s_S)
+
+ linux: vmlinux $(LD_SCRIPT-y)
+ $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
+@@ -116,6 +121,7 @@ linux: vmlinux $(LD_SCRIPT-y)
+
+ USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
+ USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
++USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
+ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
+ $(MODE_INCLUDE)
+
+@@ -123,9 +129,10 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,
+ USER_CFLAGS += -D_GNU_SOURCE
+
+ CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \
+- $(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
++ $(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
++ $(GEN_HEADERS)
+
+-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
++$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c sys_prepare
+ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+
+ archmrproper:
+@@ -161,19 +168,23 @@ $(ARCH_DIR)/include/sysdep:
+ $(ARCH_DIR)/os:
+ cd $(ARCH_DIR) && ln -sf os-$(OS) os
+
+-$(ARCH_DIR)/include/uml-config.h :
++$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
+ sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+
++filechk_$(ARCH_DIR)/include/task.h := $(ARCH_DIR)/util/mk_task
++
+ $(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
+- $< > $@
++ $(call filechk,$@)
++
++filechk_$(ARCH_DIR)/include/kern_constants.h := $(ARCH_DIR)/util/mk_constants
+
+ $(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
+- $< > $@
++ $(call filechk,$@)
+
+-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
+- $(ARCH_DIR)/util FORCE ;
++$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
++ sys_prepare FORCE ;
+
+ $(ARCH_DIR)/util: FORCE
+- @$(call descend,$@,)
++ $(MAKE) -f scripts/Makefile.build obj=$@
+
+-export SUBARCH USER_CFLAGS OS
++export SUBARCH USER_CFLAGS OS
+--- linux-2.6.0-test6/arch/um/Makefile-i386 2003-06-14 12:18:29.000000000 -0700
++++ 25/arch/um/Makefile-i386 2003-10-05 00:34:32.000000000 -0700
+@@ -16,22 +16,28 @@ SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/uti
+
+ SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
+
++sys_prepare: $(SYS_DIR)/sc.h
++
+ prepare: $(SYS_HEADERS)
+
++filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
++
+ $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
+- $< > $@
++ $(call filechk,$@)
++
++filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread
+
+ $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
+- $< > $@
++ $(call filechk,$@)
+
+-$(SYS_UTIL_DIR)/mk_sc: FORCE ;
+- @$(call descend,$(SYS_UTIL_DIR),$@)
++$(SYS_UTIL_DIR)/mk_sc: scripts/fixdep include/config/MARKER FORCE ;
++ +@$(call descend,$(SYS_UTIL_DIR),$@)
+
+-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ;
+- @$(call descend,$(SYS_UTIL_DIR),$@)
++$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ;
++ +@$(call descend,$(SYS_UTIL_DIR),$@)
+
+ $(SYS_UTIL_DIR): include/asm FORCE
+- @$(call descend,$@,)
++ +@$(call descend,$@,)
+
+ sysclean :
+ rm -f $(SYS_HEADERS)
+--- linux-2.6.0-test6/arch/um/Makefile-skas 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/um/Makefile-skas 2003-10-05 00:34:32.000000000 -0700
+@@ -14,7 +14,7 @@ MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/
+ LINK_SKAS = -Wl,-rpath,/lib
+ LD_SCRIPT_SKAS = dyn.lds.s
+
+-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
++GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
+
+-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
+- $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
++$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
++ $(call descend,$(ARCH_DIR)/kernel/skas,$@)
+--- linux-2.6.0-test6/arch/um/os-Linux/drivers/tuntap_user.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/um/os-Linux/drivers/tuntap_user.c 2003-10-05 00:34:32.000000000 -0700
+@@ -142,7 +142,7 @@ static int tuntap_open(void *data)
+ return(-errno);
+ }
+ memset(&ifr, 0, sizeof(ifr));
+- ifr.ifr_flags = IFF_TAP;
++ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
+ if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
+ printk("TUNSETIFF failed, errno = %d", errno);
+--- linux-2.6.0-test6/arch/um/os-Linux/file.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/arch/um/os-Linux/file.c 2003-10-05 00:34:32.000000000 -0700
+@@ -315,7 +315,7 @@ int os_rcv_fd(int fd, int *helper_pid_ou
+ return(new);
+ }
+
+-int create_unix_socket(char *file, int len)
++int create_unix_socket(char *file, int len, int close_on_exec)
+ {
+ struct sockaddr_un addr;
+ int sock, err;
+@@ -327,6 +327,10 @@ int create_unix_socket(char *file, int l
+ return(-errno);
+ }
+
++ if(close_on_exec && fcntl(sock, F_SETFD, 1) < 0)
++ printk("create_unix_socket : Setting FD_CLOEXEC failed, "
++ "errno = %d", errno);
++
+ addr.sun_family = AF_UNIX;
+
+ /* XXX Be more careful about overflow */
+@@ -342,6 +346,37 @@ int create_unix_socket(char *file, int l
+ return(sock);
+ }
+
++void os_flush_stdout(void)
++{
++ fflush(stdout);
++}
++
++int os_lock_file(int fd, int excl)
++{
++ int type = excl ? F_WRLCK : F_RDLCK;
++ struct flock lock = ((struct flock) { .l_type = type,
++ .l_whence = SEEK_SET,
++ .l_start = 0,
++ .l_len = 0 } );
++ int err, save;
++
++ err = fcntl(fd, F_SETLK, &lock);
++ if(!err)
++ goto out;
++
++ save = -errno;
++ err = fcntl(fd, F_GETLK, &lock);
++ if(err){
++ err = -errno;
++ goto out;
++ }
++
++ printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
++ err = save;
++ out:
++ return(err);
++}
++
+ /*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+--- linux-2.6.0-test6/arch/um/sys-i386/bugs.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/arch/um/sys-i386/bugs.c 2003-10-05 00:34:32.000000000 -0700
+@@ -8,6 +8,7 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/signal.h>
++#include <asm/ldt.h>
+ #include "kern_util.h"
+ #include "user.h"
+ #include "sysdep/ptrace.h"
+@@ -16,8 +17,8 @@
+ #define MAXTOKEN 64
+
+ /* Set during early boot */
+-int cpu_has_cmov = 1;
+-int cpu_has_xmm = 0;
++int host_has_cmov = 1;
++int host_has_xmm = 0;
+
+ static char token(int fd, char *buf, int len, char stop)
+ {
+@@ -104,6 +105,25 @@ static int check_cpu_feature(char *featu
+ return(1);
+ }
+
++static void disable_lcall(void)
++{
++ struct modify_ldt_ldt_s ldt;
++ int err;
++
++ bzero(&ldt, sizeof(ldt));
++ ldt.entry_number = 7;
++ ldt.base_addr = 0;
++ ldt.limit = 0;
++ err = modify_ldt(1, &ldt, sizeof(ldt));
++ if(err)
++ printk("Failed to disable lcall7 - errno = %d\n", errno);
++}
++
++void arch_init_thread(void)
++{
++ disable_lcall();
++}
++
+ void arch_check_bugs(void)
+ {
+ int have_it;
+@@ -113,8 +133,8 @@ void arch_check_bugs(void)
+ "checks\n");
+ return;
+ }
+- if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
+- if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
++ if(check_cpu_feature("cmov", &have_it)) host_has_cmov = have_it;
++ if(check_cpu_feature("xmm", &have_it)) host_has_xmm = have_it;
+ }
+
+ int arch_handle_signal(int sig, union uml_pt_regs *regs)
+@@ -130,18 +150,18 @@ int arch_handle_signal(int sig, union um
+ if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
+ return(0);
+
+- if(cpu_has_cmov == 0)
++ if(host_has_cmov == 0)
+ panic("SIGILL caused by cmov, which this processor doesn't "
+ "implement, boot a filesystem compiled for older "
+ "processors");
+- else if(cpu_has_cmov == 1)
++ else if(host_has_cmov == 1)
+ panic("SIGILL caused by cmov, which this processor claims to "
+ "implement");
+- else if(cpu_has_cmov == -1)
++ else if(host_has_cmov == -1)
+ panic("SIGILL caused by cmov, couldn't tell if this processor "
+ "implements it, boot a filesystem compiled for older "
+ "processors");
+- else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
++ else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
+ return(0);
+ }
+
+--- linux-2.6.0-test6/arch/um/sys-i386/Makefile 2003-06-14 12:17:59.000000000 -0700
++++ 25/arch/um/sys-i386/Makefile 2003-10-05 00:34:32.000000000 -0700
+@@ -1,7 +1,8 @@
+-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
+- ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
++obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o ptrace.o \
++ ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+
+ obj-$(CONFIG_HIGHMEM) += highmem.o
++obj-$(CONFIG_MODULES) += module.o
+
+ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
+ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+@@ -9,6 +10,8 @@ USER_OBJS := $(foreach file,$(USER_OBJS)
+ SYMLINKS = semaphore.c highmem.c module.c
+ SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
+
++clean-files := $(SYMLINKS)
++
+ semaphore.c-dir = kernel
+ highmem.c-dir = mm
+ module.c-dir = kernel
+@@ -24,8 +27,7 @@ $(USER_OBJS) : %.o: %.c
+ $(SYMLINKS):
+ $(call make_link,$@)
+
+-clean:
+- $(MAKE) -C util clean
++subdir- := util
+
+ fastdep:
+
+--- linux-2.6.0-test6/arch/um/uml.lds.S 2003-06-14 12:18:09.000000000 -0700
++++ 25/arch/um/uml.lds.S 2003-10-05 00:34:32.000000000 -0700
+@@ -26,7 +26,11 @@ SECTIONS
+ . = ALIGN(4096); /* Init code and data */
+ _stext = .;
+ __init_begin = .;
+- .text.init : { *(.text.init) }
++ .init.text : {
++ _sinittext = .;
++ *(.init.text)
++ _einittext = .;
++ }
+ . = ALIGN(4096);
+ .text :
+ {
+@@ -38,7 +42,7 @@ SECTIONS
+
+ #include "asm/common.lds.S"
+
+- .data.init : { *(.data.init) }
++ init.data : { *(init.data) }
+ .data :
+ {
+ . = ALIGN(KERNEL_STACK_SIZE); /* init_task */
+--- linux-2.6.0-test6/arch/um/util/mk_constants_kern.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/arch/um/util/mk_constants_kern.c 2003-10-05 00:34:32.000000000 -0700
+@@ -1,5 +1,6 @@
+ #include "linux/kernel.h"
+ #include "linux/stringify.h"
++#include "linux/time.h"
+ #include "asm/page.h"
+
+ extern void print_head(void);
+@@ -11,6 +12,7 @@ int main(int argc, char **argv)
+ {
+ print_head();
+ print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
++
+ print_constant_str("UM_KERN_EMERG", KERN_EMERG);
+ print_constant_str("UM_KERN_ALERT", KERN_ALERT);
+ print_constant_str("UM_KERN_CRIT", KERN_CRIT);
+@@ -19,6 +21,8 @@ int main(int argc, char **argv)
+ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
+ print_constant_str("UM_KERN_INFO", KERN_INFO);
+ print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
++
++ print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
+ print_tail();
+ return(0);
+ }
+--- linux-2.6.0-test6/arch/x86_64/boot/compressed/head.S 2003-06-26 22:07:24.000000000 -0700
++++ 25/arch/x86_64/boot/compressed/head.S 2003-10-05 00:33:43.000000000 -0700
+@@ -26,6 +26,7 @@
+ .code32
+ .text
+
++#define IN_BOOTLOADER
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+
+--- linux-2.6.0-test6/arch/x86_64/boot/compressed/misc.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/x86_64/boot/compressed/misc.c 2003-10-05 00:33:43.000000000 -0700
+@@ -9,6 +9,7 @@
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ */
+
++#define IN_BOOTLOADER
+ #include "miscsetup.h"
+ #include <asm/io.h>
+
+--- linux-2.6.0-test6/arch/x86_64/ia32/ia32_binfmt.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/arch/x86_64/ia32/ia32_binfmt.c 2003-10-05 00:33:23.000000000 -0700
+@@ -82,9 +82,12 @@ do { \
+ int i; \
+ Elf32_Off ofs = 0; \
+ for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
+- struct elf_phdr phdr = vsyscall_phdrs[i]; \
++ struct elf32_phdr phdr = vsyscall_phdrs[i]; \
+ if (phdr.p_type == PT_LOAD) { \
++ BUG_ON(ofs != 0); \
+ ofs = phdr.p_offset = offset; \
++ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
++ phdr.p_filesz = phdr.p_memsz; \
+ offset += phdr.p_filesz; \
+ } \
+ else \
+@@ -99,10 +102,10 @@ do { \
+ (const struct elf32_phdr *) (VSYSCALL32_BASE \
+ + VSYSCALL32_EHDR->e_phoff); \
+ int i; \
+- for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \
++ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
+ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+ DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \
+- vsyscall_phdrs[i].p_filesz); \
++ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ } \
+ } while (0)
+
+--- linux-2.6.0-test6/arch/x86_64/ia32/ia32_ioctl.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/arch/x86_64/ia32/ia32_ioctl.c 2003-10-05 00:34:44.000000000 -0700
+@@ -38,87 +38,6 @@ static int tiocgdev(unsigned fd, unsigne
+ return put_user(new_encode_dev(tty_devnum(real_tty)), ptr);
+ }
+
+-
+-struct raw32_config_request
+-{
+- compat_int_t raw_minor;
+- __u64 block_major;
+- __u64 block_minor;
+-} __attribute__((packed));
+-
+-static int raw_ioctl(unsigned fd, unsigned cmd, void *ptr)
+-{
+- int ret;
+- switch (cmd) {
+- case RAW_SETBIND:
+- case RAW_GETBIND: {
+- struct raw_config_request req;
+- struct raw32_config_request *user_req = ptr;
+- mm_segment_t oldfs = get_fs();
+-
+- if (get_user(req.raw_minor, &user_req->raw_minor) ||
+- get_user(req.block_major, &user_req->block_major) ||
+- get_user(req.block_minor, &user_req->block_minor))
+- return -EFAULT;
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd,cmd,(unsigned long)&req);
+- set_fs(oldfs);
+- break;
+- }
+- default:
+- ret = sys_ioctl(fd,cmd,(unsigned long)ptr);
+- break;
+- }
+- return ret;
+-}
+-
+-
+-#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int)
+-
+-static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr)
+-{
+- if (cmd == REISERFS_IOC_UNPACK32)
+- cmd = REISERFS_IOC_UNPACK;
+- return sys_ioctl(fd,cmd,ptr);
+-}
+-
+-struct dirent32 {
+- compat_int_t d_ino;
+- compat_off_t d_off;
+- unsigned short d_reclen;
+- char d_name[256]; /* We must not include limits.h! */
+-};
+-
+-#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct dirent32 [2])
+-#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct dirent32 [2])
+-
+-static int put_dirent32(struct dirent *src, struct dirent32 *dst)
+-{
+- int ret;
+- ret = put_user(src->d_ino, &dst->d_ino);
+- ret |= __put_user(src->d_off, &dst->d_off);
+- ret |= __put_user(src->d_reclen, &dst->d_reclen);
+- if (__copy_to_user(&dst->d_name, src->d_name, src->d_reclen))
+- ret |= -EFAULT;
+- return ret;
+-}
+-
+-static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr)
+-{
+- int ret;
+- mm_segment_t oldfs = get_fs();
+- struct dirent d[2];
+-
+- set_fs(KERNEL_DS);
+- ret = sys_ioctl(fd,cmd,(unsigned long)&d);
+- set_fs(oldfs);
+- if (!ret) {
+- ret |= put_dirent32(&d[0], (struct dirent32 *)ptr);
+- ret |= put_dirent32(&d[1], ((struct dirent32 *)ptr) + 1);
+- }
+- return ret;
+-}
+-
+ #define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */
+ #define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */
+ #define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */
+@@ -158,436 +77,6 @@ static int rtc32_ioctl(unsigned fd, unsi
+ return sys_ioctl(fd,cmd,arg);
+ }
+
+-struct serial_struct32 {
+- compat_int_t type;
+- compat_int_t line;
+- compat_uint_t port;
+- compat_int_t irq;
+- compat_int_t flags;
+- compat_int_t xmit_fifo_size;
+- compat_int_t custom_divisor;
+- compat_int_t baud_base;
+- unsigned short close_delay;
+- char io_type;
+- char reserved_char[1];
+- compat_int_t hub6;
+- unsigned short closing_wait; /* time to wait before closing */
+- unsigned short closing_wait2; /* no longer used... */
+- compat_uint_t iomem_base;
+- unsigned short iomem_reg_shift;
+- unsigned int port_high;
+- compat_int_t reserved[1];
+-};
+-
+-static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr)
+-{
+- typedef struct serial_struct SS;
+- struct serial_struct32 *ss32 = ptr;
+- int err;
+- struct serial_struct ss;
+- mm_segment_t oldseg = get_fs();
+- if (cmd == TIOCSSERIAL) {
+- if (copy_from_user(&ss, ss32, sizeof(struct serial_struct32)))
+- return -EFAULT;
+- memmove(&ss.iomem_reg_shift, ((char*)&ss.iomem_base)+4,
+- sizeof(SS)-offsetof(SS,iomem_reg_shift));
+- ss.iomem_base = (void *)((unsigned long)ss.iomem_base & 0xffffffff);
+- }
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
+- set_fs(oldseg);
+- if (cmd == TIOCGSERIAL && err >= 0) {
+- if (__copy_to_user(ss32,&ss,offsetof(SS,iomem_base)) ||
+- __put_user((unsigned long)ss.iomem_base >> 32 ?
+- 0xffffffff : (unsigned)(unsigned long)ss.iomem_base,
+- &ss32->iomem_base) ||
+- __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) ||
+- __put_user(ss.port_high, &ss32->port_high))
+- return -EFAULT;
+- }
+- return err;
+-}
+-
+-
+-
+-struct usbdevfs_ctrltransfer32 {
+- u8 bRequestType;
+- u8 bRequest;
+- u16 wValue;
+- u16 wIndex;
+- u16 wLength;
+- u32 timeout; /* in milliseconds */
+- compat_caddr_t data;
+-};
+-
+-#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
+-
+-static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_ctrltransfer kctrl;
+- struct usbdevfs_ctrltransfer32 *uctrl;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- int err;
+-
+- uctrl = (struct usbdevfs_ctrltransfer32 *) arg;
+-
+- if (copy_from_user(&kctrl, uctrl,
+- (sizeof(struct usbdevfs_ctrltransfer) -
+- sizeof(void *))))
+- return -EFAULT;
+-
+- if (get_user(udata, &uctrl->data))
+- return -EFAULT;
+- uptr = compat_ptr(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kctrl.wLength > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *)__get_free_page(GFP_KERNEL);
+-
+- if ((kctrl.bRequestType & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kctrl.wLength))
+- goto out;
+- }
+-
+- kctrl.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kctrl.bRequestType & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kctrl.wLength))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-struct usbdevfs_bulktransfer32 {
+- compat_uint_t ep;
+- compat_uint_t len;
+- compat_uint_t timeout; /* in milliseconds */
+- compat_caddr_t data;
+-};
+-
+-#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
+-
+-static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_bulktransfer kbulk;
+- struct usbdevfs_bulktransfer32 *ubulk;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- int err;
+-
+- ubulk = (struct usbdevfs_bulktransfer32 *) arg;
+-
+- if (get_user(kbulk.ep, &ubulk->ep) ||
+- get_user(kbulk.len, &ubulk->len) ||
+- get_user(kbulk.timeout, &ubulk->timeout) ||
+- get_user(udata, &ubulk->data))
+- return -EFAULT;
+-
+- uptr = compat_ptr(udata);
+-
+- /* In usbdevice_fs, it limits the control buffer to a page,
+- * for simplicity so do we.
+- */
+- if (!uptr || kbulk.len > PAGE_SIZE)
+- return -EINVAL;
+-
+- kptr = (void *) __get_free_page(GFP_KERNEL);
+-
+- if ((kbulk.ep & 0x80) == 0) {
+- err = -EFAULT;
+- if (copy_from_user(kptr, uptr, kbulk.len))
+- goto out;
+- }
+-
+- kbulk.data = kptr;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- ((kbulk.ep & 0x80) != 0)) {
+- if (copy_to_user(uptr, kptr, kbulk.len))
+- err = -EFAULT;
+- }
+-
+-out:
+- free_page((unsigned long) kptr);
+- return err;
+-}
+-
+-/* This needs more work before we can enable it. Unfortunately
+- * because of the fancy asynchronous way URB status/error is written
+- * back to userspace, we'll need to fiddle with USB devio internals
+- * and/or reimplement entirely the frontend of it ourselves. -DaveM
+- *
+- * The issue is:
+- *
+- * When an URB is submitted via usbdevicefs it is put onto an
+- * asynchronous queue. When the URB completes, it may be reaped
+- * via another ioctl. During this reaping the status is written
+- * back to userspace along with the length of the transfer.
+- *
+- * We must translate into 64-bit kernel types so we pass in a kernel
+- * space copy of the usbdevfs_urb structure. This would mean that we
+- * must do something to deal with the async entry reaping. First we
+- * have to deal somehow with this transitory memory we've allocated.
+- * This is problematic since there are many call sites from which the
+- * async entries can be destroyed (and thus when we'd need to free up
+- * this kernel memory). One of which is the close() op of usbdevicefs.
+- * To handle that we'd need to make our own file_operations struct which
+- * overrides usbdevicefs's release op with our own which runs usbdevicefs's
+- * real release op then frees up the kernel memory.
+- *
+- * But how to keep track of these kernel buffers? We'd need to either
+- * keep track of them in some table _or_ know about usbdevicefs internals
+- * (ie. the exact layout of its file private, which is actually defined
+- * in linux/usbdevice_fs.h, the layout of the async queues are private to
+- * devio.c)
+- *
+- * There is one possible other solution I considered, also involving knowledge
+- * of usbdevicefs internals:
+- *
+- * After an URB is submitted, we "fix up" the address back to the user
+- * space one. This would work if the status/length fields written back
+- * by the async URB completion lines up perfectly in the 32-bit type with
+- * the 64-bit kernel type. Unfortunately, it does not because the iso
+- * frame descriptors, at the end of the struct, can be written back.
+- *
+- * I think we'll just need to simply duplicate the devio URB engine here.
+- */
+-#if 0
+-struct usbdevfs_urb32 {
+- unsigned char type;
+- unsigned char endpoint;
+- compat_int_t status;
+- compat_uint_t flags;
+- compat_caddr_t buffer;
+- compat_int_t buffer_length;
+- compat_int_t actual_length;
+- compat_int_t start_frame;
+- compat_int_t number_of_packets;
+- compat_int_t error_count;
+- compat_uint_t signr;
+- compat_caddr_t usercontext; /* unused */
+- struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+-};
+-
+-#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
+-
+-static int get_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (get_user(kurb->type, &uurb->type) ||
+- __get_user(kurb->endpoint, &uurb->endpoint) ||
+- __get_user(kurb->status, &uurb->status) ||
+- __get_user(kurb->flags, &uurb->flags) ||
+- __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+- __get_user(kurb->actual_length, &uurb->actual_length) ||
+- __get_user(kurb->start_frame, &uurb->start_frame) ||
+- __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+- __get_user(kurb->error_count, &uurb->error_count) ||
+- __get_user(kurb->signr, &uurb->signr))
+- return -EFAULT;
+-
+- kurb->usercontext = 0; /* unused currently */
+-
+- return 0;
+-}
+-
+-/* Just put back the values which usbdevfs actually changes. */
+-static int put_urb32(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- if (put_user(kurb->status, &uurb->status) ||
+- __put_user(kurb->actual_length, &uurb->actual_length) ||
+- __put_user(kurb->error_count, &uurb->error_count))
+- return -EFAULT;
+-
+- if (kurb->number_of_packets != 0) {
+- int i;
+-
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- if (__put_user(kurb->iso_frame_desc[i].actual_length,
+- &uurb->iso_frame_desc[i].actual_length) ||
+- __put_user(kurb->iso_frame_desc[i].status,
+- &uurb->iso_frame_desc[i].status))
+- return -EFAULT;
+- }
+- }
+-
+- return 0;
+-}
+-
+-static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
+- struct usbdevfs_urb32 *uurb)
+-{
+- unsigned int totlen;
+- int i;
+-
+- if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
+- kurb->number_of_packets = 0;
+- return 0;
+- }
+-
+- if (kurb->number_of_packets < 1 ||
+- kurb->number_of_packets > 128)
+- return -EINVAL;
+-
+- if (copy_from_user(&kurb->iso_frame_desc[0],
+- &uurb->iso_frame_desc[0],
+- sizeof(struct usbdevfs_iso_packet_desc) *
+- kurb->number_of_packets))
+- return -EFAULT;
+-
+- totlen = 0;
+- for (i = 0; i < kurb->number_of_packets; i++) {
+- unsigned int this_len;
+-
+- this_len = kurb->iso_frame_desc[i].length;
+- if (this_len > 1023)
+- return -EINVAL;
+-
+- totlen += this_len;
+- }
+-
+- if (totlen > 32768)
+- return -EINVAL;
+-
+- kurb->buffer_length = totlen;
+-
+- return 0;
+-}
+-
+-static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_urb *kurb;
+- struct usbdevfs_urb32 *uurb;
+- mm_segment_t old_fs;
+- __u32 udata;
+- void *uptr, *kptr;
+- unsigned int buflen;
+- int err;
+-
+- uurb = (struct usbdevfs_urb32 *) arg;
+-
+- err = -ENOMEM;
+- kurb = kmalloc(sizeof(struct usbdevfs_urb) +
+- (sizeof(struct usbdevfs_iso_packet_desc) * 128),
+- GFP_KERNEL);
+- if (!kurb)
+- goto out;
+-
+- err = -EFAULT;
+- if (get_urb32(kurb, uurb))
+- goto out;
+-
+- err = get_urb32_isoframes(kurb, uurb);
+- if (err)
+- goto out;
+-
+- err = -EFAULT;
+- if (__get_user(udata, &uurb->buffer))
+- goto out;
+- uptr = compat_ptr(udata);
+-
+- buflen = kurb->buffer_length;
+- err = verify_area(VERIFY_WRITE, uptr, buflen);
+- if (err)
+- goto out;
+-
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
+- set_fs(old_fs);
+-
+- if (err >= 0) {
+- /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
+- if (put_urb32(kurb, uurb)) {
+- err = -EFAULT;
+- }
+- }
+-
+-out:
+- kfree(kurb);
+- return err;
+-}
+-#endif
+-
+-#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
+-#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
+-
+-static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- mm_segment_t old_fs;
+- void *kptr;
+- int err;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd,
+- (cmd == USBDEVFS_REAPURB32 ?
+- USBDEVFS_REAPURB :
+- USBDEVFS_REAPURBNDELAY),
+- (unsigned long) &kptr);
+- set_fs(old_fs);
+-
+- if (err >= 0 &&
+- put_user((u32)(u64)kptr, (u32 *)arg))
+- err = -EFAULT;
+-
+- return err;
+-}
+-
+-struct usbdevfs_disconnectsignal32 {
+- compat_int_t signr;
+- compat_caddr_t context;
+-};
+-
+-#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
+-
+-static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg)
+-{
+- struct usbdevfs_disconnectsignal kdis;
+- struct usbdevfs_disconnectsignal32 *udis;
+- mm_segment_t old_fs;
+- u32 uctx;
+- int err;
+-
+- udis = (struct usbdevfs_disconnectsignal32 *) arg;
+-
+- if (get_user(kdis.signr, &udis->signr) ||
+- __get_user(uctx, &udis->context))
+- return -EFAULT;
+-
+- kdis.context = (void *) (long)uctx;
+-
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+- err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
+- set_fs(old_fs);
+-
+- return err;
+-}
+ /* /proc/mtrr ioctls */
+
+
+@@ -726,27 +215,12 @@ COMPATIBLE_IOCTL(FIOQSIZE)
+
+ /* And these ioctls need translation */
+ HANDLE_IOCTL(TIOCGDEV, tiocgdev)
+-HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
+-HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
+-/* Raw devices */
+-HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
+ /* realtime device */
+ HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl)
+ HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
+ HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl)
+ HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
+ HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
+-HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
+-/* VFAT */
+-HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
+-HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
+-
+-HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
+-HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
+-/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
+-HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
+-HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+ /* take care of sizeof(sizeof()) breakage */
+ /* mtrr */
+ HANDLE_IOCTL(MTRRIOC32_ADD_ENTRY, mtrr_ioctl32)
+--- linux-2.6.0-test6/arch/x86_64/kernel/i387.c 2003-06-14 12:18:05.000000000 -0700
++++ 25/arch/x86_64/kernel/i387.c 2003-10-05 00:33:23.000000000 -0700
+@@ -138,12 +138,3 @@ int dump_task_fpu(struct task_struct *ts
+ }
+ return fpvalid;
+ }
+-
+-#ifdef CONFIG_SMP
+-void dump_smp_unlazy_fpu(void)
+-{
+- unlazy_fpu(current);
+- return;
+-}
+-#endif
+-
+--- linux-2.6.0-test6/arch/x86_64/mm/ioremap.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/arch/x86_64/mm/ioremap.c 2003-10-05 00:33:23.000000000 -0700
+@@ -159,7 +159,7 @@ void * __ioremap(unsigned long phys_addr
+ if (!area)
+ return NULL;
+ addr = area->addr;
+- if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
++ if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ vunmap(addr);
+ return NULL;
+ }
+--- linux-2.6.0-test6/CREDITS 2003-09-27 18:57:43.000000000 -0700
++++ 25/CREDITS 2003-10-05 00:33:23.000000000 -0700
+@@ -1459,6 +1459,13 @@ S: Ballinagard
+ S: Roscommon
+ S: Ireland
+
++N: Michael Hunold
++E: michael@mihu.de
++W: http://www.mihu.de/linux/
++D: Generic saa7146 video4linux-2 driver core,
++D: Driver for the "Multimedia eXtension Board", "dpc7146",
++D: "Hexium Orion", "Hexium Gemini"
++
+ N: Miguel de Icaza Amozurrutia
+ E: miguel@nuclecu.unam.mx
+ D: Linux/SPARC team, Midnight Commander maintainer
+--- linux-2.6.0-test6/Documentation/cachetlb.txt 2003-06-14 12:18:07.000000000 -0700
++++ 25/Documentation/cachetlb.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -59,9 +59,9 @@ changes occur:
+ address translations from the TLB. After running, this
+ interface must make sure that any previous page table
+ modifications for the address space 'vma->vm_mm' in the range
+- 'start' to 'end' will be visible to the cpu. That is, after
++ 'start' to 'end-1' will be visible to the cpu. That is, after
+ running, here will be no entries in the TLB for 'mm' for
+- virtual addresses in the range 'start' to 'end'.
++ virtual addresses in the range 'start' to 'end-1'.
+
+ The "vma" is the backing store being used for the region.
+ Primarily, this is used for munmap() type operations.
+@@ -100,7 +100,7 @@ changes occur:
+ unsigned long start, unsigned long end)
+
+ The software page tables for address space 'mm' for virtual
+- addresses in the range 'start' to 'end' are being torn down.
++ addresses in the range 'start' to 'end-1' are being torn down.
+
+ Some platforms cache the lowest level of the software page tables
+ in a linear virtually mapped array, to make TLB miss processing
+@@ -165,15 +165,7 @@ and have no dependency on translation in
+
+ Here are the routines, one by one:
+
+-1) void flush_cache_all(void)
+-
+- The most severe flush of all. After this interface runs,
+- the entire cpu cache is flushed.
+-
+- This is usually invoked when the kernel page tables are
+- changed, since such translations are "global" in nature.
+-
+-2) void flush_cache_mm(struct mm_struct *mm)
++1) void flush_cache_mm(struct mm_struct *mm)
+
+ This interface flushes an entire user address space from
+ the caches. That is, after running, there will be no cache
+@@ -183,13 +175,13 @@ Here are the routines, one by one:
+ page table operations such as what happens during
+ fork, exit, and exec.
+
+-3) void flush_cache_range(struct vm_area_struct *vma,
++2) void flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+
+ Here we are flushing a specific range of (user) virtual
+ addresses from the cache. After running, there will be no
+ entries in the cache for 'vma->vm_mm' for virtual addresses in
+- the range 'start' to 'end'.
++ the range 'start' to 'end-1'.
+
+ The "vma" is the backing store being used for the region.
+ Primarily, this is used for munmap() type operations.
+@@ -200,7 +192,7 @@ Here are the routines, one by one:
+ call flush_cache_page (see below) for each entry which may be
+ modified.
+
+-4) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
++3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+
+ This time we need to remove a PAGE_SIZE sized range
+ from the cache. The 'vma' is the backing structure used by
+@@ -215,6 +207,30 @@ Here are the routines, one by one:
+
+ This is used primarily during fault processing.
+
++4) void flush_cache_kmaps(void)
++
++ This routine need only be implemented if the platform utilizes
++ highmem. It will be called right before all of the kmaps
++ are invalidated.
++
++ After running, there will be no entries in the cache for
++ the kernel virtual address range PKMAP_ADDR(0) to
++ PKMAP_ADDR(LAST_PKMAP).
++
++ This routing should be implemented in asm/highmem.h
++
++5) void flush_cache_vmap(unsigned long start, unsigned long end)
++ void flush_cache_vunmap(unsigned long start, unsigned long end)
++
++ Here in these two interfaces we are flushing a specific range
++ of (kernel) virtual addresses from the cache. After running,
++ there will be no entries in the cache for the kernel address
++ space for virtual addresses in the range 'start' to 'end-1'.
++
++ The first of these two routines is invoked after map_vm_area()
++ has installed the page table entries. The second is invoked
++ before unmap_vm_area() deletes the page table entries.
++
+ There exists another whole class of cpu cache issues which currently
+ require a whole different set of interfaces to handle properly.
+ The biggest problem is that of virtual aliasing in the data cache
+@@ -317,6 +333,26 @@ maps this page at its virtual address.
+ dirty. Again, see sparc64 for examples of how
+ to deal with this.
+
++ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long user_vaddr,
++ void *dst, void *src, int len)
++ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long user_vaddr,
++ void *dst, void *src, int len)
++ When the kernel needs to copy arbitrary data in and out
++ of arbitrary user pages (f.e. for ptrace()) it will use
++ these two routines.
++
++ The page has been kmap()'d, and flush_cache_page() has
++ just been called for the user mapping of this page (if
++ necessary).
++
++ Any necessary cache flushing or other coherency operations
++ that need to occur should happen here. If the processor's
++ instruction cache does not snoop cpu stores, it is very
++ likely that you will need to flush the instruction cache
++ for copy_to_user_page().
++
+ void flush_icache_range(unsigned long start, unsigned long end)
+ When the kernel stores into addresses that it will execute
+ out of (eg when loading modules), this function is called.
+@@ -324,17 +360,6 @@ maps this page at its virtual address.
+ If the icache does not snoop stores then this routine will need
+ to flush it.
+
+- void flush_icache_user_range(struct vm_area_struct *vma,
+- struct page *page, unsigned long addr, int len)
+- This is called when the kernel stores into addresses that are
+- part of the address space of a user process (which may be some
+- other process than the current process). The addr argument
+- gives the virtual address in that process's address space,
+- page is the page which is being modified, and len indicates
+- how many bytes have been modified. The modified region must
+- not cross a page boundary. Currently this is only called from
+- kernel/ptrace.c.
+-
+ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+ All the functionality of flush_icache_page can be implemented in
+ flush_dcache_page and update_mmu_cache. In 2.7 the hope is to
+--- linux-2.6.0-test6/Documentation/cpu-freq/user-guide.txt 2003-08-08 22:55:10.000000000 -0700
++++ 25/Documentation/cpu-freq/user-guide.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -57,6 +57,8 @@ AMD mobile K6-2+
+ AMD mobile K6-3+
+ AMD mobile Duron
+ AMD mobile Athlon
++AMD Opteron
++AMD Athlon 64
+ Cyrix Media GXm
+ Intel mobile PIII and Intel mobile PIII-M on certain chipsets
+ Intel Pentium 4, Intel Xeon
+--- linux-2.6.0-test6/Documentation/crypto/api-intro.txt 2003-08-22 19:23:39.000000000 -0700
++++ 25/Documentation/crypto/api-intro.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -126,7 +126,7 @@ might already be working on.
+ BUGS
+
+ Send bug reports to:
+-James Morris <jmorris@intercode.com.au>
++James Morris <jmorris@redhat.com>
+ Cc: David S. Miller <davem@redhat.com>
+
+
+@@ -220,5 +220,5 @@ CAST5 algorithm contributors:
+ Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
+
+ Please send any credits updates or corrections to:
+-James Morris <jmorris@intercode.com.au>
++James Morris <jmorris@redhat.com>
+
+--- linux-2.6.0-test6/Documentation/DocBook/kernel-api.tmpl 2003-09-27 18:57:43.000000000 -0700
++++ 25/Documentation/DocBook/kernel-api.tmpl 2003-10-05 00:33:23.000000000 -0700
+@@ -318,6 +318,5 @@ X!Idrivers/video/console/fonts.c
+ <!-- Needs ksyms to list additional exported symbols, but no specific doc.
+ docproc do not care about sgml commants.
+ !Dkernel/ksyms.c
+-!Dnet/netsyms.c
+ -->
+ </book>
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/fb/neofb.txt 2003-10-05 00:34:22.000000000 -0700
+@@ -0,0 +1,27 @@
++the neofb framebuffer driver supports the following Neomagic chipsets:
++
++NM2070 MagicGraph 128
++NM2090 MagicGraph 128V
++NM2093 MagicGraph 128ZV
++NM2097 MagicGraph 128ZV+
++NM2160 MagicGraph 128XD
++NM2200 MagicGraph 256AV
++NM2230 MagicGraph 256AV+
++NM2360 MagicGraph 256ZX
++NM2380 MagicGraph 256XL+
++
++with the following options:
++
++disabled Disable this driver's initialization.
++internal Enable output on internal LCD Display.
++external Enable output on external CRT.
++nostretch Disable stretching of modes smaller than LCD.
++nopciburst Disable PCI burst mode.
++libretto Force Libretto 100/110 800x480 LCD.
++picturebook Force Picturebook 1024x480 LCD.
++
++at the boot prompt:
++ video=neofb:picturebook
++
++as a module:
++ modprobe neofb picturebook=1
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/andthen 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,100 @@
++
++define set_andthen
++ set var $thp=0
++ set var $thp=(struct kgdb_and_then_struct *)&kgdb_data[0]
++ set var $at_size = (sizeof kgdb_data)/(sizeof *$thp)
++ set var $at_oc=kgdb_and_then_count
++ set var $at_cc=$at_oc
++end
++
++define andthen_next
++ set var $at_cc=$arg0
++end
++
++define andthen
++ andthen_set_edge
++ if ($at_cc >= $at_oc)
++ printf "Outside window. Window size is %d\n",($at_oc-$at_low)
++ else
++ printf "%d: ",$at_cc
++ output *($thp+($at_cc++ % $at_size ))
++ printf "\n"
++ end
++end
++define andthen_set_edge
++ set var $at_oc=kgdb_and_then_count
++ set var $at_low = $at_oc - $at_size
++ if ($at_low < 0 )
++ set var $at_low = 0
++ end
++ if (( $at_cc > $at_oc) || ($at_cc < $at_low))
++ printf "Count outside of window, setting count to "
++ if ($at_cc >= $at_oc)
++ set var $at_cc = $at_oc
++ else
++ set var $at_cc = $at_low
++ end
++ printf "%d\n",$at_cc
++ end
++end
++
++define beforethat
++ andthen_set_edge
++ if ($at_cc <= $at_low)
++ printf "Outside window. Window size is %d\n",($at_oc-$at_low)
++ else
++ printf "%d: ",$at_cc-1
++ output *($thp+(--$at_cc % $at_size ))
++ printf "\n"
++ end
++end
++
++document andthen_next
++ andthen_next <count>
++ . sets the number of the event to display next. If this event
++ . is not in the event pool, either andthen or beforethat will
++ . correct it to the nearest event pool edge. The event pool
++ . ends at the last event recorded and begins <number of events>
++ . prior to that. If beforethat is used next, it will display
++ . event <count> -1.
++.
++ andthen commands are: set_andthen, andthen_next, andthen and beforethat
++end
++
++
++document andthen
++ andthen
++. displays the next event in the list. <set_andthen> sets up to display
++. the oldest saved event first.
++. <count> (optional) count of the event to display.
++. note the number of events saved is specified at configure time.
++. if events are saved between calls to andthen the index will change
++. but the displayed event will be the next one (unless the event buffer
++. is overrun).
++.
++. andthen commands are: set_andthen, andthen_next, andthen and beforethat
++end
++
++document set_andthen
++ set_andthen
++. sets up to use the <andthen> and <beforethat> commands.
++. if you have defined your own struct, use the above and
++. then enter the following:
++. p $thp=(struct kgdb_and_then_structX *)&kgdb_data[0]
++. where <kgdb_and_then_structX> is the name of your structure.
++.
++. andthen commands are: set_andthen, andthen_next, andthen and beforethat
++end
++
++document beforethat
++ beforethat
++. displays the next prior event in the list. <set_andthen> sets up to
++. display the last occuring event first.
++.
++. note the number of events saved is specified at configure time.
++. if events are saved between calls to beforethat the index will change
++. but the displayed event will be the next one (unless the event buffer
++. is overrun).
++.
++. andthen commands are: set_andthen, andthen_next, andthen and beforethat
++end
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/debug-nmi.txt 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,37 @@
++Subject: Debugging with NMI
++Date: Mon, 12 Jul 1999 11:28:31 -0500
++From: David Grothe <dave@gcom.com>
++Organization: Gcom, Inc
++To: David Grothe <dave@gcom.com>
++
++Kernel hackers:
++
++Maybe this is old hat, but it is new to me --
++
++On an ISA bus machine, if you short out the A1 and B1 pins of an ISA
++slot you will generate an NMI to the CPU. This interrupts even a
++machine that is hung in a loop with interrupts disabled. Used in
++conjunction with kgdb <
++ftp://ftp.gcom.com/pub/linux/src/kgdb-2.3.35/kgdb-2.3.35.tgz > you can
++gain debugger control of a machine that is hung in the kernel! Even
++without kgdb the kernel will print a stack trace so you can find out
++where it was hung.
++
++The A1/B1 pins are directly opposite one another and the farthest pins
++towards the bracket end of the ISA bus socket. You can stick a paper
++clip or multi-meter probe between them to short them out.
++
++I had a spare ISA bus to PC104 bus adapter around. The PC104 end of the
++board consists of two rows of wire wrap pins. So I wired a push button
++between the A1/B1 pins and now have an ISA board that I can stick into
++any ISA bus slot for debugger entry.
++
++Microsoft has a circuit diagram of a PCI card at
++http://www.microsoft.com/hwdev/DEBUGGING/DMPSW.HTM. If you want to
++build one you will have to mail them and ask for the PAL equations.
++Nobody makes one comercially.
++
++[THIS TIP COMES WITH NO WARRANTY WHATSOEVER. It works for me, but if
++your machine catches fire, it is your problem, not mine.]
++
++-- Dave (the kgdb guy)
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/gdb-globals.txt 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,71 @@
++Sender: akale@veritas.com
++Date: Fri, 23 Jun 2000 19:26:35 +0530
++From: "Amit S. Kale" <akale@veritas.com>
++Organization: Veritas Software (India)
++To: Dave Grothe <dave@gcom.com>, linux-kernel@vger.rutgers.edu
++CC: David Milburn <dmilburn@wirespeed.com>,
++ "Edouard G. Parmelan" <Edouard.Parmelan@quadratec.fr>,
++ ezannoni@cygnus.com, Keith Owens <kaos@ocs.com.au>
++Subject: Re: Module debugging using kgdb
++
++Dave Grothe wrote:
++>
++> Amit:
++>
++> There is a 2.4.0 version of kgdb on our ftp site:
++> ftp://ftp.gcom.com/pub/linux/src/kgdb. I mirrored your version of gdb
++> and loadmodule.sh there.
++>
++> Have a look at the README file and see if I go it right. If not, send
++> me some corrections and I will update it.
++>
++> Does your version of gdb solve the global variable problem?
++
++Yes.
++Thanks to Elena Zanoni, gdb (developement version) can now calculate
++correctly addresses of dynamically loaded object files. I have not been
++following gdb developement for sometime and am not sure when symbol
++address calculation fix is going to appear in a gdb stable version.
++
++Elena, any idea when the fix will make it to a prebuilt gdb from a
++redhat release?
++
++For the time being I have built a gdb developement version. It can be
++used for module debugging with loadmodule.sh script.
++
++The problem with calculating of module addresses with previous versions
++of gdb was as follows:
++gdb did not use base address of a section while calculating address of
++a symbol in the section in an object file loaded via 'add-symbol-file'.
++It used address of .text segment instead. Due to this addresses of
++symbols in .data, .bss etc. (e.g. global variables) were calculated incorrectly.
++
++Above mentioned fix allow gdb to use base address of a segment while
++calculating address of a symbol in it. It adds a parameter '-s' to
++'add-symbol-file' command for specifying base address of a segment.
++
++loadmodule.sh script works as follows.
++
++1. Copy a module file to target machine.
++2. Load the module on the target machine using insmod with -m parameter.
++insmod produces a module load map which contains base addresses of all
++sections in the module and addresses of symbols in the module file.
++3. Find all sections and their base addresses in the module from
++the module map.
++4. Generate a script that loads the module file. The script uses
++'add-symbol-file' and specifies address of text segment followed by
++addresses of all segments in the module.
++
++Here is an example gdb script produced by loadmodule.sh script.
++
++add-symbol-file foo 0xd082c060 -s .text.lock 0xd08cbfb5
++-s .fixup 0xd08cfbdf -s .rodata 0xd08cfde0 -s __ex_table 0xd08e3b38
++-s .data 0xd08e3d00 -s .bss 0xd08ec8c0 -s __ksymtab 0xd08ee838
++
++With this command gdb can calculate addresses of symbols in ANY segment
++in a module file.
++
++Regards.
++--
++Amit Kale
++Veritas Software ( http://www.veritas.com )
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/gdbinit 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,14 @@
++shell echo -e "\003" >/dev/ttyS0
++set remotebaud 38400
++target remote /dev/ttyS0
++define si
++stepi
++printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx
++printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp
++x/i $eip
++end
++define ni
++nexti
++printf "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n", $eax, $ebx, $ecx, $edx
++printf "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n", $esi, $edi, $ebp, $esp
++x/i $eip
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/gdbinit.hw 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,117 @@
++
++#Using ia-32 hardware breakpoints.
++#
++#4 hardware breakpoints are available in ia-32 processors. These breakpoints
++#do not need code modification. They are set using debug registers.
++#
++#Each hardware breakpoint can be of one of the
++#three types: execution, write, access.
++#1. An Execution breakpoint is triggered when code at the breakpoint address is
++#executed.
++#2. A write breakpoint ( aka watchpoints ) is triggered when memory location
++#at the breakpoint address is written.
++#3. An access breakpoint is triggered when memory location at the breakpoint
++#address is either read or written.
++#
++#As hardware breakpoints are available in limited number, use software
++#breakpoints ( br command in gdb ) instead of execution hardware breakpoints.
++#
++#Length of an access or a write breakpoint defines length of the datatype to
++#be watched. Length is 1 for char, 2 short , 3 int.
++#
++#For placing execution, write and access breakpoints, use commands
++#hwebrk, hwwbrk, hwabrk
++#To remove a breakpoint use hwrmbrk command.
++#
++#These commands take following types of arguments. For arguments associated
++#with each command, use help command.
++#1. breakpointno: 0 to 3
++#2. length: 1 to 3
++#3. address: Memory location in hex ( without 0x ) e.g c015e9bc
++#
++#Use the command exinfo to find which hardware breakpoint occured.
++
++#hwebrk breakpointno address
++define hwebrk
++ maintenance packet Y$arg0,0,0,$arg1
++end
++document hwebrk
++ hwebrk <breakpointno> <address>
++ Places a hardware execution breakpoint
++ <breakpointno> = 0 - 3
++ <address> = Hex digits without leading "0x".
++end
++
++#hwwbrk breakpointno length address
++define hwwbrk
++ maintenance packet Y$arg0,1,$arg1,$arg2
++end
++document hwwbrk
++ hwwbrk <breakpointno> <length> <address>
++ Places a hardware write breakpoint
++ <breakpointno> = 0 - 3
++ <length> = 1 (1 byte), 2 (2 byte), 3 (4 byte)
++ <address> = Hex digits without leading "0x".
++end
++
++#hwabrk breakpointno length address
++define hwabrk
++ maintenance packet Y$arg0,1,$arg1,$arg2
++end
++document hwabrk
++ hwabrk <breakpointno> <length> <address>
++ Places a hardware access breakpoint
++ <breakpointno> = 0 - 3
++ <length> = 1 (1 byte), 2 (2 byte), 3 (4 byte)
++ <address> = Hex digits without leading "0x".
++end
++
++#hwrmbrk breakpointno
++define hwrmbrk
++ maintenance packet y$arg0
++end
++document hwrmbrk
++ hwrmbrk <breakpointno>
++ <breakpointno> = 0 - 3
++ Removes a hardware breakpoint
++end
++
++define reboot
++ maintenance packet r
++end
++#exinfo
++define exinfo
++ maintenance packet qE
++end
++document exinfo
++ exinfo
++ Gives information about a breakpoint.
++end
++define get_th
++ p $th=(struct thread_info *)((int)$esp & ~8191)
++end
++document get_th
++ get_tu
++ Gets and prints the current thread_info pointer, Defines th to be it.
++end
++define get_cu
++ p $cu=((struct thread_info *)((int)$esp & ~8191))->task
++end
++document get_cu
++ get_cu
++ Gets and print the "current" value. Defines $cu to be it.
++end
++define int_off
++ set var $flags=$eflags
++ set $eflags=$eflags&~0x200
++ end
++define int_on
++ set var $eflags|=$flags&0x200
++ end
++document int_off
++ saves the current interrupt state and clears the processor interrupt
++ flag. Use int_on to restore the saved flag.
++end
++document int_on
++ Restores the interrupt flag saved by int_off.
++end
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/gdbinit-modules 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,146 @@
++#
++# Usefull GDB user-command to debug Linux Kernel Modules with gdbstub.
++#
++# This don't work for Linux-2.0 or older.
++#
++# Author Edouard G. Parmelan <Edouard.Parmelan@quadratec.fr>
++#
++#
++# Fri Apr 30 20:33:29 CEST 1999
++# First public release.
++#
++# Major cleanup after experiment Linux-2.0 kernel without success.
++# Symbols of a module are not in the correct order, I can't explain
++# why :(
++#
++# Fri Mar 19 15:41:40 CET 1999
++# Initial version.
++#
++# Thu Jan 6 16:29:03 CST 2000
++# A little fixing by Dave Grothe <dave@gcom.com>
++#
++# Mon Jun 19 09:33:13 CDT 2000
++# Alignment changes from Edouard Parmelan
++#
++# The basic idea is to find where insmod load the module and inform
++# GDB to load the symbol table of the module with the GDB command
++# ``add-symbol-file <object> <address>''.
++#
++# The Linux kernel holds the list of all loaded modules in module_list,
++# this list end with &kernel_module (exactly with module->next == NULL,
++# but the last module is not a real module).
++#
++# Insmod allocates the struct module before the object file. Since
++# Linux-2.1, this structure contain his size. The real address of
++# the object file is then (char*)module + module->size_of_struct.
++#
++# You can use three user functions ``mod-list'', ``mod-print-symbols''
++# and ``add-module-symbols''.
++#
++# mod-list list all loaded modules with the format:
++# <module-address> <module-name>
++#
++# As soon as you have found the address of your module, you can
++# print its exported symbols (mod-print-symbols) or inform GDB to add
++# symbols from your module file (mod-add-symbols).
++#
++# The argument that you give to mod-print-symbols or mod-add-symbols
++# is the <module-address> from the mod-list command.
++#
++# When using the mod-add-symbols command you must also give the full
++# pathname of the modules object code file.
++#
++# The command mod-add-lis is an example of how to make this easier.
++# You can edit this macro to contain the path name of your own
++# favorite module and then use it as a shorthand to load it. You
++# still need the module-address, however.
++#
++# The internal function ``mod-validate'' set the GDB variable $mod
++# as a ``struct module*'' if the kernel known the module otherwise
++# $mod is set to NULL. This ensure to not add symbols for a wrong
++# address.
++#
++# Have a nice hacking day !
++#
++#
++define mod-list
++ set $mod = (struct module*)module_list
++ # the last module is the kernel, ignore it
++ while $mod != &kernel_module
++ printf "%p\t%s\n", (long)$mod, ($mod)->name
++ set $mod = $mod->next
++ end
++end
++document mod-list
++List all modules in the form: <module-address> <module-name>
++Use the <module-address> as the argument for the other
++mod-commands: mod-print-symbols, mod-add-symbols.
++end
++
++define mod-validate
++ set $mod = (struct module*)module_list
++ while ($mod != $arg0) && ($mod != &kernel_module)
++ set $mod = $mod->next
++ end
++ if $mod == &kernel_module
++ set $mod = 0
++ printf "%p is not a module\n", $arg0
++ end
++end
++document mod-validate
++mod-validate <module-address>
++Internal user-command used to validate the module parameter.
++If <module> is a real loaded module, set $mod to it otherwise set $mod to 0.
++end
++
++
++define mod-print-symbols
++ mod-validate $arg0
++ if $mod != 0
++ set $i = 0
++ while $i < $mod->nsyms
++ set $sym = $mod->syms[$i]
++ printf "%p\t%s\n", $sym->value, $sym->name
++ set $i = $i + 1
++ end
++ end
++end
++document mod-print-symbols
++mod-print-symbols <module-address>
++Print all exported symbols of the module. see mod-list
++end
++
++
++define mod-add-symbols-align
++ mod-validate $arg0
++ if $mod != 0
++ set $mod_base = ($mod->size_of_struct + (long)$mod)
++ if ($arg2 != 0) && (($mod_base & ($arg2 - 1)) != 0)
++ set $mod_base = ($mod_base | ($arg2 - 1)) + 1
++ end
++ add-symbol-file $arg1 $mod_base
++ end
++end
++document mod-add-symbols-align
++mod-add-symbols-align <module-address> <object file path name> <align>
++Load the symbols table of the module from the object file where
++first section aligment is <align>.
++To retreive alignment, use `objdump -h <object file path name>'.
++end
++
++define mod-add-symbols
++ mod-add-symbols-align $arg0 $arg1 sizeof(long)
++end
++document mod-add-symbols
++mod-add-symbols <module-address> <object file path name>
++Load the symbols table of the module from the object file.
++Default alignment is 4. See mod-add-symbols-align.
++end
++
++define mod-add-lis
++ mod-add-symbols-align $arg0 /usr/src/LiS/streams.o 16
++end
++document mod-add-lis
++mod-add-lis <module-address>
++Does mod-add-symbols <module-address> /usr/src/LiS/streams.o
++end
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/kgdbeth.txt 2003-10-05 00:33:46.000000000 -0700
+@@ -0,0 +1,118 @@
++KGDB over ethernet
++==================
++
++Authors
++-------
++
++Robert Walsh <rjwalsh@durables.org> (2.6 port)
++wangdi <wangdi@clusterfs.com> (2.6 port)
++San Mehat (original 2.4 code)
++
++
++Introduction
++------------
++
++KGDB supports debugging over ethernet. Only a limited set of ethernet
++devices are supported right now, but adding support for new devices
++should not be too complicated. See "New Devices" below for details.
++
++
++Terminology
++-----------
++
++This document uses the following terms:
++
++ TARGET: the machine being debugged.
++ HOST: the machine running gdb.
++
++
++Usage
++-----
++
++You need to use the following command-line options on the TARGET kernel:
++
++ gdbeth=DEVICENUM
++ gdbeth_remoteip=HOSTIPADDR
++ gdbeth_remotemac=REMOTEMAC
++ gdbeth_localmac=LOCALMAC
++
++kgdbeth=DEVICENUM sets the ethernet device number to listen on for
++debugging packets. e.g. kgdbeth=0 listens on eth0.
++
++kgdbeth_remoteip=HOSTIPADDR sets the IP address of the HOST machine.
++Only packets originating from this IP address will be accepted by the
++debugger. e.g. kgdbeth_remoteip=192.168.2.2
++
++kgdbeth_remotemac=REMOTEMAC sets the ethernet address of the HOST machine.
++e.g. kgdbeth_remotemac=00:07:70:12:4E:F5
++
++kgdbeth_localmac=LOCALMAC sets the ethernet address of the TARGET machine.
++e.g. kgdbeth_localmac=00:10:9F:18:21:3C
++
++You can also set the following command-line option on the TARGET kernel:
++
++ kgdbeth_listenport=PORT
++
++kgdbeth_listenport sets the UDP port to listen on for gdb debugging
++packets. The default value is "6443". e.g. kgdbeth_listenport=7654
++causes the kernel to listen on UDP port 7654 for debugging packets.
++
++On the HOST side, run gdb as normal and use a remote UDP host as the
++target:
++
++ % gdb ./vmlinux
++ GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
++ Copyright 2003 Free Software Foundation, Inc.
++ GDB is free software, covered by the GNU General Public License, and you are
++ welcome to change it and/or distribute copies of it under certain conditions.
++ Type "show copying" to see the conditions.
++ There is absolutely no warranty for GDB. Type "show warranty" for details.
++ This GDB was configured as "i386-redhat-linux-gnu"...
++ (gdb) target remote udp:HOSTNAME:6443
++
++You can now continue as if you were debugging over a serial line.
++
++Observations
++------------
++
++I've used this with NFS and various other network applications (ssh,
++etc.) and it's doesn't appear to interfere with their operation in
++any way. It doesn't seem to effect the NIC it uses - i.e. you don't
++need a dedicated NIC for this.
++
++Limitations
++-----------
++
++In the inital release of this code you _must_ break into the system with the
++debugger by hand, early after boot, as described above.
++
++Otherwise, the first time the kernel tries to enter the debugger (say, via an
++oops or a BUG), the kgdb stub will doublefault and die because things aren't
++fully set up yet.
++
++Supported devices
++-----------------
++
++Right now, the following drivers are supported:
++
++ e100 driver (drivers/net/e100/*)
++ 3c59x driver (drivers/net/3c59x.c)
++
++
++New devices
++-----------
++
++Supporting a new device is straightforward. Just add a "poll" routine to
++the driver and hook it into the poll_controller field in the netdevice
++structure. For an example, look in drivers/net/3c59x.c and search
++for CONFIG_KGDB (two places.)
++
++The poll routine is usually quite simple - it's usually enough to just
++disable interrupts, call the device's interrupt routine and re-enable
++interrupts again.
++
++
++Bug reports
++-----------
++
++Send bug reports to Robert Walsh <rjwalsh@durables.org>.
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/kgdb.txt 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,775 @@
++Last edit: <20030806.1637.12>
++This file has information specific to the i386 kgdb option. Other
++platforms with the kgdb option may behave in a similar fashion.
++
++New features:
++============
++20030806.1557.37
++This version was made against the 2.6.0-test2 kernel. We have made the
++following changes:
++
++- The getthread() code in the stub calls find_task_by_pid(). It fails
++ if we are early in the bring up such that the pid arrays have yet to
++ be allocated. We have added a line to kernel/pid.c to make
++ "kgdb_pid_init_done" true once the arrays are allocated. This way the
++ getthread() code knows not to call. This is only used by the thread
++ debugging stuff and threads will not yet exist at this point in the
++ boot.
++
++- For some reason, gdb was not asking for a new thread list when the
++ "info thread" command was given. We changed to the newer version of
++ the thread info command and gdb now seems to ask when needed. Result,
++ we now get all threads in the thread list.
++
++- We now respond to the ThreadExtraInfo request from gdb with the thread
++ name from task_struct .comm. This then appears in the thread list.
++ Thoughts on additional options for this are welcome. Things such as
++ "has BKL" and "Preempted" come to mind. I think we could have a flag
++ word that could enable different bits of info here.
++
++- We now honor, sort of, the C and S commands. These are continue and
++ single set after delivering a signal. We ignore the signal and do the
++ requested action. This only happens when we told gdb that a signal
++ was the reason for entry, which is only done on memory faults. The
++ result is that you can now continue into the Oops.
++
++- We changed the -g to -gdwarf-2. This seems to be the same as -ggdb,
++ but it is more exact on what language to use.
++
++- We added two dwarf2 include files and a bit of code at the end of
++ entry.S. This does not yet work, so it is disabled. Still we want to
++ keep track of the code and "maybe" someone out there can fix it.
++
++- Randy Dunlap sent some fix ups for this file which are now merged.
++
++- Hugh Dickins sent a fix to a bit of code in traps.c that prevents a
++ compiler warning if CONFIG_KGDB is off (now who would do that :).
++
++- Andrew Morton sent a fix for the serial driver which is now merged.
++
++- Andrew also sent a change to the stub around the cpu managment code
++ which is also merged.
++
++- Andrew also sent a patch to make "f" as well as "g" work as SysRq
++ commands to enter kgdb, merged.
++
++- If CONFIG_KGDB and CONFIG_DEBUG_SPINLOCKS are both set we added a
++ "who" field to the spinlock data struct. This is filled with
++ "current" when ever the spinlock suceeds. Useful if you want to know
++ who has the lock.
++
++_ And last, but not least, we fixed the "get_cu" macro to properly get
++ the current value of "current".
++
++New features:
++============
++20030505.1827.27
++We are starting to align with the sourceforge version, at least in
++commands. To this end, the boot command string to start kgdb at
++boot time has been changed from "kgdb" to "gdb".
++
++Andrew Morton sent a couple of patches which are now included as follows:
++1.) We now return a flag to the interrupt handler.
++2.) We no longer use smp_num_cpus (a conflict with the lock meter).
++3.) And from William Lee Irwin III <wli@holomorphy.com> code to make
++ sure high-mem is set up before we attempt to register our interrupt
++ handler.
++We now include asm/kgdb.h from config.h so you will most likely never
++have to include it. It also 'NULLS' the kgdb macros you might have in
++your code when CONFIG_KGDB is not defined. This allows you to just
++turn off CONFIG_KGDB to turn off all the kgdb_ts() calls and such.
++This include is conditioned on the machine being an x86 so as to not
++mess with other archs.
++
++20020801.1129.03
++This is currently the version for the 2.4.18 (and beyond?) kernel.
++
++We have several new "features" beginning with this version:
++
++1.) Kgdb now syncs the "other" CPUs with a cross-CPU NMI. No more
++ waiting and it will pull that guy out of an IRQ off spin lock :)
++
++2.) We doctored up the code that tells where a task is waiting and
++ included it so that the "info thread" command will show a bit more
++ than "schedule()". Try it...
++
++3.) Added the ability to call a function from gdb. All the standard gdb
++ issues apply, i.e. if you hit a breakpoint in the function, you are
++ not allowed to call another (gdb limitation, not kgdb). To help
++ this capability we added a memory allocation function. Gdb does not
++ return this memory (it is used for strings that you pass to that function
++ you are calling from gdb) so we fixed up a way to allow you to
++ manually return the memory (see below).
++
++4.) Kgdb time stamps (kgdb_ts()) are enhanced to expand what was the
++ interrupt flag to now also include the preemption count and the
++ "in_interrupt" info. The flag is now called "with_pif" to indicate
++ the order, preempt_count, in_interrupt, flag. The preempt_count is
++ shifted left by 4 bits so you can read the count in hex by dropping
++ the low order digit. In_interrupt is in bit 1, and the flag is in
++ bit 0.
++
++5.) The command: "p kgdb_info" is now expanded and prints something
++ like:
++(gdb) p kgdb_info
++$2 = {used_malloc = 0, called_from = 0xc0107506, entry_tsc = 67468627259,
++ errcode = 0, vector = 3, print_debug_info = 0, hold_on_sstep = 1,
++ cpus_waiting = {{task = 0xc027a000, pid = 32768, hold = 0,
++ regs = 0xc027bf84}, {task = 0x0, pid = 0, hold = 0, regs = 0x0}}}
++
++ Things to note here: a.) used_malloc is the amount of memory that
++ has been malloc'ed to do calls from gdb. You can reclaim this
++ memory like this: "p kgdb_info.used_malloc=0" Cool, huh? b.)
++ cpus_waiting is now "sized" by the number of CPUs you enter at
++ configure time in the kgdb configure section. This is NOT used
++ anywhere else in the system, but it is "nice" here. c.) The task's
++ "pid" is now in the structure. This is the pid you will need to use
++ to decode to the thread id to get gdb to look at that thread.
++ Remember that the "info thread" command prints a list of threads
++ wherein it numbers each thread with its reference number followed
++ by the thread's pid. Note that the per-CPU idle threads actually
++ have pids of 0 (yes, there is more than one pid 0 in an SMP system).
++ To avoid confusion, kgdb numbers these threads with numbers beyond
++ the MAX_PID. That is why you see 32768 and above.
++
++6.) A subtle change, we now provide the complete register set for tasks
++ that are active on the other CPUs. This allows better trace back on
++ those tasks.
++
++ And, let's mention what we could not fix. Back-trace from all but the
++ thread that we trapped will, most likely, have a bogus entry in it.
++ The problem is that gdb does not recognize the entry code for
++ functions that use "current" near (at all?) the entry. The compiler
++ is putting the "current" decode as the first two instructions of the
++ function where gdb expects to find %ebp changing code. Back trace
++ also has trouble with interrupt frames. I am talking with Daniel
++ Jacobowitz about some way to fix this, but don't hold your breath.
++
++20011220.0050.35
++Major enhancement with this version is the ability to hold one or more
++CPUs in an SMP system while allowing the others to continue. Also, by
++default only the current CPU is enabled on single-step commands (please
++note that gdb issues single-step commands at times other than when you
++use the si command).
++
++Another change is to collect some useful information in
++a global structure called "kgdb_info". You should be able to just:
++
++p kgdb_info
++
++although I have seen cases where the first time this is done gdb just
++prints the first member but prints the whole structure if you then enter
++CR (carriage return or enter). This also works:
++
++p *&kgdb_info
++
++Here is a sample:
++(gdb) p kgdb_info
++$4 = {called_from = 0xc010732c, entry_tsc = 32804123790856, errcode = 0,
++ vector = 3, print_debug_info = 0}
++
++"Called_from" is the return address from the current entry into kgdb.
++Sometimes it is useful to know why you are in kgdb, for example, was
++it an NMI or a real breakpoint? The simple way to interrogate this
++return address is:
++
++l *0xc010732c
++
++which will print the surrounding few lines of source code.
++
++"Entry_tsc" is the CPU TSC on entry to kgdb (useful to compare to the
++kgdb_ts entries).
++
++"errcode" and "vector" are other entry parameters which may be helpful on
++some traps.
++
++"print_debug_info" is the internal debugging kgdb print enable flag. Yes,
++you can modify it.
++
++In SMP systems kgdb_info also includes the "cpus_waiting" structure and
++"hold_on_step":
++
++(gdb) p kgdb_info
++$7 = {called_from = 0xc0112739, entry_tsc = 1034936624074, errcode = 0,
++ vector = 2, print_debug_info = 0, hold_on_sstep = 1, cpus_waiting = {{
++ task = 0x0, hold = 0, regs = 0x0}, {task = 0xc71b8000, hold = 0,
++ regs = 0xc71b9f70}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
++ hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
++ hold = 0, regs = 0x0}, {task = 0x0, hold = 0, regs = 0x0}, {task = 0x0,
++ hold = 0, regs = 0x0}}}
++
++"Cpus_waiting" has an entry for each CPU other than the current one that
++has been stopped. Each entry contains the task_struct address for that
++CPU, the address of the regs for that task and a hold flag. All these
++have the proper typing so that, for example:
++
++p *kgdb_info.cpus_waiting[1].regs
++
++will print the registers for CPU 1.
++
++"Hold_on_sstep" is a new feature with this version and comes up set or
++true. What this means is that whenever kgdb is asked to single-step all
++other CPUs are held (i.e. not allowed to execute). The flag applies to
++all but the current CPU and, again, can be changed:
++
++p kgdb_info.hold_on_sstep=0
++
++restores the old behavior of letting all CPUs run during single-stepping.
++
++Likewise, each CPU has a "hold" flag, which if set, locks that CPU out
++of execution. Note that this has some risk in cases where the CPUs need
++to communicate with each other. If kgdb finds no CPU available on exit,
++it will push a message thru gdb and stay in kgdb. Note that it is legal
++to hold the current CPU as long as at least one CPU can execute.
++
++20010621.1117.09
++This version implements an event queue. Events are signaled by calling
++a function in the kgdb stub and may be examined from gdb. See EVENTS
++below for details. This version also tightens up the interrupt and SMP
++handling to not allow interrupts on the way to kgdb from a breakpoint
++trap. It is fine to allow these interrupts for user code, but not
++system debugging.
++
++Version
++=======
++
++This version of the kgdb package was developed and tested on
++kernel version 2.4.16. It will not install on any earlier kernels.
++It is possible that it will continue to work on later versions
++of 2.4 and then versions of 2.5 (I hope).
++
++
++Debugging Setup
++===============
++
++Designate one machine as the "development" machine. This is the
++machine on which you run your compiles and which has your source
++code for the kernel. Designate a second machine as the "target"
++machine. This is the machine that will run your experimental
++kernel.
++
++The two machines will be connected together via a serial line out
++one or the other of the COM ports of the PC. You will need the
++appropriate modem eliminator (null modem) cable(s) for this.
++
++Decide on which tty port you want the machines to communicate, then
++connect them up back-to-back using the null modem cable. COM1 is
++/dev/ttyS0 and COM2 is /dev/ttyS1. You should test this connection
++with the two machines prior to trying to debug a kernel. Once you
++have it working, on the TARGET machine, enter:
++
++setserial /dev/ttyS0 (or what ever tty you are using)
++
++and record the port address and the IRQ number.
++
++On the DEVELOPMENT machine you need to apply the patch for the kgdb
++hooks. You have probably already done that if you are reading this
++file.
++
++On your DEVELOPMENT machine, go to your kernel source directory and do
++"make Xconfig" where X is one of "x", "menu", or "". If you are
++configuring in the standard serial driver, it must not be a module.
++Either yes or no is ok, but making the serial driver a module means it
++will initialize after kgdb has set up the UART interrupt code and may
++cause a failure of the control-C option discussed below. The configure
++question for the serial driver is under the "Character devices" heading
++and is:
++
++"Standard/generic (8250/16550 and compatible UARTs) serial support"
++
++Go down to the kernel debugging menu item and open it up. Enable the
++kernel kgdb stub code by selecting that item. You can also choose to
++turn on the "-ggdb -O1" compile options. The -ggdb causes the compiler
++to put more debug info (like local symbols) in the object file. On the
++i386 -g and -ggdb are the same so this option just reduces to "O1". The
++-O1 reduces the optimization level. This may be helpful in some cases,
++be aware, however, that this may also mask the problem you are looking
++for.
++
++The baud rate. Default is 115200. What ever you choose be sure that
++the host machine is set to the same speed. I recommend the default.
++
++The port. This is the I/O address of the serial UART that you should
++have gotten using setserial as described above. The standard COM1 port
++(3f8) using IRQ 4 is default. COM2 is 2f8 which by convention uses IRQ
++3.
++
++The port IRQ (see above).
++
++Stack overflow test. This option makes a minor change in the trap,
++system call and interrupt code to detect stack overflow and transfer
++control to kgdb if it happens. (Some platforms have this in the
++baseline code, but the i386 does not.)
++
++You can also configure the system to recognize the boot option
++"console=kgdb" which if given will cause all console output during
++booting to be put thru gdb as well as other consoles. This option
++requires that gdb and kgdb be connected prior to sending console output
++so, if they are not, a breakpoint is executed to force the connection.
++This will happen before any kernel output (it is going thru gdb, right),
++and will stall the boot until the connection is made.
++
++You can also configure in a patch to SysRq to enable the kGdb SysRq.
++This request generates a breakpoint. Since the serial port IRQ line is
++set up after any serial drivers, it is possible that this command will
++work when the control-C will not.
++
++Save and exit the Xconfig program. Then do "make clean" , "make dep"
++and "make bzImage" (or whatever target you want to make). This gets the
++kernel compiled with the "-g" option set -- necessary for debugging.
++
++You have just built the kernel on your DEVELOPMENT machine that you
++intend to run on your TARGET machine.
++
++To install this new kernel, use the following installation procedure.
++Remember, you are on the DEVELOPMENT machine patching the kernel source
++for the kernel that you intend to run on the TARGET machine.
++
++Copy this kernel to your target machine using your usual procedures. I
++usually arrange to copy development:
++/usr/src/linux/arch/i386/boot/bzImage to /vmlinuz on the TARGET machine
++via a LAN based NFS access. That is, I run the cp command on the target
++and copy from the development machine via the LAN. Run Lilo (see "man
++lilo" for details on how to set this up) on the new kernel on the target
++machine so that it will boot! Then boot the kernel on the target
++machine.
++
++On the DEVELOPMENT machine, create a file called .gdbinit in the
++directory /usr/src/linux. An example .gdbinit file looks like this:
++
++shell echo -e "\003" >/dev/ttyS0
++set remotebaud 38400 (or what ever speed you have chosen)
++target remote /dev/ttyS0
++
++
++Change the "echo" and "target" definition so that it specifies the tty
++port that you intend to use. Change the "remotebaud" definition to
++match the data rate that you are going to use for the com line.
++
++You are now ready to try it out.
++
++Boot your target machine with "kgdb" in the boot command i.e. something
++like:
++
++lilo> test kgdb
++
++or if you also want console output thru gdb:
++
++lilo> test kgdb console=kgdb
++
++You should see the lilo message saying it has loaded the kernel and then
++all output stops. The kgdb stub is trying to connect with gdb. Start
++gdb something like this:
++
++
++On your DEVELOPMENT machine, cd /usr/src/linux and enter "gdb vmlinux".
++When gdb gets the symbols loaded it will read your .gdbinit file and, if
++everything is working correctly, you should see gdb print out a few
++lines indicating that a breakpoint has been taken. It will actually
++show a line of code in the target kernel inside the kgdb activation
++code.
++
++The gdb interaction should look something like this:
++
++ linux-dev:/usr/src/linux# gdb vmlinux
++ GDB is free software and you are welcome to distribute copies of it
++ under certain conditions; type "show copying" to see the conditions.
++ There is absolutely no warranty for GDB; type "show warranty" for details.
++ GDB 4.15.1 (i486-slackware-linux),
++ Copyright 1995 Free Software Foundation, Inc...
++ breakpoint () at i386-stub.c:750
++ 750 }
++ (gdb)
++
++You can now use whatever gdb commands you like to set breakpoints.
++Enter "continue" to start your target machine executing again. At this
++point the target system will run at full speed until it encounters
++your breakpoint or gets a segment violation in the kernel, or whatever.
++
++If you have the kgdb console enabled when you continue, gdb will print
++out all the console messages.
++
++The above example caused a breakpoint relatively early in the boot
++process. For the i386 kgdb it is possible to code a break instruction
++as the first C-language point in init/main.c, i.e. as the first instruction
++in start_kernel(). This could be done as follows:
++
++#include <asm/kgdb.h>
++ breakpoint();
++
++This breakpoint() is really a function that sets up the breakpoint and
++single-step hardware trap cells and then executes a breakpoint. Any
++early hard coded breakpoint will need to use this function. Once the
++trap cells are set up they need not be set again, but doing it again
++does not hurt anything, so you don't need to be concerned about which
++breakpoint is hit first. Once the trap cells are set up (and the kernel
++sets them up in due course even if breakpoint() is never called) the
++macro:
++
++BREAKPOINT;
++
++will generate an inline breakpoint. This may be more useful as it stops
++the processor at the instruction instead of in a function a step removed
++from the location of interest. In either case <asm/kgdb.h> must be
++included to define both breakpoint() and BREAKPOINT.
++
++Triggering kgdbstub at other times
++==================================
++
++Often you don't need to enter the debugger until much later in the boot
++or even after the machine has been running for some time. Once the
++kernel is booted and interrupts are on, you can force the system to
++enter the debugger by sending a control-C to the debug port. This is
++what the first line of the recommended .gdbinit file does. This allows
++you to start gdb any time after the system is up as well as when the
++system is already at a breakpoint. (In the case where the system is
++already at a breakpoint the control-C is not needed, however, it will
++be ignored by the target so no harm is done. Also note the the echo
++command assumes that the port speed is already set. This will be true
++once gdb has connected, but it is best to set the port speed before you
++run gdb.)
++
++Another simple way to do this is to put the following file in you ~/bin
++directory:
++
++#!/bin/bash
++echo -e "\003" > /dev/ttyS0
++
++Here, the ttyS0 should be replaced with what ever port you are using.
++The "\003" is control-C. Once you are connected with gdb, you can enter
++control-C at the command prompt.
++
++An alternative way to get control to the debugger is to enable the kGdb
++SysRq command. Then you would enter Alt-SysRq-g (all three keys at the
++same time, but push them down in the order given). To refresh your
++memory of the available SysRq commands try Alt-SysRq-=. Actually any
++undefined command could replace the "=", but I like to KNOW that what I
++am pushing will never be defined.
++
++Debugging hints
++===============
++
++You can break into the target machine at any time from the development
++machine by typing ^C (see above paragraph). If the target machine has
++interrupts enabled this will stop it in the kernel and enter the
++debugger.
++
++There is unfortunately no way of breaking into the kernel if it is
++in a loop with interrupts disabled, so if this happens to you then
++you need to place exploratory breakpoints or printk's into the kernel
++to find out where it is looping. The exploratory breakpoints can be
++entered either thru gdb or hard coded into the source. This is very
++handy if you do something like:
++
++if (<it hurts>) BREAKPOINT;
++
++
++There is a copy of an e-mail in the Documentation/i386/kgdb/ directory
++(debug-nmi.txt) which describes how to create an NMI on an ISA bus
++machine using a paper clip. I have a sophisticated version of this made
++by wiring a push button switch into a PC104/ISA bus adapter card. The
++adapter card nicely furnishes wire wrap pins for all the ISA bus
++signals.
++
++When you are done debugging the kernel on the target machine it is a
++good idea to leave it in a running state. This makes reboots faster,
++bypassing the fsck. So do a gdb "continue" as the last gdb command if
++this is possible. To terminate gdb itself on the development machine
++and leave the target machine running, first clear all breakpoints and
++continue, then type ^Z to suspend gdb and then kill it with "kill %1" or
++something similar.
++
++If gdbstub Does Not Work
++========================
++
++If it doesn't work, you will have to troubleshoot it. Do the easy
++things first like double checking your cabling and data rates. You
++might try some non-kernel based programs to see if the back-to-back
++connection works properly. Just something simple like cat /etc/hosts
++>/dev/ttyS0 on one machine and cat /dev/ttyS0 on the other will tell you
++if you can send data from one machine to the other. Make sure it works
++in both directions. There is no point in tearing out your hair in the
++kernel if the line doesn't work.
++
++All of the real action takes place in the file
++/usr/src/linux/arch/i386/kernel/kgdb_stub.c. That is the code on the target
++machine that interacts with gdb on the development machine. In gdb you can
++turn on a debug switch with the following command:
++
++ set remotedebug
++
++This will print out the protocol messages that gdb is exchanging with
++the target machine.
++
++Another place to look is /usr/src/arch/i386/lib/kgdb_serial.c. This is
++the code that talks to the serial port on the target side. There might
++be a problem there. In particular there is a section of this code that
++tests the UART which will tell you what UART you have if you define
++"PRNT" (just remove "_off" from the #define PRNT_off). To view this
++report you will need to boot the system without any beakpoints. This
++allows the kernel to run to the point where it calls kgdb to set up
++interrupts. At this time kgdb will test the UART and print out the type
++it finds. (You need to wait so that the printks are actually being
++printed. Early in the boot they are cached, waiting for the console to
++be enabled. Also, if kgdb is entered thru a breakpoint it is possible
++to cause a dead lock by calling printk when the console is locked. The
++stub thus avoids doing printks from breakpoints, especially in the
++serial code.) At this time, if the UART fails to do the expected thing,
++kgdb will print out (using printk) information on what failed. (These
++messages will be buried in all the other boot up messages. Look for
++lines that start with "gdb_hook_interrupt:". You may want to use dmesg
++once the system is up to view the log. If this fails or if you still
++don't connect, review your answers for the port address. Use:
++
++setserial /dev/ttyS0
++
++to get the current port and IRQ information. This command will also
++tell you what the system found for the UART type. The stub recognizes
++the following UART types:
++
++16450, 16550, and 16550A
++
++If you are really desperate you can use printk debugging in the
++kgdbstub code in the target kernel until you get it working. In particular,
++there is a global variable in /usr/src/linux/arch/i386/kernel/kgdb_stub.c
++named "remote_debug". Compile your kernel with this set to 1, rather
++than 0 and the debug stub will print out lots of stuff as it does
++what it does. Likewise there are debug printks in the kgdb_serial.c
++code that can be turned on with simple changes in the macro defines.
++
++
++Debugging Loadable Modules
++==========================
++
++This technique comes courtesy of Edouard Parmelan
++<Edouard.Parmelan@quadratec.fr>
++
++When you run gdb, enter the command
++
++source gdbinit-modules
++
++This will read in a file of gdb macros that was installed in your
++kernel source directory when kgdb was installed. This file implements
++the following commands:
++
++mod-list
++ Lists the loaded modules in the form <module-address> <module-name>
++
++mod-print-symbols <module-address>
++ Prints all the symbols in the indicated module.
++
++mod-add-symbols <module-address> <object-file-path-name>
++ Loads the symbols from the object file and associates them
++ with the indicated module.
++
++After you have loaded the module that you want to debug, use the command
++mod-list to find the <module-address> of your module. Then use that
++address in the mod-add-symbols command to load your module's symbols.
++From that point onward you can debug your module as if it were a part
++of the kernel.
++
++The file gdbinit-modules also contains a command named mod-add-lis as
++an example of how to construct a command of your own to load your
++favorite module. The idea is to "can" the pathname of the module
++in the command so you don't have to type so much.
++
++Threads
++=======
++
++Each process in a target machine is seen as a gdb thread. gdb thread
++related commands (info threads, thread n) can be used.
++
++ia-32 hardware breakpoints
++==========================
++
++kgdb stub contains support for hardware breakpoints using debugging features
++of ia-32(x86) processors. These breakpoints do not need code modification.
++They use debugging registers. 4 hardware breakpoints are available in ia-32
++processors.
++
++Each hardware breakpoint can be of one of the following three types.
++
++1. Execution breakpoint - An Execution breakpoint is triggered when code
++ at the breakpoint address is executed.
++
++ As limited number of hardware breakpoints are available, it is
++ advisable to use software breakpoints ( break command ) instead
++ of execution hardware breakpoints, unless modification of code
++ is to be avoided.
++
++2. Write breakpoint - A write breakpoint is triggered when memory
++ location at the breakpoint address is written.
++
++ A write or can be placed for data of variable length. Length of
++ a write breakpoint indicates length of the datatype to be
++ watched. Length is 1 for 1 byte data , 2 for 2 byte data, 3 for
++ 4 byte data.
++
++3. Access breakpoint - An access breakpoint is triggered when memory
++ location at the breakpoint address is either read or written.
++
++ Access breakpoints also have lengths similar to write breakpoints.
++
++IO breakpoints in ia-32 are not supported.
++
++Since gdb stub at present does not use the protocol used by gdb for hardware
++breakpoints, hardware breakpoints are accessed through gdb macros. gdb macros
++for hardware breakpoints are described below.
++
++hwebrk - Places an execution breakpoint
++ hwebrk breakpointno address
++hwwbrk - Places a write breakpoint
++ hwwbrk breakpointno length address
++hwabrk - Places an access breakpoint
++ hwabrk breakpointno length address
++hwrmbrk - Removes a breakpoint
++ hwrmbrk breakpointno
++exinfo - Tells whether a software or hardware breakpoint has occurred.
++ Prints number of the hardware breakpoint if a hardware breakpoint has
++ occurred.
++
++Arguments required by these commands are as follows
++breakpointno - 0 to 3
++length - 1 to 3
++address - Memory location in hex digits ( without 0x ) e.g c015e9bc
++
++SMP support
++==========
++
++When a breakpoint occurs or user issues a break ( Ctrl + C ) to gdb
++client, all the processors are forced to enter the debugger. Current
++thread corresponds to the thread running on the processor where
++breakpoint occurred. Threads running on other processor(s) appear
++similar to other non-running threads in the 'info threads' output.
++Within the kgdb stub there is a structure "waiting_cpus" in which kgdb
++records the values of "current" and "regs" for each CPU other than the
++one that hit the breakpoint. "current" is a pointer to the task
++structure for the task that CPU is running, while "regs" points to the
++saved registers for the task. This structure can be examined with the
++gdb "p" command.
++
++ia-32 hardware debugging registers on all processors are set to same
++values. Hence any hardware breakpoints may occur on any processor.
++
++gdb troubleshooting
++===================
++
++1. gdb hangs
++Kill it. restart gdb. Connect to target machine.
++
++2. gdb cannot connect to target machine (after killing a gdb and
++restarting another) If the target machine was not inside debugger when
++you killed gdb, gdb cannot connect because the target machine won't
++respond. In this case echo "Ctrl+C"(ASCII 3) to the serial line.
++e.g. echo -e "\003" > /dev/ttyS1
++This forces that target machine into the debugger, after which you
++can connect.
++
++3. gdb cannot connect even after echoing Ctrl+C into serial line
++Try changing serial line settings min to 1 and time to 0
++e.g. stty min 1 time 0 < /dev/ttyS1
++Try echoing again
++
++Check serial line speed and set it to correct value if required
++e.g. stty ispeed 115200 ospeed 115200 < /dev/ttyS1
++
++EVENTS
++======
++
++Ever want to know the order of things happening? Which CPU did what and
++when? How did the spinlock get the way it is? Then events are for
++you. Events are defined by calls to an event collection interface and
++saved for later examination. In this case, kgdb events are saved by a
++very fast bit of code in kgdb which is fully SMP and interrupt protected
++and they are examined by using gdb to display them. Kgdb keeps only
++the last N events, where N must be a power of two and is defined at
++configure time.
++
++
++Events are signaled to kgdb by calling:
++
++kgdb_ts(data0,data1)
++
++For each call kgdb records each call in an array along with other info.
++Here is the array definition:
++
++struct kgdb_and_then_struct {
++#ifdef CONFIG_SMP
++ int on_cpu;
++#endif
++ long long at_time;
++ int from_ln;
++ char * in_src;
++ void *from;
++ int with_if;
++ int data0;
++ int data1;
++};
++
++For SMP machines the CPU is recorded, for all machines the TSC is
++recorded (gets a time stamp) as well as the line number and source file
++the call was made from. The address of the (from), the "if" (interrupt
++flag) and the two data items are also recorded. The macro kgdb_ts casts
++the types to int, so you can put any 32-bit values here. There is a
++configure option to select the number of events you want to keep. A
++nice number might be 128, but you can keep up to 1024 if you want. The
++number must be a power of two. An "andthen" macro library is provided
++for gdb to help you look at these events. It is also possible to define
++a different structure for the event storage and cast the data to this
++structure. For example the following structure is defined in kgdb:
++
++struct kgdb_and_then_struct2 {
++#ifdef CONFIG_SMP
++ int on_cpu;
++#endif
++ long long at_time;
++ int from_ln;
++ char * in_src;
++ void *from;
++ int with_if;
++ struct task_struct *t1;
++ struct task_struct *t2;
++};
++
++If you use this for display, the data elements will be displayed as
++pointers to task_struct entries. You may want to define your own
++structure to use in casting. You should only change the last two items
++and you must keep the structure size the same. Kgdb will handle these
++as 32-bit ints, but within that constraint you can define a structure to
++cast to any 32-bit quantity. This need only be available to gdb and is
++only used for casting in the display code.
++
++Final Items
++===========
++
++I picked up this code from Amit S. Kale and enhanced it.
++
++If you make some really cool modification to this stuff, or if you
++fix a bug, please let me know.
++
++George Anzinger
++<george@mvista.com>
++
++Amit S. Kale
++<akale@veritas.com>
++
++(First kgdb by David Grothe <dave@gcom.com>)
++
++(modified by Tigran Aivazian <tigran@sco.com>)
++ Putting gdbstub into the kernel config menu.
++
++(modified by Scott Foehner <sfoehner@engr.sgi.com>)
++ Hooks for entering gdbstub at boot time.
++
++(modified by Amit S. Kale <akale@veritas.com>)
++ Threads, ia-32 hw debugging, mp support, console support,
++ nmi watchdog handling.
++
++(modified by George Anzinger <george@mvista.com>)
++ Extended threads to include the idle threads.
++ Enhancements to allow breakpoint() at first C code.
++ Use of module_init() and __setup() to automate the configure.
++ Enhanced the cpu "collection" code to work in early bring-up.
++ Added ability to call functions from gdb
++ Print info thread stuff without going back to schedule()
++ Now collect the "other" cpus with an IPI/ NMI.
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/i386/kgdb/loadmodule.sh 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,78 @@
++#/bin/sh
++# This script loads a module on a target machine and generates a gdb script.
++# source generated gdb script to load the module file at appropriate addresses
++# in gdb.
++#
++# Usage:
++# Loading the module on target machine and generating gdb script)
++# [foo]$ loadmodule.sh <modulename>
++#
++# Loading the module file into gdb
++# (gdb) source <gdbscriptpath>
++#
++# Modify following variables according to your setup.
++# TESTMACHINE - Name of the target machine
++# GDBSCRIPTS - The directory where a gdb script will be generated
++#
++# Author: Amit S. Kale (akale@veritas.com).
++#
++# If you run into problems, please check files pointed to by following
++# variables.
++# ERRFILE - /tmp/<modulename>.errs contains stderr output of insmod
++# MAPFILE - /tmp/<modulename>.map contains stdout output of insmod
++# GDBSCRIPT - $GDBSCRIPTS/load<modulename> gdb script.
++
++TESTMACHINE=foo
++GDBSCRIPTS=/home/bar
++
++if [ $# -lt 1 ] ; then {
++ echo Usage: $0 modulefile
++ exit
++} ; fi
++
++MODULEFILE=$1
++MODULEFILEBASENAME=`basename $1`
++
++if [ $MODULEFILE = $MODULEFILEBASENAME ] ; then {
++ MODULEFILE=`pwd`/$MODULEFILE
++} fi
++
++ERRFILE=/tmp/$MODULEFILEBASENAME.errs
++MAPFILE=/tmp/$MODULEFILEBASENAME.map
++GDBSCRIPT=$GDBSCRIPTS/load$MODULEFILEBASENAME
++
++function findaddr() {
++ local ADDR=0x$(echo "$SEGMENTS" | \
++ grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \
++ sed 's/[ ]*[^ ]*$//')
++ echo $ADDR
++}
++
++function checkerrs() {
++ if [ "`cat $ERRFILE`" != "" ] ; then {
++ cat $ERRFILE
++ exit
++ } fi
++}
++
++#load the module
++echo Copying $MODULEFILE to $TESTMACHINE
++rcp $MODULEFILE root@${TESTMACHINE}:
++
++echo Loading module $MODULEFILE
++rsh -l root $TESTMACHINE /sbin/insmod -m ./`basename $MODULEFILE` \
++ > $MAPFILE 2> $ERRFILE
++checkerrs
++
++SEGMENTS=`head -n 11 $MAPFILE | tail -n 10`
++TEXTADDR=$(findaddr "\\.text[^.]")
++LOADSTRING="add-symbol-file $MODULEFILE $TEXTADDR"
++SEGADDRS=`echo "$SEGMENTS" | awk '//{
++ if ($1 != ".text" && $1 != ".this" &&
++ $1 != ".kstrtab" && $1 != ".kmodtab") {
++ print " -s " $1 " 0x" $3 " "
++ }
++}'`
++LOADSTRING="$LOADSTRING $SEGADDRS"
++echo Generating script $GDBSCRIPT
++echo $LOADSTRING > $GDBSCRIPT
+--- linux-2.6.0-test6/Documentation/ioctl-number.txt 2003-09-08 13:58:55.000000000 -0700
++++ 25/Documentation/ioctl-number.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -175,10 +175,6 @@ Code Seq# Include File Comments
+ <mailto:buk@buks.ipn.de>
+ 0xA0 all linux/sdp/sdp.h Industrial Device Project
+ <mailto:kenji@bitgate.com>
+-0xA2 00-0F DVD decoder driver in development:
+- <http://linuxtv.org/developer/dvdapi.html>
+-0xA3 00-1F Philips SAA7146 dirver in development:
+- <mailto:Andreas.Beckmann@hamburg.sc.philips.com>
+ 0xA3 80-8F Port ACL in development:
+ <mailto:tlewis@mindspring.com>
+ 0xA3 90-9F linux/dtlk.h
+--- linux-2.6.0-test6/Documentation/iostats.txt 2003-06-14 12:18:06.000000000 -0700
++++ 25/Documentation/iostats.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -1,22 +1,22 @@
+ I/O statistics fields
+ ---------------
+
+-Last modified 5/15/03
++Last modified Sep 30, 2003
+
+-In 2.4.20 (and some versions before, with patches), and 2.5.45,
+-more extensive disk statistics were introduced to help measure disk
++Since 2.4.20 (and some versions before, with patches), and 2.5.45,
++more extensive disk statistics have been introduced to help measure disk
+ activity. Tools such as sar and iostat typically interpret these and do
+ the work for you, but in case you are interested in creating your own
+ tools, the fields are explained here.
+
+-In most versions of the 2.4 patch, the information is found as additional
+-fields in /proc/partitions. In 2.5, the same information is found in
+-two places: one is in the file /proc/diskstats (appears in 2.5.69 and
+-beyond), and the other is within the sysfs file system, which must be
+-mounted in order to obtain the information. Throughout this document
+-we'll assume that sysfs is mounted on /sys, although of course it may
+-be mounted anywhere. In 2.5, both /proc/diskstats and sysfs use the
+-same source for the information and so should not differ.
++In 2.4 now, the information is found as additional fields in
++/proc/partitions. In 2.6, the same information is found in two
++places: one is in the file /proc/diskstats, and the other is within
++the sysfs file system, which must be mounted in order to obtain
++the information. Throughout this document we'll assume that sysfs
++is mounted on /sys, although of course it may be mounted anywhere.
++Both /proc/diskstats and sysfs use the same source for the information
++and so should not differ.
+
+ Here are examples of these different formats:
+
+@@ -25,15 +25,15 @@ Here are examples of these different for
+ 3 1 9221278 hda1 35486 0 35496 38030 0 0 0 0 0 38030 38030
+
+
+-2.5 sysfs:
++2.6 sysfs:
+ 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
+ 35486 38030 38030 38030
+
+-2.5 diskstats:
++2.6 diskstats:
+ 3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160
+ 3 1 hda1 35486 38030 38030 38030
+
+-On 2.4 you might execute "grep 'hda ' /proc/partitions". On 2.5, you have
++On 2.4 you might execute "grep 'hda ' /proc/partitions". On 2.6, you have
+ a choice of "cat /sys/block/hda/stat" or "grep 'hda ' /proc/diskstats".
+ The advantage of one over the other is that the sysfs choice works well
+ if you are watching a known, small set of disks. /proc/diskstats may
+@@ -43,7 +43,7 @@ each snapshot of your disk statistics.
+
+ In 2.4, the statistics fields are those after the device name. In
+ the above example, the first field of statistics would be 446216.
+-By contrast, in 2.5 if you look at /sys/block/hda/stat, you'll
++By contrast, in 2.6 if you look at /sys/block/hda/stat, you'll
+ find just the eleven fields, beginning with 446216. If you look at
+ /proc/diskstats, the eleven fields will be preceded by the major and
+ minor device numbers, and device name. Each of these formats provide
+@@ -93,35 +93,35 @@ Field 11 -- weighted # of milliseconds s
+ To avoid introducing performance bottlenecks, no locks are held while
+ modifying these counters. This implies that minor inaccuracies may be
+ introduced when changes collide, so (for instance) adding up all the
+-read I/Os issued per partition should equal those made to the disks
+-... but due to the lack of locking it may only be very close.
++read I/Os issued per partition should equal those made to the disks ...
++but due to the lack of locking it may only be very close.
+
+-In release 2.5.65 the 2.5 counters were made per-cpu, which made the lack
+-of locking almost a non-issue. When the statistics are read, the per-cpu
+-counters are summed (possibly overflowing the unsigned 32-bit variable
+-they are summed to) and the result given to the user. There is no
+-convenient user interface for accessing the per-cpu counters themselves.
++In 2.6, there are counters for each cpu, which made the lack of locking
++almost a non-issue. When the statistics are read, the per-cpu counters
++are summed (possibly overflowing the unsigned 32-bit variable they are
++summed to) and the result given to the user. There is no convenient
++user interface for accessing the per-cpu counters themselves.
+
+ Disks vs Partitions
+ -------------------
+
+-There were significant changes between 2.4 and 2.5 in the I/O subsystem.
++There were significant changes between 2.4 and 2.6 in the I/O subsystem.
+ As a result, some statistic information disappeared. The translation from
+ a disk address relative to a partition to the disk address relative to
+ the host disk happens much earlier. All merges and timings now happen
+ at the disk level rather than at both the disk and partition level as
+-in 2.4. Consequently, you'll see a different statistics output on 2.5 for
++in 2.4. Consequently, you'll see a different statistics output on 2.6 for
+ partitions from that for disks. There are only *four* fields available
+-for partitions on 2.5 machines. This is reflected in the examples above.
++for partitions on 2.6 machines. This is reflected in the examples above.
+
+ Field 1 -- # of reads issued
+ This is the total number of reads issued to this partition.
+ Field 2 -- # of sectors read
+ This is the total number of sectors requested to be read from this
+ partition.
+-Field 3 -- # of reads issued
++Field 3 -- # of writes issued
+ This is the total number of writes issued to this partition.
+-Field 4 -- # of sectors read
++Field 4 -- # of sectors written
+ This is the total number of sectors requested to be written to
+ this partition.
+
+@@ -135,14 +135,16 @@ a subtle distinction that is probably un
+ Additional notes
+ ----------------
+
+-In 2.5, sysfs is not mounted by default. Here's the line you'll want
+-to add to your /etc/fstab:
++In 2.6, sysfs is not mounted by default. If your distribution of
++Linux hasn't added it already, here's the line you'll want to add to
++your /etc/fstab:
+
+ none /sys sysfs defaults 0 0
+
+
+-In 2.5, at the same time that disk statistics appeared in sysfs, they were
+-removed from /proc/stat. In 2.4, they appear in both /proc/partitions
+-and /proc/stat.
++In 2.6, all disk statistics were removed from /proc/stat. In 2.4, they
++appear in both /proc/partitions and /proc/stat, although the ones in
++/proc/stat take a very different format from those in /proc/partitions
++(see proc(5), if your system has it.)
+
+ -- ricklind@us.ibm.com
+--- linux-2.6.0-test6/Documentation/kernel-parameters.txt 2003-09-27 18:57:43.000000000 -0700
++++ 25/Documentation/kernel-parameters.txt 2003-10-05 00:34:33.000000000 -0700
+@@ -460,6 +460,10 @@ running once the system is up.
+ logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver
+ Format: <irq>
+
++ log_buf_len=n Sets the size of the printk ring buffer, in bytes.
++ Format is n, nk, nM. n must be a power of two. The
++ default is set in kernel config.
++
+ lp=0 [LP] Specify parallel ports to use, e.g,
+ lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses
+ lp=reset first parallel port). 'lp=0' disables the
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/MSI-HOWTO.txt 2003-10-05 00:36:20.000000000 -0700
+@@ -0,0 +1,321 @@
++ The MSI Driver Guide HOWTO
++ Tom L Nguyen tom.l.nguyen@intel.com
++ 10/03/2003
++
++1. About this guide
++
++This guide describes the basics of Message Signaled Interrupts(MSI), the
++advantages of using MSI over traditional interrupt mechanisms, and how
++to enable your driver to use MSI or MSI-X. Also included is a Frequently
++Asked Questions.
++
++2. Copyright 2003 Intel Corporation
++
++3. What is MSI/MSI-X?
++
++Message Signaled Interrupt (MSI), as described in the PCI Local Bus
++Specification Revision 2.3 or latest, is an optional feature, and a
++required feature for PCI Express devices. MSI enables a device function
++to request service by sending an Inbound Memory Write on its PCI bus to
++the FSB as a Message Signal Interrupt transaction. Because MSI is
++generated in the form of a Memory Write, all transaction conditions,
++such as a Retry, Master-Abort, Target-Abort or normal completion, are
++supported.
++
++A PCI device that supports MSI must also support pin IRQ assertion
++interrupt mechanism to provide backward compatibility for systems that
++do not support MSI. In Systems, which support MSI, the bus driver is
++responsible for initializing the message address and message data of
++the device function's MSI/MSI-X capability structure during device
++initial configuration.
++
++An MSI capable device function indicates MSI support by implementing
++the MSI/MSI-X capability structure in its PCI capability list. The
++device function may implement both the MSI capability structure and
++the MSI-X capability structure; however, the bus driver should not
++enable both, but instead enable only the MSI-X capability structure.
++
++The MSI capability structure contains Message Control register,
++Message Address register and Message Data register. These registers
++provide the bus driver control over MSI. The Message Control register
++indicates the MSI capability supported by the device. The Message
++Address register specifies the target address and the Message Data
++register specifies the characteristics of the message. To request
++service, the device function writes the content of the Message Data
++register to the target address. The device and its software driver
++are prohibited from writing to these registers.
++
++The MSI-X capability structure is an optional extension to MSI. It
++uses an independent and separate capability structure. There are
++some key advantages to implementing the MSI-X capability structure
++over the MSI capability structure as described below.
++
++ - Support a larger maximum number of vectors per function.
++
++ - Provide the ability for system software to configure
++ each vector with an independent message address and message
++ data, specified by a table that resides in Memory Space.
++
++ - MSI and MSI-X both support per-vector masking. Per-vector
++ masking is an optional extension of MSI but a required
++ feature for MSI-X. Per-vector masking provides the kernel
++ the ability to mask/unmask MSI when servicing its software
++ interrupt service routing handler. If per-vector masking is
++ not supported, then the device driver should provide the
++ hardware/software synchronization to ensure that the device
++ generates MSI when the driver wants it to do so.
++
++4. Why use MSI?
++
++As a benefit the simplification of board design, MSI allows board
++designers to remove out of band interrupt routing. MSI is another
++step towards a legacy-free environment.
++
++Due to increasing pressure on chipset and processor packages to
++reduce pin count, the need for interrupt pins is expected to
++diminish over time. Devices, due to pin constraints, may implement
++messages to increase performance.
++
++PCI Express endpoints uses INTx emulation (in-band messages) instead
++of IRQ pin assertion. Using INTx emulation requires interrupt
++sharing among devices connected to the same node (PCI bridge) while
++MSI is unique (non-shared) and does not require BIOS configuration
++support. As a result, the PCI Express technology requires MSI
++support for better interrupt performance.
++
++Using MSI enables the device functions to support two or more
++vectors, which can be configure to target different CPU's to
++increase scalability.
++
++5. Configuring a driver to use MSI/MSI-X
++
++By default, the kernel will not enable MSI/MSI-X on all devices that
++support this capability once the patch is installed. A kernel
++configuration option must be selected to enable MSI/MSI-X support.
++
++5.1 Including MSI support into the kernel
++
++To include MSI support into the kernel requires users to patch the
++VECTOR-base patch first and then the MSI patch because the MSI
++support needs VECTOR based scheme. Once these patches are installed,
++setting CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and
++the option for MSI-capable device drivers to selectively enable MSI
++(using pci_enable_msi as desribed below).
++
++Since the target of the inbound message is the local APIC, providing
++CONFIG_PCI_USE_VECTOR is dependent on whether CONFIG_X86_LOCAL_APIC
++is enabled or not.
++
++int pci_enable_msi(struct pci_dev *)
++
++With this new API, any existing device driver, which like to have
++MSI enabled on its device function, must call this explicitly. A
++successful call will initialize the MSI/MSI-X capability structure
++with ONE vector, regardless of whether the device function is
++capable of supporting multiple messages. This vector replaces the
++pre-assigned dev->irq with a new MSI vector. To avoid the conflict
++of new assigned vector with existing pre-assigned vector requires
++the device driver to call this API before calling request_irq(...).
++
++The below diagram shows the events, which switches the interrupt
++mode on the MSI-capable device function between MSI mode and
++PIN-IRQ assertion mode.
++
++ ------------ pci_enable_msi ------------------------
++ | | <=============== | |
++ | MSI MODE | | PIN-IRQ ASSERTION MODE |
++ | | ===============> | |
++ ------------ free_irq ------------------------
++
++5.2 Configuring for MSI support
++
++Due to the non-contiguous fashion in vector assignment of the
++existing Linux kernel, this patch does not support multiple
++messages regardless of the device function is capable of supporting
++more than one vector. The bus driver initializes only entry 0 of
++this capability if pci_enable_msi(...) is called successfully by
++the device driver.
++
++5.3 Configuring for MSI-X support
++
++Both the MSI capability structure and the MSI-X capability structure
++share the same above semantics; however, due to the ability of the
++system software to configure each vector of the MSI-X capability
++structure with an independent message address and message data, the
++non-contiguous fashion in vector assignment of the existing Linux
++kernel has no impact on supporting multiple messages on an MSI-X
++capable device functions. By default, as mentioned above, ONE vector
++should be always allocated to the MSI-X capability structure at
++entry 0. The bus driver does not initialize other entries of the
++MSI-X table.
++
++Note that the PCI subsystem should have full control of a MSI-X
++table that resides in Memory Space. The software device driver
++should not access this table.
++
++To request for additional vectors, the device software driver should
++call function msi_alloc_vectors(). It is recommended that the
++software driver should call this function once during the
++initialization phase of the device driver.
++
++The function msi_alloc_vectors(), once invoked, enables either
++all or nothing, depending on the current availability of vector
++resources. If no vector resources are available, the device function
++still works with ONE vector. If the vector resources are available
++for the number of vectors requested by the driver, this function
++will reconfigure the MSI-X capability structure of the device with
++additional messages, starting from entry 1. To emphasize this
++reason, for example, the device may be capable for supporting the
++maximum of 32 vectors while its software driver usually may request
++4 vectors.
++
++For each vector, after this successful call, the device driver is
++responsible to call other functions like request_irq(), enable_irq(),
++etc. to enable this vector with its corresponding interrupt service
++handler. It is the device driver's choice to have all vectors shared
++the same interrupt service handler or each vector with a unique
++interrupt service handler.
++
++In addition to the function msi_alloc_vectors(), another function
++msi_free_vectors() is provided to allow the software driver to
++release a number of vectors back to the vector resources. Once
++invoked, the PCI subsystem disables (masks) each vector released.
++These vectors are no longer valid for the hardware device and its
++software driver to use. Like free_irq, it recommends that the
++device driver should also call msi_free_vectors to release all
++additional vectors previously requested.
++
++int msi_alloc_vectors(struct pci_dev *dev, int *vector, int nvec)
++
++This API enables the software driver to request the PCI subsystem
++for additional messages. Depending on the number of vectors
++available, the PCI subsystem enables either all or nothing.
++
++Argument dev points to the device (pci_dev) structure.
++Argument vector is a pointer of integer type. The number of
++elements is indicated in argument nvec.
++Argument nvec is an integer indicating the number of messages
++requested.
++A return of zero indicates that the number of allocated vector is
++successfully allocated. Otherwise, indicate resources not
++available.
++
++int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec)
++
++This API enables the software driver to inform the PCI subsystem
++that it is willing to release a number of vectors back to the
++MSI resource pool. Once invoked, the PCI subsystem disables each
++MSI-X entry associated with each vector stored in the argument 2.
++These vectors are no longer valid for the hardware device and
++its software driver to use.
++
++Argument dev points to the device (pci_dev) structure.
++Argument vector is a pointer of integer type. The number of
++elements is indicated in argument nvec.
++Argument nvec is an integer indicating the number of messages
++released.
++A return of zero indicates that the number of allocated vectors
++is successfully released. Otherwise, indicates a failure.
++
++5.4 Hardware requirements for MSI support
++MSI support requires support from both system hardware and
++individual hardware device functions.
++
++5.4.1 System hardware support
++Since the target of MSI address is the local APIC CPU, enabling
++MSI support in Linux kernel is dependent on whether existing
++system hardware supports local APIC. Users should verify their
++system whether it runs when CONFIG_X86_LOCAL_APIC=y.
++
++In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set;
++however, in UP environment, users must manually set
++CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
++CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and
++the option for MSI-capable device drivers to selectively enable
++MSI (using pci_enable_msi as desribed below).
++
++Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI
++vector is allocated new during runtime and MSI support does not
++depend on BIOS support. This key independency enables MSI support
++on future IOxAPIC free platform.
++
++5.4.2 Device hardware support
++The hardware device function supports MSI by indicating the
++MSI/MSI-X capability structure on its PCI capability list. By
++default, this capability structure will not be initialized by
++the kernel to enable MSI during the system boot. In other words,
++the device function is running on its default pin assertion mode.
++Note that in many cases the hardware supporting MSI have bugs,
++which may result in system hang. The software driver of specific
++MSI-capable hardware is responsible for whether calling
++pci_enable_msi or not. A return of zero indicates the kernel
++successfully initializes the MSI/MSI-X capability structure of the
++device funtion. The device function is now running on MSI mode.
++
++5.5 How to tell whether MSI is enabled on device function
++
++At the driver level, a return of zero from pci_enable_msi(...)
++indicates to the device driver that its device function is
++initialized successfully and ready to run in MSI mode.
++
++At the user level, users can use command 'cat /proc/interrupts'
++to display the vector allocated for the device and its interrupt
++mode, as shown below.
++
++ CPU0 CPU1
++ 0: 324639 0 IO-APIC-edge timer
++ 1: 1186 0 IO-APIC-edge i8042
++ 2: 0 0 XT-PIC cascade
++ 12: 2797 0 IO-APIC-edge i8042
++ 14: 6543 0 IO-APIC-edge ide0
++ 15: 1 0 IO-APIC-edge ide1
++169: 0 0 IO-APIC-level uhci-hcd
++185: 0 0 IO-APIC-level uhci-hcd
++193: 138 10 PCI MSI aic79xx
++201: 30 0 PCI MSI aic79xx
++225: 30 0 IO-APIC-level aic7xxx
++233: 30 0 IO-APIC-level aic7xxx
++NMI: 0 0
++LOC: 324553 325068
++ERR: 0
++MIS: 0
++
++6. FAQ
++
++Q1. Are there any limitations on using the MSI?
++
++A1. If the PCI device supports MSI and conforms to the
++specification and the platform supports the APIC local bus,
++then using MSI should work.
++
++Q2. Will it work on all the Pentium processors (P3, P4, Xeon,
++AMD processors)? In P3 IPI's are transmitted on the APIC local
++bus and in P4 and Xeon they are transmitted on the system
++bus. Are there any implications with this?
++
++A2. MSI support enables a PCI device sending an inbound
++memory write (0xfeexxxxx as target address) on its PCI bus
++directly to the FSB. Since the message address has a
++redirection hint bit cleared, it should work.
++
++Q3. The target address 0xfeexxxxx will be translated by the
++Host Bridge into an interrupt message. Are there any
++limitations on the chipsets such as Intel 8xx, Intel e7xxx,
++or VIA?
++
++A3. If these chipsets support an inbound memory write with
++target address set as 0xfeexxxxx, as conformed to PCI
++specification 2.3 or latest, then it should work.
++
++Q4. From the driver point of view, if the MSI is lost because
++of the errors occur during inbound memory write, then it may
++wait for ever. Is there a mechanism for it to recover?
++
++A4. Since the target of the transaction is an inbound memory
++write, all transaction termination conditions (Retry,
++Master-Abort, Target-Abort, or normal completion) are
++supported. A device sending an MSI must abide by all the PCI
++rules and conditions regarding that inbound memory write. So,
++if a retry is signaled it must retry, etc... We believe that
++the recommendation for Abort is also a retry (refer to PCI
++specification 2.3 or latest).
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/must-fix.txt 2003-10-05 00:33:51.000000000 -0700
+@@ -0,0 +1,354 @@
++
++Must-fix bugs
++=============
++
++drivers/char/
++~~~~~~~~~~~~~
++
++o TTY locking is broken.
++
++ o see FIXME in do_tty_hangup(). This causes ppp BUGs in local_bh_enable()
++
++ o Other problems: aviro, dipankar, Alan have details.
++
++ o somebody will have to document the tty driver and ldisc API
++
++o Lack of test cases and/or stress tests is a problem. Contributions and
++ suggestions are sought.
++
++o Lots of drivers are using cli/sti and are broken.
++
++drivers/tty
++~~~~~~~~~~~
++
++o viro: we need to fix refcounting for tty_driver (oopsable race, must fix
++ anyway, hopefully about a week until it's merged) then we can do
++ tty/misc/upper levels of sound.
++
++drivers/block/
++~~~~~~~~~~~~~~
++
++o ideraid hasn't been ported to 2.5 at all yet.
++
++ We need to understand whether the proposed BIO split code will suffice
++ for this.
++
++o CD burning. There are still a few quirks to solve wrt SG_IO and ide-cd.
++
++ Jens: The basic hang has been solved (double fault in ide-cd), there still
++ seems to be some cases that don't work too well. Don't really have a
++ handle on those :/
++
++o lmb: Last time I looked at the multipath code (2.5.50 or so) it also
++ looked pretty broken; I plan to port forward the changes we did on 2.4
++ before KS.
++
++drivers/input/
++~~~~~~~~~~~~~~
++
++o rmk: unconverted keyboard/mouse drivers (there's a deadline of 2.6.0
++ currently on these remaining in my/Linus' tree.)
++
++o viro: large absence of locking.
++
++o viro: parport is nearly as bad as that and there the code is more hairy.
++ IMO parport is more of "figure out what API changes are needed for its
++ users, get them done ASAP, then fix generic layer at leisure"
++
++o (Albert Cahalan) Lots of people (check Google) get this message from the
++ kernel:
++
++ psmouse.c: Lost synchronization, throwing 2 bytes away.
++
++ (the number of bytes will be 1, 2, or 3)
++
++ At work, I get it when there is heavy NFS traffic. The mouse goes crazy,
++ jumping around and doing random cut-and-paste all over everything. This
++ is with a decently fast and modern PC.
++
++o There seem to be too many reports of keyboards and mice failing or acting
++ strangely.
++
++
++drivers/misc/
++~~~~~~~~~~~~~
++
++o rmk: UCB1[23]00 drivers, currently sitting in drivers/misc in the ARM
++ tree. (touchscreen, audio, gpio, type device.)
++
++ These need to be moved out of drivers/misc/ and into real places
++
++o viro: actually, misc.c has a good chance to die. With cdev-cidr that's
++ trivial.
++
++drivers/net/
++~~~~~~~~~~~~
++
++o rmk: network drivers. ARM people like to add tonnes of #ifdefs into
++ these to customise them to their hardware platform (eg, chip access
++ methods, addresses, etc.) I cope with this by not integrating them into my
++ tree. The result is that many ARM platforms can't be built from even my
++ tree without extra patches. This isn't sane, and has bred a culture of
++ network drivers not being submitted. I don't see this changing for 2.6
++ though.
++
++drivers/net/irda/
++~~~~~~~~~~~~~~~~~
++
++o dongle drivers need to be converted to sir-dev
++
++o irport need to be converted to sir-kthread
++
++o new drivers (irtty-sir/smsc-ircc2/donauboe) need more testing
++
++o rmk: Refuse IrDA initialisation if sizeof(structures) is incorrect (I'm
++ not sure if we still need this; I think gcc 2.95.3 on ARM shows this
++ problem though.)
++
++drivers/pci/
++~~~~~~~~~~~~
++
++o alan: Some cardbus crashes the system
++
++ (bugzilla, please?)
++
++drivers/pcmcia/
++~~~~~~~~~~~~~~~
++
++o alan: This is a locking disaster.
++
++ (rmk, brodo: in progress)
++
++drivers/pld/
++~~~~~~~~~~~~
++
++o rmk: EPXA (ARM platform) PLD hotswap drivers (drivers/pld)
++
++ (rmk: will work out what to do here. maybe drivers/arm/)
++
++drivers/video/
++~~~~~~~~~~~~~~
++
++o Lots of drivers don't compile, others do but don't work.
++
++drivers/scsi/
++~~~~~~~~~~~~~
++
++o hch: large parts of the locking are hosed or not existant
++
++ (Mike Anderson, Patrick Mansfield, Badari Pulavarty)
++
++ o shost->my_devices isn't locked down at all
++
++ o there are lots of members of struct Scsi_Host/scsi_device/scsi_cmnd
++ with very unclear locking, many of them probably want to become
++ atomic_t's or bitmaps (for the 1bit bitfields).
++
++ o there's lots of volatile abuse in the scsi code that needs to be
++ thought about.
++
++ o there's some global variables incremented without any locks
++
++o Convert am53c974, dpt_i2o, initio and pci2220i to DMA-mapping
++
++o Make inia100, cpqfc, pci2000 and dc390t compile
++
++o Convert
++
++ wd33c99 based: a2091 a3000 gpv11 mvme174 sgiwd93
++
++ 53c7xx based: amiga7xxx bvme6000 mvme16x initio am53c974 pci2000
++ pci2220i dc390t
++
++ To new error handling
++
++ It also might be possible to shift the 53c7xx based drivers over to
++ 53c700 which does the new EH stuff, but I don't have the hardware to check
++ such a shift.
++
++ For the non-compiling stuff, I've probably missed a few that just aren't
++ compilable on my platforms, so any updates would be welcome. Also, are
++ some of our non-compiling or unconverted drivers obsolete?
++
++o rmk: I have a pending todo: I need to put the scsi error handling through
++ a workout on my scsi bus from hell to make sure it does the right thing
++ and doesn't get wedged.
++
++o James B: USB hot-removal crash: "It's a known scsi refcounting issue."
++
++fs/
++~~~
++
++o AIO/direct-IO writes can race with truncate and wreck filesystems.
++ (Badari has a patch)
++
++o hch: devfs: there's a fundamental lookup vs devfsd race that's only
++ fixable by introducing a lookup vs devfs deadlock. I can't see how this is
++ fixable without getting rid of the current devfsd design. Mandrake seems
++ to have a workaround for this so this is at least not triggered so easily,
++ but that's not what I'd consider a fix..
++
++o viro: fs/char_dev.c needs removal of aeb stuff and merge of cdev-cidr.
++ In progress.
++
++o forward-port sct's O_DIRECT fixes (Badari has a patch)
++
++o viro: there is some generic stuff for namei/namespace/super, but that's a
++ slow-merge and can go in 2.6 just fine
++
++o andi: also soft needs to be fixed - there are quite a lot of
++ uninterruptible waits in sunrpc/nfs
++
++o trond: NFS has a mmap-versus-truncate problem
++
++kernel/sched.c
++~~~~~~~~~~~~~~
++
++o Starvation, general interactivity need close monitoring.
++
++kernel/
++~~~~~~~
++
++o Alan: 32bit uid support is *still* broken for process accounting.
++
++ Create a 32bit uid, turn accounting on. Shock horror it doesn't work
++ because the field is 16bit. We need an acct structure flag day for 2.6
++ IMHO
++
++ (alan has patch)
++
++o viro: core sysctl code is racy. And its interaction wiuth sysfs
++
++o (ingo) rwsems (on x86) are limited to 32766 waiting processes. This
++ means that setting pid_max to above 32K is unsafe :-(
++
++ An option is to use CONFIG_RWSEM_GENERIC_SPINLOCK variant all the time,
++ for all archs, and not inline any part of the ops.
++
++lib/kobject.c
++~~~~~~~~~~~~~
++
++o kobject refcounting (comments from Al Viro):
++
++ _anything_ can grab a temporary reference to kobject. IOW, if kobject is
++ embedded into something that could be freed - it _MUST_ have a destructor
++ and that destructor _MUST_ be the destructor for containing object.
++
++ Any violation of the above (and we already have a bunch of those) is a
++ user-triggerable memory corruption.
++
++ We can tolerate it for a while in 2.5 (e.g. during work on susbsystem we
++ can decide to switch to that way of handling objects and have subsystem
++ vulnerable for a while), but all such windows must be closed before 2.6
++ and during 2.6 we can't open them at all.
++
++o All block drivers which control multiple gendisks with a single
++ request_queue are broken, due to one-to-one assumptions in the request
++ queue sysfs hookup.
++
++mm/
++~~~
++
++o GFP_DMA32 (or something like that). Lots of ideas. jejb, zaitcev,
++ willy, arjan, wli.
++
++ Specifically, 64-bit systems need to be able to enforce 32-bit addressing
++ limits for device metadata like network cards' ring buffers and SCSI
++ command descriptors.
++
++o access_process_vm() doesn't flush right. We probably need new flushing
++ primitives to do this (davem?)
++
++
++modules
++~~~~~~~
++
++ (Rusty)
++
++net/
++~~~~
++
++ (davem)
++
++o UDP apps can in theory deadlock, because the ip_append_data path can end
++ up sleeping while the socket lock is held.
++
++ It is OK to sleep with the socket held held, normally. But in this case
++ the sleep happens while waiting for socket memory/space to become
++ available, if another context needs to take the socket lock to free up the
++ space we could hang.
++
++ I sent a rough patch on how to fix this to Alexey, and he is analyzing
++ the situation. I expect a final fix from him next week or so.
++
++o Semantics for IPSEC during operations such as TCP connect suck currently.
++
++ When we first try to connect to a destination, we may need to ask the
++ IPSEC key management daemon to resolve the IPSEC routes for us. For the
++ purposes of what the kernel needs to do, you can think of it like ARP. We
++ can't send the packet out properly until we resolve the path.
++
++ What happens now for IPSEC is basically this:
++
++ O_NONBLOCK: returns -EAGAIN over and over until route is resolved
++
++ !O_NONBLOCK: Sleeps until route is resolved
++
++ These semantics are total crap. The solution, which Alexey is working
++ on, is to allow incomplete routes to exist. These "incomplete" routes
++ merely put the packet onto a "resolution queue", and once the key manager
++ does it's thing we finish the output of the packet. This is precisely how
++ ARP works.
++
++ I don't know when Alexey will be done with this.
++
++net/*/netfilter/
++~~~~~~~~~~~~~~~~
++
++ (Rusty)
++
++o Rework conntrack hashing.
++
++o Module relationship bogosity fix (trivial, have patch).
++
++sound/
++~~~~~~
++
++o rmk: several OSS drivers for SA11xx-based hardware in need of
++ ALSA-ification and L3 bus support code for these.
++
++o rmk: linux/sound/drivers/mpu401/mpu401.c and
++ linux/sound/drivers/virmidi.c complained about 'errno' at some time in the
++ past, need to confirm whether this is still a problem.
++
++o rmk: need to complete ALSA-ification of the WaveArtist driver for both
++ NetWinder and other stuff (there's some fairly fundamental differences in
++ the way the mixer needs to be handled for the NetWinder.)
++
++
++ (Issues with forward-porting 2.4 bugfixes.)
++ (Killing off OSS is 2.7 material)
++
++
++global
++~~~~~~
++
++o 64-bit dev_t. Seems almost ready, but it's not really known how much
++ work is still to do. Patches exist in -mm but with the recent rise of the
++ neo-viro I'm not sure where things are at.
++
++o Lots of 2.4 fixes including some security are not in 2.5
++
++o There are about 60 or 70 security related checks that need doing
++ (copy_user etc) from Stanford tools. (badari is looking into this, and
++ hollisb)
++
++o A couple of hundred real looking bugzilla bugs
++
++o viro: cdev rework. Main group is pretty stable and I hope to feed it to
++ Linus RSN. That's cdev-cidr and ->i_cdev/->i_cindex stuff
++
++o Athlon prefetch oopses sometimes. It is currently disabled, and needs to
++ be fixed.
++
++
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/Documentation/should-fix.txt 2003-10-05 00:33:52.000000000 -0700
+@@ -0,0 +1,611 @@
++Not-ready features and speedups
++===============================
++
++Legend:
++
++PRI1: We're totally lame if this doesn't get in
++PRI2: Would be nice
++PRI3: Not very important
++
++drivers/block/
++~~~~~~~~~~~~~~
++
++o Framework for selecting IO schedulers. This is the main one really.
++ Once this is in place we can drop in new schedulers any old time, no risk.
++ Nick Piggin has code for this.
++
++ PRI1
++
++o viro: paride drivers need a big cleanup
++
++ PRI2
++
++drivers/char/rtc/
++~~~~~~~~~~~~~~~~~
++
++o rmk, trini: add support for alarms to the existing generic rtc driver.
++
++ PRI2
++
++console drivers
++~~~~~~~~~~~~~~~
++ (Pavel Machek <pavel@ucw.cz>)
++
++o There are few must-fix bugs in cursor handling.
++
++o Play with gpm selection for a while and your cursor gets corrupted with
++ random dots. Ouch.
++
++device mapper
++~~~~~~~~~~~~~
++
++o ioctl interface cleanup patch is ready (redo the structure layouts)
++
++ PRI1
++
++o A port of the 2.4 snapshot and mirror targets is in progress
++
++ PRI1
++
++o the fs interface to dm needs to be redone. gregkh was going to work on
++ this. viro is interested in seeing work thus-far.
++
++ PRI2
++
++drivers/net/wireless/
++~~~~~~~~~~~~~~~~~~~~~
++
++ (Jean Tourrilhes <jt@bougret.hpl.hp.com>)
++
++o get latest orinoco changes from David.
++
++ PRI1
++
++o get the latest airo.c fixes from CVS. This will hopefully fix problems
++ people have reported on the LKML.
++
++ PRI1
++
++o get HostAP driver in the kernel. No consolidation of the 802.11
++ management across driver can happen until this one is in (which is probably
++ 2.7.X material). I think Jouni is mostly ready but didn't find time for
++ it.
++
++ PRI2
++
++o get more wireless drivers into the kernel. The most "integrable" drivers
++ at this point seem the NWN driver, Pavel's Spectrum driver and the Atmel
++ driver.
++
++ PRI1
++
++o The last two drivers mentioned above are held up by firmware issues (see
++ flamewar on LKML a few days ago). So maybe fixing those firmware issues
++ should be a requirement for 2.6.X, because we can expect more wireless
++ devices to need firmware upload at startup coming to market.
++
++ (in progress?)
++
++ PRI1
++
++drivers/usb/gadget/
++~~~~~~~~~~~~~~~~~~~
++
++o rmk: SA11xx USB client/gadget code (David B has been doing some work on
++ this, and keeps trying to prod me, but unfortunately I haven't had the time
++ to look at his work, sorry David.)
++
++ PRI3
++
++fs/
++~~~
++
++o ext3 and ext2 block allocators have serious failure modes - interleaved
++ allocations.
++
++ PRI3
++
++o Integrate Chris Mason's 2.4 reiserfs ordered data and data journaling
++ patches. They make reiserfs a lot safer.
++
++ Ordered: PRI2
++ data journalled: PRI3
++
++o (Trond:) Yes: I'm still working on an atomic "open()", i.e. one
++ where we short-circuit the usual VFS path_walk() + lookup() +
++ permission() + create() + .... bullsh*t...
++
++ I have several reasons for wanting to do this (all of
++ them related to NFS of course, but much of the reasoning applies
++ to *all* networked file systems).
++
++ 1) The above sequence is simply not atomic on *any* networked
++ filesystem.
++
++ 2) It introduces a sh*tload of completely unnecessary RPC calls (why
++ do a 'permission' RPC call when the server is in *any* case going to
++ tell you whether or not this operations is allowed. Why do a
++ 'lookup()' when the 'create()' call can be made to tell you whether or
++ not a file already exists).
++
++ 3) It is incompatible with some operations: the current create()
++ doesn't pass an 'EXCLUSIVE' flag down to the filesystems.
++
++ 4) (NFS specific?) open() has very different cache consistency
++ requirements when compared to most other VFS operations.
++
++ I'd very much like for something like Peter Braam's 'lookup with
++ intent' or (better yet) for a proper dentry->open() to be integrated with
++ path_walk()/open_namei(). I'm still working on the latter (Peter has
++ already completed the lookup with intent stuff).
++
++ (All this is in progress, see http://www.fys.uio.no/~trondmy/src)
++
++ (Is awaiting Pater Braam's intent patches. Applicable to CIFS)
++
++ PRI2 (?)
++
++o (Chuck Lever <cel@citi.umich.edu>): NFS O_DIRECT support must be
++ completed. The best approach is to fall back to something like the 2.4 NFS
++ O_DIRECT support, which issues RPCs synchronously and uses the RPC
++ completion mechanism to wait for I/O completion.
++
++ PRI2
++
++o viro: cleaning up options-parsers in filesystems. (patch exists, needs
++ porting).
++
++ PRI2
++
++o aio: fs IO isn't async at present. suparna has restart patches, they're
++ in -mm. Need to get Ben to review/comment.
++
++ PRI1.
++
++o drepper: various filesystems use ->pid wrongly
++
++kernel/
++~~~~~~~
++
++o rusty: Zippel's Reference count simplification. Tricky code, but cuts
++ about 120 lines from module.c. Patch exists, needs stressing.
++
++ PRI3
++
++o rusty: Fix module-failed-init races by starting module "disabled". Patch
++ exists, requires some subsystems (ie. add_partition) to explicitly say
++ "make module live now". Without patch we are no worse off than 2.4 etc.
++
++ PRI1
++
++o Integrate userspace irq balancing daemon.
++
++ PRI2
++
++o kexec. Seems to work, was in -mm.
++
++ PRI3
++
++o rmk: lib/inflate.c must not use static variables (causes these to be
++ referenced via GOTOFF relocations in PIC decompressor. We have a PIC
++ decompressor to avoid having to hard code a per platform zImage link
++ address into the makefiles.)
++
++ PRI2
++
++o klibc merge?
++
++ PRI2
++
++mm/
++~~~
++
++o objrmap: concerns over page reclaim performance at high sharing levels,
++ and interoperation with nonlinear mappings is hairy.
++
++o oxymoron's async write-error-handling patch
++
++ PRI1
++
++o dropbehind for large files
++
++ PRI2
++
++net/
++~~~~
++
++ (davem)
++
++o Real serious use of IPSEC is hampered by lack of MPLS support. MPLS is a
++ switching technology that works by switching based upon fixed length labels
++ prepended to packets. Many people use this and IPSEC to implement VPNs
++ over public networks, it is also used for things like traffic engineering.
++
++ A good reference site is:
++
++ http://www.mplsrc.com/
++
++ Anyways, an existing (crappy) implementation exists. I've almost
++ completed a rewrite, I should have something in the tree next week.
++
++ PRI1
++
++o Sometimes we generate IP fragments when it truly isn't necessary.
++
++ The way IP fragmentation is specified, each fragment must be modulo 8
++ bytes in length. So suppose the device has an MTU that is not 0 modulo 8,
++ ethernet even classifies in this way. 1500 == (8 * 187) + 4
++
++ Our IP fragmenting engine can fragment on packets that are sized within
++ the last modulo 8 bytes of the MTU. This happens in obscure cases, but it
++ does happen.
++
++ I've proposed a fix to Alexey, whereby very late in the output path we
++ check the packet, if we fragmented but the data length would fit into the
++ MTU we unfragment the packet.
++
++ This is low priority, because technically it creates suboptimal behavior
++ rather than mis-operation.
++
++ PRI1
++
++net/*/netfilter/
++~~~~~~~~~~~~~~~~
++
++o Lots of misc. cleanups, which are happening slowly.
++
++ PRI2
++
++power management
++~~~~~~~~~~~~~~~~
++
++o PM code in mainline is currently b0rked. Fixes in -mm
++
++ PRI1
++
++o Pat and Pavel disagree over swsusp. Need to sort that out.
++
++ PRI2
++
++o Frame buffer restore codepaths (that requires some deep PCI magic)
++
++ PRI2
++
++o XFree86 hooks
++
++ PRI2
++
++o AGP restoration
++
++ PRI2
++
++o DRI restoration
++
++ (davej/Alan: not super-critical, can crash laptop on restore. davej
++ looking into it.)
++
++ PRI2
++
++o IDE suspend/resume without races (Ben is looking at this a little)
++
++ PRI2
++
++o Pat: There are already CPU device structures; MTRRs should be a
++ dynamically registered interface of CPUs, which implies there needs
++ to be some other glue to know that there are MTRRs that need to be
++ saved/restored.
++
++ PRI1
++
++global
++~~~~~~
++
++o We need a kernel side API for reporting error events to userspace (could
++ be async to 2.6 itself)
++
++ (Prototype core based on netlink exists)
++
++ PRI2
++
++o Kai: Introduce a sane, easy and standard way to build external modules
++ - make clean and make modules_install are both broken
++
++ PRI2
++
++drivers
++~~~~~~~
++
++o Alan: Cardbus/PCMCIA requires all Russell's stuff is merged to do
++ multiheader right and so on
++
++ PRI1
++
++drivers/acpi/
++~~~~~~~~~~~~~
++
++o Fix acpi for all newer IBM Thinkpads see
++ http://bugme.osdl.org/show_bug.cgi?id=1038 for more information
++
++o alan: VIA APIC stuff is one bit of this, there are also some other
++ reports that were caused by ACPI not setting level v edge trigger some
++ times
++
++ PRI1
++
++o mochel: it seems the acpi irq routing code could use a serious rewrite.
++
++ grover: The problem is the ACPI irq routing code is trying to piggyback
++ on the existing MPS-specific data structures, and it's generally a hack.
++ So yes mochel is right, but it is also purging MPS-ities from common code
++ as well. I've done some preliminary work in this area and it doesn't seem
++ to break anything (yet) but a rewrite in this area imho should not be
++ rushed out the door. And, I think the above bugs can be fixed w/o the
++ rewrite.
++
++ PRI2
++
++o mochel: ACPI suspend doesn't work. Important, not cricital. Pat is
++ working it.
++
++ PRI2
++
++drivers/block/
++~~~~~~~~~~~~~~
++
++o Floppy is almost unusably buggy still
++
++ akpm: we need more people to test & report.
++
++ alan: "Floppy has worked for me since the patches that went in 2.5.69-ac
++ and I think -bk somewhere"
++
++ PRI1
++
++drivers/char/
++~~~~~~~~~~~~~
++
++
++drivers/ide/
++~~~~~~~~~~~~
++
++ (Alan)
++
++o IDE PIO has occasional unexplained PIO disk eating reports
++
++ PRI1
++
++o IDE has multiple zillions of races/hangs in 2.5 still
++
++ PRI1
++
++o IDE scsi needs rewriting
++
++ PRI2
++
++o IDE needs significant reworking to handle Simplex right
++
++ PRI2
++
++o IDE hotplug handling for 2.5 is completely broken still
++
++ PRI2
++
++o There are lots of other IDE bugs that wont go away until the taskfile
++ stuff is included, the locking bugs that allow any user to hang the IDE
++ layer in 2.5, and some other updates are forward ported. (esp. HPT372N).
++
++ PRI1
++
++drivers/isdn/
++~~~~~~~~~~~~~
++
++ (Kai, rmk)
++
++o isdn_tty locking is completely broken (cli() and friends)
++
++ PRI2
++
++o fix other drivers
++
++ PRI2
++
++o lots more cleanups, adaption to recent APIs etc
++
++ PRI3
++
++o fixup tty-based ISDN drivers which provide TIOCM* ioctls (see my recent
++ 3-set patch for serial stuff)
++
++ Alternatively, we could re-introduce the fallback to driver ioctl parsing
++ for these if not enough drivers get updated.
++
++ PRI3
++
++drivers/net/
++~~~~~~~~~~~~
++
++o davej: Either Wireless network drivers or PCMCIA broke somewhen. A
++ configuration that worked fine under 2.4 doesn't receive any packets. Need
++ to look into this more to make sure I don't have any misconfiguration that
++ just 'happened to work' under 2.4
++
++ PRI1
++
++drivers/scsi/
++~~~~~~~~~~~~~
++
++o jejb: qlogic -
++
++ o Merge the feral driver. It covers all qlogic chips: 1020 all the way
++ up to 23xxx. http://linux-scsi.bkbits.net/scsi-isp-2.5
++
++ o qla2xxx: only for FC chips. Has significant build issues. hch
++ promises to send me a "must fix" list for this.
++ http://linux-scsi.bkbits.net/scsi-qla2xxx-2.5
++
++ PRI2
++
++arch/i386/
++~~~~~~~~~~
++
++o Also PC9800 merge needs finishing to the point we want for 2.6 (not all).
++
++ PRI3
++
++o davej: PAT support (for mtrr exhaustion w/ AGP)
++
++ PRI2
++
++o 2.5.x won't boot on some 440GX
++
++ alan: Problem understood now, feasible fix in 2.4/2.4-ac. (440GX has two
++ IRQ routers, we use the $PIR table with the PIIX, but the 440GX doesnt use
++ the PIIX for its IRQ routing). Fall back to BIOS for 440GX works and Intel
++ concurs.
++
++ PRI1
++
++o 2.5.x doesn't handle VIA APIC right yet.
++
++ 1. We must write the PCI_INTERRUPT_LINE
++
++ 2. We have quirk handlers that seem to trash it.
++
++ PRI1
++
++o ACPI needs the relax patches merging to work on lots of laptops
++
++ alan: ACPI relax stuff is in 2.4-ac, compaq workaround is in next -ac
++ coming. These seem to deliver the goods - toshibas now work a treat. Some
++ other relax bits are being discussed (assume local0 starts 0 etc) and
++ progress looks great. This can occur before 2.6 or during.
++
++ PRI1
++
++o ECC driver questions are not yet sorted (DaveJ is working on this) (Dan
++ Hollis)
++
++ alan: ECC - I have some test bits from Dan's stuff - they need no kernel
++ core changes for most platforms. That means we can treat it as a random
++ driver merge.
++
++ PRI3
++
++o alan: 2.4 has some fixes for tsc handling bugs. One where some bioses in
++ SMM mode mess up our toggle on the time high/low or mangle the counter and
++ one where a few chips need religious use of _p for timer access and we
++ don't do that. This is forward porting little bits of fixup.
++
++ ACPI HZ stuff we can't trap - a lot of ACPI is implemented as outb's
++ triggering SMM traps
++
++ PRI1
++
++arch/x86_64/
++~~~~~~~~~~~~
++
++ (Andi)
++
++o time handling is broken. Need to move up 2.4 time.c code.
++
++ PRI1
++
++o NMI watchdog seems to tick too fast
++
++ PRI2
++
++o not very well tested. probably more bugs lurking.
++
++ PRI1
++
++o need to coredump 64bit vsyscall code with dwarf2
++
++ PRI2
++
++o Consider merging of Erich Focht's very clean and simple homenode NUMA
++ scheduler (I have my own in 2.4, but Erich's 2.5 version is much cleaner)
++
++ PRI2
++
++o Consider port of the Simple NUMA API from 2.4/homenode.
++
++ PRI3
++
++o move 64bit signal trampolines into vsyscall code and add dwarf2 for it.
++ (in progress)
++
++ PRI1
++
++o describe kernel assembly with dwarf2 annotations for kgdb
++
++ PRI3
++
++arch/alpha/
++~~~~~~~~~~~
++
++o rth: Ptrace writes are broken. This means we can't (reliably) set
++ breakpoints or modify variables from gdb.
++
++ PRI1
++
++arch/arm/
++~~~~~~~~~
++
++o rmk: missing raw keyboard translation tables for all ARM machines.
++ Haven't even looked into this at all. This could be messy since there
++ isn't an ARM architecture standard. I'm presently hoping that it won't be
++ an issue. If it does, I guess we'll see drivers/char/keyboard.c explode.
++
++ PRI2
++
++arch/others/
++~~~~~~~~~~~~
++
++o SH needs resyncing, as do some other ports. SH64 needs merging.
++ No impact on mainstream platforms hopefully.
++
++ PRI2
++
++arch/s390/
++~~~~~~~~~
++
++o A nastly memory management problem causes random crashes. These appear
++ to be fixed/hidden by the objrmap patch, more investigation is needed.
++
++ PRI1
++
++drivers/s390/
++~~~~~~~~~~~~~
++
++o Early userspace and 64 bit dev_t will allow the removal of most of
++ dasd_devmap.c and dasd_genhd.c.
++
++ PRI2
++
++o The 3270 console driver needs to be replaced with a working one
++ (prototype is there, needs to be finished).
++
++ PRI2
++
++o Minor interface changes are pending in cio/ when the z990 machines are
++ out.
++
++ PRI2
++
++o Jan Glauber is working on a fix for the timer issues related to running
++ on virtualized CPUs (wall-clock vs. cpu time).
++
++ PRI1
++
++o a block device driver for ramdisks shared among virtual machines
++
++ PRI3
++
++o driver for crypto hardware
++
++ PRI3
++
++o 'claw' network device driver
++
++ PRI3
++
+--- linux-2.6.0-test6/Documentation/zorro.txt 2003-07-27 12:14:38.000000000 -0700
++++ 25/Documentation/zorro.txt 2003-10-05 00:33:23.000000000 -0700
+@@ -2,7 +2,7 @@
+ ----------------------------------------
+
+ Written by Geert Uytterhoeven <geert@linux-m68k.org>
+-Last revised: February 27, 2000
++Last revised: September 5, 2003
+
+
+ 1. Introduction
+@@ -75,7 +75,7 @@ they are CPU physical addresses as well.
+ The treatment of these regions depends on the type of Zorro space:
+
+ - Zorro II address space is always mapped and does not have to be mapped
+- explicitly using ioremap().
++ explicitly using z_ioremap().
+
+ Conversion from bus/physical Zorro II addresses to kernel virtual addresses
+ and vice versa is done using:
+@@ -83,22 +83,20 @@ The treatment of these regions depends o
+ virt_addr = ZTWO_VADDR(bus_addr);
+ bus_addr = ZTWO_PADDR(virt_addr);
+
+- - Zorro III address space must be mapped explicitly using ioremap() first
++ - Zorro III address space must be mapped explicitly using z_ioremap() first
+ before it can be accessed:
+
+- virt_addr = ioremap(bus_addr, size);
++ virt_addr = z_ioremap(bus_addr, size);
+ ...
+- iounmap(virt_addr);
++ z_iounmap(virt_addr);
+
+
+ 5. References
+ -------------
+
+ linux/include/linux/zorro.h
+-linux/include/linux/ioport.h
+-linux/include/asm-m68k/io.h
+-linux/include/asm-m68k/amigahw.h
+-linux/include/asm-ppc/io.h
++linux/include/asm-{m68k,ppc}/zorro.h
++linux/include/linux/zorro_ids.h
+ linux/drivers/zorro
+ /proc/bus/zorro
+
+--- linux-2.6.0-test6/drivers/acorn/block/fd1772.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/acorn/block/fd1772.c 2003-10-05 00:34:00.000000000 -0700
+@@ -365,13 +365,12 @@ static void finish_fdc_done(int dummy);
+ static void floppy_off(unsigned int nr);
+ static void setup_req_params(int drive);
+ static void redo_fd_request(void);
+-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
++static int fd_ioctl(struct block_device *bdev, struct file *filp, unsigned int
+ cmd, unsigned long param);
+ static void fd_probe(int drive);
+ static int fd_test_drive_present(int drive);
+ static void config_types(void);
+-static int floppy_open(struct inode *inode, struct file *filp);
+-static int floppy_release(struct inode *inode, struct file *filp);
++static int floppy_open(struct block_device *bdev, struct file *filp);
+ static void do_fd_request(request_queue_t *);
+
+ /************************* End of Prototypes **************************/
+@@ -1309,11 +1308,9 @@ static int invalidate_drive(struct block
+ return 0;
+ }
+
+-static int fd_ioctl(struct inode *inode, struct file *filp,
++static int fd_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param)
+ {
+- struct block_device *bdev = inode->i_bdev;
+-
+ switch (cmd) {
+ case FDFMTEND:
+ case FDFLUSH:
+@@ -1453,10 +1450,11 @@ static void config_types(void)
+ * drive with different device numbers.
+ */
+
+-static int floppy_open(struct inode *inode, struct file *filp)
++static int floppy_open(struct block_device *bdev, struct file *filp)
+ {
+- int drive = iminor(inode) & 3;
+- int type = iminor(inode) >> 2;
++ struct archy_floppy_struct *p = bdev->bd_disk->private_data;
++ int drive = p - unit;
++ int type = MINOR(bdev->bd_dev) >> 2;
+ int old_dev = fd_device[drive];
+
+ if (fd_ref[drive] && old_dev != type)
+@@ -1476,10 +1474,13 @@ static int floppy_open(struct inode *ino
+ return 0;
+
+ if (filp->f_mode & 3) {
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (filp->f_mode & 2) {
+- if (unit[drive].wpstat) {
+- floppy_release(inode, filp);
++ if (p->wpstat) {
++ if (fd_ref[drive] < 0)
++ fd_ref[drive] = 0;
++ else
++ fd_ref[drive]--;
+ return -EROFS;
+ }
+ }
+@@ -1487,10 +1488,10 @@ static int floppy_open(struct inode *ino
+ return 0;
+ }
+
+-
+-static int floppy_release(struct inode *inode, struct file *filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- int drive = iminor(inode) & 3;
++ struct archy_floppy_struct *p = disk->private_data;
++ int drive = p - unit;
+
+ if (fd_ref[drive] < 0)
+ fd_ref[drive] = 0;
+--- linux-2.6.0-test6/drivers/acorn/block/mfmhd.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/acorn/block/mfmhd.c 2003-10-05 00:33:54.000000000 -0700
+@@ -1153,9 +1153,9 @@ static int mfm_initdrives(void)
+ * The 'front' end of the mfm driver follows...
+ */
+
+-static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
++static int mfm_ioctl(struct block_device *bdev, struct file *file, u_int cmd, u_long arg)
+ {
+- struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
++ struct mfm_info *p = bdev->bd_disk->private_data;
+ struct hd_geometry *geo = (struct hd_geometry *) arg;
+ if (cmd != HDIO_GETGEO)
+ return -EINVAL;
+@@ -1167,7 +1167,7 @@ static int mfm_ioctl(struct inode *inode
+ return -EFAULT;
+ if (put_user (p->cylinders, &geo->cylinders))
+ return -EFAULT;
+- if (put_user (get_start_sect(inode->i_bdev), &geo->start))
++ if (put_user (get_start_sect(bdev), &geo->start))
+ return -EFAULT;
+ return 0;
+ }
+--- linux-2.6.0-test6/drivers/acpi/asus_acpi.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/drivers/acpi/asus_acpi.c 2003-10-05 00:33:23.000000000 -0700
+@@ -26,13 +26,17 @@
+ * Johann Wiesner - Small compile fixes
+ * John Belmonte - ACPI code for Toshiba laptop was a good starting point.
+ *
+- * TODO
++ * TODO:
+ * add Fn key status
+- * Add mode selection on module loading (parameter) -> still necessary ?
++ * Add mode selection on module loading (parameter) -> still necessary?
+ * Complete display switching -- may require dirty hacks?
+- *
+ */
+
++#include <linux/config.h>
++#if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS) && defined (MODULE)
++#include <linux/modversions.h>
++#endif
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -41,7 +45,7 @@
+ #include <acpi/acpi_drivers.h>
+ #include <acpi/acpi_bus.h>
+
+-#define ASUS_ACPI_VERSION "0.24a"
++#define ASUS_ACPI_VERSION "0.26"
+
+ #define PROC_ASUS "asus" //the directory
+ #define PROC_MLED "mled"
+@@ -110,20 +114,24 @@ struct asus_hotk {
+ struct model_data *methods; //methods available on the laptop
+ u8 brightness; //brighness level
+ enum {
+- L2X = 0, //L200D -> TODO check Q11 (Fn+F8)
+- // Calling this method simply hang the
++ A1X=0, //A1340D, A1300F
++ A2X, //A2500H
++ D1X, //D1
++ L1X, //L1400B
++ L2X, //L2000D -> TODO check Q11 (Fn+F8)
++ // Calling this method simply hangs the
+ // computer, ISMI method hangs the laptop.
+- L3X, //L3C
+ L3D, //L3400D
++ L3X, //L3C
++ L5X, //L5C TODO this model seems to have one more
++ // LED, add support
+ M2X, //M2400E
++ M3N, //M3700N, but also S1300N -> TODO WLED
+ S1X, //S1300A -> TODO special keys do not work ?
+- D1X, //D1
+- L1X, //L1400B
+- A1X, //A1340D, A1300F
+- J1X, //S200 (J1)
+- //TODO A1370D does not seems to have a ATK device
++ S2X, //S200 (J1 reported), Victor MP-XP7210
++ //TODO A1370D does not seem to have an ATK device
+ // L8400 model doesn't have ATK
+- END_MODEL,
++ END_MODEL
+ } model; //Models currently supported
+ u16 event_count[128]; //count for each event TODO make this better
+ };
+@@ -133,7 +141,8 @@ struct asus_hotk {
+ #define S1X_PREFIX "\\_SB.PCI0.PX40."
+ #define L1X_PREFIX S1X_PREFIX
+ #define A1X_PREFIX "\\_SB.PCI0.ISA.EC0."
+-#define J1X_PREFIX A1X_PREFIX
++#define S2X_PREFIX A1X_PREFIX
++#define M3N_PREFIX "\\_SB.PCI0.SBRG.EC0."
+
+ static struct model_data model_conf[END_MODEL] = {
+ /*
+@@ -147,33 +156,43 @@ static struct model_data model_conf[END_
+ * it seems to be a kind of switch, but what for ?
+ *
+ */
++ {"A1X", "MLED", "\\MAIL", NULL, NULL, A1X_PREFIX "_Q10", "\\BKLI",
++ A1X_PREFIX "_Q0E", A1X_PREFIX "_Q0F", NULL, NULL, NULL, NULL, NULL},
++
++ {"A2X", "MLED", NULL, "WLED", "\\SG66", "\\Q10", "\\BAOF",
++ "\\Q0E", "\\Q0F", "SPLV", "GPLV", "\\CMOD", "SDSP", "\\INFB"},
++
++ {"D1X", "MLED", NULL, NULL, NULL, "\\Q0D", "\\GP11",
++ "\\Q0C", "\\Q0B", NULL, NULL, "\\BLVL", "SDSP","\\INFB"},
++
++ {"L1X", "MLED", NULL, "WLED", NULL, L1X_PREFIX "Q10", "\\PNOF",
++ L1X_PREFIX "Q0F", L1X_PREFIX "Q0E", "SPLV", "GPLV", "\\BRIT", NULL, NULL},
++
+ {"L2X", "MLED", "\\SGP6", "WLED", "\\RCP3", "\\Q10", "\\SGP0",
+ "\\Q0E", "\\Q0F", NULL, NULL, NULL, "SDSP", "\\INFB"},
+
++ {"L3D", "MLED", "\\MALD", "WLED", NULL, "\\Q10", "\\BKLG",
++ "\\Q0E", "\\Q0F", "SPLV", "GPLV", "\\BLVL", "SDSP", "\\INFB"},
++
+ {"L3X", "MLED", NULL, "WLED", NULL, L3X_PREFIX "_Q10", "\\GL32",
+ L3X_PREFIX "_Q0F", L3X_PREFIX "_Q0E", "SPLV", "GPLV", "\\BLVL", "SDSP",
+ "\\_SB.PCI0.PCI1.VGAC.NMAP"},
+
+- {"L3D", "MLED", "\\MALD", "WLED", NULL, "\\Q10", "\\BKLG",
+- "\\Q0E", "\\Q0F", "SPLV", "GPLV", "\\BLVL", "SDSP", "\\INFB"},
+-
++ {"L5X", "MLED", NULL, "WLED", "WRED", "\\Q0D", "\\BAOF",
++ "\\Q0C","\\Q0B", "SPLV", "GPLV", NULL, "SDSP", "\\INFB"},
++
+ {"M2X", "MLED", NULL, "WLED", NULL, "\\Q10", "\\GP06",
+ "\\Q0E","\\Q0F", "SPLV", "GPLV", NULL, "SDSP", "\\INFB"},
++
++ {"M3N", "MLED", NULL, "WLED", "\\PO33", M3N_PREFIX "_Q10", "\\BKLT",
++ M3N_PREFIX "_Q0F", M3N_PREFIX "_Q0E", "SPLV", "GPLV", "\\LBTN", "SDSP",
++ "\\ADVG"},
+
+ {"S1X", "MLED", "\\EMLE", "WLED", NULL, S1X_PREFIX "Q10", "\\PNOF",
+ S1X_PREFIX "Q0F", S1X_PREFIX "Q0E", "SPLV", "GPLV", "\\BRIT", NULL, NULL},
+
+- {"D1X", "MLED", NULL, NULL, NULL, "\\Q0D", "\\GP11",
+- "\\Q0C", "\\Q0B", NULL, NULL, "\\BLVL", "SDSP","\\INFB"},
+-
+- {"L1X", "MLED", NULL, "WLED", NULL, L1X_PREFIX "Q10", "\\PNOF",
+- L1X_PREFIX "Q0F", L1X_PREFIX "Q0E", "SPLV", "GPLV", "\\BRIT", NULL, NULL},
+-
+- {"A1X", "MLED", "\\MAIL", NULL, NULL, A1X_PREFIX "_Q10", "\\BKLI",
+- A1X_PREFIX "_Q0E", A1X_PREFIX "_Q0F", NULL, NULL, NULL, NULL, NULL},
+-
+- {"J1X", "MLED", "\\MAIL", NULL, NULL, J1X_PREFIX "_Q10", "\\BKLI",
+- J1X_PREFIX "_Q0B", J1X_PREFIX "_Q0A", NULL, NULL, NULL, NULL, NULL}
++ {"S2X", "MLED", "\\MAIL", NULL, NULL, S2X_PREFIX "_Q10", "\\BKLI",
++ S2X_PREFIX "_Q0B", S2X_PREFIX "_Q0A", NULL, NULL, NULL, NULL, NULL}
+ };
+
+ /* procdir we use */
+@@ -234,7 +253,7 @@ static int read_acpi_int(acpi_handle han
+ output.length = sizeof(out_obj);
+ output.pointer = &out_obj;
+
+- status = acpi_evaluate_object(handle, (char*) method, NULL, &output);
++ status = acpi_evaluate_object(handle, (char *) method, NULL, &output);
+ *val = out_obj.integer.value;
+ return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER);
+ }
+@@ -249,6 +268,7 @@ proc_read_info(char *page, char **start,
+ void *data)
+ {
+ int len = 0;
++ int sfun;
+ struct asus_hotk *hotk = (struct asus_hotk *) data;
+ char buf[16]; //enough for all info
+ /*
+@@ -257,28 +277,27 @@ proc_read_info(char *page, char **start,
+ */
+
+ len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n");
+- len +=
+- sprintf(page + len, "Model reference : %s\n",
+- hotk->methods->name);
++ len += sprintf(page + len, "Model reference : %s\n",
++ hotk->methods->name);
++ if(read_acpi_int(hotk->handle, "SFUN", &sfun))
++ len += sprintf(page + len, "SFUN value : 0x%04x\n", sfun);
+ if (asus_info) {
+- snprintf(buf, 5, "%s", asus_info->signature);
+- len += sprintf(page + len, "ACPI signature : %s\n", buf);
+ snprintf(buf, 16, "%d", asus_info->length);
+- len += sprintf(page + len, "Table length : %s\n", buf);
+- snprintf(buf, 16, "%d", asus_info->revision);
+- len += sprintf(page + len, "ACPI minor version : %s\n", buf);
++ len += sprintf(page + len, "DSDT length : %s\n", buf);
+ snprintf(buf, 16, "%d", asus_info->checksum);
+- len += sprintf(page + len, "Checksum : %s\n", buf);
++ len += sprintf(page + len, "DSDT checksum : %s\n", buf);
++ snprintf(buf, 16, "%d", asus_info->revision);
++ len += sprintf(page + len, "DSDT revision : %s\n", buf);
+ snprintf(buf, 7, "%s", asus_info->oem_id);
+- len += sprintf(page + len, "OEM identification : %s\n", buf);
++ len += sprintf(page + len, "OEM id : %s\n", buf);
+ snprintf(buf, 9, "%s", asus_info->oem_table_id);
+ len += sprintf(page + len, "OEM table id : %s\n", buf);
+ snprintf(buf, 16, "%x", asus_info->oem_revision);
+- len += sprintf(page + len, "OEM rev number : 0x%s\n", buf);
++ len += sprintf(page + len, "OEM revision : 0x%s\n", buf);
+ snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
+- len += sprintf(page + len, "ASL comp vendor ID : %s\n", buf);
++ len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
+ snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
+- len += sprintf(page + len, "ASL comp rev number: 0x%s\n", buf);
++ len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf);
+ }
+
+ return len;
+@@ -304,7 +323,7 @@ proc_read_mled(char *page, char **start,
+ &led_status))
+ len = sprintf(page, "%d\n", led_status);
+ else
+- printk(KERN_NOTICE "Asus ACPI: Error reading MLED "
++ printk(KERN_WARNING "Asus ACPI: Error reading MLED "
+ "status\n");
+ } else {
+ len = sprintf(page, "%d\n", (hotk->status & MLED_ON) ? 1 : 0);
+@@ -334,7 +353,7 @@ proc_write_mled(struct file *file, const
+ /* We don't have to check mt_mled exists if we are here :) */
+ if (!write_acpi_int(hotk->handle, hotk->methods->mt_mled, led_out,
+ NULL))
+- printk(KERN_NOTICE "Asus ACPI: MLED write failed\n");
++ printk(KERN_WARNING "Asus ACPI: MLED write failed\n");
+
+
+
+@@ -355,11 +374,11 @@ proc_read_wled(char *page, char **start,
+ int led_status;
+
+ if (hotk->methods->wled_status) {
+- if (read_acpi_int(NULL, hotk->methods->mled_status,
++ if (read_acpi_int(NULL, hotk->methods->wled_status,
+ &led_status))
+ len = sprintf(page, "%d\n", led_status);
+ else
+- printk(KERN_NOTICE "Asus ACPI: Error reading WLED "
++ printk(KERN_WARNING "Asus ACPI: Error reading WLED "
+ "status\n");
+ } else {
+ len = sprintf(page, "%d\n", (hotk->status & WLED_ON) ? 1 : 0);
+@@ -386,7 +405,7 @@ proc_write_wled(struct file *file, const
+ /* We don't have to check if mt_wled exists if we are here :) */
+ if (!write_acpi_int(hotk->handle, hotk->methods->mt_wled, led_out,
+ NULL))
+- printk(KERN_NOTICE "Asus ACPI: WLED write failed\n");
++ printk(KERN_WARNING "Asus ACPI: WLED write failed\n");
+
+
+ return count;
+@@ -399,7 +418,7 @@ static int get_lcd_state(struct asus_hot
+
+ /* We don't have to check anything, if we are here */
+ if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd))
+- printk(KERN_NOTICE "Asus ACPI: Error reading LCD status\n");
++ printk(KERN_WARNING "Asus ACPI: Error reading LCD status\n");
+
+ if (hotk->model == L2X)
+ lcd = ~lcd;
+@@ -438,7 +457,7 @@ proc_write_lcd(struct file *file, const
+ acpi_evaluate_object(NULL, hotk->methods->mt_lcd_switch,
+ NULL, NULL);
+ if (ACPI_FAILURE(status))
+- printk(KERN_NOTICE "Asus ACPI: Error switching LCD\n");
++ printk(KERN_WARNING "Asus ACPI: Error switching LCD\n");
+ }
+
+ return count;
+@@ -452,15 +471,15 @@ static void set_brightness(int value, st
+ {
+ acpi_status status = 0;
+
+- /* ATKD laptop */
++ /* SPLV laptop */
+ if(hotk->methods->brightness_set) {
+ if (!write_acpi_int(hotk->handle, hotk->methods->brightness_set,
+ value, NULL))
+- printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n");
++ printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ return;
+ }
+
+- /* HOTK laptop if we are here, act as appropriate */
++ /* No SPLV method if we are here, act as appropriate */
+ value -= hotk->brightness;
+ while (value != 0) {
+ status = acpi_evaluate_object(NULL, (value > 0) ?
+@@ -469,7 +488,7 @@ static void set_brightness(int value, st
+ NULL, NULL);
+ (value > 0) ? value-- : value++;
+ if (ACPI_FAILURE(status))
+- printk(KERN_NOTICE "Asus ACPI: Error changing brightness\n");
++ printk(KERN_WARNING "Asus ACPI: Error changing brightness\n");
+ }
+ return;
+ }
+@@ -478,15 +497,15 @@ static int read_brightness(struct asus_h
+ {
+ int value;
+
+- if(hotk->methods->brightness_get) { /* ATKD laptop */
++ if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
+ if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get,
+ &value))
+- printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n");
++ printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
+ } else if (hotk->methods->brightness_status) { /* For D1 for example */
+ if (!read_acpi_int(NULL, hotk->methods->brightness_status,
+ &value))
+- printk(KERN_NOTICE "Asus ACPI: Error reading brightness\n");
+- } else /* HOTK laptop */
++ printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
++ } else /* No GPLV method */
+ value = hotk->brightness;
+ return value;
+ }
+@@ -512,7 +531,7 @@ proc_write_brn(struct file *file, const
+ /* 0 <= value <= 15 */
+ set_brightness(value, hotk);
+ } else {
+- printk(KERN_NOTICE "Asus ACPI: Error reading user input\n");
++ printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
+ }
+
+ return count;
+@@ -523,7 +542,7 @@ static void set_display(int value, struc
+ /* no sanity check needed for now */
+ if (!write_acpi_int(hotk->handle, hotk->methods->display_set,
+ value, NULL))
+- printk(KERN_NOTICE "Asus ACPI: Error setting display\n");
++ printk(KERN_WARNING "Asus ACPI: Error setting display\n");
+ return;
+ }
+
+@@ -540,12 +559,12 @@ proc_read_disp(char *page, char **start,
+ struct asus_hotk *hotk = (struct asus_hotk *) data;
+
+ if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
+- printk(KERN_NOTICE "Asus ACPI: Error reading display status\n");
++ printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
+ return sprintf(page, "%d\n", value);
+ }
+
+ /*
+- * Preliminary support for display switching. As of now: 0x01 should activate
++ * Experimental support for display switching. As of now: 0x01 should activate
+ * the LCD output, 0x02 should do for CRT, and 0x04 for TV-Out. Any combination
+ * (bitwise) of these will suffice. I never actually tested 3 displays hooked up
+ * simultaneously, so be warned.
+@@ -562,13 +581,13 @@ proc_write_disp(struct file *file, const
+ if (sscanf(buffer, "%d", &value) == 1)
+ set_display(value, hotk);
+ else {
+- printk(KERN_NOTICE "Asus ACPI: Error reading user input\n");
++ printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
+ }
+
+ return count;
+ }
+
+-static int asus_hotk_add_fs(struct acpi_device *device)
++static int __init asus_hotk_add_fs(struct acpi_device *device)
+ {
+ struct proc_dir_entry *proc;
+ struct asus_hotk *hotk = acpi_driver_data(device);
+@@ -582,7 +601,7 @@ static int asus_hotk_add_fs(struct acpi_
+
+ if ((asus_uid == 0) && (asus_gid == 0)){
+ mode = S_IFREG | S_IRUGO | S_IWUGO;
+- }else{
++ } else {
+ mode = S_IFREG | S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP;
+ }
+
+@@ -598,7 +617,7 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_INFOS
++ printk(KERN_WARNING " Unable to create " PROC_INFOS
+ " fs entry\n");
+ }
+
+@@ -612,7 +631,7 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_WLED
++ printk(KERN_WARNING " Unable to create " PROC_WLED
+ " fs entry\n");
+ }
+ }
+@@ -627,7 +646,7 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_MLED
++ printk(KERN_WARNING " Unable to create " PROC_MLED
+ " fs entry\n");
+ }
+ }
+@@ -646,7 +665,7 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_LCD
++ printk(KERN_WARNING " Unable to create " PROC_LCD
+ " fs entry\n");
+ }
+ }
+@@ -662,7 +681,7 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_BRN
++ printk(KERN_WARNING " Unable to create " PROC_BRN
+ " fs entry\n");
+ }
+ }
+@@ -677,19 +696,19 @@ static int asus_hotk_add_fs(struct acpi_
+ proc->uid = asus_uid;
+ proc->gid = asus_gid;;
+ } else {
+- printk(KERN_NOTICE " Unable to create " PROC_DISP
++ printk(KERN_WARNING " Unable to create " PROC_DISP
+ " fs entry\n");
+ }
+ }
+
+- return (AE_OK);
++ return 0;
+ }
+
+
+ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
+ {
+ /* TODO Find a better way to handle events count. Here, in data, we receive
+- * the hotk, so we can make anything !!
++ * the hotk, so we can do anything!
+ */
+ struct asus_hotk *hotk = (struct asus_hotk *) data;
+
+@@ -712,19 +731,40 @@ static void asus_hotk_notify(acpi_handle
+ * This function is used to initialize the hotk with right values. In this
+ * method, we can make all the detection we want, and modify the hotk struct
+ */
+-static int asus_hotk_get_info(struct asus_hotk *hotk)
++static int __init asus_hotk_get_info(struct asus_hotk *hotk)
+ {
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
++ struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *model = NULL;
++ int bsts_result;
++ acpi_status status;
+
+- /*
+- * We have to write 0 on init this far for all ASUS models
++ /*
++ * Get DSDT headers early enough to allow for differentiating between
++ * models, but late enough to allow acpi_bus_register_driver() to fail
++ * before doing anything ACPI-specific. Should we encounter a machine,
++ * which needs special handling (i.e. its hotkey device has a different
++ * HID), this bit will be moved. A global variable asus_info contains
++ * the DSDT header.
+ */
++ status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
++ if (ACPI_FAILURE(status))
++ printk(KERN_WARNING " Couldn't get the DSDT table header\n");
++ else
++ asus_info = (struct acpi_table_header *) dsdt.pointer;
++
++ /* We have to write 0 on init this far for all ASUS models */
+ if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
+- printk(KERN_NOTICE " Hotkey initialization failed\n");
++ printk(KERN_ERR " Hotkey initialization failed\n");
+ return -ENODEV;
+ }
+
++ /* For testing purposes */
++ if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
++ printk(KERN_WARNING " Error calling BSTS\n");
++ else if (bsts_result)
++ printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", bsts_result);
++
+ /*
+ * Here, we also use asus_info to make decision. For example, on INIT
+ * method, S1X and L1X models both reports to be L84F, but they don't
+@@ -749,26 +789,34 @@ static int asus_hotk_get_info(struct asu
+ hotk->model = L3X;
+ else if (strncmp(model->string.pointer, "M2", 2) == 0)
+ hotk->model = M2X;
++ else if (strncmp(model->string.pointer, "M3N", 3) == 0 ||
++ strncmp(model->string.pointer, "S1N", 3) == 0)
++ hotk->model = M3N; /* S1300N is similar enough */
+ else if (strncmp(model->string.pointer, "L2", 2) == 0)
+ hotk->model = L2X;
+- else if (strncmp(model->string.pointer, "L8", 2) == 0)
++ else if (strncmp(model->string.pointer, "L8", 2) == 0) {
+ /* S1300A reports L84F, but L1400B too */
+- if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
+- hotk->model = L1X;
+- else
++ if (asus_info) {
++ if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
++ hotk->model = L1X;
++ } else
+ hotk->model = S1X;
++ }
+ else if (strncmp(model->string.pointer, "D1", 2) == 0)
+ hotk->model = D1X;
+ else if (strncmp(model->string.pointer, "A1", 2) == 0)
+ hotk->model = A1X;
++ else if (strncmp(model->string.pointer, "A2", 2) == 0)
++ hotk->model = A2X;
+ else if (strncmp(model->string.pointer, "J1", 2) == 0)
+- hotk->model = J1X;
+-
++ hotk->model = S2X;
++ else if (strncmp(model->string.pointer, "L5", 2) == 0)
++ hotk->model = L5X;
+
+ if (hotk->model == END_MODEL) {
+ /* By default use the same values, as I don't know others */
+- printk("unsupported, trying default values, contact the "
+- "developers\n");
++ printk("unsupported, trying default values, supply the "
++ "developers with your DSDT\n");
+ hotk->model = L2X;
+ } else {
+ printk("supported\n");
+@@ -783,7 +831,7 @@ static int asus_hotk_get_info(struct asu
+
+
+
+-static int asus_hotk_check(struct asus_hotk *hotk)
++static int __init asus_hotk_check(struct asus_hotk *hotk)
+ {
+ int result = 0;
+
+@@ -797,7 +845,7 @@ static int asus_hotk_check(struct asus_h
+ if (hotk->device->status.present) {
+ result = asus_hotk_get_info(hotk);
+ } else {
+- printk(KERN_NOTICE " Hotkey device not present, aborting\n");
++ printk(KERN_ERR " Hotkey device not present, aborting\n");
+ return(-EINVAL);
+ }
+
+@@ -806,7 +854,7 @@ static int asus_hotk_check(struct asus_h
+
+
+
+-static int asus_hotk_add(struct acpi_device *device)
++static int __init asus_hotk_add(struct acpi_device *device)
+ {
+ struct asus_hotk *hotk = NULL;
+ acpi_status status = AE_OK;
+@@ -815,6 +863,9 @@ static int asus_hotk_add(struct acpi_dev
+ if (!device)
+ return(-EINVAL);
+
++ printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
++ ASUS_ACPI_VERSION);
++
+ hotk =
+ (struct asus_hotk *) kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
+ if (!hotk)
+@@ -842,25 +893,23 @@ static int asus_hotk_add(struct acpi_dev
+ */
+ status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
+ asus_hotk_notify, hotk);
+- if (ACPI_FAILURE(status)) {
+- printk(KERN_NOTICE
+- " Error installing notify handler\n");
+- } else {
+- printk(KERN_DEBUG
+- " Notify Handler installed successfully\n");
+- }
++ if (ACPI_FAILURE(status))
++ printk(KERN_ERR " Error installing notify handler\n");
+
+- /* For HOTK laptops: init the hotk->brightness value */
++ /* For laptops without GPLV: init the hotk->brightness value */
+ if ((!hotk->methods->brightness_get) && (!hotk->methods->brightness_status) &&
+ (hotk->methods->brightness_up && hotk->methods->brightness_down)) {
+ status = acpi_evaluate_object(NULL, hotk->methods->brightness_down,
+ NULL, NULL);
+ if (ACPI_FAILURE(status))
+- printk(KERN_NOTICE " Error changing brightness\n");
+- status = acpi_evaluate_object(NULL, hotk->methods->brightness_up,
+- NULL, NULL);
+- if (ACPI_FAILURE(status))
+- printk(KERN_NOTICE " Error changing brightness\n");
++ printk(KERN_WARNING " Error changing brightness\n");
++ else {
++ status = acpi_evaluate_object(NULL, hotk->methods->brightness_up,
++ NULL, NULL);
++ if (ACPI_FAILURE(status))
++ printk(KERN_WARNING " Strange, error changing"
++ " brightness\n");
++ }
+ }
+
+ end:
+@@ -887,7 +936,7 @@ static int asus_hotk_remove(struct acpi_
+ status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
+ asus_hotk_notify);
+ if (ACPI_FAILURE(status))
+- printk(KERN_NOTICE "Error removing notify handler\n");
++ printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
+
+ kfree(hotk);
+
+@@ -899,35 +948,17 @@ static int asus_hotk_remove(struct acpi_
+
+ static int __init asus_acpi_init(void)
+ {
+- int result = 0;
+- acpi_status status = 0;
+- struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
+-
+- printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
+- ASUS_ACPI_VERSION);
+- /*
+- * Here is the code to know the model we are running on. We need to
+- * know this before calling the acpi_bus_register_driver function, in
+- * case the HID for the laptop we are running on is different from
+- * ACPI_HOTK_HID, which I have never seen yet :)
+- *
+- * This information is then available in the global var asus_info
+- */
+- status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
+- if (ACPI_FAILURE(status)) {
+- printk(KERN_NOTICE " Couldn't get the DSDT table header\n");
+- } else {
+- asus_info = (struct acpi_table_header *) dsdt.pointer;
+- }
++ int result;
+
+ asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
+- if (!asus_proc_dir)
++ if (!asus_proc_dir) {
++ printk(KERN_ERR "Asus ACPI: Unable to create /proc entry");
+ return(-ENODEV);
++ }
+ asus_proc_dir->owner = THIS_MODULE;
+
+ result = acpi_bus_register_driver(&asus_hotk_driver);
+ if (result < 0) {
+- printk(KERN_NOTICE " Error registering " ACPI_HOTK_NAME " \n");
+ remove_proc_entry(PROC_ASUS, acpi_root_dir);
+ return(-ENODEV);
+ }
+--- linux-2.6.0-test6/drivers/acpi/bus.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/bus.c 2003-10-05 00:33:23.000000000 -0700
+@@ -634,8 +634,7 @@ acpi_bus_init (void)
+ * the EC parameters out of that.
+ */
+ status = acpi_ec_ecdt_probe();
+- if (ACPI_FAILURE(status))
+- goto error1;
++ /* Ignore result. Not having an ECDT is not fatal. */
+ #endif
+
+ status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dsfield.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dsfield.c 2003-10-05 00:33:23.000000000 -0700
+@@ -105,27 +105,33 @@ acpi_ds_create_buffer_field (
+ return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ }
+
+- /*
+- * During the load phase, we want to enter the name of the field into
+- * the namespace. During the execute phase (when we evaluate the size
+- * operand), we want to lookup the name
+- */
+- if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
+- flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
++ if (walk_state->deferred_node) {
++ node = walk_state->deferred_node;
++ status = AE_OK;
+ }
+ else {
+- flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
+- }
++ /*
++ * During the load phase, we want to enter the name of the field into
++ * the namespace. During the execute phase (when we evaluate the size
++ * operand), we want to lookup the name
++ */
++ if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
++ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
++ }
++ else {
++ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
++ }
+
+- /*
+- * Enter the name_string into the namespace
+- */
+- status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+- ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
+- flags, walk_state, &(node));
+- if (ACPI_FAILURE (status)) {
+- ACPI_REPORT_NSERROR (arg->common.value.string, status);
+- return_ACPI_STATUS (status);
++ /*
++ * Enter the name_string into the namespace
++ */
++ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
++ ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
++ flags, walk_state, &(node));
++ if (ACPI_FAILURE (status)) {
++ ACPI_REPORT_NSERROR (arg->common.value.string, status);
++ return_ACPI_STATUS (status);
++ }
+ }
+
+ /* We could put the returned object (Node) on the object stack for later, but
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dsinit.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dsinit.c 2003-10-05 00:33:23.000000000 -0700
+@@ -135,7 +135,7 @@ acpi_ds_init_one_object (
+ }
+
+ /*
+- * Always parse methods to detect errors, we may delete
++ * Always parse methods to detect errors, we will delete
+ * the parse tree below
+ */
+ status = acpi_ds_parse_method (obj_handle);
+@@ -150,7 +150,7 @@ acpi_ds_init_one_object (
+ }
+
+ /*
+- * Delete the parse tree. We simple re-parse the method
++ * Delete the parse tree. We simply re-parse the method
+ * for every execution since there isn't much overhead
+ */
+ acpi_ns_delete_namespace_subtree (obj_handle);
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dsopcode.c 2003-06-14 12:18:30.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dsopcode.c 2003-10-05 00:33:23.000000000 -0700
+@@ -65,7 +65,7 @@
+ *
+ * RETURN: Status.
+ *
+- * DESCRIPTION: Late execution of region or field arguments
++ * DESCRIPTION: Late (deferred) execution of region or field arguments
+ *
+ ****************************************************************************/
+
+@@ -111,7 +111,10 @@ acpi_ds_execute_arguments (
+ return_ACPI_STATUS (status);
+ }
+
++ /* Mark this parse as a deferred opcode */
++
+ walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
++ walk_state->deferred_node = node;
+
+ /* Pass1: Parse the entire declaration */
+
+@@ -128,7 +131,7 @@ acpi_ds_execute_arguments (
+ arg->common.node = node;
+ acpi_ps_delete_parse_tree (op);
+
+- /* Evaluate the address and length arguments for the Buffer Field */
++ /* Evaluate the deferred arguments */
+
+ op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ if (!op) {
+@@ -144,6 +147,8 @@ acpi_ds_execute_arguments (
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
++ /* Execute the opcode and arguments */
++
+ status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
+ aml_length, NULL, NULL, 3);
+ if (ACPI_FAILURE (status)) {
+@@ -151,6 +156,9 @@ acpi_ds_execute_arguments (
+ return_ACPI_STATUS (status);
+ }
+
++ /* Mark this execution as a deferred opcode */
++
++ walk_state->deferred_node = node;
+ status = acpi_ps_parse_aml (walk_state);
+ acpi_ps_delete_parse_tree (op);
+ return_ACPI_STATUS (status);
+@@ -192,7 +200,7 @@ acpi_ds_get_buffer_field_arguments (
+ node = obj_desc->buffer_field.node;
+
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL));
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field JIT Init\n",
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
+ node->name.ascii));
+
+ /* Execute the AML code for the term_arg arguments */
+@@ -207,7 +215,7 @@ acpi_ds_get_buffer_field_arguments (
+ *
+ * FUNCTION: acpi_ds_get_buffer_arguments
+ *
+- * PARAMETERS: obj_desc - A valid Bufferobject
++ * PARAMETERS: obj_desc - A valid Buffer object
+ *
+ * RETURN: Status.
+ *
+@@ -240,7 +248,7 @@ acpi_ds_get_buffer_arguments (
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer JIT Init\n"));
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
+
+ /* Execute the AML code for the term_arg arguments */
+
+@@ -254,7 +262,7 @@ acpi_ds_get_buffer_arguments (
+ *
+ * FUNCTION: acpi_ds_get_package_arguments
+ *
+- * PARAMETERS: obj_desc - A valid Packageobject
++ * PARAMETERS: obj_desc - A valid Package object
+ *
+ * RETURN: Status.
+ *
+@@ -287,7 +295,7 @@ acpi_ds_get_package_arguments (
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package JIT Init\n"));
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
+
+ /* Execute the AML code for the term_arg arguments */
+
+@@ -335,11 +343,12 @@ acpi_ds_get_region_arguments (
+
+ node = obj_desc->region.node;
+
+- ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
++ ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
+
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Init at AML %p\n",
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Arg Init at AML %p\n",
+ node->name.ascii, extra_desc->extra.aml_start));
+
++ /* Execute the argument AML */
+
+ status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
+ extra_desc->extra.aml_length, extra_desc->extra.aml_start);
+@@ -505,14 +514,16 @@ acpi_ds_init_buffer_field (
+ goto cleanup;
+ }
+
+-
+ /* Entire field must fit within the current length of the buffer */
+
+ if ((bit_offset + bit_count) >
+ (8 * (u32) buffer_desc->buffer.length)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+- "Field size %d exceeds Buffer size %d (bits)\n",
+- bit_offset + bit_count, 8 * (u32) buffer_desc->buffer.length));
++ "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
++ ((struct acpi_namespace_node *) result_desc)->name.ascii,
++ bit_offset + bit_count,
++ buffer_desc->buffer.node->name.ascii,
++ 8 * (u32) buffer_desc->buffer.length));
+ status = AE_AML_BUFFER_LIMIT;
+ goto cleanup;
+ }
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dsutils.c 2003-06-14 12:18:09.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dsutils.c 2003-10-05 00:33:23.000000000 -0700
+@@ -53,6 +53,7 @@
+ #define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsutils")
+
++
+ #ifndef ACPI_NO_METHOD_EXECUTION
+
+ /*******************************************************************************
+@@ -196,7 +197,6 @@ result_not_used:
+ acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
+
+ return_VALUE (FALSE);
+-
+ }
+
+
+@@ -239,7 +239,6 @@ acpi_ds_delete_result_if_not_used (
+ return_VOID;
+ }
+
+-
+ if (!acpi_ds_is_result_used (op, walk_state)) {
+ /*
+ * Must pop the result stack (obj_desc should be equal to result_obj)
+@@ -389,61 +388,77 @@ acpi_ds_create_operand (
+ * in name_string
+ */
+
++
+ /*
+- * Differentiate between a namespace "create" operation
+- * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
+- * IMODE_EXECUTE) in order to support the creation of
+- * namespace objects during the execution of control methods.
++ * Special handling for buffer_field declarations. This is a deferred
++ * opcode that unfortunately defines the field name as the last
++ * parameter instead of the first. We get here when we are performing
++ * the deferred execution, so the actual name of the field is already
++ * in the namespace. We don't want to attempt to look it up again
++ * because we may be executing in a different scope than where the
++ * actual opcode exists.
+ */
+- parent_op = arg->common.parent;
+- op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
+- if ((op_info->flags & AML_NSNODE) &&
+- (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
+- (parent_op->common.aml_opcode != AML_REGION_OP) &&
+- (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
+- /* Enter name into namespace if not found */
+-
+- interpreter_mode = ACPI_IMODE_LOAD_PASS2;
++ if ((walk_state->deferred_node) &&
++ (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
++ (arg_index != 0)) {
++ obj_desc = ACPI_CAST_PTR (union acpi_operand_object, walk_state->deferred_node);
++ status = AE_OK;
+ }
++ else /* All other opcodes */ {
++ /*
++ * Differentiate between a namespace "create" operation
++ * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
++ * IMODE_EXECUTE) in order to support the creation of
++ * namespace objects during the execution of control methods.
++ */
++ parent_op = arg->common.parent;
++ op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
++ if ((op_info->flags & AML_NSNODE) &&
++ (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
++ (parent_op->common.aml_opcode != AML_REGION_OP) &&
++ (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
++ /* Enter name into namespace if not found */
+
+- else {
+- /* Return a failure if name not found */
+-
+- interpreter_mode = ACPI_IMODE_EXECUTE;
+- }
++ interpreter_mode = ACPI_IMODE_LOAD_PASS2;
++ }
++ else {
++ /* Return a failure if name not found */
+
+- status = acpi_ns_lookup (walk_state->scope_info, name_string,
+- ACPI_TYPE_ANY, interpreter_mode,
+- ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+- walk_state,
+- ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
+- /*
+- * The only case where we pass through (ignore) a NOT_FOUND
+- * error is for the cond_ref_of opcode.
+- */
+- if (status == AE_NOT_FOUND) {
+- if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
+- /*
+- * For the Conditional Reference op, it's OK if
+- * the name is not found; We just need a way to
+- * indicate this to the interpreter, set the
+- * object to the root
+- */
+- obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
+- status = AE_OK;
++ interpreter_mode = ACPI_IMODE_EXECUTE;
+ }
+
+- else {
+- /*
+- * We just plain didn't find it -- which is a
+- * very serious error at this point
+- */
+- status = AE_AML_NAME_NOT_FOUND;
++ status = acpi_ns_lookup (walk_state->scope_info, name_string,
++ ACPI_TYPE_ANY, interpreter_mode,
++ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
++ walk_state,
++ ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
++ /*
++ * The only case where we pass through (ignore) a NOT_FOUND
++ * error is for the cond_ref_of opcode.
++ */
++ if (status == AE_NOT_FOUND) {
++ if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
++ /*
++ * For the Conditional Reference op, it's OK if
++ * the name is not found; We just need a way to
++ * indicate this to the interpreter, set the
++ * object to the root
++ */
++ obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
++ status = AE_OK;
++ }
++ else {
++ /*
++ * We just plain didn't find it -- which is a
++ * very serious error at this point
++ */
++ status = AE_AML_NAME_NOT_FOUND;
++ }
+ }
+- }
+
+- if (ACPI_FAILURE (status)) {
+- ACPI_REPORT_NSERROR (name_string, status);
++ if (ACPI_FAILURE (status)) {
++ ACPI_REPORT_NSERROR (name_string, status);
++ }
+ }
+
+ /* Free the namestring created above */
+@@ -464,8 +479,6 @@ acpi_ds_create_operand (
+ }
+ ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+ }
+-
+-
+ else {
+ /* Check for null name case */
+
+@@ -480,7 +493,6 @@ acpi_ds_create_operand (
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg));
+ }
+-
+ else {
+ opcode = arg->common.aml_opcode;
+ }
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dswload.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dswload.c 2003-10-05 00:33:23.000000000 -0700
+@@ -248,6 +248,14 @@ acpi_ds_load1_begin_op (
+ * buffer_field, or Package), the name of the object is already
+ * in the namespace.
+ */
++ if (walk_state->deferred_node) {
++ /* This name is already in the namespace, get the node */
++
++ node = walk_state->deferred_node;
++ status = AE_OK;
++ break;
++ }
++
+ flags = ACPI_NS_NO_UPSEARCH;
+ if ((walk_state->opcode != AML_SCOPE_OP) &&
+ (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
+@@ -589,7 +597,17 @@ acpi_ds_load2_begin_op (
+ * Enter the named type into the internal namespace. We enter the name
+ * as we go downward in the parse tree. Any necessary subobjects that involve
+ * arguments to the opcode must be created as we go back up the parse tree later.
++ *
++ * Note: Name may already exist if we are executing a deferred opcode.
+ */
++ if (walk_state->deferred_node) {
++ /* This name is already in the namespace, get the node */
++
++ node = walk_state->deferred_node;
++ status = AE_OK;
++ break;
++ }
++
+ status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, walk_state, &(node));
+ break;
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dswscope.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dswscope.c 2003-10-05 00:33:23.000000000 -0700
+@@ -121,10 +121,9 @@ acpi_ds_scope_stack_push (
+ /* Make sure object type is valid */
+
+ if (!acpi_ut_valid_object_type (type)) {
+- ACPI_REPORT_WARNING (("ds_scope_stack_push: type code out of range\n"));
++ ACPI_REPORT_WARNING (("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+ }
+
+-
+ /* Allocate a new scope object */
+
+ scope_info = acpi_ut_create_generic_state ();
+@@ -146,13 +145,13 @@ acpi_ds_scope_stack_push (
+ old_scope_info = walk_state->scope_info;
+ if (old_scope_info) {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+- "[%4.4s] (%10s)",
++ "[%4.4s] (%s)",
+ old_scope_info->scope.node->name.ascii,
+ acpi_ut_get_type_name (old_scope_info->common.value)));
+ }
+ else {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+- "[\\___] (%10s)", "ROOT"));
++ "[\\___] (%s)", "ROOT"));
+ }
+
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+@@ -163,7 +162,6 @@ acpi_ds_scope_stack_push (
+ /* Push new scope object onto stack */
+
+ acpi_ut_push_generic_state (&walk_state->scope_info, scope_info);
+-
+ return_ACPI_STATUS (AE_OK);
+ }
+
+@@ -207,7 +205,7 @@ acpi_ds_scope_stack_pop (
+ walk_state->scope_depth--;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+- "[%.2d] Popped scope [%4.4s] (%10s), New scope -> ",
++ "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
+ (u32) walk_state->scope_depth,
+ scope_info->scope.node->name.ascii,
+ acpi_ut_get_type_name (scope_info->common.value)));
+@@ -225,7 +223,6 @@ acpi_ds_scope_stack_pop (
+ }
+
+ acpi_ut_delete_generic_state (scope_info);
+-
+ return_ACPI_STATUS (AE_OK);
+ }
+
+--- linux-2.6.0-test6/drivers/acpi/dispatcher/dswstate.c 2003-06-14 12:18:32.000000000 -0700
++++ 25/drivers/acpi/dispatcher/dswstate.c 2003-10-05 00:33:23.000000000 -0700
+@@ -56,11 +56,12 @@
+ * FUNCTION: acpi_ds_result_insert
+ *
+ * PARAMETERS: Object - Object to push
++ * Index - Where to insert the object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+- * DESCRIPTION: Push an object onto this walk's result stack
++ * DESCRIPTION: Insert an object onto this walk's result stack
+ *
+ ******************************************************************************/
+
+@@ -114,6 +115,7 @@ acpi_ds_result_insert (
+ * FUNCTION: acpi_ds_result_remove
+ *
+ * PARAMETERS: Object - Where to return the popped object
++ * Index - Where to extract the object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+@@ -233,6 +235,7 @@ acpi_ds_result_pop (
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
++
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_pop_from_bottom
+@@ -295,7 +298,6 @@ acpi_ds_result_pop_from_bottom (
+ *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
+ state, walk_state));
+
+-
+ return (AE_OK);
+ }
+
+@@ -358,8 +360,7 @@ acpi_ds_result_push (
+ *
+ * FUNCTION: acpi_ds_result_stack_push
+ *
+- * PARAMETERS: Object - Object to push
+- * walk_state - Current Walk state
++ * PARAMETERS: walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+@@ -420,7 +421,6 @@ acpi_ds_result_stack_pop (
+ return (AE_AML_NO_OPERAND);
+ }
+
+-
+ state = acpi_ut_pop_generic_state (&walk_state->results);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+@@ -572,6 +572,7 @@ acpi_ds_obj_stack_pop_object (
+ }
+ #endif
+
++
+ /*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_pop
+@@ -641,6 +642,7 @@ acpi_ds_obj_stack_pop_and_delete (
+ u32 i;
+ union acpi_operand_object *obj_desc;
+
++
+ ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete");
+
+
+@@ -883,8 +885,15 @@ acpi_ds_create_walk_state (
+ * FUNCTION: acpi_ds_init_aml_walk
+ *
+ * PARAMETERS: walk_state - New state to be initialized
++ * Op - Current parse op
++ * method_node - Control method NS node, if any
++ * aml_start - Start of AML
++ * aml_length - Length of AML
++ * Params - Method args, if any
++ * return_obj_desc - Where to store a return object, if any
++ * pass_number - 1, 2, or 3
+ *
+- * RETURN: None
++ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
+ *
+@@ -927,9 +936,9 @@ acpi_ds_init_aml_walk (
+
+ if (method_node) {
+ walk_state->parser_state.start_node = method_node;
+- walk_state->walk_type = ACPI_WALK_METHOD;
+- walk_state->method_node = method_node;
+- walk_state->method_desc = acpi_ns_get_attached_object (method_node);
++ walk_state->walk_type = ACPI_WALK_METHOD;
++ walk_state->method_node = method_node;
++ walk_state->method_desc = acpi_ns_get_attached_object (method_node);
+
+ /* Push start scope on scope stack and make it current */
+
+@@ -956,6 +965,7 @@ acpi_ds_init_aml_walk (
+ while (extra_op && !extra_op->common.node) {
+ extra_op = extra_op->common.parent;
+ }
++
+ if (!extra_op) {
+ parser_state->start_node = NULL;
+ }
+@@ -1014,7 +1024,7 @@ acpi_ds_delete_walk_state (
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state));
+ }
+
+- /* Always must free any linked control states */
++ /* Always must free any linked control states */
+
+ while (walk_state->control_state) {
+ state = walk_state->control_state;
+--- linux-2.6.0-test6/drivers/acpi/ec.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/drivers/acpi/ec.c 2003-10-05 00:33:24.000000000 -0700
+@@ -32,7 +32,7 @@
+ #include <asm/io.h>
+ #include <acpi/acpi_bus.h>
+ #include <acpi/acpi_drivers.h>
+-
++#include <acpi/actypes.h>
+
+ #define _COMPONENT ACPI_EC_COMPONENT
+ ACPI_MODULE_NAME ("acpi_ec")
+@@ -412,7 +412,10 @@ acpi_ec_space_setup (
+ * The EC object is in the handler context and is needed
+ * when calling the acpi_ec_space_handler.
+ */
+- *return_context = handler_context;
++ if(function == ACPI_REGION_DEACTIVATE)
++ *return_context = NULL;
++ else
++ *return_context = handler_context;
+
+ return AE_OK;
+ }
+--- linux-2.6.0-test6/drivers/acpi/events/evregion.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/acpi/events/evregion.c 2003-10-05 00:33:24.000000000 -0700
+@@ -382,7 +382,7 @@ acpi_ev_detach_region(
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object **last_obj_ptr;
+ acpi_adr_space_setup region_setup;
+- void *region_context;
++ void **region_context;
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
+
+@@ -394,7 +394,7 @@ acpi_ev_detach_region(
+ if (!region_obj2) {
+ return_VOID;
+ }
+- region_context = region_obj2->extra.region_context;
++ region_context = ®ion_obj2->extra.region_context;
+
+ /* Get the address handler from the region object */
+
+@@ -450,7 +450,7 @@ acpi_ev_detach_region(
+
+ region_setup = handler_obj->address_space.setup;
+ status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
+- handler_obj->address_space.context, ®ion_context);
++ handler_obj->address_space.context, region_context);
+
+ /* Init routine may fail, Just ignore errors */
+
+--- linux-2.6.0-test6/drivers/acpi/executer/excreate.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/acpi/executer/excreate.c 2003-10-05 00:33:24.000000000 -0700
+@@ -286,7 +286,7 @@ acpi_ex_create_region (
+ ACPI_FUNCTION_TRACE ("ex_create_region");
+
+
+- /* Get the Node from the object stack */
++ /* Get the Namespace Node */
+
+ node = walk_state->op->common.node;
+
+@@ -311,7 +311,6 @@ acpi_ex_create_region (
+ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
+ acpi_ut_get_region_name (region_space), region_space));
+
+-
+ /* Create the region descriptor */
+
+ obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
+@@ -375,6 +374,7 @@ acpi_ex_create_table_region (
+
+ ACPI_FUNCTION_TRACE ("ex_create_table_region");
+
++
+ /* Get the Node from the object stack */
+
+ node = walk_state->op->common.node;
+@@ -392,7 +392,6 @@ acpi_ex_create_table_region (
+ status = acpi_tb_find_table (operand[1]->string.pointer,
+ operand[2]->string.pointer,
+ operand[3]->string.pointer, &table);
+-
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+@@ -489,7 +488,6 @@ acpi_ex_create_processor (
+ status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
+ obj_desc, ACPI_TYPE_PROCESSOR);
+
+-
+ /* Remove local reference to the object */
+
+ acpi_ut_remove_reference (obj_desc);
+@@ -540,7 +538,6 @@ acpi_ex_create_power_resource (
+ status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
+ obj_desc, ACPI_TYPE_POWER);
+
+-
+ /* Remove local reference to the object */
+
+ acpi_ut_remove_reference (obj_desc);
+@@ -609,7 +606,6 @@ acpi_ex_create_method (
+ obj_desc->method.concurrency = (u8)
+ (((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1);
+ }
+-
+ else {
+ obj_desc->method.concurrency = INFINITE_CONCURRENCY;
+ }
+--- linux-2.6.0-test6/drivers/acpi/executer/exfldio.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/drivers/acpi/executer/exfldio.c 2003-10-05 00:33:24.000000000 -0700
+@@ -139,7 +139,41 @@ acpi_ex_setup_region (
+ field_datum_byte_offset, obj_desc->common_field.access_byte_width,
+ rgn_desc->region.node->name.ascii, rgn_desc->region.length));
+
+- return_ACPI_STATUS (AE_AML_REGION_LIMIT);
++ #ifdef CONFIG_ACPI_RELAXED_AML
++ {
++ /*
++ * Allow access to the field if it is within the region size
++ * rounded up to a multiple of the access byte width. This
++ * overcomes "off-by-one" programming errors in the AML often
++ * found in Toshiba laptops. These errors were allowed by
++ * the Microsoft ASL compiler.
++ */
++ u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
++ obj_desc->common_field.access_byte_width);
++
++ if (rounded_length < (obj_desc->common_field.base_byte_offset
++ + field_datum_byte_offset
++ + obj_desc->common_field.access_byte_width)) {
++ return_ACPI_STATUS (AE_AML_REGION_LIMIT);
++ } else {
++ static int warn_once = 1;
++ if (warn_once) {
++ // Could also associate a flag with each field, and
++ // warn once for each field.
++ ACPI_REPORT_WARNING((
++ "The ACPI AML in your computer contains errors, "
++ "please nag the manufacturer to correct it.\n"));
++ ACPI_REPORT_WARNING((
++ "Allowing relaxed access to fields; "
++ "turn on CONFIG_ACPI_DEBUG for details.\n"));
++ warn_once = 0;
++ }
++ return_ACPI_STATUS (AE_OK);
++ }
++ }
++ #else
++ return_ACPI_STATUS (AE_AML_REGION_LIMIT);
++ #endif
+ }
+
+ return_ACPI_STATUS (AE_OK);
+--- linux-2.6.0-test6/drivers/acpi/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/acpi/Kconfig 2003-10-05 00:36:23.000000000 -0700
+@@ -3,34 +3,14 @@
+ #
+
+ menu "ACPI (Advanced Configuration and Power Interface) Support"
+-
+-config ACPI_HT
+- bool "ACPI Processor Enumeration for HT"
+- depends on X86
+- default y
+- ---help---
+- ACPI enumerates both logical (a.k.a. Hyper-Threaded -- HT)
+- and physical processors. It is designed to obsolete several older
+- specifications, including the MultiProcessor Specification (MPS),
+- which supported only physical processors.
+-
+- CONFIG_ACPI_HT includes the minimal ACPI boot-time code
+- necessary to enumerate logical processors and enable HT.
+-
+- CONFIG_ACPI includes CONFIG_ACPI_HT, plus IO APIC enumeration,
+- and the hooks to run the ACPI AML interpreter for run-time events.
+-
+- When CONFIG_ACPI is selected, the command-line option "acpi=ht"
+- is available to run just the ACPI boot-time code -- just as if
+- only CONFIG_ACPI_HT were selected.
+-
+- Note that "acpi=off" can be used to disable all ACPI code in the kernel.
+-
+-config ACPI
+- bool "Full ACPI Support"
+ depends on !X86_VISWS
+ depends on !IA64_HP_SIM
+- depends on IA64 || (X86 || ACPI_HT)
++ depends on IA64 || X86
++
++config ACPI
++ bool "ACPI Support"
++ depends on IA64 || X86
++
+ default y
+ ---help---
+ Advanced Configuration and Power Interface (ACPI) support for
+@@ -62,12 +42,19 @@ config ACPI
+
+ config ACPI_BOOT
+ bool
+- depends on ACPI || ACPI_HT
++ depends on ACPI || X86_HT
++ default y
++
++config ACPI_INTERPRETER
++ bool
++ depends on ACPI
++ depends on !IA64_SGI_SN
+ default y
+
+ config ACPI_SLEEP
+ bool "Sleep States (EXPERIMENTAL)"
+ depends on X86 && ACPI
++ depends on ACPI_INTERPRETER
+ depends on EXPERIMENTAL && PM
+ default y
+ ---help---
+@@ -93,7 +80,8 @@ config ACPI_SLEEP_PROC_FS
+
+ config ACPI_AC
+ tristate "AC Adapter"
+- depends on X86 && ACPI
++ depends on X86
++ depends on ACPI_INTERPRETER
+ default m
+ help
+ This driver adds support for the AC Adapter object, which indicates
+@@ -102,7 +90,8 @@ config ACPI_AC
+
+ config ACPI_BATTERY
+ tristate "Battery"
+- depends on X86 && ACPI
++ depends on X86
++ depends on ACPI_INTERPRETER
+ default m
+ help
+ This driver adds support for battery information through
+@@ -111,7 +100,7 @@ config ACPI_BATTERY
+
+ config ACPI_BUTTON
+ tristate "Button"
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default m
+ help
+@@ -123,7 +112,7 @@ config ACPI_BUTTON
+
+ config ACPI_FAN
+ tristate "Fan"
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default m
+ help
+@@ -132,7 +121,7 @@ config ACPI_FAN
+
+ config ACPI_PROCESSOR
+ tristate "Processor"
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default m
+ help
+@@ -152,14 +141,15 @@ config ACPI_THERMAL
+
+ config ACPI_NUMA
+ bool "NUMA support"
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on NUMA
+ depends on !X86_64
+ default y if IA64_GENERIC || IA64_SGI_SN2
+
+ config ACPI_ASUS
+ tristate "ASUS/Medion Laptop Extras"
+- depends on X86 && ACPI
++ depends on X86
++ depends on ACPI_INTERPRETER
+ default m
+ ---help---
+ This driver provides support for extra features of ACPI-compatible
+@@ -170,6 +160,9 @@ config ACPI_ASUS
+ display brightness and output, switching the LCD backlight on and off,
+ and most importantly, allows you to blink those fancy LEDs intended
+ for reporting mail and wireless status.
++
++ Note: display switching code is currently considered EXPERIMENTAL,
++ toying with these values may even lock your machine.
+
+ All settings are changed via /proc/acpi/asus directory entries. Owner
+ and group for these entries can be set with asus_uid and asus_gid
+@@ -185,7 +178,8 @@ config ACPI_ASUS
+
+ config ACPI_TOSHIBA
+ tristate "Toshiba Laptop Extras"
+- depends on X86 && ACPI
++ depends on X86
++ depends on ACPI_INTERPRETER
+ default m
+ ---help---
+ This driver adds support for access to certain system settings
+@@ -212,7 +206,7 @@ config ACPI_TOSHIBA
+
+ config ACPI_DEBUG
+ bool "Debug Statements"
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default n
+ help
+@@ -222,19 +216,14 @@ config ACPI_DEBUG
+
+ config ACPI_BUS
+ bool
+- depends on ACPI
+- depends on !IA64_SGI_SN
+- default y
+-
+-config ACPI_INTERPRETER
+- bool
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default y
+
+ config ACPI_EC
+ bool
+- depends on X86 && ACPI
++ depends on X86
++ depends on ACPI_INTERPRETER
+ default y
+ help
+ This driver is required on some systems for the proper operation of
+@@ -243,19 +232,19 @@ config ACPI_EC
+
+ config ACPI_POWER
+ bool
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default y
+
+ config ACPI_PCI
+ bool
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default PCI
+
+ config ACPI_SYSTEM
+ bool
+- depends on ACPI
++ depends on ACPI_INTERPRETER
+ depends on !IA64_SGI_SN
+ default y
+ help
+@@ -263,10 +252,28 @@ config ACPI_SYSTEM
+ dump your ACPI DSDT table using /proc/acpi/dsdt.
+
+ config ACPI_EFI
+- bool
+- depends on ACPI
+- depends on IA64
+- default y
++ bool "Obtain RSDP from EFI Configuration Table"
++ depends on ACPI_INTERPRETER
++ depends on IA64 || X86
++ default n
++ help
++ On EFI Systems the RSDP pointer is passed to the kernel via
++ the EFI Configuration Table. On Itanium systems this is
++ standard and required. For IA-32, systems that have
++ EFI firmware should leave this enabled. Platforms with
++ traditional legacy BIOS should disable this option.
++
++config ACPI_RELAXED_AML
++ bool "Relaxed AML"
++ depends on ACPI_INTERPRETER
++ depends on !IA64_SGI_SN
++ default n
++ help
++ If you say `Y' here, the ACPI interpreter will relax its checking
++ for valid AML and will ignore some AML mistakes, such as off-by-one
++ errors in region sizes. Some laptops may require this option. In
++ particular, many Toshiba laptops require this for correct operation
++ of the AC module.
+
+ endmenu
+
+--- linux-2.6.0-test6/drivers/acpi/Makefile 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/Makefile 2003-10-05 00:33:23.000000000 -0700
+@@ -18,7 +18,7 @@ obj-$(CONFIG_ACPI) := acpi_ksyms.o
+ # ACPI Boot-Time Table Parsing
+ #
+ obj-$(CONFIG_ACPI_BOOT) += tables.o
+-obj-$(CONFIG_ACPI) += blacklist.o
++obj-$(CONFIG_ACPI_INTERPRETER) += blacklist.o
+
+ #
+ # ACPI Core Subsystem (Interpreter)
+--- linux-2.6.0-test6/drivers/acpi/namespace/nsdump.c 2003-06-14 12:18:33.000000000 -0700
++++ 25/drivers/acpi/namespace/nsdump.c 2003-10-05 00:33:24.000000000 -0700
+@@ -234,7 +234,7 @@ acpi_ns_dump_one_object (
+
+ case ACPI_TYPE_DEVICE:
+
+- acpi_os_printf ("Notify object: %p", obj_desc);
++ acpi_os_printf ("Notify Object: %p\n", obj_desc);
+ break;
+
+
+@@ -371,7 +371,7 @@ acpi_ns_dump_one_object (
+ case ACPI_TYPE_LOCAL_BANK_FIELD:
+ case ACPI_TYPE_LOCAL_INDEX_FIELD:
+
+- acpi_os_printf (" Off %.2X Len %.2X Acc %.2hd\n",
++ acpi_os_printf ("Off %.2X Len %.2X Acc %.2hd\n",
+ (obj_desc->common_field.base_byte_offset * 8)
+ + obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.bit_length,
+--- linux-2.6.0-test6/drivers/acpi/namespace/nssearch.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/acpi/namespace/nssearch.c 2003-10-05 00:33:24.000000000 -0700
+@@ -96,7 +96,7 @@ acpi_ns_search_node (
+
+ scope_name = acpi_ns_get_external_pathname (node);
+ if (scope_name) {
+- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching %s [%p] For %4.4s (%s)\n",
++ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching %s (%p) For [%4.4s] (%s)\n",
+ scope_name, node, (char *) &target_name, acpi_ut_get_type_name (type)));
+
+ ACPI_MEM_FREE (scope_name);
+@@ -117,9 +117,9 @@ acpi_ns_search_node (
+ * Found matching entry.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+- "Name %4.4s Type [%s] found in scope [%4.4s] %p\n",
++ "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
+ (char *) &target_name, acpi_ut_get_type_name (next_node->type),
+- next_node->name.ascii, next_node));
++ next_node, node->name.ascii, node));
+
+ *return_node = next_node;
+ return_ACPI_STATUS (AE_OK);
+@@ -143,7 +143,7 @@ acpi_ns_search_node (
+ /* Searched entire namespace level, not found */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+- "Name %4.4s Type [%s] not found in search in scope [%4.4s] %p first child %p\n",
++ "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
+ (char *) &target_name, acpi_ut_get_type_name (type),
+ node->name.ascii, node, node->child));
+
+--- linux-2.6.0-test6/drivers/acpi/namespace/nsutils.c 2003-06-14 12:18:21.000000000 -0700
++++ 25/drivers/acpi/namespace/nsutils.c 2003-10-05 00:33:24.000000000 -0700
+@@ -175,6 +175,11 @@ acpi_ns_print_node_pathname (
+ acpi_status status;
+
+
++ if (!node) {
++ acpi_os_printf ("[NULL NAME]");
++ return;
++ }
++
+ /* Convert handle to a full pathname and print it (with supplied message) */
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+@@ -470,11 +475,11 @@ acpi_ns_build_internal_name (
+ *result = 0;
+
+ if (info->fully_qualified) {
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (abs) \"\\%s\"\n",
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
+ internal_name, internal_name));
+ }
+ else {
+- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (rel) \"%s\"\n",
++ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
+ internal_name, internal_name));
+ }
+
+--- linux-2.6.0-test6/drivers/acpi/osl.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/osl.c 2003-10-05 00:36:22.000000000 -0700
+@@ -43,7 +43,6 @@
+
+ #ifdef CONFIG_ACPI_EFI
+ #include <linux/efi.h>
+-u64 efi_mem_attributes (u64 phys_addr);
+ #endif
+
+
+--- linux-2.6.0-test6/drivers/acpi/parser/psparse.c 2003-06-14 12:17:59.000000000 -0700
++++ 25/drivers/acpi/parser/psparse.c 2003-10-05 00:33:24.000000000 -0700
+@@ -437,7 +437,6 @@ acpi_ps_parse_loop (
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+-
+ parser_state = &walk_state->parser_state;
+ walk_state->arg_types = 0;
+
+@@ -705,10 +704,9 @@ acpi_ps_parse_loop (
+ walk_state->arg_types = 0;
+ break;
+
+-
+ default:
+
+- /* Op is not a constant or string, append each argument */
++ /* Op is not a constant or string, append each argument to the Op */
+
+ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
+ !walk_state->arg_count) {
+@@ -727,23 +725,23 @@ acpi_ps_parse_loop (
+ INCREMENT_ARG_LIST (walk_state->arg_types);
+ }
+
++ /* Special processing for certain opcodes */
++
+ switch (op->common.aml_opcode) {
+ case AML_METHOD_OP:
+
+- /* For a method, save the length and address of the body */
+-
+ /*
+- * Skip parsing of control method or opregion body,
++ * Skip parsing of control method
+ * because we don't have enough info in the first pass
+- * to parse them correctly.
++ * to parse it correctly.
++ *
++ * Save the length and address of the body
+ */
+ op->named.data = parser_state->aml;
+ op->named.length = (u32) (parser_state->pkg_end - parser_state->aml);
+- /*
+- * Skip body of method. For op_regions, we must continue
+- * parsing because the opregion is not a standalone
+- * package (We don't know where the end is).
+- */
++
++ /* Skip body of method */
++
+ parser_state->aml = parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ break;
+@@ -756,15 +754,15 @@ acpi_ps_parse_loop (
+ (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
+ (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
+ /*
+- * Skip parsing of
++ * Skip parsing of Buffers and Packages
+ * because we don't have enough info in the first pass
+ * to parse them correctly.
+ */
+ op->named.data = aml_op_start;
+ op->named.length = (u32) (parser_state->pkg_end - aml_op_start);
+- /*
+- * Skip body
+- */
++
++ /* Skip body */
++
+ parser_state->aml = parser_state->pkg_end;
+ walk_state->arg_count = 0;
+ }
+@@ -778,6 +776,7 @@ acpi_ps_parse_loop (
+ break;
+
+ default:
++
+ /* No action for all other opcodes */
+ break;
+ }
+--- linux-2.6.0-test6/drivers/acpi/pci_irq.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/pci_irq.c 2003-10-05 00:36:20.000000000 -0700
+@@ -71,6 +71,9 @@ acpi_pci_irq_find_prt_entry (
+
+ ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
+
++ if (!acpi_prt.count)
++ return_PTR(NULL);
++
+ /*
+ * Parse through all PRT entries looking for a match on the specified
+ * PCI device's segment, bus, device, and pin (don't care about func).
+@@ -234,7 +237,7 @@ acpi_pci_irq_add_prt (
+ PCI Interrupt Routing Support
+ -------------------------------------------------------------------------- */
+
+-static int
++int
+ acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin)
+ {
+ struct acpi_prt_entry *entry = NULL;
+--- linux-2.6.0-test6/drivers/acpi/pci_link.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/acpi/pci_link.c 2003-10-05 00:33:24.000000000 -0700
+@@ -220,7 +220,6 @@ acpi_pci_link_check_current (
+ return AE_CTRL_TERMINATE;
+ }
+
+-
+ static int
+ acpi_pci_link_get_current (
+ struct acpi_pci_link *link)
+@@ -279,6 +278,28 @@ end:
+ return_VALUE(result);
+ }
+
++static int
++acpi_pci_link_try_get_current (
++ struct acpi_pci_link *link,
++ int irq)
++{
++ int result;
++
++ ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
++
++ result = acpi_pci_link_get_current(link);
++ if (result && link->irq.active) {
++ return_VALUE(result);
++ }
++
++ if (!link->irq.active) {
++ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
++ printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device));
++ link->irq.active = irq;
++ }
++
++ return 0;
++}
+
+ static int
+ acpi_pci_link_set (
+@@ -294,6 +315,7 @@ acpi_pci_link_set (
+ struct acpi_buffer buffer = {sizeof(resource)+1, &resource};
+ int i = 0;
+ int valid = 0;
++ int resource_type = 0;
+
+ ACPI_FUNCTION_TRACE("acpi_pci_link_set");
+
+@@ -317,20 +339,32 @@ acpi_pci_link_set (
+ }
+ }
+
++ /* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
++ * an extended one */
++ if (irq <= 15) {
++ resource_type = ACPI_RSTYPE_IRQ;
++ } else {
++ resource_type = ACPI_RSTYPE_EXT_IRQ;
++ }
++
++retry_programming:
++
+ memset(&resource, 0, sizeof(resource));
+
+ /* NOTE: PCI interrupts are always level / active_low / shared. But not all
+ interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for
+ parameters */
+- if (irq <= 15) {
++ switch(resource_type) {
++ case ACPI_RSTYPE_IRQ:
+ resource.res.id = ACPI_RSTYPE_IRQ;
+ resource.res.length = sizeof(struct acpi_resource);
+ resource.res.data.irq.edge_level = link->irq.edge_level;
+ resource.res.data.irq.active_high_low = link->irq.active_high_low;
+ resource.res.data.irq.number_of_interrupts = 1;
+ resource.res.data.irq.interrupts[0] = irq;
+- }
+- else {
++ break;
++
++ case ACPI_RSTYPE_EXT_IRQ:
+ resource.res.id = ACPI_RSTYPE_EXT_IRQ;
+ resource.res.length = sizeof(struct acpi_resource);
+ resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
+@@ -339,11 +373,21 @@ acpi_pci_link_set (
+ resource.res.data.extended_irq.number_of_interrupts = 1;
+ resource.res.data.extended_irq.interrupts[0] = irq;
+ /* ignore resource_source, it's optional */
++ break;
+ }
+ resource.end.id = ACPI_RSTYPE_END_TAG;
+
+ /* Attempt to set the resource */
+ status = acpi_set_current_resources(link->handle, &buffer);
++
++ /* if we failed and IRQ <= 15, try again with an extended descriptor */
++ if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
++ resource_type = ACPI_RSTYPE_EXT_IRQ;
++ printk(PREFIX "Retrying with extended IRQ descriptor\n");
++ goto retry_programming;
++ }
++
++ /* check for total failure */
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
+ return_VALUE(-ENODEV);
+@@ -361,7 +405,7 @@ acpi_pci_link_set (
+ }
+
+ /* Make sure the active IRQ is the one we requested. */
+- result = acpi_pci_link_get_current(link);
++ result = acpi_pci_link_try_get_current(link, irq);
+ if (result) {
+ return_VALUE(result);
+ }
+@@ -456,16 +500,16 @@ static int acpi_pci_link_allocate(struct
+ irq = link->irq.active;
+ } else {
+ irq = link->irq.possible[0];
+- }
+
+- /*
+- * Select the best IRQ. This is done in reverse to promote
++ /*
++ * Select the best IRQ. This is done in reverse to promote
+ * the use of IRQs 9, 10, 11, and >15.
+ */
+ for (i=(link->irq.possible_count-1); i>0; i--) {
+ if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+ irq = link->irq.possible[i];
+ }
++ }
+
+ /* Attempt to enable the link device at this IRQ. */
+ if (acpi_pci_link_set(link, irq)) {
+@@ -574,10 +618,6 @@ acpi_pci_link_add (
+ else
+ printk(" %d", link->irq.possible[i]);
+ }
+- if (!link->irq.active)
+- printk(", disabled");
+- else if (!found)
+- printk(", enabled at IRQ %d", link->irq.active);
+ printk(")\n");
+
+ /* TBD: Acquire/release lock */
+--- linux-2.6.0-test6/drivers/acpi/tables.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/tables.c 2003-10-05 00:33:24.000000000 -0700
+@@ -69,7 +69,8 @@ struct acpi_table_sdt {
+
+ static unsigned long sdt_pa; /* Physical Address */
+ static unsigned long sdt_count; /* Table count */
+-static struct acpi_table_sdt *sdt_entry;
++
++static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES];
+
+ void
+ acpi_table_print (
+@@ -418,12 +419,6 @@ acpi_table_get_sdt (
+ sdt_count = ACPI_MAX_TABLES;
+ }
+
+- sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt));
+- if (!sdt_entry) {
+- printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n");
+- return -ENOMEM;
+- }
+-
+ for (i = 0; i < sdt_count; i++)
+ sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
+ }
+@@ -470,12 +465,6 @@ acpi_table_get_sdt (
+ sdt_count = ACPI_MAX_TABLES;
+ }
+
+- sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt));
+- if (!sdt_entry) {
+- printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n");
+- return -ENOMEM;
+- }
+-
+ for (i = 0; i < sdt_count; i++)
+ sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
+ }
+--- linux-2.6.0-test6/drivers/acpi/toshiba_acpi.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/acpi/toshiba_acpi.c 2003-10-05 00:33:24.000000000 -0700
+@@ -41,7 +41,6 @@
+ #include <linux/init.h>
+ #include <linux/types.h>
+ #include <linux/proc_fs.h>
+-#include <linux/version.h>
+
+ #include <acpi/acpi_drivers.h>
+
+--- linux-2.6.0-test6/drivers/acpi/utilities/utdelete.c 2003-06-14 12:18:20.000000000 -0700
++++ 25/drivers/acpi/utilities/utdelete.c 2003-10-05 00:34:43.000000000 -0700
+@@ -417,6 +417,8 @@ acpi_ut_update_object_reference (
+ union acpi_generic_state *state_list = NULL;
+ union acpi_generic_state *state;
+
++ union acpi_operand_object *tmp;
++
+
+ ACPI_FUNCTION_TRACE_PTR ("ut_update_object_reference", object);
+
+@@ -448,8 +450,15 @@ acpi_ut_update_object_reference (
+ switch (ACPI_GET_OBJECT_TYPE (object)) {
+ case ACPI_TYPE_DEVICE:
+
+- acpi_ut_update_ref_count (object->device.system_notify, action);
+- acpi_ut_update_ref_count (object->device.device_notify, action);
++ tmp = object->device.system_notify;
++ if(tmp && tmp->common.reference_count<=1 && action == REF_DECREMENT)
++ object->device.system_notify = NULL;
++ acpi_ut_update_ref_count (tmp, action);
++
++ tmp = object->device.device_notify;
++ if(tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)
++ object->device.device_notify = NULL;
++ acpi_ut_update_ref_count (tmp, action);
+ break;
+
+
+@@ -467,6 +476,9 @@ acpi_ut_update_object_reference (
+ */
+ status = acpi_ut_create_update_state_and_push (
+ object->package.elements[i], action, &state_list);
++ tmp = object->package.elements[i];
++ if(tmp && tmp->common.reference_count<=1 && action == REF_DECREMENT) /*reference count didn't refresh now*/
++ object->package.elements[i] = NULL;
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
+@@ -478,6 +490,9 @@ acpi_ut_update_object_reference (
+
+ status = acpi_ut_create_update_state_and_push (
+ object->buffer_field.buffer_obj, action, &state_list);
++ tmp = object->buffer_field.buffer_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->buffer_field.buffer_obj = NULL;
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
+@@ -491,6 +506,9 @@ acpi_ut_update_object_reference (
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
++ tmp = object->field.region_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->field.region_obj = NULL;
+ break;
+
+
+@@ -501,12 +519,18 @@ acpi_ut_update_object_reference (
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
++ tmp = object->bank_field.bank_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->bank_field.bank_obj = NULL;
+
+ status = acpi_ut_create_update_state_and_push (
+ object->bank_field.region_obj, action, &state_list);
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
++ tmp = object->bank_field.region_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->bank_field.region_obj = NULL;
+ break;
+
+
+@@ -517,12 +541,18 @@ acpi_ut_update_object_reference (
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
++ tmp = object->index_field.index_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->index_field.index_obj = NULL;
+
+ status = acpi_ut_create_update_state_and_push (
+ object->index_field.data_obj, action, &state_list);
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
++ tmp = object->index_field.data_obj;
++ if( tmp && tmp->common.reference_count <=1 && action == REF_DECREMENT)/*reference count didn't refresh now*/
++ object->index_field.data_obj = NULL;
+ break;
+
+
+--- linux-2.6.0-test6/drivers/block/acsi.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/acsi.c 2003-10-05 00:34:00.000000000 -0700
+@@ -63,6 +63,7 @@ typedef void Scsi_Device; /* hack to avo
+ #include <linux/hdreg.h> /* for HDIO_GETGEO */
+ #include <linux/blkpg.h>
+ #include <linux/buffer_head.h>
++#include <linux/blkdev.h>
+
+ #include <asm/setup.h>
+ #include <asm/pgtable.h>
+@@ -346,7 +347,7 @@ struct acsi_error {
+ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
+ rwflag, int enable);
+ static int acsi_reqsense( char *buffer, int targ, int lun);
+-static void acsi_print_error(const unsigned char *errblk, int struct acsi_info_struct *aip);
++static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
+ static irqreturn_t acsi_interrupt (int irq, void *data, struct pt_regs *fp);
+ static void unexpected_acsi_interrupt( void );
+ static void bad_rw_intr( void );
+@@ -358,10 +359,9 @@ static void copy_from_acsibuffer( void )
+ static void do_end_requests( void );
+ static void do_acsi_request( request_queue_t * );
+ static void redo_acsi_request( void );
+-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
++static int acsi_ioctl(struct block_device *bdev, struct file *file, unsigned int
+ cmd, unsigned long arg );
+-static int acsi_open( struct inode * inode, struct file * filp );
+-static int acsi_release( struct inode * inode, struct file * file );
++static int acsi_open(struct block_device *bdev, struct file *filp);
+ static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
+ static int acsi_change_blk_size( int target, int lun);
+ static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
+@@ -1080,10 +1080,10 @@ static void redo_acsi_request( void )
+ ***********************************************************************/
+
+
+-static int acsi_ioctl( struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg )
++static int acsi_ioctl(struct block_device *bdev, struct file *file,
++ unsigned int cmd, unsigned long arg )
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+ switch (cmd) {
+ case HDIO_GETGEO:
+@@ -1095,7 +1095,7 @@ static int acsi_ioctl( struct inode *ino
+ put_user( 64, &geo->heads );
+ put_user( 32, &geo->sectors );
+ put_user( aip->size >> 11, &geo->cylinders );
+- put_user(get_start_sect(inode->i_bdev), &geo->start);
++ put_user(get_start_sect(bdev), &geo->start);
+ return 0;
+ }
+ case SCSI_IOCTL_GET_IDLUN:
+@@ -1125,16 +1125,16 @@ static int acsi_ioctl( struct inode *ino
+ *
+ */
+
+-static int acsi_open( struct inode * inode, struct file * filp )
++static int acsi_open(struct block_device *bdev, struct file *filp)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+
+ if (aip->access_count == 0 && aip->removable) {
+ #if 0
+ aip->changed = 1; /* safety first */
+ #endif
+- check_disk_change( inode->i_bdev );
++ check_disk_change(bdev);
+ if (aip->changed) /* revalidate was not successful (no medium) */
+ return -ENXIO;
+ acsi_prevent_removal(aip, 1);
+@@ -1142,10 +1142,11 @@ static int acsi_open( struct inode * ino
+ aip->access_count++;
+
+ if (filp && filp->f_mode) {
+- check_disk_change( inode->i_bdev );
++ check_disk_change(bdev);
+ if (filp->f_mode & 2) {
+ if (aip->read_only) {
+- acsi_release( inode, filp );
++ if (--aip->access_count == 0 && aip->removable)
++ acsi_prevent_removal(aip, 0);
+ return -EROFS;
+ }
+ }
+@@ -1159,9 +1160,8 @@ static int acsi_open( struct inode * ino
+ * be forgotten about...
+ */
+
+-static int acsi_release( struct inode * inode, struct file * file )
++static int acsi_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct acsi_info_struct *aip = disk->private_data;
+ if (--aip->access_count == 0 && aip->removable)
+ acsi_prevent_removal(aip, 0);
+@@ -1327,8 +1327,6 @@ static int acsi_mode_sense( int target,
+ ********************************************************************/
+
+
+-extern struct block_device_operations acsi_fops;
+-
+ static struct gendisk *acsi_gendisk[MAX_DEV];
+
+ #define MAX_SCSI_DEVICE_CODE 10
+--- linux-2.6.0-test6/drivers/block/amiflop.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/amiflop.c 2003-10-05 00:34:00.000000000 -0700
+@@ -1434,10 +1434,11 @@ static void do_fd_request(request_queue_
+ redo_fd_request();
+ }
+
+-static int fd_ioctl(struct inode *inode, struct file *filp,
++static int fd_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param)
+ {
+- int drive = iminor(inode) & 3;
++ struct amiga_floppy_struct *floppy = bdev->bd_disk->private_data;
++ int drive = floppy - unit;
+ static struct floppy_struct getprm;
+
+ switch(cmd){
+@@ -1459,7 +1460,7 @@ static int fd_ioctl(struct inode *inode,
+ rel_fdc();
+ return -EBUSY;
+ }
+- fsync_bdev(inode->i_bdev);
++ fsync_bdev(bdev);
+ if (fd_motor_on(drive) == 0) {
+ rel_fdc();
+ return -ENODEV;
+@@ -1488,7 +1489,7 @@ static int fd_ioctl(struct inode *inode,
+ break;
+ case FDFMTEND:
+ floppy_off(drive);
+- invalidate_bdev(inode->i_bdev, 0);
++ invalidate_bdev(bdev, 0);
+ break;
+ case FDGETPRM:
+ memset((void *)&getprm, 0, sizeof (getprm));
+@@ -1559,10 +1560,11 @@ static void fd_probe(int dev)
+ * /dev/PS0 etc), and disallows simultaneous access to the same
+ * drive with different device numbers.
+ */
+-static int floppy_open(struct inode *inode, struct file *filp)
++static int floppy_open(struct block_device *bdev, struct file *filp)
+ {
+- int drive = iminor(inode) & 3;
+- int system = (iminor(inode) & 4) >> 2;
++ struct amiga_floppy_struct *p = bdev->bd_disk->private_data;
++ int drive = p - unit;
++ int system = (MINOR(bdev->bd_dev) & 4) >> 2;
+ int old_dev;
+ unsigned long flags;
+
+@@ -1572,7 +1574,7 @@ static int floppy_open(struct inode *ino
+ return -EBUSY;
+
+ if (filp && filp->f_mode & 3) {
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (filp->f_mode & 2 ) {
+ int wrprot;
+
+@@ -1607,9 +1609,10 @@ static int floppy_open(struct inode *ino
+ return 0;
+ }
+
+-static int floppy_release(struct inode * inode, struct file * filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- int drive = iminor(inode) & 3;
++ struct amiga_floppy_struct *p = disk->private_data;
++ int drive = p - unit;
+
+ if (unit[drive].dirty == 1) {
+ del_timer (flush_track_timer + drive);
+--- linux-2.6.0-test6/drivers/block/as-iosched.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/as-iosched.c 2003-10-05 00:36:08.000000000 -0700
+@@ -174,12 +174,14 @@ static kmem_cache_t *arq_pool;
+ * IO Context helper functions
+ */
+ /* Debug */
+-static atomic_t nr_as_io_requests = ATOMIC_INIT(0);
++extern atomic_t global_nr_requests;
++static atomic_t nr_as_io_contexts = ATOMIC_INIT(0);
+
+ /* Called to deallocate the as_io_context */
+ static void free_as_io_context(struct as_io_context *aic)
+ {
+- atomic_dec(&nr_as_io_requests);
++ WARN_ON(atomic_read(&nr_as_io_contexts) == 0);
++ atomic_dec(&nr_as_io_contexts);
+ kfree(aic);
+ }
+
+@@ -195,7 +197,9 @@ static struct as_io_context *alloc_as_io
+
+ ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+ if (ret) {
+- atomic_inc(&nr_as_io_requests);
++ atomic_inc(&nr_as_io_contexts);
++ WARN_ON(atomic_read(&nr_as_io_contexts) ==
++ 1 + nr_threads + atomic_read(&global_nr_requests));
+ ret->dtor = free_as_io_context;
+ ret->exit = exit_as_io_context;
+ ret->state = 1 << AS_TASK_RUNNING;
+@@ -914,6 +918,8 @@ static void as_completed_request(request
+ struct as_rq *arq = RQ_DATA(rq);
+ struct as_io_context *aic;
+
++ WARN_ON(!list_empty(&rq->queuelist));
++
+ if (unlikely(arq->state != AS_RQ_DISPATCHED))
+ return;
+
+@@ -926,6 +932,7 @@ static void as_completed_request(request
+ if (ad->batch_data_dir == REQ_SYNC)
+ ad->new_batch = 1;
+ }
++ WARN_ON(ad->nr_dispatched == 0);
+ ad->nr_dispatched--;
+
+ /*
+@@ -1140,8 +1147,6 @@ static void as_move_to_dispatch(struct a
+ /*
+ * take it off the sort and fifo list, add to dispatch queue
+ */
+- as_remove_queued_request(ad->q, rq);
+-
+ insert = ad->dispatch->prev;
+
+ while (!list_empty(&rq->queuelist)) {
+@@ -1159,6 +1164,7 @@ static void as_move_to_dispatch(struct a
+ ad->nr_dispatched++;
+ }
+
++ as_remove_queued_request(ad->q, rq);
+ list_add(&rq->queuelist, insert);
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
+@@ -1325,12 +1331,27 @@ static struct request *as_next_request(r
+ static inline void
+ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias)
+ {
++ struct request *req = arq->request;
++ struct list_head *insert = alias->request->queuelist.prev;
++
++ /*
++ * Transfer list of aliases
++ */
++ while (!list_empty(&req->queuelist)) {
++ struct request *__rq = list_entry_rq(req->queuelist.next);
++ struct as_rq *__arq = RQ_DATA(__rq);
++
++ list_move_tail(&__rq->queuelist, &alias->request->queuelist);
++
++ WARN_ON(__arq->state != AS_RQ_QUEUED);
++ }
++
+ /*
+ * Another request with the same start sector on the rbtree.
+ * Link this request to that sector. They are untangled in
+ * as_move_to_dispatch
+ */
+- list_add_tail(&arq->request->queuelist, &alias->request->queuelist);
++ list_add(&arq->request->queuelist, insert);
+
+ /*
+ * Don't want to have to handle merges.
+@@ -1390,9 +1411,6 @@ static void as_add_request(struct as_dat
+ }
+ }
+
+-
+-
+-
+ arq->state = AS_RQ_QUEUED;
+ }
+
+@@ -1596,7 +1614,8 @@ static void as_merged_request(request_qu
+ */
+ }
+
+- q->last_merge = req;
++ if (arq->on_hash)
++ q->last_merge = req;
+ }
+
+ static void
+--- linux-2.6.0-test6/drivers/block/ataflop.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/ataflop.c 2003-10-05 00:34:00.000000000 -0700
+@@ -364,13 +364,12 @@ static void finish_fdc_done( int dummy )
+ static __inline__ void copy_buffer( void *from, void *to);
+ static void setup_req_params( int drive );
+ static void redo_fd_request( void);
+-static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int
++static int fd_ioctl(struct block_device *bdev, struct file *filp, unsigned int
+ cmd, unsigned long param);
+ static void fd_probe( int drive );
+ static int fd_test_drive_present( int drive );
+ static void config_types( void );
+-static int floppy_open( struct inode *inode, struct file *filp );
+-static int floppy_release( struct inode * inode, struct file * filp );
++static int floppy_open(struct block_device *bdev, struct file *filp );
+
+ /************************* End of Prototypes **************************/
+
+@@ -1496,10 +1495,10 @@ void do_fd_request(request_queue_t * q)
+ atari_enable_irq( IRQ_MFP_FDC );
+ }
+
+-static int fd_ioctl(struct inode *inode, struct file *filp,
++static int fd_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct atari_floppy_struct *floppy = disk->private_data;
+ int drive = floppy - unit;
+ int type = floppy->type;
+@@ -1673,7 +1672,7 @@ static int fd_ioctl(struct inode *inode,
+ /* invalidate the buffer track to force a reread */
+ BufferDrive = -1;
+ set_bit(drive, &fake_change);
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ return 0;
+ default:
+ return -EINVAL;
+@@ -1816,10 +1815,10 @@ static void __init config_types( void )
+ * drive with different device numbers.
+ */
+
+-static int floppy_open( struct inode *inode, struct file *filp )
++static int floppy_open(struct block_device *bdev, struct file *filp )
+ {
+- struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
+- int type = iminor(inode) >> 2;
++ struct atari_floppy_struct *p = bdev->bd_disk->private_data;
++ int type = MINOR(bdev->bd_dev) >> 2;
+
+ DPRINT(("fd_open: type=%d\n",type));
+ if (p->ref && p->type != type)
+@@ -1839,14 +1838,13 @@ static int floppy_open( struct inode *in
+ return 0;
+
+ if (filp->f_mode & 3) {
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (filp->f_mode & 2) {
+ if (p->wpstat) {
+ if (p->ref < 0)
+ p->ref = 0;
+ else
+ p->ref--;
+- floppy_release(inode, filp);
+ return -EROFS;
+ }
+ }
+@@ -1855,9 +1853,9 @@ static int floppy_open( struct inode *in
+ }
+
+
+-static int floppy_release( struct inode * inode, struct file * filp )
++static int floppy_release(struct gendisk *disk)
+ {
+- struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
++ struct atari_floppy_struct *p = disk->private_data;
+ if (p->ref < 0)
+ p->ref = 0;
+ else if (!p->ref--) {
+--- linux-2.6.0-test6/drivers/block/cciss.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/cciss.c 2003-10-05 00:34:00.000000000 -0700
+@@ -111,12 +111,10 @@ static struct board_type products[] = {
+
+ static ctlr_info_t *hba[MAX_CTLR];
+
+-static struct proc_dir_entry *proc_cciss;
+-
+ static void do_cciss_request(request_queue_t *q);
+-static int cciss_open(struct inode *inode, struct file *filep);
+-static int cciss_release(struct inode *inode, struct file *filep);
+-static int cciss_ioctl(struct inode *inode, struct file *filep,
++static int cciss_open(struct block_device *bdev, struct file *filep);
++static int cciss_release(struct gendisk *disk);
++static int cciss_ioctl(struct block_device *bdev, struct file *filep,
+ unsigned int cmd, unsigned long arg);
+
+ static int revalidate_allvol(ctlr_info_t *host);
+@@ -137,8 +135,6 @@ static int cciss_proc_get_info(char *buf
+ int length, int *eof, void *data);
+ static void cciss_procinit(int i);
+ #else
+-static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+- int length, int *eof, void *data) { return 0;}
+ static void cciss_procinit(int i) {}
+ #endif /* CONFIG_PROC_FS */
+
+@@ -156,6 +152,9 @@ static struct block_device_operations cc
+ * Report information about this controller.
+ */
+ #ifdef CONFIG_PROC_FS
++
++static struct proc_dir_entry *proc_cciss;
++
+ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+ {
+@@ -363,13 +362,13 @@ static inline drive_info_struct *get_drv
+ /*
+ * Open. Make sure the device is really there.
+ */
+-static int cciss_open(struct inode *inode, struct file *filep)
++static int cciss_open(struct block_device *bdev, struct file *filep)
+ {
+- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
++ ctlr_info_t *host = get_host(bdev->bd_disk);
++ drive_info_struct *drv = get_drv(bdev->bd_disk);
+
+ #ifdef CCISS_DEBUG
+- printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
++ printk(KERN_DEBUG "cciss_open %s\n", bdev->bd_disk->disk_name);
+ #endif /* CCISS_DEBUG */
+
+ /*
+@@ -379,7 +378,7 @@ static int cciss_open(struct inode *inod
+ * for "raw controller".
+ */
+ if (drv->nr_blocks == 0) {
+- if (iminor(inode) != 0)
++ if (bdev != bdev->bd_contains || drv != host->drv)
+ return -ENXIO;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+@@ -391,13 +390,13 @@ static int cciss_open(struct inode *inod
+ /*
+ * Close. Sync first.
+ */
+-static int cciss_release(struct inode *inode, struct file *filep)
++static int cciss_release(struct gendisk *disk)
+ {
+- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
+- drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
++ ctlr_info_t *host = get_host(disk);
++ drive_info_struct *drv = get_drv(disk);
+
+ #ifdef CCISS_DEBUG
+- printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name);
++ printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name);
+ #endif /* CCISS_DEBUG */
+
+ drv->usage_count--;
+@@ -408,10 +407,9 @@ static int cciss_release(struct inode *i
+ /*
+ * ioctl
+ */
+-static int cciss_ioctl(struct inode *inode, struct file *filep,
++static int cciss_ioctl(struct block_device *bdev, struct file *filep,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ ctlr_info_t *host = get_host(disk);
+ drive_info_struct *drv = get_drv(disk);
+@@ -434,7 +432,7 @@ static int cciss_ioctl(struct inode *ino
+ driver_geo.sectors = 0x3f;
+ driver_geo.cylinders = (int)drv->nr_blocks / (0xff*0x3f);
+ }
+- driver_geo.start= get_start_sect(inode->i_bdev);
++ driver_geo.start= get_start_sect(bdev);
+ if (copy_to_user((void *) arg, &driver_geo,
+ sizeof( struct hd_geometry)))
+ return -EFAULT;
+@@ -636,9 +634,11 @@ static int cciss_ioctl(struct inode *ino
+ {
+ return -EINVAL;
+ }
++#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
+ /* Check kmalloc limits */
+ if(iocommand.buf_size > 128000)
+ return -EINVAL;
++#endif
+ if(iocommand.buf_size > 0)
+ {
+ buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/block/cfq-iosched.c 2003-10-05 00:34:17.000000000 -0700
+@@ -0,0 +1,707 @@
++/*
++ * linux/drivers/block/cfq-iosched.c
++ *
++ * CFQ, or complete fairness queueing, disk scheduler.
++ *
++ * Based on ideas from a previously unfinished io
++ * scheduler (round robin per-process disk scheduling) and Andrea Arcangeli.
++ *
++ * Copyright (C) 2003 Jens Axboe <axboe@suse.de>
++ */
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/blkdev.h>
++#include <linux/elevator.h>
++#include <linux/bio.h>
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/compiler.h>
++#include <linux/hash.h>
++#include <linux/rbtree.h>
++#include <linux/mempool.h>
++
++/*
++ * tunables
++ */
++static int cfq_quantum = 4;
++static int cfq_queued = 8;
++
++#define CFQ_QHASH_SHIFT 6
++#define CFQ_QHASH_ENTRIES (1 << CFQ_QHASH_SHIFT)
++#define list_entry_qhash(entry) list_entry((entry), struct cfq_queue, cfq_hash)
++
++#define CFQ_MHASH_SHIFT 8
++#define CFQ_MHASH_BLOCK(sec) ((sec) >> 3)
++#define CFQ_MHASH_ENTRIES (1 << CFQ_MHASH_SHIFT)
++#define CFQ_MHASH_FN(sec) (hash_long(CFQ_MHASH_BLOCK((sec)),CFQ_MHASH_SHIFT))
++#define ON_MHASH(crq) !list_empty(&(crq)->hash)
++#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
++#define list_entry_hash(ptr) list_entry((ptr), struct cfq_rq, hash)
++
++#define list_entry_cfqq(ptr) list_entry((ptr), struct cfq_queue, cfq_list)
++
++#define RQ_DATA(rq) ((struct cfq_rq *) (rq)->elevator_private)
++
++static kmem_cache_t *crq_pool;
++static kmem_cache_t *cfq_pool;
++static mempool_t *cfq_mpool;
++
++struct cfq_data {
++ struct list_head rr_list;
++ struct list_head *dispatch;
++ struct list_head *cfq_hash;
++
++ struct list_head *crq_hash;
++
++ unsigned int busy_queues;
++ unsigned int max_queued;
++
++ mempool_t *crq_pool;
++};
++
++struct cfq_queue {
++ struct list_head cfq_hash;
++ struct list_head cfq_list;
++ struct rb_root sort_list;
++ int pid;
++ int queued[2];
++#if 0
++ /*
++ * with a simple addition like this, we can do io priorities. almost.
++ * does need a split request free list, too.
++ */
++ int io_prio
++#endif
++};
++
++struct cfq_rq {
++ struct rb_node rb_node;
++ sector_t rb_key;
++
++ struct request *request;
++
++ struct cfq_queue *cfq_queue;
++
++ struct list_head hash;
++};
++
++static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq);
++static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid);
++static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq);
++
++/*
++ * lots of deadline iosched dupes, can be abstracted later...
++ */
++static inline void __cfq_del_crq_hash(struct cfq_rq *crq)
++{
++ list_del_init(&crq->hash);
++}
++
++static inline void cfq_del_crq_hash(struct cfq_rq *crq)
++{
++ if (ON_MHASH(crq))
++ __cfq_del_crq_hash(crq);
++}
++
++static void cfq_remove_merge_hints(request_queue_t *q, struct cfq_rq *crq)
++{
++ cfq_del_crq_hash(crq);
++
++ if (q->last_merge == crq->request)
++ q->last_merge = NULL;
++}
++
++static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
++{
++ struct request *rq = crq->request;
++
++ BUG_ON(ON_MHASH(crq));
++
++ list_add(&crq->hash, &cfqd->crq_hash[CFQ_MHASH_FN(rq_hash_key(rq))]);
++}
++
++static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
++{
++ struct list_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)];
++ struct list_head *entry, *next = hash_list->next;
++
++ while ((entry = next) != hash_list) {
++ struct cfq_rq *crq = list_entry_hash(entry);
++ struct request *__rq = crq->request;
++
++ next = entry->next;
++
++ BUG_ON(!ON_MHASH(crq));
++
++ if (!rq_mergeable(__rq)) {
++ __cfq_del_crq_hash(crq);
++ continue;
++ }
++
++ if (rq_hash_key(__rq) == offset)
++ return __rq;
++ }
++
++ return NULL;
++}
++
++/*
++ * rb tree support functions
++ */
++#define RB_NONE (2)
++#define RB_EMPTY(node) ((node)->rb_node == NULL)
++#define RB_CLEAR(node) ((node)->rb_color = RB_NONE)
++#define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL)
++#define ON_RB(node) ((node)->rb_color != RB_NONE)
++#define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node)
++#define rq_rb_key(rq) (rq)->sector
++
++static inline void cfq_del_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
++{
++ if (ON_RB(&crq->rb_node)) {
++ cfqq->queued[rq_data_dir(crq->request)]--;
++ rb_erase(&crq->rb_node, &cfqq->sort_list);
++ crq->cfq_queue = NULL;
++ }
++}
++
++static struct cfq_rq *
++__cfq_add_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
++{
++ struct rb_node **p = &cfqq->sort_list.rb_node;
++ struct rb_node *parent = NULL;
++ struct cfq_rq *__crq;
++
++ while (*p) {
++ parent = *p;
++ __crq = rb_entry_crq(parent);
++
++ if (crq->rb_key < __crq->rb_key)
++ p = &(*p)->rb_left;
++ else if (crq->rb_key > __crq->rb_key)
++ p = &(*p)->rb_right;
++ else
++ return __crq;
++ }
++
++ rb_link_node(&crq->rb_node, parent, p);
++ return 0;
++}
++
++static void
++cfq_add_crq_rb(struct cfq_data *cfqd, struct cfq_queue *cfqq,struct cfq_rq *crq)
++{
++ struct request *rq = crq->request;
++ struct cfq_rq *__alias;
++
++ crq->rb_key = rq_rb_key(rq);
++ cfqq->queued[rq_data_dir(rq)]++;
++retry:
++ __alias = __cfq_add_crq_rb(cfqq, crq);
++ if (!__alias) {
++ rb_insert_color(&crq->rb_node, &cfqq->sort_list);
++ crq->cfq_queue = cfqq;
++ return;
++ }
++
++ cfq_del_crq_rb(cfqq, __alias);
++ cfq_dispatch_sort(cfqd->dispatch, __alias);
++ goto retry;
++}
++
++static struct request *
++cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
++{
++ struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->tgid);
++ struct rb_node *n;
++
++ if (!cfqq)
++ goto out;
++
++ n = cfqq->sort_list.rb_node;
++ while (n) {
++ struct cfq_rq *crq = rb_entry_crq(n);
++
++ if (sector < crq->rb_key)
++ n = n->rb_left;
++ else if (sector > crq->rb_key)
++ n = n->rb_right;
++ else
++ return crq->request;
++ }
++
++out:
++ return NULL;
++}
++
++static void cfq_remove_request(request_queue_t *q, struct request *rq)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_rq *crq = RQ_DATA(rq);
++
++ if (crq) {
++ struct cfq_queue *cfqq = crq->cfq_queue;
++
++ cfq_remove_merge_hints(q, crq);
++ list_del_init(&rq->queuelist);
++
++ if (cfqq) {
++ cfq_del_crq_rb(cfqq, crq);
++
++ if (RB_EMPTY(&cfqq->sort_list))
++ cfq_put_queue(cfqd, cfqq);
++ }
++ }
++}
++
++static int
++cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct request *__rq;
++ int ret;
++
++ ret = elv_try_last_merge(q, bio);
++ if (ret != ELEVATOR_NO_MERGE) {
++ __rq = q->last_merge;
++ goto out_insert;
++ }
++
++ __rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
++ if (__rq) {
++ BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
++
++ if (elv_rq_merge_ok(__rq, bio)) {
++ ret = ELEVATOR_BACK_MERGE;
++ goto out;
++ }
++ }
++
++ __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
++ if (__rq) {
++ if (elv_rq_merge_ok(__rq, bio)) {
++ ret = ELEVATOR_FRONT_MERGE;
++ goto out;
++ }
++ }
++
++ return ELEVATOR_NO_MERGE;
++out:
++ q->last_merge = __rq;
++out_insert:
++ *req = __rq;
++ return ret;
++}
++
++static void cfq_merged_request(request_queue_t *q, struct request *req)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_rq *crq = RQ_DATA(req);
++
++ cfq_del_crq_hash(crq);
++ cfq_add_crq_hash(cfqd, crq);
++
++ if (ON_RB(&crq->rb_node) && (rq_rb_key(req) != crq->rb_key)) {
++ struct cfq_queue *cfqq = crq->cfq_queue;
++
++ cfq_del_crq_rb(cfqq, crq);
++ cfq_add_crq_rb(cfqd, cfqq, crq);
++ }
++
++ q->last_merge = req;
++}
++
++static void
++cfq_merged_requests(request_queue_t *q, struct request *req,
++ struct request *next)
++{
++ cfq_merged_request(q, req);
++ cfq_remove_request(q, next);
++}
++
++static void cfq_dispatch_sort(struct list_head *head, struct cfq_rq *crq)
++{
++ struct list_head *entry = head;
++ struct request *__rq;
++
++ if (!list_empty(head)) {
++ __rq = list_entry_rq(head->next);
++
++ if (crq->request->sector < __rq->sector) {
++ entry = head->prev;
++ goto link;
++ }
++ }
++
++ while ((entry = entry->prev) != head) {
++ __rq = list_entry_rq(entry);
++
++ if (crq->request->sector <= __rq->sector)
++ break;
++ }
++
++link:
++ list_add_tail(&crq->request->queuelist, entry);
++}
++
++static inline void
++__cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd,
++ struct cfq_queue *cfqq)
++{
++ struct cfq_rq *crq = rb_entry_crq(rb_first(&cfqq->sort_list));
++
++ cfq_del_crq_rb(cfqq, crq);
++ cfq_remove_merge_hints(q, crq);
++ cfq_dispatch_sort(cfqd->dispatch, crq);
++}
++
++static int cfq_dispatch_requests(request_queue_t *q, struct cfq_data *cfqd)
++{
++ struct cfq_queue *cfqq;
++ struct list_head *entry, *tmp;
++ int ret, queued, good_queues;
++
++ if (list_empty(&cfqd->rr_list))
++ return 0;
++
++ queued = ret = 0;
++restart:
++ good_queues = 0;
++ list_for_each_safe(entry, tmp, &cfqd->rr_list) {
++ cfqq = list_entry_cfqq(cfqd->rr_list.next);
++
++ BUG_ON(RB_EMPTY(&cfqq->sort_list));
++
++ __cfq_dispatch_requests(q, cfqd, cfqq);
++
++ if (RB_EMPTY(&cfqq->sort_list))
++ cfq_put_queue(cfqd, cfqq);
++ else
++ good_queues++;
++
++ queued++;
++ ret = 1;
++ }
++
++ if ((queued < cfq_quantum) && good_queues)
++ goto restart;
++
++ return ret;
++}
++
++static struct request *cfq_next_request(request_queue_t *q)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct request *rq;
++
++ if (!list_empty(cfqd->dispatch)) {
++ struct cfq_rq *crq;
++dispatch:
++ rq = list_entry_rq(cfqd->dispatch->next);
++
++ BUG_ON(q->last_merge == rq);
++ crq = RQ_DATA(rq);
++ if (crq)
++ BUG_ON(ON_MHASH(crq));
++
++ return rq;
++ }
++
++ if (cfq_dispatch_requests(q, cfqd))
++ goto dispatch;
++
++ return NULL;
++}
++
++static inline struct cfq_queue *
++__cfq_find_cfq_hash(struct cfq_data *cfqd, int pid, const int hashval)
++{
++ struct list_head *hash_list = &cfqd->cfq_hash[hashval];
++ struct list_head *entry;
++
++ list_for_each(entry, hash_list) {
++ struct cfq_queue *__cfqq = list_entry_qhash(entry);
++
++ if (__cfqq->pid == pid)
++ return __cfqq;
++ }
++
++ return NULL;
++}
++
++static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *cfqd, int pid)
++{
++ const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT);
++
++ return __cfq_find_cfq_hash(cfqd, pid, hashval);
++}
++
++static void cfq_put_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
++{
++ cfqd->busy_queues--;
++ list_del(&cfqq->cfq_list);
++ list_del(&cfqq->cfq_hash);
++ mempool_free(cfqq, cfq_mpool);
++}
++
++static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, int pid)
++{
++ const int hashval = hash_long(current->tgid, CFQ_QHASH_SHIFT);
++ struct cfq_queue *cfqq = __cfq_find_cfq_hash(cfqd, pid, hashval);
++
++ if (!cfqq) {
++ cfqq = mempool_alloc(cfq_mpool, GFP_NOIO);
++
++ INIT_LIST_HEAD(&cfqq->cfq_hash);
++ INIT_LIST_HEAD(&cfqq->cfq_list);
++ RB_CLEAR_ROOT(&cfqq->sort_list);
++
++ cfqq->pid = pid;
++ cfqq->queued[0] = cfqq->queued[1] = 0;
++ list_add(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
++ }
++
++ return cfqq;
++}
++
++static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq)
++{
++ struct cfq_queue *cfqq;
++
++ cfqq = cfq_get_queue(cfqd, current->tgid);
++
++ cfq_add_crq_rb(cfqd, cfqq, crq);
++
++ if (list_empty(&cfqq->cfq_list)) {
++ list_add(&cfqq->cfq_list, &cfqd->rr_list);
++ cfqd->busy_queues++;
++ }
++}
++
++static void
++cfq_insert_request(request_queue_t *q, struct request *rq, int where)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_rq *crq = RQ_DATA(rq);
++
++ switch (where) {
++ case ELEVATOR_INSERT_BACK:
++ while (cfq_dispatch_requests(q, cfqd))
++ ;
++ list_add_tail(&rq->queuelist, cfqd->dispatch);
++ break;
++ case ELEVATOR_INSERT_FRONT:
++ list_add(&rq->queuelist, cfqd->dispatch);
++ break;
++ case ELEVATOR_INSERT_SORT:
++ BUG_ON(!blk_fs_request(rq));
++ cfq_enqueue(cfqd, crq);
++ break;
++ default:
++ printk("%s: bad insert point %d\n", __FUNCTION__,where);
++ return;
++ }
++
++ if (rq_mergeable(rq)) {
++ cfq_add_crq_hash(cfqd, crq);
++
++ if (!q->last_merge)
++ q->last_merge = rq;
++ }
++}
++
++static int cfq_queue_empty(request_queue_t *q)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++
++ if (list_empty(cfqd->dispatch) && list_empty(&cfqd->rr_list))
++ return 1;
++
++ return 0;
++}
++
++static struct request *
++cfq_former_request(request_queue_t *q, struct request *rq)
++{
++ struct cfq_rq *crq = RQ_DATA(rq);
++ struct rb_node *rbprev = rb_prev(&crq->rb_node);
++
++ if (rbprev)
++ return rb_entry_crq(rbprev)->request;
++
++ return NULL;
++}
++
++static struct request *
++cfq_latter_request(request_queue_t *q, struct request *rq)
++{
++ struct cfq_rq *crq = RQ_DATA(rq);
++ struct rb_node *rbnext = rb_next(&crq->rb_node);
++
++ if (rbnext)
++ return rb_entry_crq(rbnext)->request;
++
++ return NULL;
++}
++
++static int cfq_may_queue(request_queue_t *q, int rw)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_queue *cfqq;
++ int ret = 1;
++
++ if (!cfqd->busy_queues)
++ goto out;
++
++ cfqq = cfq_find_cfq_hash(cfqd, current->tgid);
++ if (cfqq) {
++ int limit = (q->nr_requests - cfq_queued) / cfqd->busy_queues;
++
++ if (limit < 3)
++ limit = 3;
++ else if (limit > cfqd->max_queued)
++ limit = cfqd->max_queued;
++
++ if (cfqq->queued[rw] > limit)
++ ret = 0;
++ }
++out:
++ return ret;
++}
++
++static void cfq_put_request(request_queue_t *q, struct request *rq)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_rq *crq = RQ_DATA(rq);
++
++ if (crq) {
++ BUG_ON(q->last_merge == rq);
++ BUG_ON(ON_MHASH(crq));
++
++ mempool_free(crq, cfqd->crq_pool);
++ rq->elevator_private = NULL;
++ }
++}
++
++static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
++{
++ struct cfq_data *cfqd = q->elevator.elevator_data;
++ struct cfq_rq *crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
++
++ if (crq) {
++ RB_CLEAR(&crq->rb_node);
++ crq->request = rq;
++ crq->cfq_queue = NULL;
++ INIT_LIST_HEAD(&crq->hash);
++ rq->elevator_private = crq;
++ return 0;
++ }
++
++ return 1;
++}
++
++static void cfq_exit(request_queue_t *q, elevator_t *e)
++{
++ struct cfq_data *cfqd = e->elevator_data;
++
++ e->elevator_data = NULL;
++ mempool_destroy(cfqd->crq_pool);
++ kfree(cfqd->crq_hash);
++ kfree(cfqd->cfq_hash);
++ kfree(cfqd);
++}
++
++static int cfq_init(request_queue_t *q, elevator_t *e)
++{
++ struct cfq_data *cfqd;
++ int i;
++
++ cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
++ if (!cfqd)
++ return -ENOMEM;
++
++ memset(cfqd, 0, sizeof(*cfqd));
++ INIT_LIST_HEAD(&cfqd->rr_list);
++
++ cfqd->crq_hash = kmalloc(sizeof(struct list_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
++ if (!cfqd->crq_hash)
++ goto out_crqhash;
++
++ cfqd->cfq_hash = kmalloc(sizeof(struct list_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL);
++ if (!cfqd->cfq_hash)
++ goto out_cfqhash;
++
++ cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool);
++ if (!cfqd->crq_pool)
++ goto out_crqpool;
++
++ for (i = 0; i < CFQ_MHASH_ENTRIES; i++)
++ INIT_LIST_HEAD(&cfqd->crq_hash[i]);
++ for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
++ INIT_LIST_HEAD(&cfqd->cfq_hash[i]);
++
++ cfqd->dispatch = &q->queue_head;
++ e->elevator_data = cfqd;
++
++ /*
++ * just set it to some high value, we want anyone to be able to queue
++ * some requests. fairness is handled differently
++ */
++ cfqd->max_queued = q->nr_requests;
++ q->nr_requests = 8192;
++
++ return 0;
++out_crqpool:
++ kfree(cfqd->cfq_hash);
++out_cfqhash:
++ kfree(cfqd->crq_hash);
++out_crqhash:
++ kfree(cfqd);
++ return -ENOMEM;
++}
++
++static int __init cfq_slab_setup(void)
++{
++ crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0,
++ NULL, NULL);
++
++ if (!crq_pool)
++ panic("cfq_iosched: can't init crq pool\n");
++
++ cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0,
++ NULL, NULL);
++
++ if (!cfq_pool)
++ panic("cfq_iosched: can't init cfq pool\n");
++
++ cfq_mpool = mempool_create(64, mempool_alloc_slab, mempool_free_slab, cfq_pool);
++
++ if (!cfq_mpool)
++ panic("cfq_iosched: can't init cfq mpool\n");
++
++ return 0;
++}
++
++subsys_initcall(cfq_slab_setup);
++
++elevator_t iosched_cfq = {
++ .elevator_name = "cfq",
++ .elevator_merge_fn = cfq_merge,
++ .elevator_merged_fn = cfq_merged_request,
++ .elevator_merge_req_fn = cfq_merged_requests,
++ .elevator_next_req_fn = cfq_next_request,
++ .elevator_add_req_fn = cfq_insert_request,
++ .elevator_remove_req_fn = cfq_remove_request,
++ .elevator_queue_empty_fn = cfq_queue_empty,
++ .elevator_former_req_fn = cfq_former_request,
++ .elevator_latter_req_fn = cfq_latter_request,
++ .elevator_set_req_fn = cfq_set_request,
++ .elevator_put_req_fn = cfq_put_request,
++ .elevator_may_queue_fn = cfq_may_queue,
++ .elevator_init_fn = cfq_init,
++ .elevator_exit_fn = cfq_exit,
++};
++
++EXPORT_SYMBOL(iosched_cfq);
+--- linux-2.6.0-test6/drivers/block/cpqarray.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/cpqarray.c 2003-10-05 00:34:00.000000000 -0700
+@@ -99,8 +99,6 @@ static struct board_type products[] = {
+
+ static struct gendisk *ida_gendisk[MAX_CTLR][NWD];
+
+-static struct proc_dir_entry *proc_array;
+-
+ /* Debug... */
+ #define DBG(s) do { s } while(0)
+ /* Debug (general info)... */
+@@ -130,9 +128,9 @@ static int sendcmd(
+ unsigned int blkcnt,
+ unsigned int log_unit );
+
+-static int ida_open(struct inode *inode, struct file *filep);
+-static int ida_release(struct inode *inode, struct file *filep);
+-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
++static int ida_open(struct block_device *bdev, struct file *filep);
++static int ida_release(struct gendisk *disk);
++static int ida_ioctl(struct block_device *bdev, struct file *filep, unsigned int cmd, unsigned long arg);
+ static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
+
+ static void do_ida_request(request_queue_t *q);
+@@ -153,8 +151,6 @@ static void ida_procinit(int i);
+ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+ #else
+ static void ida_procinit(int i) {}
+-static int ida_proc_get_info(char *buffer, char **start, off_t offset,
+- int length, int *eof, void *data) { return 0;}
+ #endif
+
+ static inline drv_info_t *get_drv(struct gendisk *disk)
+@@ -179,6 +175,8 @@ static struct block_device_operations id
+
+ #ifdef CONFIG_PROC_FS
+
++static struct proc_dir_entry *proc_array;
++
+ /*
+ * Get us a file in /proc/array that says something about each controller.
+ * Create /proc/array if it doesn't exist yet.
+@@ -717,12 +715,12 @@ DBGINFO(
+ /*
+ * Open. Make sure the device is really there.
+ */
+-static int ida_open(struct inode *inode, struct file *filep)
++static int ida_open(struct block_device *bdev, struct file *filep)
+ {
+- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
+- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
++ drv_info_t *drv = get_drv(bdev->bd_disk);
++ ctlr_info_t *host = get_host(bdev->bd_disk);
+
+- DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));
++ DBGINFO(printk("ida_open %s\n", bdev->bd_disk->disk_name));
+ /*
+ * Root is allowed to open raw volume zero even if it's not configured
+ * so array config can still work. I don't think I really like this,
+@@ -742,9 +740,9 @@ static int ida_open(struct inode *inode,
+ /*
+ * Close. Sync first.
+ */
+-static int ida_release(struct inode *inode, struct file *filep)
++static int ida_release(struct gendisk *disk)
+ {
+- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
++ ctlr_info_t *host = get_host(disk);
+ host->usage_count--;
+ return 0;
+ }
+@@ -1024,10 +1022,10 @@ static void ida_timer(unsigned long tdat
+ * ida_ioctl does some miscellaneous stuff like reporting drive geometry,
+ * setting readahead and submitting commands from userspace to the controller.
+ */
+-static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
++static int ida_ioctl(struct block_device *bdev, struct file *filep, unsigned int cmd, unsigned long arg)
+ {
+- drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
+- ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
++ drv_info_t *drv = get_drv(bdev->bd_disk);
++ ctlr_info_t *host = get_host(bdev->bd_disk);
+ int error;
+ int diskinfo[4];
+ struct hd_geometry *geo = (struct hd_geometry *)arg;
+@@ -1048,7 +1046,7 @@ static int ida_ioctl(struct inode *inode
+ put_user(diskinfo[0], &geo->heads);
+ put_user(diskinfo[1], &geo->sectors);
+ put_user(diskinfo[2], &geo->cylinders);
+- put_user(get_start_sect(inode->i_bdev), &geo->start);
++ put_user(get_start_sect(bdev), &geo->start);
+ return 0;
+ case IDAGETDRVINFO:
+ if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
+@@ -1078,7 +1076,7 @@ out_passthru:
+ put_user(host->ctlr_sig, (int*)arg);
+ return 0;
+ case IDAREVALIDATEVOLS:
+- if (iminor(inode) != 0)
++ if (bdev != bdev->bd_contains || drv != host->drv)
+ return -ENXIO;
+ return revalidate_allvol(host);
+ case IDADRIVERVERSION:
+--- linux-2.6.0-test6/drivers/block/DAC960.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/DAC960.c 2003-10-05 00:33:58.000000000 -0700
+@@ -67,9 +67,9 @@ static long disk_size(DAC960_Controller_
+ }
+ }
+
+-static int DAC960_open(struct inode *inode, struct file *file)
++static int DAC960_open(struct block_device *bdev, struct file *file)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ DAC960_Controller_T *p = disk->queue->queuedata;
+ int drive_nr = (long)disk->private_data;
+
+@@ -84,17 +84,17 @@ static int DAC960_open(struct inode *ino
+ return -ENXIO;
+ }
+
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+
+ if (!get_capacity(p->disks[drive_nr]))
+ return -ENXIO;
+ return 0;
+ }
+
+-static int DAC960_ioctl(struct inode *inode, struct file *file,
++static int DAC960_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ DAC960_Controller_T *p = disk->queue->queuedata;
+ int drive_nr = (long)disk->private_data;
+ struct hd_geometry g, *loc = (struct hd_geometry *)arg;
+@@ -128,7 +128,7 @@ static int DAC960_ioctl(struct inode *in
+ g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
+ }
+
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+
+ return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ }
+--- linux-2.6.0-test6/drivers/block/floppy98.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/floppy98.c 2003-10-05 00:34:01.000000000 -0700
+@@ -3484,14 +3484,14 @@ static int get_floppy_geometry(int drive
+ return 0;
+ }
+
+-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++static int fd_ioctl(struct block_device *bdev, struct file *filp, unsigned int cmd,
+ unsigned long param)
+ {
+ #define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
+ #define OUT(c,x) case c: outparam = (const char *) (x); break
+ #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
+
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)bdev->bd_disk->private_data;
+ int i, type = ITYPE(UDRS->fd_device);
+ int ret;
+ int size;
+@@ -3566,11 +3566,11 @@ static int fd_ioctl(struct inode *inode,
+ current_type[drive] = NULL;
+ floppy_sizes[drive] = MAX_DISK_SIZE << 1;
+ UDRS->keep_data = 0;
+- return invalidate_drive(inode->i_bdev);
++ return invalidate_drive(bdev);
+ case FDSETPRM:
+ case FDDEFPRM:
+ return set_geometry(cmd, & inparam.g,
+- drive, type, inode->i_bdev);
++ drive, type, bdev);
+ case FDGETPRM:
+ ECALL(get_floppy_geometry(drive, type,
+ (struct floppy_struct**)
+@@ -3625,7 +3625,7 @@ static int fd_ioctl(struct inode *inode,
+ case FDFMTEND:
+ case FDFLUSH:
+ LOCK_FDC(drive,1);
+- return invalidate_drive(inode->i_bdev);
++ return invalidate_drive(bdev);
+
+ case FDSETEMSGTRESH:
+ UDP->max_errors.reporting =
+@@ -3735,9 +3735,9 @@ static void __init config_types(void)
+ printk("\n");
+ }
+
+-static int floppy_release(struct inode * inode, struct file * filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)disk->private_data;
+
+ down(&open_lock);
+ if (UDRS->fd_ref < 0)
+@@ -3758,11 +3758,10 @@ static int floppy_release(struct inode *
+ * /dev/PS0 etc), and disallows simultaneous access to the same
+ * drive with different device numbers.
+ */
+-#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
+
+-static int floppy_open(struct inode * inode, struct file * filp)
++static int floppy_open(struct block_device *bdev, struct file *filp)
+ {
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)bdev->bd_disk->private_data;
+ int old_dev;
+ int try;
+ int res = -EBUSY;
+@@ -3789,7 +3788,7 @@ static int floppy_open(struct inode * in
+
+ down(&open_lock);
+ old_dev = UDRS->fd_device;
+- if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
++ if (opened_bdev[drive] && opened_bdev[drive] != bdev)
+ goto out2;
+
+ if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
+@@ -3809,7 +3808,7 @@ static int floppy_open(struct inode * in
+ else
+ UDRS->fd_ref++;
+
+- opened_bdev[drive] = inode->i_bdev;
++ opened_bdev[drive] = bdev;
+
+ res = -ENXIO;
+
+@@ -3844,9 +3843,9 @@ static int floppy_open(struct inode * in
+ }
+ }
+
+- UDRS->fd_device = iminor(inode);
+- set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
+- if (old_dev != -1 && old_dev != iminor(inode)) {
++ UDRS->fd_device = MINOR(bdev->bd_dev);
++ set_capacity(disks[drive], floppy_sizes[MINOR(bdev->bd_dev)]);
++ if (old_dev != -1 && old_dev != MINOR(bdev->bd_dev)) {
+ if (buffer_drive == drive)
+ buffer_track = -1;
+ }
+@@ -3859,8 +3858,7 @@ static int floppy_open(struct inode * in
+ /* Allow ioctls if we have write-permissions even if read-only open.
+ * Needed so that programs such as fdrawcmd still can work on write
+ * protected disks */
+- if ((filp->f_mode & 2) ||
+- (inode->i_sb && (permission(inode,2) == 0)))
++ if ((filp->f_mode & 2) || permission(filp->f_dentry->d_inode,2) == 0)
+ filp->private_data = (void*) 8;
+
+ if (UFDCS->rawcmd == 1)
+@@ -3873,7 +3871,7 @@ static int floppy_open(struct inode * in
+ if (!(filp->f_flags & O_NDELAY)) {
+ if (filp->f_mode & 3) {
+ UDRS->last_checked = 0;
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (UTESTF(FD_DISK_CHANGED))
+ goto out;
+ }
+--- linux-2.6.0-test6/drivers/block/floppy.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/floppy.c 2003-10-05 00:34:01.000000000 -0700
+@@ -3456,14 +3456,14 @@ static int get_floppy_geometry(int drive
+ return 0;
+ }
+
+-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
++static int fd_ioctl(struct block_device *bdev, struct file *filp, unsigned int cmd,
+ unsigned long param)
+ {
+ #define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
+ #define OUT(c,x) case c: outparam = (const char *) (x); break
+ #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
+
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)bdev->bd_disk->private_data;
+ int i, type = ITYPE(UDRS->fd_device);
+ int ret;
+ int size;
+@@ -3539,11 +3539,11 @@ static int fd_ioctl(struct inode *inode,
+ current_type[drive] = NULL;
+ floppy_sizes[drive] = MAX_DISK_SIZE << 1;
+ UDRS->keep_data = 0;
+- return invalidate_drive(inode->i_bdev);
++ return invalidate_drive(bdev);
+ case FDSETPRM:
+ case FDDEFPRM:
+ return set_geometry(cmd, & inparam.g,
+- drive, type, inode->i_bdev);
++ drive, type, bdev);
+ case FDGETPRM:
+ ECALL(get_floppy_geometry(drive, type,
+ (struct floppy_struct**)
+@@ -3574,7 +3574,7 @@ static int fd_ioctl(struct inode *inode,
+ case FDFMTEND:
+ case FDFLUSH:
+ LOCK_FDC(drive,1);
+- return invalidate_drive(inode->i_bdev);
++ return invalidate_drive(bdev);
+
+ case FDSETEMSGTRESH:
+ UDP->max_errors.reporting =
+@@ -3685,9 +3685,9 @@ static void __init config_types(void)
+ printk("\n");
+ }
+
+-static int floppy_release(struct inode * inode, struct file * filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)disk->private_data;
+
+ down(&open_lock);
+ if (UDRS->fd_ref < 0)
+@@ -3708,9 +3708,9 @@ static int floppy_release(struct inode *
+ * /dev/PS0 etc), and disallows simultaneous access to the same
+ * drive with different device numbers.
+ */
+-static int floppy_open(struct inode * inode, struct file * filp)
++static int floppy_open(struct block_device *bdev, struct file * filp)
+ {
+- int drive = (long)inode->i_bdev->bd_disk->private_data;
++ int drive = (long)bdev->bd_disk->private_data;
+ int old_dev;
+ int try;
+ int res = -EBUSY;
+@@ -3719,7 +3719,7 @@ static int floppy_open(struct inode * in
+ filp->private_data = (void*) 0;
+ down(&open_lock);
+ old_dev = UDRS->fd_device;
+- if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
++ if (opened_bdev[drive] && opened_bdev[drive] != bdev)
+ goto out2;
+
+ if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
+@@ -3739,7 +3739,7 @@ static int floppy_open(struct inode * in
+ else
+ UDRS->fd_ref++;
+
+- opened_bdev[drive] = inode->i_bdev;
++ opened_bdev[drive] = bdev;
+
+ res = -ENXIO;
+
+@@ -3774,9 +3774,9 @@ static int floppy_open(struct inode * in
+ }
+ }
+
+- UDRS->fd_device = iminor(inode);
+- set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
+- if (old_dev != -1 && old_dev != iminor(inode)) {
++ UDRS->fd_device = MINOR(bdev->bd_dev);
++ set_capacity(disks[drive], floppy_sizes[MINOR(bdev->bd_dev)]);
++ if (old_dev != -1 && old_dev != MINOR(bdev->bd_dev)) {
+ if (buffer_drive == drive)
+ buffer_track = -1;
+ }
+@@ -3784,8 +3784,7 @@ static int floppy_open(struct inode * in
+ /* Allow ioctls if we have write-permissions even if read-only open.
+ * Needed so that programs such as fdrawcmd still can work on write
+ * protected disks */
+- if ((filp->f_mode & 2) ||
+- (inode->i_sb && (permission(inode,2, NULL) == 0)))
++ if ((filp->f_mode & 2) || permission(filp->f_dentry->d_inode,2,NULL) == 0)
+ filp->private_data = (void*) 8;
+
+ if (UFDCS->rawcmd == 1)
+@@ -3794,7 +3793,7 @@ static int floppy_open(struct inode * in
+ if (!(filp->f_flags & O_NDELAY)) {
+ if (filp->f_mode & 3) {
+ UDRS->last_checked = 0;
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (UTESTF(FD_DISK_CHANGED))
+ goto out;
+ }
+--- linux-2.6.0-test6/drivers/block/initrd.c 2003-06-14 12:18:51.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,100 +0,0 @@
+-
+-#include <linux/blkdev.h>
+-#include <linux/genhd.h>
+-#include <linux/initrd.h>
+-#include <linux/init.h>
+-#include <linux/major.h>
+-#include <linux/module.h>
+-#include <linux/spinlock.h>
+-#include <asm/uaccess.h>
+-
+-
+-unsigned long initrd_start, initrd_end;
+-int initrd_below_start_ok;
+-
+-static int initrd_users;
+-static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED;
+-
+-static struct gendisk *initrd_disk;
+-
+-static ssize_t initrd_read(struct file *file, char *buf,
+- size_t count, loff_t *ppos)
+-{
+- int left = initrd_end - initrd_start - *ppos;
+-
+- if (count > left)
+- count = left;
+- if (count == 0)
+- return 0;
+- if (copy_to_user(buf, (char *)initrd_start + *ppos, count))
+- return -EFAULT;
+-
+- *ppos += count;
+- return count;
+-}
+-
+-static int initrd_release(struct inode *inode,struct file *file)
+-{
+-
+- blkdev_put(inode->i_bdev, BDEV_FILE);
+-
+- spin_lock(&initrd_users_lock);
+- if (!--initrd_users) {
+- spin_unlock(&initrd_users_lock);
+- del_gendisk(initrd_disk);
+- free_initrd_mem(initrd_start, initrd_end);
+- initrd_start = 0;
+- } else
+- spin_unlock(&initrd_users_lock);
+-
+- return 0;
+-}
+-
+-static struct file_operations initrd_fops = {
+- .read = initrd_read,
+- .release = initrd_release,
+-};
+-
+-static int initrd_open(struct inode *inode, struct file *filp)
+-{
+- if (!initrd_start)
+- return -ENODEV;
+-
+- spin_lock(&initrd_users_lock);
+- initrd_users++;
+- spin_unlock(&initrd_users_lock);
+-
+- filp->f_op = &initrd_fops;
+- return 0;
+-}
+-
+-static struct block_device_operations initrd_bdops = {
+- .owner = THIS_MODULE,
+- .open = initrd_open,
+-};
+-
+-static int __init initrd_init(void)
+-{
+- initrd_disk = alloc_disk(1);
+- if (!initrd_disk)
+- return -ENOMEM;
+-
+- initrd_disk->major = RAMDISK_MAJOR;
+- initrd_disk->first_minor = INITRD_MINOR;
+- initrd_disk->fops = &initrd_bdops;
+-
+- sprintf(initrd_disk->disk_name, "initrd");
+- sprintf(initrd_disk->devfs_name, "rd/initrd");
+-
+- set_capacity(initrd_disk, (initrd_end-initrd_start+511) >> 9);
+- add_disk(initrd_disk);
+- return 0;
+-}
+-
+-static void __exit initrd_exit(void)
+-{
+- put_disk(initrd_disk);
+-}
+-
+-module_init(initrd_init);
+-module_exit(initrd_exit);
+--- linux-2.6.0-test6/drivers/block/ioctl.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/ioctl.c 2003-10-05 00:34:11.000000000 -0700
+@@ -132,10 +132,9 @@ static int put_u64(unsigned long arg, u6
+ return put_user(val, (u64 *)arg);
+ }
+
+-int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
++int blkdev_ioctl(struct block_device *bdev, struct file *file, unsigned cmd,
+ unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ struct backing_dev_info *bdi;
+ int holder;
+@@ -194,7 +193,7 @@ int blkdev_ioctl(struct inode *inode, st
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (disk->fops->ioctl) {
+- ret = disk->fops->ioctl(inode, file, cmd, arg);
++ ret = disk->fops->ioctl(bdev, file, cmd, arg);
+ if (ret != -EINVAL)
+ return ret;
+ }
+@@ -203,7 +202,7 @@ int blkdev_ioctl(struct inode *inode, st
+ return 0;
+ case BLKROSET:
+ if (disk->fops->ioctl) {
+- ret = disk->fops->ioctl(inode, file, cmd, arg);
++ ret = disk->fops->ioctl(bdev, file, cmd, arg);
+ if (ret != -EINVAL)
+ return ret;
+ }
+@@ -215,7 +214,7 @@ int blkdev_ioctl(struct inode *inode, st
+ return 0;
+ default:
+ if (disk->fops->ioctl)
+- return disk->fops->ioctl(inode, file, cmd, arg);
++ return disk->fops->ioctl(bdev, file, cmd, arg);
+ }
+ return -ENOTTY;
+ }
+--- linux-2.6.0-test6/drivers/block/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -6,7 +6,7 @@ menu "Block devices"
+
+ config BLK_DEV_FD
+ tristate "Normal floppy disk support"
+- depends on !X86_PC9800 && !ARCH_S390
++ depends on ISA || M68 || SPARC64
+ ---help---
+ If you want to use the floppy disk drive(s) of your PC under Linux,
+ say Y. Information about this driver, especially important for IBM
+@@ -35,7 +35,7 @@ config BLK_DEV_FD98
+
+ config BLK_DEV_SWIM_IOP
+ bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)"
+- depends on MAC && EXPERIMENTAL
++ depends on MAC && EXPERIMENTAL && BROKEN
+ help
+ Say Y here to support the SWIM (Super Woz Integrated Machine) IOP
+ floppy controller on the Macintosh IIfx and Quadra 900/950.
+@@ -63,7 +63,7 @@ config AMIGA_Z2RAM
+
+ config ATARI_ACSI
+ tristate "Atari ACSI support"
+- depends on ATARI
++ depends on ATARI && BROKEN
+ ---help---
+ This enables support for the Atari ACSI interface. The driver
+ supports hard disks and CD-ROMs, which have 512-byte sectors, or can
+--- linux-2.6.0-test6/drivers/block/Kconfig.iosched 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/block/Kconfig.iosched 2003-10-05 00:34:17.000000000 -0700
+@@ -27,3 +27,10 @@ config IOSCHED_DEADLINE
+ a disk at any one time, its behaviour is almost identical to the
+ anticipatory I/O scheduler and so is a good choice.
+
++config IOSCHED_CFQ
++ bool "CFQ I/O scheduler" if EMBEDDED
++ default y
++ ---help---
++ The CFQ I/O scheduler tries to distribute bandwidth equally
++ among all processes in the system. It should provide a fair
++ working environment, suitable for desktop systems.
+--- linux-2.6.0-test6/drivers/block/ll_rw_blk.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/ll_rw_blk.c 2003-10-05 00:36:58.000000000 -0700
+@@ -119,7 +119,7 @@ static void set_queue_congested(request_
+
+ /**
+ * blk_get_backing_dev_info - get the address of a queue's backing_dev_info
+- * @dev: device
++ * @bdev: device
+ *
+ * Locates the passed device's request queue and returns the address of its
+ * backing_dev_info
+@@ -414,8 +414,8 @@ void blk_queue_segment_boundary(request_
+
+ /**
+ * blk_queue_dma_alignment - set dma length and memory alignment
+- * @q: the request queue for the device
+- * @dma_mask: alignment mask
++ * @q: the request queue for the device
++ * @mask: alignment mask
+ *
+ * description:
+ * set required memory and length aligment for direct dma transactions.
+@@ -1152,7 +1152,7 @@ void blk_stop_queue(request_queue_t *q)
+
+ /**
+ * blk_run_queue - run a single device queue
+- * @q The queue to run
++ * @q: The queue to run
+ */
+ void blk_run_queue(struct request_queue *q)
+ {
+@@ -1257,6 +1257,8 @@ static elevator_t *chosen_elevator =
+ &iosched_as;
+ #elif defined(CONFIG_IOSCHED_DEADLINE)
+ &iosched_deadline;
++#elif defined(CONFIG_IOSCHED_CFQ)
++ &iosched_cfq;
+ #elif defined(CONFIG_IOSCHED_NOOP)
+ &elevator_noop;
+ #else
+@@ -1275,6 +1277,10 @@ static int __init elevator_setup(char *s
+ if (!strcmp(str, "as"))
+ chosen_elevator = &iosched_as;
+ #endif
++#ifdef CONFIG_IOSCHED_CFQ
++ if (!strcmp(str, "cfq"))
++ chosen_elevator = &iosched_cfq;
++#endif
+ #ifdef CONFIG_IOSCHED_NOOP
+ if (!strcmp(str, "noop"))
+ chosen_elevator = &elevator_noop;
+@@ -1459,6 +1465,8 @@ static void freed_request(request_queue_
+ }
+ }
+
++atomic_t global_nr_requests = ATOMIC_INIT(0);
++
+ #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
+ /*
+ * Get a free request, queue_lock must not be held
+@@ -1536,6 +1544,8 @@ static struct request *get_request(reque
+ rq->data = NULL;
+ rq->sense = NULL;
+
++ atomic_inc(&global_nr_requests);
++
+ out:
+ put_io_context(ioc);
+ return rq;
+@@ -1766,6 +1776,9 @@ void __blk_put_request(request_queue_t *
+
+ blk_free_request(q, req);
+ freed_request(q, rw);
++
++ WARN_ON(atomic_read(&global_nr_requests) == 0);
++ atomic_dec(&global_nr_requests);
+ }
+ }
+
+@@ -1787,25 +1800,50 @@ void blk_put_request(struct request *req
+ }
+
+ /**
+- * blk_congestion_wait - wait for a queue to become uncongested
++ * blk_congestion_wait_wq - wait for a queue to become uncongested,
+ * @rw: READ or WRITE
+ * @timeout: timeout in jiffies
++ * @wait : wait queue entry to use for waiting or async notification
++ * (NULL defaults to synchronous behaviour)
+ *
+ * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion.
+ * If no queues are congested then just wait for the next request to be
+ * returned.
++ *
++ * If the wait queue parameter specifies an async i/o callback,
++ * then instead of blocking, just register the callback on the wait
++ * queue for async notification when the queue gets uncongested.
+ */
+-void blk_congestion_wait(int rw, long timeout)
++int blk_congestion_wait_wq(int rw, long timeout, wait_queue_t *wait)
+ {
+- DEFINE_WAIT(wait);
+ wait_queue_head_t *wqh = &congestion_wqh[rw];
++ DEFINE_WAIT(local_wait);
++
++ if (!wait)
++ wait = &local_wait;
+
+ blk_run_queues();
+- prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
++ prepare_to_wait(wqh, wait, TASK_UNINTERRUPTIBLE);
++ if (!is_sync_wait(wait)) {
++ /*
++ * if we've queued an async wait queue
++ * callback do not block; just tell the
++ * caller to return and retry later when
++ * the callback is notified
++ */
++ return -EIOCBRETRY;
++ }
+ io_schedule_timeout(timeout);
+- finish_wait(wqh, &wait);
++ finish_wait(wqh, wait);
++ return 0;
+ }
+
++void blk_congestion_wait(int rw, long timeout)
++{
++ blk_congestion_wait_wq(rw, timeout, NULL);
++}
++
++
+ /*
+ * Has to be called with the request spinlock acquired
+ */
+@@ -2592,6 +2630,7 @@ void put_io_context(struct io_context *i
+ if (ioc->aic && ioc->aic->dtor)
+ ioc->aic->dtor(ioc->aic);
+ kfree(ioc);
++ WARN_ON(atomic_read(&nr_io_contexts) == 0);
+ atomic_dec(&nr_io_contexts);
+ }
+ }
+@@ -2634,6 +2673,9 @@ struct io_context *get_io_context(int gf
+ ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+ if (ret) {
+ atomic_inc(&nr_io_contexts);
++ WARN_ON(atomic_read(&nr_io_contexts) ==
++ 1 + nr_threads + atomic_read(&global_nr_requests));
++
+ atomic_set(&ret->refcount, 1);
+ ret->pid = tsk->pid;
+ ret->last_waited = jiffies; /* doesn't matter... */
+--- linux-2.6.0-test6/drivers/block/loop.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/loop.c 2003-10-05 00:34:11.000000000 -0700
+@@ -140,8 +140,7 @@ figure_loop_size(struct loop_device *lo)
+ sector_t x;
+
+ /* Compute loopsize in bytes */
+- size = i_size_read(lo->lo_backing_file->f_dentry->
+- d_inode->i_mapping->host);
++ size = i_size_read(lo->lo_backing_file->f_mapping->host);
+ offset = lo->lo_offset;
+ loopsize = size - offset;
+ if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
+@@ -175,7 +174,7 @@ static int
+ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
+ {
+ struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct address_space_operations *aops = mapping->a_ops;
+ struct page *page;
+ char *kaddr, *data;
+@@ -660,6 +659,7 @@ static int loop_set_fd(struct loop_devic
+ struct file *file;
+ struct inode *inode;
+ struct block_device *lo_device = NULL;
++ struct address_space *mapping;
+ unsigned lo_blocksize;
+ int lo_flags = 0;
+ int error;
+@@ -676,14 +676,16 @@ static int loop_set_fd(struct loop_devic
+ if (!file)
+ goto out;
+
+- error = -EINVAL;
+- inode = file->f_dentry->d_inode;
++ mapping = file->f_mapping;
++ inode = mapping->host;
+
+ if (!(file->f_mode & FMODE_WRITE))
+ lo_flags |= LO_FLAGS_READ_ONLY;
+
++ error = -EINVAL;
++
+ if (S_ISBLK(inode->i_mode)) {
+- lo_device = inode->i_bdev;
++ lo_device = I_BDEV(inode);
+ if (lo_device == bdev) {
+ error = -EBUSY;
+ goto out;
+@@ -692,7 +694,7 @@ static int loop_set_fd(struct loop_devic
+ if (bdev_read_only(lo_device))
+ lo_flags |= LO_FLAGS_READ_ONLY;
+ } else if (S_ISREG(inode->i_mode)) {
+- struct address_space_operations *aops = inode->i_mapping->a_ops;
++ struct address_space_operations *aops = mapping->a_ops;
+ /*
+ * If we can't read - sorry. If we only can't write - well,
+ * it's going to be read-only.
+@@ -728,9 +730,8 @@ static int loop_set_fd(struct loop_devic
+ fput(file);
+ goto out_putf;
+ }
+- lo->old_gfp_mask = mapping_gfp_mask(inode->i_mapping);
+- mapping_set_gfp_mask(inode->i_mapping,
+- lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
++ lo->old_gfp_mask = mapping_gfp_mask(mapping);
++ mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
+
+ set_blocksize(bdev, lo_blocksize);
+
+@@ -846,7 +847,7 @@ static int loop_clr_fd(struct loop_devic
+ memset(lo->lo_file_name, 0, LO_NAME_SIZE);
+ invalidate_bdev(bdev, 0);
+ set_capacity(disks[lo->lo_number], 0);
+- mapping_set_gfp_mask(filp->f_dentry->d_inode->i_mapping, gfp);
++ mapping_set_gfp_mask(filp->f_mapping, gfp);
+ lo->lo_state = Lo_unbound;
+ fput(filp);
+ /* This is safe: open() is still holding a reference. */
+@@ -1056,19 +1057,19 @@ loop_get_status64(struct loop_device *lo
+ return err;
+ }
+
+-static int lo_ioctl(struct inode * inode, struct file * file,
++static int lo_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
++ struct loop_device *lo = bdev->bd_disk->private_data;
+ int err;
+
+ down(&lo->lo_ctl_mutex);
+ switch (cmd) {
+ case LOOP_SET_FD:
+- err = loop_set_fd(lo, file, inode->i_bdev, arg);
++ err = loop_set_fd(lo, file, bdev, arg);
+ break;
+ case LOOP_CLR_FD:
+- err = loop_clr_fd(lo, inode->i_bdev);
++ err = loop_clr_fd(lo, bdev);
+ break;
+ case LOOP_SET_STATUS:
+ err = loop_set_status_old(lo, (struct loop_info *) arg);
+@@ -1089,9 +1090,9 @@ static int lo_ioctl(struct inode * inode
+ return err;
+ }
+
+-static int lo_open(struct inode *inode, struct file *file)
++static int lo_open(struct block_device *bdev, struct file *file)
+ {
+- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
++ struct loop_device *lo = bdev->bd_disk->private_data;
+
+ down(&lo->lo_ctl_mutex);
+ lo->lo_refcnt++;
+@@ -1100,9 +1101,9 @@ static int lo_open(struct inode *inode,
+ return 0;
+ }
+
+-static int lo_release(struct inode *inode, struct file *file)
++static int lo_release(struct gendisk *disk)
+ {
+- struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
++ struct loop_device *lo = disk->private_data;
+
+ down(&lo->lo_ctl_mutex);
+ --lo->lo_refcnt;
+--- linux-2.6.0-test6/drivers/block/Makefile 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/block/Makefile 2003-10-05 00:34:17.000000000 -0700
+@@ -18,6 +18,7 @@ obj-y := elevator.o ll_rw_blk.o ioctl.o
+ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
+ obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
+ obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
++obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
+ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
+ obj-$(CONFIG_BLK_DEV_FD) += floppy.o
+ obj-$(CONFIG_BLK_DEV_FD98) += floppy98.o
+@@ -28,7 +29,6 @@ obj-$(CONFIG_ATARI_ACSI) += acsi.o
+ obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
+ obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
+ obj-$(CONFIG_BLK_DEV_RAM) += rd.o
+-obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
+ obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
+ obj-$(CONFIG_BLK_DEV_PS2) += ps2esdi.o
+ obj-$(CONFIG_BLK_DEV_XD) += xd.o
+--- linux-2.6.0-test6/drivers/block/nbd.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/block/nbd.c 2003-10-05 00:33:54.000000000 -0700
+@@ -535,10 +535,10 @@ static void do_nbd_request(request_queue
+ return;
+ }
+
+-static int nbd_ioctl(struct inode *inode, struct file *file,
++static int nbd_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
++ struct nbd_device *lo = bdev->bd_disk->private_data;
+ int error;
+ struct request sreq ;
+
+@@ -593,7 +593,7 @@ static int nbd_ioctl(struct inode *inode
+ error = -EINVAL;
+ file = fget(arg);
+ if (file) {
+- inode = file->f_dentry->d_inode;
++ struct inode *inode = file->f_dentry->d_inode;
+ if (inode->i_sock) {
+ lo->file = file;
+ lo->sock = SOCKET_I(inode);
+@@ -606,20 +606,20 @@ static int nbd_ioctl(struct inode *inode
+ case NBD_SET_BLKSIZE:
+ lo->blksize = arg;
+ lo->bytesize &= ~(lo->blksize-1);
+- inode->i_bdev->bd_inode->i_size = lo->bytesize;
+- set_blocksize(inode->i_bdev, lo->blksize);
++ bdev->bd_inode->i_size = lo->bytesize;
++ set_blocksize(bdev, lo->blksize);
+ set_capacity(lo->disk, lo->bytesize >> 9);
+ return 0;
+ case NBD_SET_SIZE:
+ lo->bytesize = arg & ~(lo->blksize-1);
+- inode->i_bdev->bd_inode->i_size = lo->bytesize;
+- set_blocksize(inode->i_bdev, lo->blksize);
++ bdev->bd_inode->i_size = lo->bytesize;
++ set_blocksize(bdev, lo->blksize);
+ set_capacity(lo->disk, lo->bytesize >> 9);
+ return 0;
+ case NBD_SET_SIZE_BLOCKS:
+ lo->bytesize = ((u64) arg) * lo->blksize;
+- inode->i_bdev->bd_inode->i_size = lo->bytesize;
+- set_blocksize(inode->i_bdev, lo->blksize);
++ bdev->bd_inode->i_size = lo->bytesize;
++ set_blocksize(bdev, lo->blksize);
+ set_capacity(lo->disk, lo->bytesize >> 9);
+ return 0;
+ case NBD_DO_IT:
+@@ -664,11 +664,11 @@ static int nbd_ioctl(struct inode *inode
+ case NBD_PRINT_DEBUG:
+ #ifdef PARANOIA
+ printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n",
+- inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
++ bdev->bd_disk->disk_name, lo->queue_head.next,
+ lo->queue_head.prev, requests_in, requests_out);
+ #else
+ printk(KERN_INFO "%s: next = %p, prev = %p\n",
+- inode->i_bdev->bd_disk->disk_name,
++ bdev->bd_disk->disk_name,
+ lo->queue_head.next, lo->queue_head.prev);
+ #endif
+ return 0;
+--- linux-2.6.0-test6/drivers/block/paride/pcd.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/block/paride/pcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -243,23 +243,23 @@ static int pcd_warned; /* Have we logge
+
+ /* kernel glue structures */
+
+-static int pcd_block_open(struct inode *inode, struct file *file)
++static int pcd_block_open(struct block_device *bdev, struct file *file)
+ {
+- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+- return cdrom_open(&cd->info, inode, file);
++ struct pcd_unit *cd = bdev->bd_disk->private_data;
++ return cdrom_open(&cd->info, bdev, file);
+ }
+
+-static int pcd_block_release(struct inode *inode, struct file *file)
++static int pcd_block_release(struct gendisk *disk)
+ {
+- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+- return cdrom_release(&cd->info, file);
++ struct pcd_unit *cd = disk->private_data;
++ return cdrom_release(&cd->info);
+ }
+
+-static int pcd_block_ioctl(struct inode *inode, struct file *file,
++static int pcd_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- struct pcd_unit *cd = inode->i_bdev->bd_disk->private_data;
+- return cdrom_ioctl(&cd->info, inode, cmd, arg);
++ struct pcd_unit *cd = bdev->bd_disk->private_data;
++ return cdrom_ioctl(&cd->info, bdev, cmd, arg);
+ }
+
+ static int pcd_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/block/paride/pd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/paride/pd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -236,11 +236,11 @@ MODULE_PARM(drive3, "1-8i");
+ #define IDE_EJECT 0xed
+
+ void pd_setup(char *str, int *ints);
+-static int pd_open(struct inode *inode, struct file *file);
++static int pd_open(struct block_device *bdev, struct file *file);
+ static void do_pd_request(request_queue_t * q);
+-static int pd_ioctl(struct inode *inode, struct file *file,
++static int pd_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg);
+-static int pd_release(struct inode *inode, struct file *file);
++static int pd_release(struct gendisk *disk);
+ static int pd_revalidate(struct gendisk *p);
+ static int pd_detect(void);
+ static void do_pd_read(void);
+@@ -304,8 +304,6 @@ static char *pd_errs[17] = { "ERR", "IND
+
+ /* kernel glue structures */
+
+-extern struct block_device_operations pd_fops;
+-
+ static struct block_device_operations pd_fops = {
+ .owner = THIS_MODULE,
+ .open = pd_open,
+@@ -337,9 +335,9 @@ static void pd_init_units(void)
+ }
+ }
+
+-static int pd_open(struct inode *inode, struct file *file)
++static int pd_open(struct block_device *bdev, struct file *file)
+ {
+- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
++ struct pd_unit *disk = bdev->bd_disk->private_data;
+
+ disk->access++;
+
+@@ -350,10 +348,10 @@ static int pd_open(struct inode *inode,
+ return 0;
+ }
+
+-static int pd_ioctl(struct inode *inode, struct file *file,
++static int pd_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
++ struct pd_unit *disk = bdev->bd_disk->private_data;
+ struct hd_geometry *geo = (struct hd_geometry *) arg;
+ struct hd_geometry g;
+
+@@ -372,7 +370,7 @@ static int pd_ioctl(struct inode *inode,
+ g.sectors = disk->sectors;
+ g.cylinders = disk->cylinders;
+ }
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
+ return -EFAULT;
+ return 0;
+@@ -381,9 +379,9 @@ static int pd_ioctl(struct inode *inode,
+ }
+ }
+
+-static int pd_release(struct inode *inode, struct file *file)
++static int pd_release(struct gendisk *p)
+ {
+- struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
++ struct pd_unit *disk = p->private_data;
+
+ if (!--disk->access && disk->removable)
+ pd_doorlock(disk, IDE_DOORUNLOCK);
+--- linux-2.6.0-test6/drivers/block/paride/pf.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/block/paride/pf.c 2003-10-05 00:34:01.000000000 -0700
+@@ -222,12 +222,12 @@ MODULE_PARM(drive3, "1-7i");
+ #define ATAPI_READ_10 0x28
+ #define ATAPI_WRITE_10 0x2a
+
+-static int pf_open(struct inode *inode, struct file *file);
++static int pf_open(struct block_device *bdev, struct file *file);
+ static void do_pf_request(request_queue_t * q);
+-static int pf_ioctl(struct inode *inode, struct file *file,
++static int pf_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg);
+
+-static int pf_release(struct inode *inode, struct file *file);
++static int pf_release(struct gendisk *disk);
+
+ static int pf_detect(void);
+ static void do_pf_read(void);
+@@ -315,9 +315,9 @@ void pf_init_units(void)
+ }
+ }
+
+-static int pf_open(struct inode *inode, struct file *file)
++static int pf_open(struct block_device *bdev, struct file *file)
+ {
+- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
++ struct pf_unit *pf = bdev->bd_disk->private_data;
+
+ pf_identify(pf);
+
+@@ -334,9 +334,9 @@ static int pf_open(struct inode *inode,
+ return 0;
+ }
+
+-static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++static int pf_ioctl(struct block_device *bdev, struct file *file, unsigned int cmd, unsigned long arg)
+ {
+- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
++ struct pf_unit *pf = bdev->bd_disk->private_data;
+ struct hd_geometry *geo = (struct hd_geometry *) arg;
+ struct hd_geometry g;
+ sector_t capacity;
+@@ -365,9 +365,9 @@ static int pf_ioctl(struct inode *inode,
+ return 0;
+ }
+
+-static int pf_release(struct inode *inode, struct file *file)
++static int pf_release(struct gendisk *disk)
+ {
+- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
++ struct pf_unit *pf = disk->private_data;
+
+ if (pf->access <= 0)
+ return -EINVAL;
+--- linux-2.6.0-test6/drivers/block/ps2esdi.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/ps2esdi.c 2003-10-05 00:33:54.000000000 -0700
+@@ -39,7 +39,7 @@
+ #include <linux/genhd.h>
+ #include <linux/ps2esdi.h>
+ #include <linux/blkdev.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/module.h>
+@@ -81,7 +81,7 @@ static void (*current_int_handler) (u_in
+ static void ps2esdi_normal_interrupt_handler(u_int);
+ static void ps2esdi_initial_reset_int_handler(u_int);
+ static void ps2esdi_geometry_int_handler(u_int);
+-static int ps2esdi_ioctl(struct inode *inode, struct file *file,
++static int ps2esdi_ioctl(struct block_device *bdev, struct file *file,
+ u_int cmd, u_long arg);
+
+ static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
+@@ -1059,10 +1059,10 @@ static void dump_cmd_complete_status(u_i
+
+ }
+
+-static int ps2esdi_ioctl(struct inode *inode,
++static int ps2esdi_ioctl(struct block_device *bdev,
+ struct file *file, u_int cmd, u_long arg)
+ {
+- struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
++ struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
+ struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
+ int err;
+
+@@ -1073,7 +1073,7 @@ static int ps2esdi_ioctl(struct inode *i
+ put_user(p->head, (char *) &geometry->heads);
+ put_user(p->sect, (char *) &geometry->sectors);
+ put_user(p->cyl, (short *) &geometry->cylinders);
+- put_user(get_start_sect(inode->i_bdev), (long *) &geometry->start);
++ put_user(get_start_sect(bdev), (long *) &geometry->start);
+ return 0;
+ }
+
+--- linux-2.6.0-test6/drivers/block/rd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/rd.c 2003-10-05 00:34:30.000000000 -0700
+@@ -1,15 +1,15 @@
+ /*
+ * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta.
+- *
+- * (C) Chad Page, Theodore Ts'o, et. al, 1995.
++ *
++ * (C) Chad Page, Theodore Ts'o, et. al, 1995.
+ *
+ * This RAM disk is designed to have filesystems created on it and mounted
+- * just like a regular floppy disk.
+- *
++ * just like a regular floppy disk.
++ *
+ * It also does something suggested by Linus: use the buffer cache as the
+ * RAM disk data. This makes it possible to dynamically allocate the RAM disk
+- * buffer - with some consequences I have to deal with as I write this.
+- *
++ * buffer - with some consequences I have to deal with as I write this.
++ *
+ * This code is based on the original ramdisk.c, written mostly by
+ * Theodore Ts'o (TYT) in 1991. The code was largely rewritten by
+ * Chad Page to use the buffer cache to store the RAM disk data in
+@@ -33,7 +33,7 @@
+ *
+ * Added initrd: Werner Almesberger & Hans Lermen, Feb '96
+ *
+- * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
++ * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
+ * - Chad Page
+ *
+ * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98
+@@ -60,7 +60,7 @@
+ #include <asm/uaccess.h>
+
+ /* The RAM disk size is now a parameter */
+-#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
++#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
+
+ /* Various static variables go here. Most are used only in the RAM disk code.
+ */
+@@ -73,7 +73,7 @@ static struct request_queue *rd_queue[NU
+ * Parameters for the boot-loading of the RAM disk. These are set by
+ * init/main.c (from arguments to the kernel command line) or from the
+ * architecture-specific setup routine (from the stored boot sector
+- * information).
++ * information).
+ */
+ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */
+ /*
+@@ -94,7 +94,7 @@ int rd_blocksize = BLOCK_SIZE; /* bloc
+ * 2000 Transmeta Corp.
+ * aops copied from ramfs.
+ */
+-static int ramdisk_readpage(struct file *file, struct page * page)
++static int ramdisk_readpage(struct file *file, struct page *page)
+ {
+ if (!PageUptodate(page)) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+@@ -108,7 +108,8 @@ static int ramdisk_readpage(struct file
+ return 0;
+ }
+
+-static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
++static int ramdisk_prepare_write(struct file *file, struct page *page,
++ unsigned offset, unsigned to)
+ {
+ if (!PageUptodate(page)) {
+ void *kaddr = kmap_atomic(page, KM_USER0);
+@@ -122,7 +123,8 @@ static int ramdisk_prepare_write(struct
+ return 0;
+ }
+
+-static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
++static int ramdisk_commit_write(struct file *file, struct page *page,
++ unsigned offset, unsigned to)
+ {
+ return 0;
+ }
+@@ -212,7 +214,7 @@ static int rd_blkdev_pagecache_IO(int rw
+ * 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Added devfs support
+ *
+ */
+-static int rd_make_request(request_queue_t * q, struct bio *bio)
++static int rd_make_request(request_queue_t *q, struct bio *bio)
+ {
+ struct block_device *bdev = bio->bi_bdev;
+ struct address_space * mapping = bdev->bd_inode->i_mapping;
+@@ -242,17 +244,19 @@ fail:
+ return 0;
+ }
+
+-static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++static int rd_ioctl(struct block_device *bdev, struct file *file,
++ unsigned int cmd, unsigned long arg)
+ {
+ int error;
+- struct block_device *bdev = inode->i_bdev;
+
+ if (cmd != BLKFLSBUF)
+ return -EINVAL;
+
+- /* special: we want to release the ramdisk memory,
+- it's not like with the other blockdevices where
+- this ioctl only flushes away the buffer cache. */
++ /*
++ * special: we want to release the ramdisk memory, it's not like with
++ * the other blockdevices where this ioctl only flushes away the buffer
++ * cache
++ */
+ error = -EBUSY;
+ down(&bdev->bd_sem);
+ if (bdev->bd_openers <= 2) {
+@@ -268,16 +272,15 @@ static struct backing_dev_info rd_backin
+ .memory_backed = 1, /* Does not contribute to dirty memory */
+ };
+
+-static int rd_open(struct inode * inode, struct file * filp)
++static int rd_open(struct block_device *bdev, struct file *filp)
+ {
+- unsigned unit = iminor(inode);
++ unsigned unit = MINOR(bdev->bd_dev);
+
+ /*
+ * Immunize device against invalidate_buffers() and prune_icache().
+ */
+ if (rd_bdev[unit] == NULL) {
+- struct block_device *bdev = inode->i_bdev;
+- inode = igrab(bdev->bd_inode);
++ struct inode *inode = igrab(bdev->bd_inode);
+ rd_bdev[unit] = bdev;
+ bdev->bd_openers++;
+ bdev->bd_block_size = rd_blocksize;
+@@ -295,12 +298,14 @@ static struct block_device_operations rd
+ .ioctl = rd_ioctl,
+ };
+
+-/* Before freeing the module, invalidate all of the protected buffers! */
+-static void __exit rd_cleanup (void)
++/*
++ * Before freeing the module, invalidate all of the protected buffers!
++ */
++static void __exit rd_cleanup(void)
+ {
+ int i;
+
+- for (i = 0 ; i < NUM_RAMDISKS; i++) {
++ for (i = 0; i < NUM_RAMDISKS; i++) {
+ struct block_device *bdev = rd_bdev[i];
+ rd_bdev[i] = NULL;
+ if (bdev) {
+@@ -311,17 +316,19 @@ static void __exit rd_cleanup (void)
+ put_disk(rd_disks[i]);
+ }
+ devfs_remove("rd");
+- unregister_blkdev(RAMDISK_MAJOR, "ramdisk" );
++ unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
+ }
+
+-/* This is the registration and initialization section of the RAM disk driver */
+-static int __init rd_init (void)
++/*
++ * This is the registration and initialization section of the RAM disk driver
++ */
++static int __init rd_init(void)
+ {
+ int i;
+ int err = -ENOMEM;
+
+ if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
+- (rd_blocksize & (rd_blocksize-1))) {
++ (rd_blocksize & (rd_blocksize-1))) {
+ printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
+ rd_blocksize);
+ rd_blocksize = BLOCK_SIZE;
+@@ -362,8 +369,8 @@ static int __init rd_init (void)
+
+ /* rd_size is given in kB */
+ printk("RAMDISK driver initialized: "
+- "%d RAM disks of %dK size %d blocksize\n",
+- NUM_RAMDISKS, rd_size, rd_blocksize);
++ "%d RAM disks of %dK size %d blocksize\n",
++ NUM_RAMDISKS, rd_size, rd_blocksize);
+
+ return 0;
+ out_queue:
+--- linux-2.6.0-test6/drivers/block/scsi_ioctl.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/block/scsi_ioctl.c 2003-10-05 00:36:48.000000000 -0700
+@@ -25,6 +25,7 @@
+ #include <linux/cdrom.h>
+ #include <linux/slab.h>
+ #include <linux/bio.h>
++#include <linux/times.h>
+ #include <asm/uaccess.h>
+
+ #include <scsi/scsi.h>
+@@ -140,40 +141,36 @@ static int sg_emulated_host(request_queu
+ }
+
+ static int sg_io(request_queue_t *q, struct block_device *bdev,
+- struct sg_io_hdr *uptr)
++ struct sg_io_hdr *hdr)
+ {
+ unsigned long start_time;
+ int reading, writing;
+- struct sg_io_hdr hdr;
+ struct request *rq;
+ struct bio *bio;
+ char sense[SCSI_SENSE_BUFFERSIZE];
+ void *buffer;
+
+- if (copy_from_user(&hdr, uptr, sizeof(*uptr)))
+- return -EFAULT;
+-
+- if (hdr.interface_id != 'S')
++ if (hdr->interface_id != 'S')
+ return -EINVAL;
+- if (hdr.cmd_len > sizeof(rq->cmd))
++ if (hdr->cmd_len > sizeof(rq->cmd))
+ return -EINVAL;
+
+ /*
+ * we'll do that later
+ */
+- if (hdr.iovec_count)
++ if (hdr->iovec_count)
+ return -EOPNOTSUPP;
+
+- if (hdr.dxfer_len > (q->max_sectors << 9))
++ if (hdr->dxfer_len > (q->max_sectors << 9))
+ return -EIO;
+
+ reading = writing = 0;
+ buffer = NULL;
+ bio = NULL;
+- if (hdr.dxfer_len) {
+- unsigned int bytes = (hdr.dxfer_len + 511) & ~511;
++ if (hdr->dxfer_len) {
++ unsigned int bytes = (hdr->dxfer_len + 511) & ~511;
+
+- switch (hdr.dxfer_direction) {
++ switch (hdr->dxfer_direction) {
+ default:
+ return -EINVAL;
+ case SG_DXFER_TO_FROM_DEV:
+@@ -191,8 +188,8 @@ static int sg_io(request_queue_t *q, str
+ * first try to map it into a bio. reading from device will
+ * be a write to vm.
+ */
+- bio = bio_map_user(bdev, (unsigned long) hdr.dxferp,
+- hdr.dxfer_len, reading);
++ bio = bio_map_user(bdev, (unsigned long) hdr->dxferp,
++ hdr->dxfer_len, reading);
+
+ /*
+ * if bio setup failed, fall back to slow approach
+@@ -203,11 +200,11 @@ static int sg_io(request_queue_t *q, str
+ return -ENOMEM;
+
+ if (writing) {
+- if (copy_from_user(buffer, hdr.dxferp,
+- hdr.dxfer_len))
++ if (copy_from_user(buffer, hdr->dxferp,
++ hdr->dxfer_len))
+ goto out_buffer;
+ } else
+- memset(buffer, 0, hdr.dxfer_len);
++ memset(buffer, 0, hdr->dxfer_len);
+ }
+ }
+
+@@ -216,11 +213,10 @@ static int sg_io(request_queue_t *q, str
+ /*
+ * fill in request structure
+ */
+- rq->cmd_len = hdr.cmd_len;
+- if (copy_from_user(rq->cmd, hdr.cmdp, hdr.cmd_len))
+- goto out_request;
+- if (sizeof(rq->cmd) != hdr.cmd_len)
+- memset(rq->cmd + hdr.cmd_len, 0, sizeof(rq->cmd) - hdr.cmd_len);
++ rq->cmd_len = hdr->cmd_len;
++ memcpy(rq->cmd, hdr->cmdp, hdr->cmd_len);
++ if (sizeof(rq->cmd) != hdr->cmd_len)
++ memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len);
+
+ memset(sense, 0, sizeof(sense));
+ rq->sense = sense;
+@@ -234,9 +230,9 @@ static int sg_io(request_queue_t *q, str
+ blk_rq_bio_prep(q, rq, bio);
+
+ rq->data = buffer;
+- rq->data_len = hdr.dxfer_len;
++ rq->data_len = hdr->dxfer_len;
+
+- rq->timeout = (hdr.timeout * HZ) / 1000;
++ rq->timeout = (hdr->timeout * HZ) / 1000;
+ if (!rq->timeout)
+ rq->timeout = q->sg_timeout;
+ if (!rq->timeout)
+@@ -254,33 +250,30 @@ static int sg_io(request_queue_t *q, str
+ bio_unmap_user(bio, reading);
+
+ /* write to all output members */
+- hdr.status = rq->errors;
+- hdr.masked_status = (hdr.status >> 1) & 0x1f;
+- hdr.msg_status = 0;
+- hdr.host_status = 0;
+- hdr.driver_status = 0;
+- hdr.info = 0;
+- if (hdr.masked_status || hdr.host_status || hdr.driver_status)
+- hdr.info |= SG_INFO_CHECK;
+- hdr.resid = rq->data_len;
+- hdr.duration = ((jiffies - start_time) * 1000) / HZ;
+- hdr.sb_len_wr = 0;
++ hdr->status = rq->errors;
++ hdr->masked_status = (hdr->status >> 1) & 0x1f;
++ hdr->msg_status = 0;
++ hdr->host_status = 0;
++ hdr->driver_status = 0;
++ hdr->info = 0;
++ if (hdr->masked_status || hdr->host_status || hdr->driver_status)
++ hdr->info |= SG_INFO_CHECK;
++ hdr->resid = rq->data_len;
++ hdr->duration = ((jiffies - start_time) * 1000) / HZ;
++ hdr->sb_len_wr = 0;
+
+- if (rq->sense_len && hdr.sbp) {
+- int len = min((unsigned int) hdr.mx_sb_len, rq->sense_len);
++ if (rq->sense_len && hdr->sbp) {
++ int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
+
+- if (!copy_to_user(hdr.sbp, rq->sense, len))
+- hdr.sb_len_wr = len;
++ if (!copy_to_user(hdr->sbp, rq->sense, len))
++ hdr->sb_len_wr = len;
+ }
+
+ blk_put_request(rq);
+
+- if (copy_to_user(uptr, &hdr, sizeof(*uptr)))
+- goto out_buffer;
+-
+ if (buffer) {
+ if (reading)
+- if (copy_to_user(hdr.dxferp, buffer, hdr.dxfer_len))
++ if (copy_to_user(hdr->dxferp, buffer, hdr->dxfer_len))
+ goto out_buffer;
+
+ kfree(buffer);
+@@ -289,8 +282,6 @@ static int sg_io(request_queue_t *q, str
+ /* may not have succeeded, but output values written to control
+ * structure (struct sg_io_hdr). */
+ return 0;
+-out_request:
+- blk_put_request(rq);
+ out_buffer:
+ kfree(buffer);
+ return -EFAULT;
+@@ -319,7 +310,7 @@ static int sg_scsi_ioctl(request_queue_t
+ return -EFAULT;
+ if (in_len > PAGE_SIZE || out_len > PAGE_SIZE)
+ return -EINVAL;
+- if (get_user(opcode, sic->data))
++ if (get_user(opcode, (int *)sic->data))
+ return -EFAULT;
+
+ bytes = max(in_len, out_len);
+@@ -437,9 +428,71 @@ int scsi_cmd_ioctl(struct block_device *
+ case SG_EMULATED_HOST:
+ err = sg_emulated_host(q, (int *) arg);
+ break;
+- case SG_IO:
+- err = sg_io(q, bdev, (struct sg_io_hdr *) arg);
++ case SG_IO: {
++ struct sg_io_hdr hdr;
++
++ if (copy_from_user(&hdr, (struct sg_io_hdr *) arg, sizeof(hdr))) {
++ err = -EFAULT;
++ break;
++ }
++ err = sg_io(q, bdev, &hdr);
++ if (copy_to_user((struct sg_io_hdr *) arg, &hdr, sizeof(hdr)))
++ err = -EFAULT;
+ break;
++ }
++ case CDROM_SEND_PACKET: {
++ struct cdrom_generic_command cgc;
++ struct sg_io_hdr hdr;
++
++ if (copy_from_user(&cgc, (struct cdrom_generic_command *) arg, sizeof(cgc))) {
++ err = -EFAULT;
++ break;
++ }
++ cgc.timeout = clock_t_to_jiffies(cgc.timeout);
++ memset(&hdr, 0, sizeof(hdr));
++ hdr.interface_id = 'S';
++ hdr.cmd_len = sizeof(cgc.cmd);
++ hdr.dxfer_len = cgc.buflen;
++ err = 0;
++ switch (cgc.data_direction) {
++ case CGC_DATA_UNKNOWN:
++ hdr.dxfer_direction = SG_DXFER_UNKNOWN;
++ break;
++ case CGC_DATA_WRITE:
++ hdr.dxfer_direction = SG_DXFER_TO_DEV;
++ break;
++ case CGC_DATA_READ:
++ hdr.dxfer_direction = SG_DXFER_FROM_DEV;
++ break;
++ case CGC_DATA_NONE:
++ hdr.dxfer_direction = SG_DXFER_NONE;
++ break;
++ default:
++ err = -EINVAL;
++ }
++ if (err)
++ break;
++
++ hdr.dxferp = cgc.buffer;
++ hdr.sbp = (char *) cgc.sense;
++ if (hdr.sbp)
++ hdr.mx_sb_len = sizeof(struct request_sense);
++ hdr.timeout = cgc.timeout;
++ hdr.cmdp = cgc.cmd;
++ hdr.cmd_len = sizeof(cgc.cmd);
++ err = sg_io(q, bdev, &hdr);
++
++ if (hdr.status)
++ err = -EIO;
++
++ cgc.stat = err;
++ cgc.buflen = hdr.resid;
++ if (copy_to_user((struct cdrom_generic_command *) arg, &cgc, sizeof(cgc)))
++ err = -EFAULT;
++
++ break;
++ }
++
+ /*
+ * old junk scsi send command ioctl
+ */
+--- linux-2.6.0-test6/drivers/block/swim3.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/block/swim3.c 2003-10-05 00:34:01.000000000 -0700
+@@ -239,10 +239,9 @@ static int grab_drive(struct floppy_stat
+ int interruptible);
+ static void release_drive(struct floppy_state *fs);
+ static int fd_eject(struct floppy_state *fs);
+-static int floppy_ioctl(struct inode *inode, struct file *filp,
++static int floppy_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param);
+-static int floppy_open(struct inode *inode, struct file *filp);
+-static int floppy_release(struct inode *inode, struct file *filp);
++static int floppy_open(struct block_device *bdev, struct file *filp);
+ static int floppy_check_change(struct gendisk *disk);
+ static int floppy_revalidate(struct gendisk *disk);
+ static int swim3_add_device(struct device_node *swims);
+@@ -811,10 +810,10 @@ static int fd_eject(struct floppy_state
+ static struct floppy_struct floppy_type =
+ { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
+
+-static int floppy_ioctl(struct inode *inode, struct file *filp,
++static int floppy_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = bdev->bd_disk->private_data;
+ int err;
+
+ if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
+@@ -838,9 +837,9 @@ static int floppy_ioctl(struct inode *in
+ return -ENOTTY;
+ }
+
+-static int floppy_open(struct inode *inode, struct file *filp)
++static int floppy_open(struct block_device *bdev, struct file *filp)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = bdev->bd_disk->private_data;
+ volatile struct swim3 *sw = fs->swim3;
+ int n, err = 0;
+
+@@ -876,7 +875,7 @@ static int floppy_open(struct inode *ino
+
+ if (err == 0 && (filp->f_flags & O_NDELAY) == 0
+ && (filp->f_mode & 3)) {
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (fs->ejected)
+ err = -ENXIO;
+ }
+@@ -904,9 +903,9 @@ static int floppy_open(struct inode *ino
+ return 0;
+ }
+
+-static int floppy_release(struct inode *inode, struct file *filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = disk->private_data;
+ volatile struct swim3 *sw = fs->swim3;
+ if (fs->ref_count > 0 && --fs->ref_count == 0) {
+ swim3_action(fs, MOTOR_OFF);
+--- linux-2.6.0-test6/drivers/block/swim_iop.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/block/swim_iop.c 2003-10-05 00:34:01.000000000 -0700
+@@ -31,6 +31,7 @@
+ #include <linux/delay.h>
+ #include <linux/fd.h>
+ #include <linux/ioctl.h>
++#include <linux/blkdev.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+ #include <asm/mac_iop.h>
+@@ -97,10 +98,10 @@ static void swimiop_receive(struct iop_m
+ static void swimiop_status_update(int, struct swim_drvstatus *);
+ static int swimiop_eject(struct floppy_state *fs);
+
+-static int floppy_ioctl(struct inode *inode, struct file *filp,
++static int floppy_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param);
+-static int floppy_open(struct inode *inode, struct file *filp);
+-static int floppy_release(struct inode *inode, struct file *filp);
++static int floppy_open(struct block_device *bdev, struct file *filp);
++static int floppy_release(struct gendisk *disk);
+ static int floppy_check_change(struct gendisk *disk);
+ static int floppy_revalidate(struct gendisk *disk);
+ static int grab_drive(struct floppy_state *fs, enum swim_state state,
+@@ -347,10 +348,10 @@ static int swimiop_eject(struct floppy_s
+ static struct floppy_struct floppy_type =
+ { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
+
+-static int floppy_ioctl(struct inode *inode, struct file *filp,
++static int floppy_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long param)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = bdev->bd_disk->private_data;
+ int err;
+
+ if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))
+@@ -371,15 +372,15 @@ static int floppy_ioctl(struct inode *in
+ return -ENOTTY;
+ }
+
+-static int floppy_open(struct inode *inode, struct file *filp)
++static int floppy_open(struct block_device *bdev, struct file *filp)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = bdev->bd_disk->private_data;
+
+ if (fs->ref_count == -1 || filp->f_flags & O_EXCL)
+ return -EBUSY;
+
+ if ((filp->f_flags & O_NDELAY) == 0 && (filp->f_mode & 3)) {
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ if (fs->ejected)
+ return -ENXIO;
+ }
+@@ -395,9 +396,9 @@ static int floppy_open(struct inode *ino
+ return 0;
+ }
+
+-static int floppy_release(struct inode *inode, struct file *filp)
++static int floppy_release(struct gendisk *disk)
+ {
+- struct floppy_state *fs = inode->i_bdev->bd_disk->private_data;
++ struct floppy_state *fs = disk->private_data;
+ if (fs->ref_count > 0)
+ fs->ref_count--;
+ return 0;
+--- linux-2.6.0-test6/drivers/block/umem.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/umem.c 2003-10-05 00:33:58.000000000 -0700
+@@ -153,7 +153,6 @@ struct cardinfo {
+ };
+
+ static struct cardinfo cards[MM_MAXCARDS];
+-static struct block_device_operations mm_fops;
+ static struct timer_list battery_timer;
+
+ static int num_cards = 0;
+@@ -818,10 +817,10 @@ static int mm_revalidate(struct gendisk
+ -- mm_ioctl
+ -----------------------------------------------------------------------------------
+ */
+-static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
++static int mm_ioctl(struct block_device *bdev, struct file *f, unsigned int cmd, unsigned long arg)
+ {
+ if (cmd == HDIO_GETGEO) {
+- struct cardinfo *card = i->i_bdev->bd_disk->private_data;
++ struct cardinfo *card = bdev->bd_disk->private_data;
+ int size = card->mm_size * (1024 / MM_HARDSECT);
+ struct hd_geometry geo;
+ /*
+@@ -831,7 +830,7 @@ static int mm_ioctl(struct inode *i, str
+ */
+ geo.heads = 64;
+ geo.sectors = 32;
+- geo.start = get_start_sect(i->i_bdev);
++ geo.start = get_start_sect(bdev);
+ geo.cylinders = size / (geo.heads * geo.sectors);
+
+ if (copy_to_user((void *) arg, &geo, sizeof(geo)))
+--- linux-2.6.0-test6/drivers/block/xd.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/xd.c 2003-10-05 00:33:54.000000000 -0700
+@@ -322,9 +322,9 @@ static void do_xd_request (request_queue
+ }
+
+ /* xd_ioctl: handle device ioctl's */
+-static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
++static int xd_ioctl (struct block_device *bdev,struct file *file,u_int cmd,u_long arg)
+ {
+- XD_INFO *p = inode->i_bdev->bd_disk->private_data;
++ XD_INFO *p = bdev->bd_disk->private_data;
+
+ switch (cmd) {
+ case HDIO_GETGEO:
+@@ -334,7 +334,7 @@ static int xd_ioctl (struct inode *inode
+ g.heads = p->heads;
+ g.sectors = p->sectors;
+ g.cylinders = p->cylinders;
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
+ }
+ case HDIO_SET_DMA:
+--- linux-2.6.0-test6/drivers/block/xd.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/drivers/block/xd.h 2003-10-05 00:33:54.000000000 -0700
+@@ -105,7 +105,7 @@ static u_char xd_detect (u_char *control
+ static u_char xd_initdrives (void (*init_drive)(u_char drive));
+
+ static void do_xd_request (request_queue_t * q);
+-static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg);
++static int xd_ioctl (struct block_device *bdev,struct file *file,unsigned int cmd,unsigned long arg);
+ static int xd_readwrite (u_char operation,XD_INFO *disk,char *buffer,u_int block,u_int count);
+ static void xd_recalibrate (u_char drive);
+
+--- linux-2.6.0-test6/drivers/block/z2ram.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/block/z2ram.c 2003-10-05 00:34:01.000000000 -0700
+@@ -67,7 +67,6 @@ static int current_device = -1;
+
+ static spinlock_t z2ram_lock = SPIN_LOCK_UNLOCKED;
+
+-static struct block_device_operations z2_fops;
+ static struct gendisk *z2ram_gendisk;
+
+ static void do_z2_request(request_queue_t *q)
+@@ -141,7 +140,7 @@ get_chipram( void )
+ }
+
+ static int
+-z2_open( struct inode *inode, struct file *filp )
++z2_open( struct block_device *bdev, struct file *filp )
+ {
+ int device;
+ int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) *
+@@ -150,7 +149,7 @@ z2_open( struct inode *inode, struct fil
+ sizeof( z2ram_map[0] );
+ int rc = -ENOMEM;
+
+- device = iminor(inode);
++ device = MINOR(bdev->bd_dev);
+
+ if ( current_device != -1 && current_device != device )
+ {
+@@ -301,8 +300,7 @@ err_out:
+ return rc;
+ }
+
+-static int
+-z2_release( struct inode *inode, struct file *filp )
++static int z2_release(struct gendisk *disk)
+ {
+ if ( current_device == -1 )
+ return 0;
+--- linux-2.6.0-test6/drivers/cdrom/aztcd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/aztcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -330,10 +330,10 @@ static int aztGetToc(int multi);
+
+ /* Kernel Interface Functions */
+ static int check_aztcd_media_change(struct gendisk *disk);
+-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
++static int aztcd_ioctl(struct block_device *bdev, struct file *fp, unsigned int cmd,
+ unsigned long arg);
+-static int aztcd_open(struct inode *ip, struct file *fp);
+-static int aztcd_release(struct inode *inode, struct file *file);
++static int aztcd_open(struct block_device *bdev, struct file *fp);
++static int aztcd_release(struct gendisk *disk);
+
+ static struct block_device_operations azt_fops = {
+ .owner = THIS_MODULE,
+@@ -1153,7 +1153,7 @@ static int check_aztcd_media_change(stru
+ /*
+ * Kernel IO-controls
+ */
+-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
++static int aztcd_ioctl(struct block_device *bdev, struct file *fp, unsigned int cmd,
+ unsigned long arg)
+ {
+ int i;
+@@ -1171,8 +1171,6 @@ static int aztcd_ioctl(struct inode *ip,
+ cmd, jiffies);
+ printk("aztcd Status %x\n", getAztStatus());
+ #endif
+- if (!ip)
+- RETURNM("aztcd_ioctl 1", -EINVAL);
+ if (getAztStatus() < 0)
+ RETURNM("aztcd_ioctl 2", -EIO);
+ if ((!aztTocUpToDate) || (aztDiskChanged)) {
+@@ -1624,7 +1622,7 @@ static void azt_invalidate_buffers(void)
+ /*
+ * Open the device special file. Check that a disk is in.
+ */
+-static int aztcd_open(struct inode *ip, struct file *fp)
++static int aztcd_open(struct block_device *bdev, struct file *fp)
+ {
+ int st;
+
+@@ -1673,12 +1671,11 @@ static int aztcd_open(struct inode *ip,
+ /*
+ * On close, we flush all azt blocks from the buffer cache.
+ */
+-static int aztcd_release(struct inode *inode, struct file *file)
++static int aztcd_release(struct gendisk *disk)
+ {
+ #ifdef AZT_DEBUG
+ printk("aztcd: executing aztcd_release\n");
+- printk("inode: %p, device: %s file: %p\n", inode,
+- inode->i_bdev->bd_disk->disk_name, file);
++ printk("disk: %p, device: %s\n", disk, disk->disk_name);
+ #endif
+ if (!--azt_open_count) {
+ azt_invalidate_buffers();
+--- linux-2.6.0-test6/drivers/cdrom/cdrom.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/cdrom/cdrom.c 2003-10-05 00:33:59.000000000 -0700
+@@ -367,6 +367,7 @@ int register_cdrom(struct cdrom_device_i
+ ENSURE(generic_packet, CDC_GENERIC_PACKET);
+ cdi->mc_flags = 0;
+ cdo->n_minors = 0;
++ cdi->for_data = 0;
+ cdi->options = CDO_USE_FFLAGS;
+
+ if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY))
+@@ -416,7 +417,7 @@ int unregister_cdrom(struct cdrom_device
+ * is in their own interest: device control becomes a lot easier
+ * this way.
+ */
+-int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
++int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, struct file *fp)
+ {
+ int ret;
+
+@@ -437,7 +438,7 @@ int cdrom_open(struct cdrom_device_info
+ cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
+ /* Do this on open. Don't wait for mount, because they might
+ not be mounting, but opening with O_NONBLOCK */
+- check_disk_change(ip->i_bdev);
++ check_disk_change(bdev);
+ return ret;
+ }
+
+@@ -530,6 +531,7 @@ int open_for_data(struct cdrom_device_in
+ cdinfo(CD_OPEN, "door locked.\n");
+ }
+ cdinfo(CD_OPEN, "device opened successfully.\n");
++ cdi->for_data = 1;
+ return ret;
+
+ /* Something failed. Try to unlock the drive, because some drivers
+@@ -605,30 +607,29 @@ int check_for_audio_disc(struct cdrom_de
+
+
+ /* Admittedly, the logic below could be performed in a nicer way. */
+-int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
++int cdrom_release(struct cdrom_device_info *cdi)
+ {
+ struct cdrom_device_ops *cdo = cdi->ops;
+- int opened_for_data;
+
+ cdinfo(CD_CLOSE, "entering cdrom_release\n");
+
+ if (cdi->use_count > 0)
+ cdi->use_count--;
+- if (cdi->use_count == 0)
+- cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
+- if (cdi->use_count == 0 &&
+- cdo->capability & CDC_LOCK && !keeplocked) {
++ if (cdi->use_count) {
++ cdo->release(cdi);
++ return 0;
++ }
++
++ cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
++ if (cdo->capability & CDC_LOCK && !keeplocked) {
+ cdinfo(CD_CLOSE, "Unlocking door!\n");
+ cdo->lock_door(cdi, 0);
+ }
+- opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
+- !(fp && fp->f_flags & O_NONBLOCK);
+ cdo->release(cdi);
+- if (cdi->use_count == 0) { /* last process that closes dev*/
+- if (opened_for_data &&
+- cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
+- cdo->tray_move(cdi, 1);
+- }
++ if (cdi->for_data &&
++ cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
++ cdo->tray_move(cdi, 1);
++ cdi->for_data = 0;
+ return 0;
+ }
+
+@@ -1433,14 +1434,14 @@ static int cdrom_read_block(struct cdrom
+ * these days. ATAPI / SCSI specific code now mainly resides in
+ * mmc_ioct().
+ */
+-int cdrom_ioctl(struct cdrom_device_info *cdi, struct inode *ip,
++int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct cdrom_device_ops *cdo = cdi->ops;
+ int ret;
+
+ /* Try the generic SCSI command ioctl's first.. */
+- ret = scsi_cmd_ioctl(ip->i_bdev, cmd, arg);
++ ret = scsi_cmd_ioctl(bdev, cmd, arg);
+ if (ret != -ENOTTY)
+ return ret;
+
+@@ -1593,7 +1594,7 @@ int cdrom_ioctl(struct cdrom_device_info
+ cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
+ if (!CDROM_CAN(CDC_RESET))
+ return -ENOSYS;
+- invalidate_bdev(ip->i_bdev, 0);
++ invalidate_bdev(bdev, 0);
+ return cdo->reset(cdi);
+ }
+
+@@ -1856,57 +1857,6 @@ static int cdrom_switch_blocksize(struct
+ return cdo->generic_packet(cdi, &cgc);
+ }
+
+-static int cdrom_do_cmd(struct cdrom_device_info *cdi,
+- struct cdrom_generic_command *cgc)
+-{
+- struct request_sense *usense, sense;
+- unsigned char *ubuf;
+- int ret;
+-
+- if (cgc->data_direction == CGC_DATA_UNKNOWN)
+- return -EINVAL;
+-
+- if (cgc->buflen < 0 || cgc->buflen >= 131072)
+- return -EINVAL;
+-
+- usense = cgc->sense;
+- cgc->sense = &sense;
+- if (usense && !access_ok(VERIFY_WRITE, usense, sizeof(*usense))) {
+- return -EFAULT;
+- }
+-
+- ubuf = cgc->buffer;
+- if (cgc->data_direction == CGC_DATA_READ ||
+- cgc->data_direction == CGC_DATA_WRITE) {
+- cgc->buffer = kmalloc(cgc->buflen, GFP_KERNEL);
+- if (cgc->buffer == NULL)
+- return -ENOMEM;
+- }
+-
+-
+- if (cgc->data_direction == CGC_DATA_READ) {
+- if (!access_ok(VERIFY_READ, ubuf, cgc->buflen)) {
+- kfree(cgc->buffer);
+- return -EFAULT;
+- }
+- } else if (cgc->data_direction == CGC_DATA_WRITE) {
+- if (copy_from_user(cgc->buffer, ubuf, cgc->buflen)) {
+- kfree(cgc->buffer);
+- return -EFAULT;
+- }
+- }
+-
+- ret = cdi->ops->generic_packet(cdi, cgc);
+- __copy_to_user(usense, cgc->sense, sizeof(*usense));
+- if (!ret && cgc->data_direction == CGC_DATA_READ)
+- __copy_to_user(ubuf, cgc->buffer, cgc->buflen);
+- if (cgc->data_direction == CGC_DATA_READ ||
+- cgc->data_direction == CGC_DATA_WRITE) {
+- kfree(cgc->buffer);
+- }
+- return ret;
+-}
+-
+ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+ unsigned long arg)
+ {
+@@ -2176,14 +2126,6 @@ static int mmc_ioctl(struct cdrom_device
+ return 0;
+ }
+
+- case CDROM_SEND_PACKET: {
+- if (!CDROM_CAN(CDC_GENERIC_PACKET))
+- return -ENOSYS;
+- cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n");
+- IOCTL_IN(arg, struct cdrom_generic_command, cgc);
+- cgc.timeout = clock_t_to_jiffies(cgc.timeout);
+- return cdrom_do_cmd(cdi, &cgc);
+- }
+ case CDROM_NEXT_WRITABLE: {
+ long next = 0;
+ cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n");
+--- linux-2.6.0-test6/drivers/cdrom/cdu31a.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/cdu31a.c 2003-10-05 00:34:01.000000000 -0700
+@@ -3167,20 +3167,20 @@ static struct cdrom_device_info scd_info
+ .name = "cdu31a"
+ };
+
+-static int scd_block_open(struct inode *inode, struct file *file)
++static int scd_block_open(struct block_device *bdev, struct file *file)
+ {
+- return cdrom_open(&scd_info, inode, file);
++ return cdrom_open(&scd_info, bdev, file);
+ }
+
+-static int scd_block_release(struct inode *inode, struct file *file)
++static int scd_block_release(struct gendisk *disk)
+ {
+- return cdrom_release(&scd_info, file);
++ return cdrom_release(&scd_info);
+ }
+
+-static int scd_block_ioctl(struct inode *inode, struct file *file,
++static int scd_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- return cdrom_ioctl(&scd_info, inode, cmd, arg);
++ return cdrom_ioctl(&scd_info, bdev, cmd, arg);
+ }
+
+ static int scd_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/cdrom/cm206.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/cm206.c 2003-10-05 00:34:01.000000000 -0700
+@@ -1350,20 +1350,20 @@ static struct cdrom_device_info cm206_in
+ .name = "cm206",
+ };
+
+-static int cm206_block_open(struct inode *inode, struct file *file)
++static int cm206_block_open(struct block_device *bdev, struct file *file)
+ {
+- return cdrom_open(&cm206_info, inode, file);
++ return cdrom_open(&cm206_info, bdev, file);
+ }
+
+-static int cm206_block_release(struct inode *inode, struct file *file)
++static int cm206_block_release(struct gendisk *disk)
+ {
+- return cdrom_release(&cm206_info, file);
++ return cdrom_release(&cm206_info);
+ }
+
+-static int cm206_block_ioctl(struct inode *inode, struct file *file,
++static int cm206_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- return cdrom_ioctl(&cm206_info, inode, cmd, arg);
++ return cdrom_ioctl(&cm206_info, bdev, cmd, arg);
+ }
+
+ static int cm206_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/cdrom/gscd.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/cdrom/gscd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -91,10 +91,10 @@ static void gscd_bin2bcd(unsigned char *
+ /* Schnittstellen zum Kern/FS */
+
+ static void __do_gscd_request(unsigned long dummy);
+-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
++static int gscd_ioctl(struct block_device *, struct file *, unsigned int,
+ unsigned long);
+-static int gscd_open(struct inode *, struct file *);
+-static int gscd_release(struct inode *, struct file *);
++static int gscd_open(struct block_device *, struct file *);
++static int gscd_release(struct gendisk *disk);
+ static int check_gscd_med_chg(struct gendisk *disk);
+
+ /* GoldStar Funktionen */
+@@ -190,8 +190,8 @@ __setup("gscd=", gscd_setup);
+
+ #endif
+
+-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
+- unsigned long arg)
++static int gscd_ioctl(struct block_device *bdev, struct file *fp,
++ unsigned int cmd, unsigned long arg)
+ {
+ unsigned char to_do[10];
+ unsigned char dummy;
+@@ -338,7 +338,7 @@ static void gscd_read_cmd(struct request
+ * Open the device special file. Check that a disk is in.
+ */
+
+-static int gscd_open(struct inode *ip, struct file *fp)
++static int gscd_open(struct block_device *bdev, struct file *fp)
+ {
+ int st;
+
+@@ -368,7 +368,7 @@ static int gscd_open(struct inode *ip, s
+ * On close, we flush all gscd blocks from the buffer cache.
+ */
+
+-static int gscd_release(struct inode *inode, struct file *file)
++static int gscd_release(struct gendisk *disk)
+ {
+
+ #ifdef GSCD_DEBUG
+--- linux-2.6.0-test6/drivers/cdrom/mcd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/mcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -214,20 +214,20 @@ static struct cdrom_device_info mcd_info
+ .name = "mcd",
+ };
+
+-static int mcd_block_open(struct inode *inode, struct file *file)
++static int mcd_block_open(struct block_device *bdev, struct file *file)
+ {
+- return cdrom_open(&mcd_info, inode, file);
++ return cdrom_open(&mcd_info, bdev, file);
+ }
+
+-static int mcd_block_release(struct inode *inode, struct file *file)
++static int mcd_block_release(struct gendisk *disk)
+ {
+- return cdrom_release(&mcd_info, file);
++ return cdrom_release(&mcd_info);
+ }
+
+-static int mcd_block_ioctl(struct inode *inode, struct file *file,
++static int mcd_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- return cdrom_ioctl(&mcd_info, inode, cmd, arg);
++ return cdrom_ioctl(&mcd_info, bdev, cmd, arg);
+ }
+
+ static int mcd_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/cdrom/mcdx.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/mcdx.c 2003-10-05 00:34:01.000000000 -0700
+@@ -221,23 +221,23 @@ struct s_drive_stuff {
+ int mcdx_init(void);
+ void do_mcdx_request(request_queue_t * q);
+
+-static int mcdx_block_open(struct inode *inode, struct file *file)
++static int mcdx_block_open(struct block_device *bdev, struct file *file)
+ {
+- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_open(&p->info, inode, file);
++ struct s_drive_stuff *p = bdev->bd_disk->private_data;
++ return cdrom_open(&p->info, bdev, file);
+ }
+
+-static int mcdx_block_release(struct inode *inode, struct file *file)
++static int mcdx_block_release(struct gendisk *disk)
+ {
+- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_release(&p->info, file);
++ struct s_drive_stuff *p = disk->private_data;
++ return cdrom_release(&p->info);
+ }
+
+-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
++static int mcdx_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_ioctl(&p->info, inode, cmd, arg);
++ struct s_drive_stuff *p = bdev->bd_disk->private_data;
++ return cdrom_ioctl(&p->info, bdev, cmd, arg);
+ }
+
+ static int mcdx_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/cdrom/optcd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/optcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -1713,16 +1713,13 @@ static int cdromreset(void)
+ /* VFS calls */
+
+
+-static int opt_ioctl(struct inode *ip, struct file *fp,
++static int opt_ioctl(struct block_device *bdev, struct file *fp,
+ unsigned int cmd, unsigned long arg)
+ {
+ int status, err, retval = 0;
+
+ DEBUG((DEBUG_VFS, "starting opt_ioctl"));
+
+- if (!ip)
+- return -EINVAL;
+-
+ if (cmd == CDROMRESET)
+ return cdromreset();
+
+@@ -1844,7 +1841,7 @@ static int opt_ioctl(struct inode *ip, s
+ static int open_count = 0;
+
+ /* Open device special file; check that a disk is in. */
+-static int opt_open(struct inode *ip, struct file *fp)
++static int opt_open(struct block_device *bdev, struct file *fp)
+ {
+ DEBUG((DEBUG_VFS, "starting opt_open"));
+
+@@ -1904,13 +1901,12 @@ err_out:
+
+
+ /* Release device special file; flush all blocks from the buffer cache */
+-static int opt_release(struct inode *ip, struct file *fp)
++static int opt_release(struct gendisk *disk)
+ {
+ int status;
+
+ DEBUG((DEBUG_VFS, "executing opt_release"));
+- DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
+- ip, ip->i_bdev->bd_disk->disk_name, fp));
++ DEBUG((DEBUG_VFS, "disk: %p, device: %s\n", disk, disk->disk_name));
+
+ if (!--open_count) {
+ toc_uptodate = 0;
+--- linux-2.6.0-test6/drivers/cdrom/sbpcd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/sbpcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -363,7 +363,6 @@
+
+ #include <linux/module.h>
+
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+@@ -5357,23 +5356,23 @@ static int sbp_data(struct request *req)
+ }
+ /*==========================================================================*/
+
+-static int sbpcd_block_open(struct inode *inode, struct file *file)
++static int sbpcd_block_open(struct block_device *bdev, struct file *file)
+ {
+- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_open(p->sbpcd_infop, inode, file);
++ struct sbpcd_drive *p = bdev->bd_disk->private_data;
++ return cdrom_open(p->sbpcd_infop, bdev, file);
+ }
+
+-static int sbpcd_block_release(struct inode *inode, struct file *file)
++static int sbpcd_block_release(struct gendisk *disk)
+ {
+- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_release(p->sbpcd_infop, file);
++ struct sbpcd_drive *p = disk->private_data;
++ return cdrom_release(p->sbpcd_infop);
+ }
+
+-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
++static int sbpcd_block_ioctl(struct block_device *bdev, struct file *file,
+ unsigned cmd, unsigned long arg)
+ {
+- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
+- return cdrom_ioctl(p->sbpcd_infop, inode, cmd, arg);
++ struct sbpcd_drive *p = bdev->bd_disk->private_data;
++ return cdrom_ioctl(p->sbpcd_infop, bdev, cmd, arg);
+ }
+
+ static int sbpcd_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/cdrom/sjcd.c 2003-09-08 13:58:56.000000000 -0700
++++ 25/drivers/cdrom/sjcd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -713,16 +713,13 @@ static int sjcd_tray_open(void)
+ /*
+ * Do some user commands.
+ */
+-static int sjcd_ioctl(struct inode *ip, struct file *fp,
++static int sjcd_ioctl(struct block_device *bdev, struct file *fp,
+ unsigned int cmd, unsigned long arg)
+ {
+ #if defined( SJCD_TRACE )
+ printk("SJCD:ioctl\n");
+ #endif
+
+- if (ip == NULL)
+- return (-EINVAL);
+-
+ sjcd_get_status();
+ if (!sjcd_status_valid)
+ return (-EIO);
+@@ -1522,7 +1519,7 @@ static void do_sjcd_request(request_queu
+ /*
+ * Open the device special file. Check disk is in.
+ */
+-static int sjcd_open(struct inode *ip, struct file *fp)
++static int sjcd_open(struct block_device *bdev, struct file *fp)
+ {
+ /*
+ * Check the presence of device.
+@@ -1607,7 +1604,7 @@ static int sjcd_open(struct inode *ip, s
+ /*
+ * On close, we flush all sjcd blocks from the buffer cache.
+ */
+-static int sjcd_release(struct inode *inode, struct file *file)
++static int sjcd_release(struct gendisk *disk)
+ {
+ int s;
+
+--- linux-2.6.0-test6/drivers/cdrom/sonycd535.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/cdrom/sonycd535.c 2003-10-05 00:34:01.000000000 -0700
+@@ -201,7 +201,7 @@
+
+ static int read_subcode(void);
+ static void sony_get_toc(void);
+-static int cdu_open(struct inode *inode, struct file *filp);
++static int cdu_open(struct block_device *bdev, struct file *filp);
+ static inline unsigned int int_to_bcd(unsigned int val);
+ static unsigned int bcd_to_int(unsigned int bcd);
+ static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
+@@ -1061,7 +1061,7 @@ sony_get_subchnl_info(long arg)
+ * The big ugly ioctl handler.
+ */
+ static int
+-cdu_ioctl(struct inode *inode,
++cdu_ioctl(struct block_device *bdev,
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+@@ -1363,9 +1363,7 @@ cdu_ioctl(struct inode *inode,
+ * Open the drive for operations. Spin the drive up and read the table of
+ * contents if these have not already been done.
+ */
+-static int
+-cdu_open(struct inode *inode,
+- struct file *filp)
++static int cdu_open(struct block_device *bdev, struct file *filp)
+ {
+ Byte status[2], cmd_buff[2];
+
+@@ -1388,7 +1386,7 @@ cdu_open(struct inode *inode,
+ sony_inuse = 0;
+ return -EIO;
+ }
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ sony_usage++;
+
+ #ifdef LOCK_DOORS
+@@ -1405,9 +1403,7 @@ cdu_open(struct inode *inode,
+ * Close the drive. Spin it down if no task is using it. The spin
+ * down will fail if playing audio, so audio play is OK.
+ */
+-static int
+-cdu_release(struct inode *inode,
+- struct file *filp)
++static int cdu_release(struct gendisk *disk)
+ {
+ Byte status[2], cmd_no;
+
+--- linux-2.6.0-test6/drivers/char/agp/amd64-agp.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/agp/amd64-agp.c 2003-10-05 00:33:24.000000000 -0700
+@@ -91,9 +91,9 @@ static int amd64_insert_memory(struct ag
+ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+ tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+
+- BUG_ON(tmp & 0xffffff0000000ffc);
+- pte = (tmp & 0x000000ff00000000) >> 28;
+- pte |=(tmp & 0x00000000fffff000);
++ BUG_ON(tmp & 0xffffff0000000ffcULL);
++ pte = (tmp & 0x000000ff00000000ULL) >> 28;
++ pte |=(tmp & 0x00000000fffff000ULL);
+ pte |= GPTE_VALID | GPTE_COHERENT;
+
+ agp_bridge->gatt_table[j] = pte;
+--- linux-2.6.0-test6/drivers/char/agp/via-agp.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/agp/via-agp.c 2003-10-05 00:33:24.000000000 -0700
+@@ -251,6 +251,11 @@ static struct agp_device_ids via_agp_dev
+ .chipset_name = "Pro 266",
+ },
+
++ {
++ .device_id = PCI_DEVICE_ID_VIA_XN266,
++ .chipset_name = "Apollo Pro266",
++ },
++
+ /* VT8361 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_8361,
+--- linux-2.6.0-test6/drivers/char/amiserial.c 2003-07-27 12:14:38.000000000 -0700
++++ 25/drivers/char/amiserial.c 2003-10-05 00:33:24.000000000 -0700
+@@ -32,7 +32,6 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+
+ #undef SERIAL_PARANOIA_CHECK
+ #define SERIAL_DO_RESTART
+--- linux-2.6.0-test6/drivers/char/cyclades.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/cyclades.c 2003-10-05 00:33:24.000000000 -0700
+@@ -670,7 +670,6 @@ static char rcsid[] =
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+-#include <linux/version.h>
+
+ #include <linux/stat.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/drivers/char/dsp56k.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/dsp56k.c 2003-10-05 00:33:24.000000000 -0700
+@@ -24,7 +24,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/slab.h> /* for kmalloc() and kfree() */
+ #include <linux/sched.h> /* for struct wait_queue etc */
+ #include <linux/major.h>
+--- linux-2.6.0-test6/drivers/char/dtlk.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/dtlk.c 2003-10-05 00:33:24.000000000 -0700
+@@ -48,7 +48,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+
+ #define KERNEL
+ #include <linux/types.h>
+--- linux-2.6.0-test6/drivers/char/dz.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/char/dz.c 2003-10-05 00:33:24.000000000 -0700
+@@ -23,7 +23,6 @@ Qua Jun 27 15:02:26 BRT 2001
+
+ /* #define DEBUG_DZ 1 */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+
+ #include <linux/config.h>
+--- linux-2.6.0-test6/drivers/char/ftape/compressor/zftape-compress.c 2003-06-14 12:18:32.000000000 -0700
++++ 25/drivers/char/ftape/compressor/zftape-compress.c 2003-10-05 00:33:24.000000000 -0700
+@@ -31,6 +31,7 @@
+ char zftc_rev[] = "$Revision: 1.1.4.1 $";
+ char zftc_dat[] = "$Date: 2003/10/10 09:31:08 $";
+
++#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/char/ftape/lowlevel/fdc-io.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/ftape/lowlevel/fdc-io.c 2003-10-05 00:33:24.000000000 -0700
+@@ -30,7 +30,6 @@
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/ioport.h>
+-#include <linux/version.h>
+ #include <linux/interrupt.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+--- linux-2.6.0-test6/drivers/char/generic_serial.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/generic_serial.c 2003-10-05 00:33:24.000000000 -0700
+@@ -348,7 +348,7 @@ int gs_real_chars_in_buffer(struct tty_s
+ static int gs_wait_tx_flushed (void * ptr, int timeout)
+ {
+ struct gs_port *port = ptr;
+- long end_jiffies;
++ unsigned long end_jiffies;
+ int jiffies_to_transmit, charsleft = 0, rv = 0;
+ int rcib;
+
+--- linux-2.6.0-test6/drivers/char/i8k.c 2003-06-14 12:18:01.000000000 -0700
++++ 25/drivers/char/i8k.c 2003-10-05 00:33:24.000000000 -0700
+@@ -17,7 +17,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/init.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/drivers/char/ip2/i2os.h 2003-07-27 12:14:38.000000000 -0700
++++ 25/drivers/char/ip2/i2os.h 2003-10-05 00:33:24.000000000 -0700
+@@ -25,7 +25,6 @@
+
+ #include "ip2types.h"
+ #include <asm/io.h> /* For inb, etc */
+-#include <linux/version.h>
+
+ //------------------------------------
+ // Defines for I/O instructions:
+--- linux-2.6.0-test6/drivers/char/ip2main.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/ip2main.c 2003-10-05 00:33:24.000000000 -0700
+@@ -84,8 +84,6 @@
+ /************/
+ #include <linux/config.h>
+
+-#include <linux/version.h>
+-
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+ #include <linux/fcntl.h>
+--- linux-2.6.0-test6/drivers/char/isicom.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/char/isicom.c 2003-10-05 00:33:24.000000000 -0700
+@@ -38,7 +38,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/tty.h>
+ #include <linux/termios.h>
+--- linux-2.6.0-test6/drivers/char/istallion.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/istallion.c 2003-10-05 00:33:24.000000000 -0700
+@@ -35,7 +35,6 @@
+ #include <linux/serial.h>
+ #include <linux/cdk.h>
+ #include <linux/comstats.h>
+-#include <linux/version.h>
+ #include <linux/istallion.h>
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+--- linux-2.6.0-test6/drivers/char/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -954,6 +954,15 @@ config RAW_DRIVER
+ Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
+ See the raw(8) manpage for more details.
+
++config MAX_RAW_DEVS
++ int "Maximum number of RAW devices to support (1-8192)"
++ depends on RAW_DRIVER
++ default "256"
++ help
++ The maximum number of RAW devices that are supported.
++ Default is 256. Increase this number in case you need lots of
++ raw devices.
++
+ config HANGCHECK_TIMER
+ tristate "Hangcheck timer"
+ depends on X86_64 || X86
+--- linux-2.6.0-test6/drivers/char/keyboard.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/keyboard.c 2003-10-05 00:33:38.000000000 -0700
+@@ -1052,6 +1052,9 @@ void kbd_keycode(unsigned int keycode, i
+ }
+ if (sysrq_down && down && !rep) {
+ handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
++#ifdef CONFIG_KGDB_SYSRQ
++ sysrq_down = 0; /* in case we miss the "up" event */
++#endif
+ return;
+ }
+ #endif
+--- linux-2.6.0-test6/drivers/char/lp_old98.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/lp_old98.c 2003-10-05 00:33:24.000000000 -0700
+@@ -23,7 +23,6 @@
+ #include <linux/fcntl.h>
+ #include <linux/delay.h>
+ #include <linux/console.h>
+-#include <linux/version.h>
+ #include <linux/fs.h>
+
+ #include <asm/io.h>
+--- linux-2.6.0-test6/drivers/char/mem.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/mem.c 2003-10-05 00:36:19.000000000 -0700
+@@ -40,6 +40,7 @@ extern void fbmem_init(void);
+ extern void tapechar_init(void);
+ #endif
+
++#ifdef pgprot_noncached
+ /*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+@@ -65,19 +66,21 @@ static inline int uncached_access(struct
+ && addr >= __pa(high_memory);
+ #elif defined(CONFIG_IA64)
+ /*
+- * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
++ * On ia64, we ignore O_SYNC because we cannot tolerate memory
++ * attribute aliases.
+ */
+ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+ #else
+ /*
+- * Accessing memory above the top the kernel knows about or through a file pointer
+- * that was marked O_SYNC will be done non-cached.
++ * Accessing memory above the top the kernel knows about or through a
++ * file pointer that was marked O_SYNC will be done non-cached.
+ */
+ if (file->f_flags & O_SYNC)
+ return 1;
+ return addr >= __pa(high_memory);
+ #endif
+ }
++#endif /* pgprot_noncached */
+
+ static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
+ const char * buf, size_t count, loff_t *ppos)
+@@ -159,28 +162,24 @@ static ssize_t write_mem(struct file * f
+ return do_write_mem(file, __va(p), p, buf, count, ppos);
+ }
+
+-static int mmap_mem(struct file * file, struct vm_area_struct * vma)
++static int mmap_mem(struct file *file, struct vm_area_struct *vma)
+ {
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+- int uncached;
+
+- uncached = uncached_access(file, offset);
+ #ifdef pgprot_noncached
+- if (uncached)
++ if (uncached_access(file, offset))
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ #endif
+
+- /* Don't try to swap out physical pages.. */
+- vma->vm_flags |= VM_RESERVED;
+-
+ /*
+- * Don't dump addresses that are not real memory to a core file.
++ * Don't try to swap out physical pages..
++ * And treat /dev/mem mappings as "IO" regions: they may not
++ * describe valid pageframes.
+ */
+- if (uncached)
+- vma->vm_flags |= VM_IO;
++ vma->vm_flags |= VM_RESERVED|VM_IO;
+
+- if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start,
+- vma->vm_page_prot))
++ if (remap_page_range(vma, vma->vm_start, offset,
++ vma->vm_end-vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ return 0;
+ }
+--- linux-2.6.0-test6/drivers/char/misc.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/misc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -157,12 +157,11 @@ static int misc_open(struct inode * inod
+ list_for_each_entry(c, &misc_list, list) {
+ if (c->minor == minor) {
+ new_fops = fops_get(c->fops);
+- if (!new_fops)
+- goto fail;
+ break;
+ }
+ }
+- goto fail;
++ if (!new_fops)
++ goto fail;
+ }
+
+ err = 0;
+--- linux-2.6.0-test6/drivers/char/moxa.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/moxa.c 2003-10-05 00:33:24.000000000 -0700
+@@ -32,7 +32,6 @@
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+-#include <linux/version.h>
+ #include <linux/mm.h>
+ #include <linux/ioport.h>
+ #include <linux/errno.h>
+--- linux-2.6.0-test6/drivers/char/mxser.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/char/mxser.c 2003-10-05 00:33:24.000000000 -0700
+@@ -39,7 +39,6 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+--- linux-2.6.0-test6/drivers/char/n_tty.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/n_tty.c 2003-10-05 00:36:15.000000000 -0700
+@@ -974,7 +974,8 @@ do_it_again:
+ /* NOTE: not yet done after every sleep pending a thorough
+ check of the logic of this change. -- jlc */
+ /* don't stop on /dev/console */
+- if (file->f_op->write != redirected_tty_write && current->tty == tty) {
++ if (file->f_op->write != redirected_tty_write &&
++ process_tty(current) == tty) {
+ if (tty->pgrp <= 0)
+ printk("read_chan: tty->pgrp <= 0!\n");
+ else if (process_group(current) != tty->pgrp) {
+--- linux-2.6.0-test6/drivers/char/pcmcia/synclink_cs.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/pcmcia/synclink_cs.c 2003-10-05 00:33:24.000000000 -0700
+@@ -37,7 +37,6 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+--- linux-2.6.0-test6/drivers/char/pcxx.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/pcxx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -65,7 +65,6 @@
+ #include <linux/tty_driver.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+-#include <linux/version.h>
+
+ #ifndef MODULE
+ #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
+--- linux-2.6.0-test6/drivers/char/random.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/random.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1735,7 +1735,7 @@ random_ioctl(struct inode * inode, struc
+ tmp = kmalloc(size * sizeof(__u32), GFP_KERNEL);
+
+ if (!tmp)
+- return -EFAULT;
++ return -ENOMEM;
+
+ spin_lock_irqsave(&random_state->lock, flags);
+ ent_count = random_state->entropy_count;
+--- linux-2.6.0-test6/drivers/char/raw.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/raw.c 2003-10-05 00:34:12.000000000 -0700
+@@ -20,8 +20,6 @@
+
+ #include <asm/uaccess.h>
+
+-#define MAX_RAW_MINORS 256
+-
+ struct raw_device_data {
+ struct block_device *binding;
+ int inuse;
+@@ -76,9 +74,8 @@ static int raw_open(struct inode *inode,
+ goto out;
+ }
+ filp->f_flags |= O_DIRECT;
+- if (++raw_devices[minor].inuse == 1)
+- filp->f_dentry->d_inode->i_mapping =
+- bdev->bd_inode->i_mapping;
++ filp->f_mapping = bdev->bd_inode->i_mapping;
++ raw_devices[minor].inuse++;
+ }
+ filp->private_data = bdev;
+ out:
+@@ -97,11 +94,7 @@ static int raw_release(struct inode *ino
+
+ down(&raw_mutex);
+ bdev = raw_devices[minor].binding;
+- if (--raw_devices[minor].inuse == 0) {
+- /* Here inode->i_mapping == bdev->bd_inode->i_mapping */
+- inode->i_mapping = &inode->i_data;
+- inode->i_mapping->backing_dev_info = &default_backing_dev_info;
+- }
++ --raw_devices[minor].inuse;
+ up(&raw_mutex);
+
+ bd_release(bdev);
+--- linux-2.6.0-test6/drivers/char/rio/rio_linux.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/rio/rio_linux.c 2003-10-05 00:33:24.000000000 -0700
+@@ -53,7 +53,6 @@
+ #include <linux/fcntl.h>
+ #include <linux/major.h>
+ #include <linux/delay.h>
+-#include <linux/version.h>
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <linux/miscdevice.h>
+--- linux-2.6.0-test6/drivers/char/rocket.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/rocket.c 2003-10-05 00:36:15.000000000 -0700
+@@ -85,11 +85,9 @@
+ #include <linux/string.h>
+ #include <linux/fcntl.h>
+ #include <linux/ptrace.h>
+-#include <linux/major.h>
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+ #include <linux/wait.h>
+-#include <linux/delay.h>
+ #include <linux/pci.h>
+ #include <asm/uaccess.h>
+ #include <asm/atomic.h>
+@@ -955,7 +953,7 @@ static int rp_open(struct tty_struct *tt
+ /*
+ * Info->count is now 1; so it's safe to sleep now.
+ */
+- info->session = current->session;
++ info->session = process_session(current);
+ info->pgrp = process_group(current);
+
+ if ((info->flags & ROCKET_INITIALIZED) == 0) {
+--- linux-2.6.0-test6/drivers/char/ser_a2232.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/ser_a2232.c 2003-10-05 00:33:24.000000000 -0700
+@@ -703,7 +703,7 @@ static int a2232_init_drivers(void)
+ a2232_driver->name = "ttyY";
+ a2232_driver->major = A2232_NORMAL_MAJOR;
+ a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
+- a2232_driver->subtype = SERIAL_TTY_NORMAL;
++ a2232_driver->subtype = SERIAL_TYPE_NORMAL;
+ a2232_driver->init_termios = tty_std_termios;
+ a2232_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+--- linux-2.6.0-test6/drivers/char/serial167.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/serial167.c 2003-10-05 00:33:24.000000000 -0700
+@@ -70,7 +70,6 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+ #include <linux/init.h>
+
+--- linux-2.6.0-test6/drivers/char/stallion.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/stallion.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/version.h> /* for linux/stallion.h */
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ #include <linux/tty.h>
+--- linux-2.6.0-test6/drivers/char/sx.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/sx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -240,7 +240,6 @@
+ #include "sxwindow.h"
+
+ #include <linux/generic_serial.h>
+-#include <asm/uaccess.h>
+ #include "sx.h"
+
+
+--- linux-2.6.0-test6/drivers/char/sysrq.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/sysrq.c 2003-10-05 00:33:38.000000000 -0700
+@@ -35,6 +35,25 @@
+ #include <linux/spinlock.h>
+
+ #include <asm/ptrace.h>
++#ifdef CONFIG_KGDB_SYSRQ
++
++#define GDB_OP &kgdb_op
++static void kgdb_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
++{
++ printk("kgdb sysrq\n");
++ breakpoint();
++}
++
++static struct sysrq_key_op kgdb_op = {
++ .handler = kgdb_sysrq,
++ .help_msg = "kGdb|Fgdb",
++ .action_msg = "Debug breakpoint\n",
++};
++
++#else
++#define GDB_OP NULL
++#endif
++
+
+ extern void reset_vc(unsigned int);
+
+@@ -238,8 +257,8 @@ static struct sysrq_key_op *sysrq_key_ta
+ /* c */ NULL,
+ /* d */ NULL,
+ /* e */ &sysrq_term_op,
+-/* f */ NULL,
+-/* g */ NULL,
++/* f */ GDB_OP,
++/* g */ GDB_OP,
+ /* h */ NULL,
+ /* i */ &sysrq_kill_op,
+ /* j */ NULL,
+--- linux-2.6.0-test6/drivers/char/toshiba.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/char/toshiba.c 2003-10-05 00:33:24.000000000 -0700
+@@ -57,7 +57,6 @@
+ #define TOSH_DEBUG 0
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/types.h>
+@@ -85,7 +84,6 @@ static int tosh_fn = 0;
+ MODULE_PARM(tosh_fn, "i");
+
+
+-static int tosh_get_info(char *, char **, off_t, int);
+ static int tosh_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
+
+@@ -104,6 +102,7 @@ static struct miscdevice tosh_device = {
+ /*
+ * Read the Fn key status
+ */
++#ifdef CONFIG_PROC_FS
+ static int tosh_fn_status(void)
+ {
+ unsigned char scan;
+@@ -120,6 +119,7 @@ static int tosh_fn_status(void)
+
+ return (int) scan;
+ }
++#endif
+
+
+ /*
+@@ -291,6 +291,7 @@ static int tosh_ioctl(struct inode *ip,
+ /*
+ * Print the information for /proc/toshiba
+ */
++#ifdef CONFIG_PROC_FS
+ int tosh_get_info(char *buffer, char **start, off_t fpos, int length)
+ {
+ char *temp;
+@@ -319,6 +320,7 @@ int tosh_get_info(char *buffer, char **s
+
+ return temp-buffer;
+ }
++#endif
+
+
+ /*
+--- linux-2.6.0-test6/drivers/char/tty_io.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/tty_io.c 2003-10-05 00:36:15.000000000 -0700
+@@ -314,7 +314,7 @@ struct tty_driver *get_tty_driver(dev_t
+ */
+ int tty_check_change(struct tty_struct * tty)
+ {
+- if (current->tty != tty)
++ if (process_tty(current) != tty)
+ return 0;
+ if (tty->pgrp <= 0) {
+ printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
+@@ -481,14 +481,14 @@ void do_tty_hangup(void *data)
+ if (tty->session > 0) {
+ struct list_head *l;
+ for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) {
+- if (p->tty == tty)
+- p->tty = NULL;
+- if (!p->leader)
++ if (process_tty(p) == tty)
++ p->signal->tty = NULL;
++ if (!process_session_leader(p))
+ continue;
+ send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+ send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+ if (tty->pgrp > 0)
+- p->tty_old_pgrp = tty->pgrp;
++ p->signal->tty_old_pgrp = tty->pgrp;
+ }
+ }
+ read_unlock(&tasklist_lock);
+@@ -565,15 +565,15 @@ void disassociate_ctty(int on_exit)
+
+ lock_kernel();
+
+- tty = current->tty;
++ tty = process_tty(current);
+ if (tty) {
+ tty_pgrp = tty->pgrp;
+ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
+ tty_vhangup(tty);
+ } else {
+- if (current->tty_old_pgrp) {
+- kill_pg(current->tty_old_pgrp, SIGHUP, on_exit);
+- kill_pg(current->tty_old_pgrp, SIGCONT, on_exit);
++ if (current->signal->tty_old_pgrp) {
++ kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
++ kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
+ }
+ unlock_kernel();
+ return;
+@@ -584,13 +584,13 @@ void disassociate_ctty(int on_exit)
+ kill_pg(tty_pgrp, SIGCONT, on_exit);
+ }
+
+- current->tty_old_pgrp = 0;
++ current->signal->tty_old_pgrp = 0;
+ tty->session = 0;
+ tty->pgrp = -1;
+
+ read_lock(&tasklist_lock);
+- for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid)
+- p->tty = NULL;
++ for_each_task_pid(process_session(current), PIDTYPE_SID, p, l, pid)
++ p->signal->tty = NULL;
+ read_unlock(&tasklist_lock);
+ unlock_kernel();
+ }
+@@ -1218,10 +1218,10 @@ static void release_dev(struct file * fi
+
+ read_lock(&tasklist_lock);
+ for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+- p->tty = NULL;
++ p->signal->tty = NULL;
+ if (o_tty)
+ for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid)
+- p->tty = NULL;
++ p->signal->tty = NULL;
+ read_unlock(&tasklist_lock);
+ }
+
+@@ -1292,10 +1292,10 @@ static int tty_open(struct inode * inode
+ retry_open:
+ noctty = filp->f_flags & O_NOCTTY;
+ if (device == MKDEV(TTYAUX_MAJOR,0)) {
+- if (!current->tty)
++ if (!process_tty(current))
+ return -ENXIO;
+- driver = current->tty->driver;
+- index = current->tty->index;
++ driver = process_tty(current)->driver;
++ index = process_tty(current)->index;
+ filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
+ /* noctty = 1; */
+ goto got_driver;
+@@ -1389,15 +1389,13 @@ got_driver:
+ filp->f_op = &tty_fops;
+ goto retry_open;
+ }
+- if (!noctty &&
+- current->leader &&
+- !current->tty &&
+- tty->session == 0) {
++ if (!noctty && process_session_leader(current) &&
++ !process_tty(current) && tty->session == 0) {
+ task_lock(current);
+- current->tty = tty;
++ current->signal->tty = tty;
+ task_unlock(current);
+- current->tty_old_pgrp = 0;
+- tty->session = current->session;
++ current->signal->tty_old_pgrp = 0;
++ tty->session = process_session(current);
+ tty->pgrp = process_group(current);
+ }
+ return 0;
+@@ -1455,7 +1453,7 @@ static int tiocsti(struct tty_struct *tt
+ {
+ char ch, mbz = 0;
+
+- if ((current->tty != tty) && !capable(CAP_SYS_ADMIN))
++ if ((process_tty(current) != tty) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (get_user(ch, arg))
+ return -EFAULT;
+@@ -1541,14 +1539,14 @@ static int tiocsctty(struct tty_struct *
+ struct pid *pid;
+ task_t *p;
+
+- if (current->leader &&
+- (current->session == tty->session))
++ if (process_session_leader(current) &&
++ (process_session(current) == tty->session))
+ return 0;
+ /*
+ * The process must be a session leader and
+ * not have a controlling tty already.
+ */
+- if (!current->leader || current->tty)
++ if (!process_session_leader(current) || process_tty(current))
+ return -EPERM;
+ if (tty->session > 0) {
+ /*
+@@ -1562,16 +1560,16 @@ static int tiocsctty(struct tty_struct *
+
+ read_lock(&tasklist_lock);
+ for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+- p->tty = NULL;
++ p->signal->tty = NULL;
+ read_unlock(&tasklist_lock);
+ } else
+ return -EPERM;
+ }
+ task_lock(current);
+- current->tty = tty;
++ current->signal->tty = tty;
+ task_unlock(current);
+- current->tty_old_pgrp = 0;
+- tty->session = current->session;
++ current->signal->tty_old_pgrp = 0;
++ tty->session = process_session(current);
+ tty->pgrp = process_group(current);
+ return 0;
+ }
+@@ -1582,12 +1580,13 @@ static int tiocgpgrp(struct tty_struct *
+ * (tty == real_tty) is a cheap way of
+ * testing if the tty is NOT a master pty.
+ */
+- if (tty == real_tty && current->tty != real_tty)
++ if (tty == real_tty && process_tty(current) != real_tty)
+ return -ENOTTY;
+ return put_user(real_tty->pgrp, arg);
+ }
+
+-static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
++static int tiocspgrp(struct tty_struct *tty,
++ struct tty_struct *real_tty, pid_t *arg)
+ {
+ pid_t pgrp;
+ int retval = tty_check_change(real_tty);
+@@ -1596,15 +1595,14 @@ static int tiocspgrp(struct tty_struct *
+ return -ENOTTY;
+ if (retval)
+ return retval;
+- if (!current->tty ||
+- (current->tty != real_tty) ||
+- (real_tty->session != current->session))
++ if (!process_tty(current) || (process_tty(current) != real_tty) ||
++ (real_tty->session != process_session(current)))
+ return -ENOTTY;
+ if (get_user(pgrp, (pid_t *) arg))
+ return -EFAULT;
+ if (pgrp < 0)
+ return -EINVAL;
+- if (session_of_pgrp(pgrp) != current->session)
++ if (session_of_pgrp(pgrp) != process_session(current))
+ return -EPERM;
+ real_tty->pgrp = pgrp;
+ return 0;
+@@ -1616,7 +1614,7 @@ static int tiocgsid(struct tty_struct *t
+ * (tty == real_tty) is a cheap way of
+ * testing if the tty is NOT a master pty.
+ */
+- if (tty == real_tty && current->tty != real_tty)
++ if (tty == real_tty && process_tty(current) != real_tty)
+ return -ENOTTY;
+ if (real_tty->session <= 0)
+ return -ENOTTY;
+@@ -1774,12 +1772,12 @@ int tty_ioctl(struct inode * inode, stru
+ clear_bit(TTY_EXCLUSIVE, &tty->flags);
+ return 0;
+ case TIOCNOTTY:
+- if (current->tty != tty)
++ if (process_tty(current) != tty)
+ return -ENOTTY;
+- if (current->leader)
++ if (process_session_leader(current))
+ disassociate_ctty(0);
+ task_lock(current);
+- current->tty = NULL;
++ current->signal->tty = NULL;
+ task_unlock(current);
+ return 0;
+ case TIOCSCTTY:
+@@ -1883,10 +1881,10 @@ static void __do_SAK(void *arg)
+ tty->driver->flush_buffer(tty);
+ read_lock(&tasklist_lock);
+ for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
+- if (p->tty == tty || session > 0) {
++ if (process_tty(p) == tty || session > 0) {
+ printk(KERN_NOTICE "SAK: killed process %d"
+- " (%s): p->session==tty->session\n",
+- p->pid, p->comm);
++ " (%s): process_session(p)==tty->session\n",
++ p->pid, p->comm);
+ send_sig(SIGKILL, p, 1);
+ continue;
+ }
+--- linux-2.6.0-test6/drivers/char/vme_scc.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/vme_scc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -29,7 +29,6 @@
+ #include <linux/fcntl.h>
+ #include <linux/major.h>
+ #include <linux/delay.h>
+-#include <linux/version.h>
+ #include <linux/slab.h>
+ #include <linux/miscdevice.h>
+ #include <linux/console.h>
+--- linux-2.6.0-test6/drivers/char/vt.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/char/vt.c 2003-10-05 00:36:15.000000000 -0700
+@@ -2226,7 +2226,7 @@ int tioclinux(struct tty_struct *tty, un
+
+ if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE)
+ return -EINVAL;
+- if (current->tty != tty && !capable(CAP_SYS_ADMIN))
++ if (process_tty(current) != tty && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (get_user(type, (char *)arg))
+ return -EFAULT;
+--- linux-2.6.0-test6/drivers/char/vt_ioctl.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/char/vt_ioctl.c 2003-10-05 00:36:15.000000000 -0700
+@@ -380,7 +380,7 @@ int vt_ioctl(struct tty_struct *tty, str
+ * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
+ */
+ perm = 0;
+- if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG))
++ if (process_tty(current) == tty || capable(CAP_SYS_TTY_CONFIG))
+ perm = 1;
+
+ kbd = kbd_table + console;
+@@ -1188,4 +1188,3 @@ void change_console(unsigned int new_con
+
+ complete_change_console(new_console);
+ }
+-
+--- linux-2.6.0-test6/drivers/char/watchdog/amd7xx_tco.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/char/watchdog/amd7xx_tco.c 2003-10-05 00:33:24.000000000 -0700
+@@ -19,13 +19,11 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/miscdevice.h>
+ #include <linux/watchdog.h>
+ #include <linux/ioport.h>
+ #include <linux/spinlock.h>
+-#include <linux/ioport.h>
+ #include <asm/semaphore.h>
+ #include <asm/io.h>
+ #include <asm/uaccess.h>
+--- linux-2.6.0-test6/drivers/cpufreq/cpufreq.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/cpufreq/cpufreq.c 2003-10-05 00:36:14.000000000 -0700
+@@ -449,6 +449,9 @@ static int cpufreq_remove_dev (struct sy
+ if (!kobject_get(&data->kobj))
+ return -EFAULT;
+
++ if (cpufreq_driver->target)
++ __cpufreq_governor(data, CPUFREQ_GOV_STOP);
++
+ kobject_unregister(&data->kobj);
+
+ kobject_put(&data->kobj);
+@@ -459,9 +462,6 @@ static int cpufreq_remove_dev (struct sy
+ */
+ wait_for_completion(&data->kobj_unregister);
+
+- if (cpufreq_driver->target)
+- __cpufreq_governor(data, CPUFREQ_GOV_STOP);
+-
+ if (cpufreq_driver->exit)
+ cpufreq_driver->exit(data);
+
+--- linux-2.6.0-test6/drivers/eisa/eisa-bus.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/eisa/eisa-bus.c 2003-10-05 00:36:11.000000000 -0700
+@@ -33,23 +33,22 @@ static struct eisa_device_info __initdat
+ #endif
+
+ #define EISA_MAX_FORCED_DEV 16
+-#define EISA_FORCED_OFFSET 2
+
+-static int enable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET] = { 1, EISA_MAX_FORCED_DEV, };
+-static int disable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET] = { 1, EISA_MAX_FORCED_DEV, };
++static int enable_dev[EISA_MAX_FORCED_DEV];
++static int enable_dev_count;
++static int disable_dev[EISA_MAX_FORCED_DEV];
++static int disable_dev_count;
+
+ static int is_forced_dev (int *forced_tab,
++ int forced_count,
+ struct eisa_root_device *root,
+ struct eisa_device *edev)
+ {
+ int i, x;
+
+- for (i = 0; i < EISA_MAX_FORCED_DEV; i++) {
+- if (!forced_tab[EISA_FORCED_OFFSET + i])
+- return 0;
+-
++ for (i = 0; i < forced_count; i++) {
+ x = (root->bus_nr << 8) | edev->slot;
+- if (forced_tab[EISA_FORCED_OFFSET + i] == x)
++ if (forced_tab[i] == x)
+ return 1;
+ }
+
+@@ -198,10 +197,10 @@ static int __init eisa_init_device (stru
+ #endif
+ }
+
+- if (is_forced_dev (enable_dev, root, edev))
++ if (is_forced_dev (enable_dev, enable_dev_count, root, edev))
+ edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED;
+
+- if (is_forced_dev (disable_dev, root, edev))
++ if (is_forced_dev (disable_dev, disable_dev_count, root, edev))
+ edev->state = EISA_CONFIG_FORCED;
+
+ return 0;
+@@ -418,20 +417,13 @@ static int __init eisa_init (void)
+ return 0;
+ }
+
+-/* Couldn't use intarray with checking on... :-( */
+-#undef param_check_intarray
+-#define param_check_intarray(name, p)
+-
+-module_param(enable_dev, intarray, 0444);
+-module_param(disable_dev, intarray, 0444);
++module_param_array(enable_dev, int, enable_dev_count, 0444);
++module_param_array(disable_dev, int, disable_dev_count, 0444);
+
+ postcore_initcall (eisa_init);
+
+-#ifndef CONFIG_EISA_ALWAYS
+-int EISA_bus;
+-EXPORT_SYMBOL(EISA_bus);
+-#endif
+-
++int EISA_bus; /* for legacy drivers */
++EXPORT_SYMBOL (EISA_bus);
+ EXPORT_SYMBOL (eisa_bus_type);
+ EXPORT_SYMBOL (eisa_driver_register);
+ EXPORT_SYMBOL (eisa_driver_unregister);
+--- linux-2.6.0-test6/drivers/i2c/busses/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/i2c/busses/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -285,7 +285,7 @@ config I2C_VELLEMAN
+ will be called i2c-velleman.
+
+ config I2C_VIA
+- tristate "VIA 82C58B"
++ tristate "VIA 82C586B"
+ depends on I2C_ALGOBIT && PCI && EXPERIMENTAL
+ help
+
+--- linux-2.6.0-test6/drivers/i2c/i2c-sensor.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/i2c/i2c-sensor.c 2003-10-05 00:33:24.000000000 -0700
+@@ -133,7 +133,7 @@ int i2c_detect(struct i2c_adapter *adapt
+ i += 2) {
+ if (((adapter_id == address_data->probe[i]) ||
+ ((address_data->
+- probe[i] == ANY_I2C_BUS) & !is_isa))
++ probe[i] == ANY_I2C_BUS) && !is_isa))
+ && (addr == address_data->probe[i + 1])) {
+ dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
+ found = 1;
+@@ -141,7 +141,7 @@ int i2c_detect(struct i2c_adapter *adapt
+ }
+ for (i = 0; !found && (address_data->probe_range[i] != I2C_CLIENT_END); i += 3) {
+ if ( ((adapter_id == address_data->probe_range[i]) ||
+- ((address_data->probe_range[i] == ANY_I2C_BUS) & !is_isa)) &&
++ ((address_data->probe_range[i] == ANY_I2C_BUS) && !is_isa)) &&
+ (addr >= address_data->probe_range[i + 1]) &&
+ (addr <= address_data->probe_range[i + 2])) {
+ found = 1;
+--- linux-2.6.0-test6/drivers/ide/ide.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/ide.c 2003-10-05 00:33:58.000000000 -0700
+@@ -457,7 +457,7 @@ void ide_probe_module (void)
+
+ EXPORT_SYMBOL(ide_probe_module);
+
+-static int ide_open (struct inode * inode, struct file * filp)
++static int ide_open (struct block_device *bdev, struct file * filp)
+ {
+ return -ENXIO;
+ }
+@@ -1800,27 +1800,26 @@ static int __init match_parm (char *s, c
+
+ #ifdef CONFIG_BLK_DEV_PDC4030
+ static int __initdata probe_pdc4030;
+-extern void init_pdc4030(void);
+ #endif
+ #ifdef CONFIG_BLK_DEV_ALI14XX
+ static int __initdata probe_ali14xx;
+-extern void init_ali14xx(void);
++extern int ali14xx_init(void);
+ #endif
+ #ifdef CONFIG_BLK_DEV_UMC8672
+ static int __initdata probe_umc8672;
+-extern void init_umc8672(void);
++extern int umc8672_init(void);
+ #endif
+ #ifdef CONFIG_BLK_DEV_DTC2278
+ static int __initdata probe_dtc2278;
+-extern void init_dtc2278(void);
++extern int dtc2278_init(void);
+ #endif
+ #ifdef CONFIG_BLK_DEV_HT6560B
+ static int __initdata probe_ht6560b;
+-extern void init_ht6560b(void);
++extern int ht6560b_init(void);
+ #endif
+ #ifdef CONFIG_BLK_DEV_QD65XX
+ static int __initdata probe_qd65xx;
+-extern void init_qd65xx(void);
++extern int qd65xx_init(void);
+ #endif
+
+ static int __initdata is_chipset_set[MAX_HWIFS];
+@@ -2238,8 +2237,9 @@ static void __init probe_for_hwifs (void
+ #endif /* CONFIG_BLK_DEV_CMD640 */
+ #ifdef CONFIG_BLK_DEV_PDC4030
+ {
+- extern int ide_probe_for_pdc4030(void);
+- (void) ide_probe_for_pdc4030();
++ extern int pdc4030_init(void);
++ if (probe_pdc4030)
++ (void)pdc4030_init();
+ }
+ #endif /* CONFIG_BLK_DEV_PDC4030 */
+ #ifdef CONFIG_BLK_DEV_IDE_PMAC
+@@ -2595,29 +2595,25 @@ int __init ide_init (void)
+
+ init_ide_data();
+
+-#ifdef CONFIG_BLK_DEV_PDC4030
+- if (probe_pdc4030)
+- init_pdc4030();
+-#endif
+ #ifdef CONFIG_BLK_DEV_ALI14XX
+ if (probe_ali14xx)
+- init_ali14xx();
++ (void)ali14xx_init();
+ #endif
+ #ifdef CONFIG_BLK_DEV_UMC8672
+ if (probe_umc8672)
+- init_umc8672();
++ (void)umc8672_init();
+ #endif
+ #ifdef CONFIG_BLK_DEV_DTC2278
+ if (probe_dtc2278)
+- init_dtc2278();
++ (void)dtc2278_init();
+ #endif
+ #ifdef CONFIG_BLK_DEV_HT6560B
+ if (probe_ht6560b)
+- init_ht6560b();
++ (void)ht6560b_init();
+ #endif
+ #ifdef CONFIG_BLK_DEV_QD65XX
+ if (probe_qd65xx)
+- init_qd65xx();
++ (void)qd65xx_init();
+ #endif
+
+ initializing = 1;
+--- linux-2.6.0-test6/drivers/ide/ide-cd.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/ide/ide-cd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -3331,39 +3331,38 @@ static ide_driver_t ide_cdrom_driver = {
+ .complete_power_step = ide_cdrom_complete_power_step,
+ };
+
+-static int idecd_open(struct inode * inode, struct file * file)
++static int idecd_open(struct block_device *bdev, struct file * file)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = bdev->bd_disk->private_data;
+ struct cdrom_info *info = drive->driver_data;
+ int rc = -ENOMEM;
+ drive->usage++;
+
+ if (!info->buffer)
+ info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
+- if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
++ if (!info->buffer || (rc = cdrom_open(&info->devinfo, bdev, file)))
+ drive->usage--;
+ return rc;
+ }
+
+-static int idecd_release(struct inode * inode, struct file * file)
++static int idecd_release(struct gendisk *disk)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = disk->private_data;
+ struct cdrom_info *info = drive->driver_data;
+
+- cdrom_release (&info->devinfo, file);
++ cdrom_release(&info->devinfo);
+ drive->usage--;
+ return 0;
+ }
+
+-static int idecd_ioctl (struct inode *inode, struct file *file,
++static int idecd_ioctl (struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+ if (err == -EINVAL) {
+ struct cdrom_info *info = drive->driver_data;
+- err = cdrom_ioctl(&info->devinfo, inode, cmd, arg);
++ err = cdrom_ioctl(&info->devinfo, bdev, cmd, arg);
+ }
+ return err;
+ }
+--- linux-2.6.0-test6/drivers/ide/ide-disk.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/ide-disk.c 2003-10-05 00:34:01.000000000 -0700
+@@ -1734,9 +1734,9 @@ static ide_driver_t idedisk_driver = {
+ .complete_power_step = idedisk_complete_power_step,
+ };
+
+-static int idedisk_open(struct inode *inode, struct file *filp)
++static int idedisk_open(struct block_device *bdev, struct file *filp)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = bdev->bd_disk->private_data;
+ drive->usage++;
+ if (drive->removable && drive->usage == 1) {
+ ide_task_t args;
+@@ -1744,7 +1744,7 @@ static int idedisk_open(struct inode *in
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
+ args.command_type = ide_cmd_type_parser(&args);
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ /*
+ * Ignore the return code from door_lock,
+ * since the open() has already succeeded,
+@@ -1782,9 +1782,9 @@ static int ide_cacheflush_p(ide_drive_t
+ return 0;
+ }
+
+-static int idedisk_release(struct inode *inode, struct file *filp)
++static int idedisk_release(struct gendisk *disk)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = disk->private_data;
+ if (drive->removable && drive->usage == 1) {
+ ide_task_t args;
+ memset(&args, 0, sizeof(ide_task_t));
+@@ -1798,10 +1798,9 @@ static int idedisk_release(struct inode
+ return 0;
+ }
+
+-static int idedisk_ioctl(struct inode *inode, struct file *file,
++static int idedisk_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ return generic_ide_ioctl(bdev, cmd, arg);
+ }
+
+--- linux-2.6.0-test6/drivers/ide/ide-floppy.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/ide-floppy.c 2003-10-05 00:34:01.000000000 -0700
+@@ -156,7 +156,6 @@ typedef struct idefloppy_packet_command_
+ int request_transfer; /* Bytes to transfer */
+ int actually_transferred; /* Bytes actually transferred */
+ int buffer_size; /* Size of our data buffer */
+- char *b_data; /* Pointer which runs on the buffers */
+ int b_count; /* Missing/Available data on the current buffer */
+ struct request *rq; /* The corresponding request */
+ u8 *buffer; /* Data buffer */
+@@ -515,9 +514,6 @@ typedef struct {
+ u8 reserved[4];
+ } idefloppy_mode_parameter_header_t;
+
+-#define IDEFLOPPY_MIN(a,b) ((a)<(b) ? (a):(b))
+-#define IDEFLOPPY_MAX(a,b) ((a)>(b) ? (a):(b))
+-
+ /*
+ * Too bad. The drive wants to send us data which we are not ready to accept.
+ * Just throw it away.
+@@ -575,59 +571,68 @@ static int idefloppy_do_end_request(ide_
+ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
+ {
+ struct request *rq = pc->rq;
+- struct bio *bio = rq->bio;
+- int count;
++ struct bio_vec *bvec;
++ struct bio *bio;
++ unsigned long flags;
++ char *data;
++ int count, i, done = 0;
++
++ rq_for_each_bio(bio, rq) {
++ bio_for_each_segment(bvec, bio, i) {
++ if (!bcount)
++ break;
++
++ count = min(bvec->bv_len, bcount);
++
++ data = bvec_kmap_irq(bvec, &flags);
++ atapi_input_bytes(drive, data, count);
++ bvec_kunmap_irq(data, &flags);
+
+- while (bcount) {
+- if (pc->b_count == bio->bi_size) {
+- rq->sector += rq->current_nr_sectors;
+- rq->nr_sectors -= rq->current_nr_sectors;
+- idefloppy_do_end_request(drive, 1, 0);
+- if ((bio = rq->bio) != NULL)
+- pc->b_count = 0;
+- }
+- if (bio == NULL) {
+- printk(KERN_ERR "%s: bio == NULL in "
+- "idefloppy_input_buffers, bcount == %d\n",
+- drive->name, bcount);
+- idefloppy_discard_data(drive, bcount);
+- return;
+- }
+- count = IDEFLOPPY_MIN(bio->bi_size - pc->b_count, bcount);
+- atapi_input_bytes(drive, bio_data(bio) + pc->b_count, count);
+- bcount -= count;
+- pc->b_count += count;
++ bcount -= count;
++ pc->b_count += count;
++ done += count;
++ }
++ }
++
++ idefloppy_do_end_request(drive, 1, done >> 9);
++
++ if (bcount) {
++ printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
++ idefloppy_discard_data(drive, bcount);
+ }
+ }
+
+ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
+ {
+ struct request *rq = pc->rq;
+- struct bio *bio = rq->bio;
+- int count;
+-
+- while (bcount) {
+- if (!pc->b_count) {
+- rq->sector += rq->current_nr_sectors;
+- rq->nr_sectors -= rq->current_nr_sectors;
+- idefloppy_do_end_request(drive, 1, 0);
+- if ((bio = rq->bio) != NULL) {
+- pc->b_data = bio_data(bio);
+- pc->b_count = bio->bi_size;
+- }
++ struct bio *bio;
++ struct bio_vec *bvec;
++ unsigned long flags;
++ int count, i, done = 0;
++ char *data;
++
++ rq_for_each_bio(bio, rq) {
++ bio_for_each_segment(bvec, bio, i) {
++ if (!bcount)
++ break;
++
++ count = min(bvec->bv_len, bcount);
++
++ data = bvec_kmap_irq(bvec, &flags);
++ atapi_output_bytes(drive, data, count);
++ bvec_kunmap_irq(data, &flags);
++
++ bcount -= count;
++ pc->b_count += count;
++ done += count;
+ }
+- if (bio == NULL) {
+- printk(KERN_ERR "%s: bio == NULL in "
+- "idefloppy_output_buffers, bcount == %d\n",
+- drive->name, bcount);
+- idefloppy_write_zeros(drive, bcount);
+- return;
+- }
+- count = IDEFLOPPY_MIN(pc->b_count, bcount);
+- atapi_output_bytes(drive, pc->b_data, count);
+- bcount -= count;
+- pc->b_data += count;
+- pc->b_count -= count;
++ }
++
++ idefloppy_do_end_request(drive, 1, done >> 9);
++
++ if (bcount) {
++ printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
++ idefloppy_write_zeros(drive, bcount);
+ }
+ }
+
+@@ -732,8 +737,6 @@ static void idefloppy_init_pc (idefloppy
+ pc->request_transfer = 0;
+ pc->buffer = pc->pc_buffer;
+ pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE;
+- pc->b_data = NULL;
+-// pc->bio = NULL;
+ pc->callback = &idefloppy_pc_callback;
+ }
+
+@@ -1199,7 +1202,6 @@ static void idefloppy_create_rw_cmd (ide
+ put_unaligned(htonl(block), (unsigned int *) &pc->c[2]);
+ pc->callback = &idefloppy_rw_callback;
+ pc->rq = rq;
+- pc->b_data = rq->buffer;
+ pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ if (rq->flags & REQ_RW)
+ set_bit(PC_WRITING, &pc->flags);
+@@ -1864,9 +1866,9 @@ static ide_driver_t idefloppy_driver = {
+ .drives = LIST_HEAD_INIT(idefloppy_driver.drives),
+ };
+
+-static int idefloppy_open(struct inode *inode, struct file *filp)
++static int idefloppy_open(struct block_device *bdev, struct file *filp)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = bdev->bd_disk->private_data;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ idefloppy_pc_t pc;
+
+@@ -1906,7 +1908,7 @@ static int idefloppy_open(struct inode *
+ idefloppy_create_prevent_cmd(&pc, 1);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+ } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
+ drive->usage--;
+ return -EBUSY;
+@@ -1914,9 +1916,9 @@ static int idefloppy_open(struct inode *
+ return 0;
+ }
+
+-static int idefloppy_release(struct inode *inode, struct file *filp)
++static int idefloppy_release(struct gendisk *disk)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = disk->private_data;
+ idefloppy_pc_t pc;
+
+ debug_log(KERN_INFO "Reached idefloppy_release\n");
+@@ -1936,10 +1938,9 @@ static int idefloppy_release(struct inod
+ return 0;
+ }
+
+-static int idefloppy_ioctl(struct inode *inode, struct file *file,
++static int idefloppy_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+--- linux-2.6.0-test6/drivers/ide/ide-proc.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/drivers/ide/ide-proc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -522,7 +522,8 @@ int proc_ide_write_settings
+ if (*p != ':')
+ goto parse_error;
+ len = IDE_MIN(p - start, MAX_LEN);
+- strlcpy(name, start, IDE_MIN(len, MAX_LEN));
++ strncpy(name, start, IDE_MIN(len, MAX_LEN));
++ name[len] = 0;
+
+ if (n > 0) {
+ --n;
+--- linux-2.6.0-test6/drivers/ide/ide-tape.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/ide-tape.c 2003-10-05 00:34:01.000000000 -0700
+@@ -6338,24 +6338,23 @@ static struct file_operations idetape_fo
+ .release = idetape_chrdev_release,
+ };
+
+-static int idetape_open(struct inode *inode, struct file *filp)
++static int idetape_open(struct block_device *bdev, struct file *filp)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = bdev->bd_disk->private_data;
+ drive->usage++;
+ return 0;
+ }
+
+-static int idetape_release(struct inode *inode, struct file *filp)
++static int idetape_release(struct gendisk *disk)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = disk->private_data;
+ drive->usage--;
+ return 0;
+ }
+
+-static int idetape_ioctl(struct inode *inode, struct file *file,
++static int idetape_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+ if (err == -EINVAL)
+--- linux-2.6.0-test6/drivers/ide/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/ide/Kconfig 2003-10-05 00:36:28.000000000 -0700
+@@ -740,6 +740,13 @@ config BLK_DEV_SVWKS
+ This driver adds PIO/(U)DMA support for the ServerWorks OSB4/CSB5
+ chipsets.
+
++config BLK_DEV_SGIIOC4
++ tristate "Silicon Graphics IOC4 chipset support"
++ help
++ This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
++ chipset. Please say Y here, if you have an Altix System from
++ Silicon Graphics Inc.
++
+ config BLK_DEV_SIIMAGE
+ tristate "Silicon Image chipset support"
+ help
+--- linux-2.6.0-test6/drivers/ide/legacy/ali14xx.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/ali14xx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -198,22 +198,12 @@ static int __init initRegisters (void) {
+ return t;
+ }
+
+-int __init probe_ali14xx (void)
++static int __init ali14xx_probe(void)
+ {
+- /* auto-detect IDE controller port */
+- if (!findPort()) {
+- printk(KERN_ERR "ali14xx: not found.\n");
+- return 1;
+- }
++ ide_hwif_t *hwif, *mate;
+
+- printk(KERN_DEBUG "ali14xx: base= 0x%03x, regOn = 0x%02x.\n", basePort, regOn);
+- ide_hwifs[0].chipset = ide_ali14xx;
+- ide_hwifs[1].chipset = ide_ali14xx;
+- ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
+- ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
+- ide_hwifs[0].mate = &ide_hwifs[1];
+- ide_hwifs[1].mate = &ide_hwifs[0];
+- ide_hwifs[1].channel = 1;
++ printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
++ basePort, regOn);
+
+ /* initialize controller registers */
+ if (!initRegisters()) {
+@@ -221,74 +211,59 @@ int __init probe_ali14xx (void)
+ return 1;
+ }
+
+- probe_hwif_init(&ide_hwifs[0]);
+- probe_hwif_init(&ide_hwifs[1]);
++ hwif = &ide_hwifs[0];
++ mate = &ide_hwifs[1];
+
+- return 0;
+-}
++ hwif->chipset = ide_ali14xx;
++ hwif->tuneproc = &ali14xx_tune_drive;
++ hwif->mate = mate;
++
++ mate->chipset = ide_ali14xx;
++ mate->tuneproc = &ali14xx_tune_drive;
++ mate->mate = hwif;
++ mate->channel = 1;
+
+-static void ali14xx_release (void)
+-{
+- if (ide_hwifs[0].chipset != ide_ali14xx &&
+- ide_hwifs[1].chipset != ide_ali14xx)
+- return;
++ probe_hwif_init(hwif);
++ probe_hwif_init(mate);
+
+- ide_hwifs[0].chipset = ide_unknown;
+- ide_hwifs[1].chipset = ide_unknown;
+- ide_hwifs[0].tuneproc = NULL;
+- ide_hwifs[1].tuneproc = NULL;
+- ide_hwifs[0].mate = NULL;
+- ide_hwifs[1].mate = NULL;
++ return 0;
+ }
+
+-#ifndef MODULE
+-/*
+- * init_ali14xx:
+- *
+- * called by ide.c when parsing command line
+- */
+-
+-void __init init_ali14xx (void)
++/* Can be called directly from ide.c. */
++int __init ali14xx_init(void)
+ {
+ /* auto-detect IDE controller port */
+- if (findPort())
+- if (probe_ali14xx())
+- goto no_detect;
+- return;
+-
+-no_detect:
++ if (findPort()) {
++ if (ali14xx_probe())
++ return -ENODEV;
++ return 0;
++ }
+ printk(KERN_ERR "ali14xx: not found.\n");
+- ali14xx_release();
++ return -ENODEV;
+ }
+
+-#else
+-
+-MODULE_AUTHOR("see local file");
+-MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
+-MODULE_LICENSE("GPL");
+-
+-static int __init ali14xx_mod_init(void)
++#ifdef MODULE
++static void __exit ali14xx_release_hwif(ide_hwif_t *hwif)
+ {
+- /* auto-detect IDE controller port */
+- if (findPort())
+- if (probe_ali14xx()) {
+- ali14xx_release();
+- return -ENODEV;
+- }
++ if (hwif->chipset != ide_ali14xx)
++ return;
+
+- if (ide_hwifs[0].chipset != ide_ali14xx &&
+- ide_hwifs[1].chipset != ide_ali14xx) {
+- ali14xx_release();
+- return -ENODEV;
+- }
+- return 0;
++ hwif->chipset = ide_unknown;
++ hwif->tuneproc = NULL;
++ hwif->mate = NULL;
++ hwif->channel = 0;
+ }
+-module_init(ali14xx_mod_init);
+
+-static void __exit ali14xx_mod_exit(void)
++static void __exit ali14xx_exit(void)
+ {
+- ali14xx_release();
++ ali14xx_release_hwif(&ide_hwifs[0]);
++ ali14xx_release_hwif(&ide_hwifs[1]);
+ }
+-module_exit(ali14xx_mod_exit);
++
++module_init(ali14xx_init);
++module_exit(ali14xx_exit);
+ #endif
+
++MODULE_AUTHOR("see local file");
++MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/legacy/dtc2278.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/dtc2278.c 2003-10-05 00:33:24.000000000 -0700
+@@ -95,9 +95,16 @@ static void tune_dtc2278 (ide_drive_t *d
+ HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
+ }
+
+-void __init probe_dtc2278 (void)
++static int __init probe_dtc2278(void)
+ {
+ unsigned long flags;
++ ide_hwif_t *hwif, *mate;
++
++ hwif = &ide_hwifs[0];
++ mate = &ide_hwifs[1];
++
++ if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
++ return 1;
+
+ local_irq_save(flags);
+ /*
+@@ -117,76 +124,60 @@ void __init probe_dtc2278 (void)
+ #endif
+ local_irq_restore(flags);
+
+- ide_hwifs[0].serialized = 1;
+- ide_hwifs[1].serialized = 1;
+- ide_hwifs[0].chipset = ide_dtc2278;
+- ide_hwifs[1].chipset = ide_dtc2278;
+- ide_hwifs[0].tuneproc = &tune_dtc2278;
+- ide_hwifs[0].drives[0].no_unmask = 1;
+- ide_hwifs[0].drives[1].no_unmask = 1;
+- ide_hwifs[1].drives[0].no_unmask = 1;
+- ide_hwifs[1].drives[1].no_unmask = 1;
+- ide_hwifs[0].mate = &ide_hwifs[1];
+- ide_hwifs[1].mate = &ide_hwifs[0];
+- ide_hwifs[1].channel = 1;
++ hwif->serialized = 1;
++ hwif->chipset = ide_dtc2278;
++ hwif->tuneproc = &tune_dtc2278;
++ hwif->drives[0].no_unmask = 1;
++ hwif->drives[1].no_unmask = 1;
++ hwif->mate = mate;
++
++ mate->serialized = 1;
++ mate->chipset = ide_dtc2278;
++ mate->drives[0].no_unmask = 1;
++ mate->drives[1].no_unmask = 1;
++ mate->mate = hwif;
++ mate->channel = 1;
++
++ probe_hwif_init(hwif);
++ probe_hwif_init(mate);
+
+- probe_hwif_init(&ide_hwifs[0]);
+- probe_hwif_init(&ide_hwifs[1]);
++ return 0;
+ }
+
+-static void dtc2278_release (void)
++/* Can be called directly from ide.c. */
++int __init dtc2278_init(void)
+ {
+- if (ide_hwifs[0].chipset != ide_dtc2278 &&
+- ide_hwifs[1].chipset != ide_dtc2278)
++ if (probe_dtc2278()) {
++ printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
++ return -EBUSY;
++ }
++ return 0;
++}
++
++#ifdef MODULE
++static void __exit dtc2278_release_hwif(ide_hwif_t *hwif)
++{
++ if (hwif->chipset != ide_dtc2278)
+ return;
+
+- ide_hwifs[0].serialized = 0;
+- ide_hwifs[1].serialized = 0;
+- ide_hwifs[0].chipset = ide_unknown;
+- ide_hwifs[1].chipset = ide_unknown;
+- ide_hwifs[0].tuneproc = NULL;
+- ide_hwifs[0].drives[0].no_unmask = 0;
+- ide_hwifs[0].drives[1].no_unmask = 0;
+- ide_hwifs[1].drives[0].no_unmask = 0;
+- ide_hwifs[1].drives[1].no_unmask = 0;
+- ide_hwifs[0].mate = NULL;
+- ide_hwifs[1].mate = NULL;
++ hwif->serialized = 0;
++ hwif->chipset = ide_unknown;
++ hwif->tuneproc = NULL;
++ hwif->drives[0].no_unmask = 0;
++ hwif->drives[1].no_unmask = 0;
++ hwif->mate = NULL;
+ }
+
+-#ifndef MODULE
+-/*
+- * init_dtc2278:
+- *
+- * called by ide.c when parsing command line
+- */
+-
+-void __init init_dtc2278 (void)
++static void __exit dtc2278_exit(void)
+ {
+- probe_dtc2278();
++ dtc2278_release_hwif(&ide_hwifs[0]);
++ dtc2278_release_hwif(&ide_hwifs[1]);
+ }
+
+-#else
++module_init(dtc2278_init);
++module_exit(dtc2278_exit);
++#endif
+
+ MODULE_AUTHOR("See Local File");
+ MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
+ MODULE_LICENSE("GPL");
+-
+-static int __init dtc2278_mod_init(void)
+-{
+- probe_dtc2278();
+- if (ide_hwifs[0].chipset != ide_dtc2278 &&
+- ide_hwifs[1].chipset != ide_dtc2278) {
+- dtc2278_release();
+- return -ENODEV;
+- }
+- return 0;
+-}
+-module_init(dtc2278_mod_init);
+-
+-static void __exit dtc2278_mod_exit(void)
+-{
+- dtc2278_release();
+-}
+-module_exit(dtc2278_mod_exit);
+-#endif
+-
+--- linux-2.6.0-test6/drivers/ide/legacy/hd98.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/ide/legacy/hd98.c 2003-10-05 00:33:54.000000000 -0700
+@@ -652,10 +652,10 @@ static void do_hd_request (request_queue
+ enable_irq(HD_IRQ);
+ }
+
+-static int hd_ioctl(struct inode * inode, struct file * file,
++static int hd_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
++ struct hd_i_struct *disk = bdev->bd_disk->private_data;
+ struct hd_geometry *loc = (struct hd_geometry *) arg;
+ struct hd_geometry g;
+
+@@ -666,7 +666,7 @@ static int hd_ioctl(struct inode * inode
+ g.heads = disk->head;
+ g.sectors = disk->sect;
+ g.cylinders = disk->cyl;
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ }
+
+--- linux-2.6.0-test6/drivers/ide/legacy/hd.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/ide/legacy/hd.c 2003-10-05 00:33:54.000000000 -0700
+@@ -656,10 +656,10 @@ static void do_hd_request (request_queue
+ enable_irq(HD_IRQ);
+ }
+
+-static int hd_ioctl(struct inode * inode, struct file * file,
++static int hd_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
++ struct hd_i_struct *disk = bdev->bd_disk->private_data;
+ struct hd_geometry *loc = (struct hd_geometry *) arg;
+ struct hd_geometry g;
+
+@@ -670,7 +670,7 @@ static int hd_ioctl(struct inode * inode
+ g.heads = disk->head;
+ g.sectors = disk->sect;
+ g.cylinders = disk->cyl;
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ }
+
+--- linux-2.6.0-test6/drivers/ide/legacy/ht6560b.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/ht6560b.c 2003-10-05 00:33:24.000000000 -0700
+@@ -304,35 +304,16 @@ static void tune_ht6560b (ide_drive_t *d
+ #endif
+ }
+
+-void ht6560b_release (void)
+-{
+- if (ide_hwifs[0].chipset != ide_ht6560b &&
+- ide_hwifs[1].chipset != ide_ht6560b)
+- return;
+-
+- ide_hwifs[0].chipset = ide_unknown;
+- ide_hwifs[1].chipset = ide_unknown;
+- ide_hwifs[0].tuneproc = NULL;
+- ide_hwifs[1].tuneproc = NULL;
+- ide_hwifs[0].selectproc = NULL;
+- ide_hwifs[1].selectproc = NULL;
+- ide_hwifs[0].serialized = 0;
+- ide_hwifs[1].serialized = 0;
+- ide_hwifs[0].mate = NULL;
+- ide_hwifs[1].mate = NULL;
+-
+- ide_hwifs[0].drives[0].drive_data = 0;
+- ide_hwifs[0].drives[1].drive_data = 0;
+- ide_hwifs[1].drives[0].drive_data = 0;
+- ide_hwifs[1].drives[1].drive_data = 0;
+- release_region(HT_CONFIG_PORT, 1);
+-}
+-
+-static int __init ht6560b_mod_init(void)
++/* Can be called directly from ide.c. */
++int __init ht6560b_init(void)
+ {
++ ide_hwif_t *hwif, *mate;
+ int t;
+
+- if (!request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name)) {
++ hwif = &ide_hwifs[0];
++ mate = &ide_hwifs[1];
++
++ if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
+ printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
+ __FUNCTION__);
+ return -ENODEV;
+@@ -343,39 +324,33 @@ static int __init ht6560b_mod_init(void)
+ goto release_region;
+ }
+
+- ide_hwifs[0].chipset = ide_ht6560b;
+- ide_hwifs[1].chipset = ide_ht6560b;
+- ide_hwifs[0].selectproc = &ht6560b_selectproc;
+- ide_hwifs[1].selectproc = &ht6560b_selectproc;
+- ide_hwifs[0].tuneproc = &tune_ht6560b;
+- ide_hwifs[1].tuneproc = &tune_ht6560b;
+- ide_hwifs[0].serialized = 1; /* is this needed? */
+- ide_hwifs[1].serialized = 1; /* is this needed? */
+- ide_hwifs[0].mate = &ide_hwifs[1];
+- ide_hwifs[1].mate = &ide_hwifs[0];
+- ide_hwifs[1].channel = 1;
++ hwif->chipset = ide_ht6560b;
++ hwif->selectproc = &ht6560b_selectproc;
++ hwif->tuneproc = &tune_ht6560b;
++ hwif->serialized = 1; /* is this needed? */
++ hwif->mate = mate;
++
++ mate->chipset = ide_ht6560b;
++ mate->selectproc = &ht6560b_selectproc;
++ mate->tuneproc = &tune_ht6560b;
++ mate->serialized = 1; /* is this needed? */
++ mate->mate = hwif;
++ mate->channel = 1;
+
+ /*
+ * Setting default configurations for drives
+ */
+ t = (HT_CONFIG_DEFAULT << 8);
+ t |= HT_TIMING_DEFAULT;
+- ide_hwifs[0].drives[0].drive_data = t;
+- ide_hwifs[0].drives[1].drive_data = t;
+- t |= (HT_SECONDARY_IF << 8);
+- ide_hwifs[1].drives[0].drive_data = t;
+- ide_hwifs[1].drives[1].drive_data = t;
++ hwif->drives[0].drive_data = t;
++ hwif->drives[1].drive_data = t;
+
+- probe_hwif_init(&ide_hwifs[0]);
+- probe_hwif_init(&ide_hwifs[1]);
++ t |= (HT_SECONDARY_IF << 8);
++ mate->drives[0].drive_data = t;
++ mate->drives[1].drive_data = t;
+
+-#ifdef MODULE
+- if (ide_hwifs[0].chipset != ide_ht6560b &&
+- ide_hwifs[1].chipset != ide_ht6560b) {
+- ht6560b_release();
+- return -ENODEV;
+- }
+-#endif
++ probe_hwif_init(hwif);
++ probe_hwif_init(mate);
+
+ return 0;
+
+@@ -384,24 +359,34 @@ release_region:
+ return -ENODEV;
+ }
+
+-MODULE_AUTHOR("See Local File");
+-MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
+-MODULE_LICENSE("GPL");
+-
+ #ifdef MODULE
+-static void __exit ht6560b_mod_exit(void)
++static void __exit ht6560b_release_hwif(ide_hwif_t *hwif)
+ {
+- ht6560b_release();
++ if (hwif->chipset != ide_ht6560b)
++ return;
++
++ hwif->chipset = ide_unknown;
++ hwif->tuneproc = NULL;
++ hwif->selectproc = NULL;
++ hwif->serialized = 0;
++ hwif->mate = NULL;
++ hwif->channel = 0;
++
++ hwif->drives[0].drive_data = 0;
++ hwif->drives[1].drive_data = 0;
+ }
+
+-module_init(ht6560b_mod_init);
+-module_exit(ht6560b_mod_exit);
+-#else
+-/*
+- * called by ide.c when parsing command line
+- */
+-void __init init_ht6560b (void)
++static void __exit ht6560b_exit(void)
+ {
+- ht6560b_mod_init(); /* ignore return value */
++ ht6560b_release_hwif(&ide_hwifs[0]);
++ ht6560b_release_hwif(&ide_hwifs[1]);
++ release_region(HT_CONFIG_PORT, 1);
+ }
++
++module_init(ht6560b_init);
++module_exit(ht6560b_exit);
+ #endif
++
++MODULE_AUTHOR("See Local File");
++MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/legacy/pdc4030.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/pdc4030.c 2003-10-05 00:33:24.000000000 -0700
+@@ -147,8 +147,6 @@ int pdc4030_identify(ide_drive_t *drive)
+ return pdc4030_cmd(drive, PROMISE_IDENTIFY);
+ }
+
+-int enable_promise_support;
+-
+ /*
+ * setup_pdc4030()
+ * Completes the setup of a Promise DC4030 controller card, once found.
+@@ -296,33 +294,24 @@ int __init detect_pdc4030(ide_hwif_t *hw
+ }
+ }
+
+-
+-int __init ide_probe_for_pdc4030(void)
++int __init pdc4030_init(void)
+ {
+ unsigned int index;
+ ide_hwif_t *hwif;
+
+-#ifndef MODULE
+- if (enable_promise_support == 0)
+- return;
+-#endif
+-
+ for (index = 0; index < MAX_HWIFS; index++) {
+ hwif = &ide_hwifs[index];
+ if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) {
+-#ifndef MODULE
+- setup_pdc4030(hwif);
+-#else
+- return setup_pdc4030(hwif);
+-#endif
++ if (!setup_pdc4030(hwif))
++ return -ENODEV;
++ return 0;
+ }
+ }
+-#ifdef MODULE
+- return 0;
+-#endif
++ return -ENODEV;
+ }
+
+-static void __exit release_pdc4030(ide_hwif_t *hwif, ide_hwif_t *mate)
++#ifdef MODULE
++static void __exit pdc4030_release_hwif(ide_hwif_t *hwif)
+ {
+ hwif->chipset = ide_unknown;
+ hwif->selectproc = NULL;
+@@ -333,72 +322,24 @@ static void __exit release_pdc4030(ide_h
+ hwif->drives[1].keep_settings = 0;
+ hwif->drives[0].noprobe = 0;
+ hwif->drives[1].noprobe = 0;
+-
+- if (mate != NULL) {
+- mate->chipset = ide_unknown;
+- mate->selectproc = NULL;
+- mate->serialized = 0;
+- mate->drives[0].io_32bit = 0;
+- mate->drives[1].io_32bit = 0;
+- mate->drives[0].keep_settings = 0;
+- mate->drives[1].keep_settings = 0;
+- mate->drives[0].noprobe = 0;
+- mate->drives[1].noprobe = 0;
+- }
+ }
+
+-#ifndef MODULE
+-/*
+- * init_pdc4030:
+- *
+- * called by ide.c when parsing command line
+- */
+-
+-void __init init_pdc4030(void)
++static void __exit pdc4030_exit(void)
+ {
+- enable_promise_support = 1;
++ unsigned int index;
++
++ for (index = 0; index < MAX_HWIFS; index++)
++ pdc4030_release_hwif(&ide_hwifs[index]);
+ }
+
+-#else
++module_init(pdc4030_init);
++module_exit(pdc4030_exit);
++#endif
+
+ MODULE_AUTHOR("Peter Denison");
+ MODULE_DESCRIPTION("Support of Promise 4030 VLB series IDE chipsets");
+ MODULE_LICENSE("GPL");
+
+-static int __init pdc4030_mod_init(void)
+-{
+- if (enable_promise_support == 0)
+- enable_promise_support = 1;
+-
+- if (!ide_probe_for_pdc4030())
+- return -ENODEV;
+- return 0;
+-}
+-module_init(pdc4030_mod_init);
+-
+-static void __exit pdc4030_mod_exit(void)
+-{
+- unsigned int index;
+- ide_hwif_t *hwif;
+-
+- if (enable_promise_support == 0)
+- return;
+-
+- for (index = 0; index < MAX_HWIFS; index++) {
+- hwif = &ide_hwifs[index];
+- if (hwif->chipset == ide_pdc4030) {
+- ide_hwif_t *mate = &ide_hwifs[hwif->index+1];
+- if (mate->chipset == ide_pdc4030)
+- release_pdc4030(hwif, mate);
+- else
+- release_pdc4030(hwif, NULL);
+- }
+- }
+- enable_promise_support = 0;
+-}
+-module_exit(pdc4030_mod_exit);
+-#endif
+-
+ /*
+ * promise_read_intr() is the handler for disk read/multread interrupts
+ */
+--- linux-2.6.0-test6/drivers/ide/legacy/qd65xx.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/qd65xx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -338,12 +338,12 @@ static int __init qd_testreg(int port)
+ * called to setup an ata channel : adjusts attributes & links for tuning
+ */
+
+-void __init qd_setup (int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (ide_drive_t *, u8 pio))
++static void __init qd_setup(ide_hwif_t *hwif, int base, int config,
++ unsigned int data0, unsigned int data1,
++ void (*tuneproc) (ide_drive_t *, u8 pio))
+ {
+- ide_hwif_t *hwif = &ide_hwifs[unit];
+-
+ hwif->chipset = ide_qd65xx;
+- hwif->channel = unit;
++ hwif->channel = hwif->index;
+ hwif->select_data = base;
+ hwif->config_data = config;
+ hwif->drives[0].drive_data = data0;
+@@ -354,19 +354,20 @@ void __init qd_setup (int unit, int base
+ probe_hwif_init(hwif);
+ }
+
++#ifdef MODULE
+ /*
+ * qd_unsetup:
+ *
+ * called to unsetup an ata channel : back to default values, unlinks tuning
+ */
+-static void __exit qd_unsetup (int unit)
++static void __exit qd_unsetup(ide_hwif_t *hwif)
+ {
+- ide_hwif_t *hwif = &ide_hwifs[unit];
+ u8 config = hwif->config_data;
+ int base = hwif->select_data;
+ void *tuneproc = (void *) hwif->tuneproc;
+
+- if (!(hwif->chipset == ide_qd65xx)) return;
++ if (hwif->chipset != ide_qd65xx)
++ return;
+
+ printk(KERN_NOTICE "%s: back to defaults\n", hwif->name);
+
+@@ -381,13 +382,14 @@ static void __exit qd_unsetup (int unit)
+ qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
+ } else {
+- qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
++ qd_write_reg(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+ }
+ } else {
+ printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
+ printk(KERN_WARNING "keeping settings !\n");
+ }
+ }
++#endif
+
+ /*
+ * qd_probe:
+@@ -396,8 +398,9 @@ static void __exit qd_unsetup (int unit)
+ * return 1 if another qd may be probed
+ */
+
+-int __init qd_probe (int base)
++static int __init qd_probe(int base)
+ {
++ ide_hwif_t *hwif;
+ u8 config;
+ u8 unit;
+
+@@ -414,9 +417,8 @@ int __init qd_probe (int base)
+
+ /* qd6500 found */
+
+- printk(KERN_NOTICE "%s: qd6500 at %#x\n",
+- ide_hwifs[unit].name, base);
+-
++ hwif = &ide_hwifs[unit];
++ printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
+ printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
+ config, QD_ID3);
+
+@@ -425,8 +427,8 @@ int __init qd_probe (int base)
+ return 1;
+ }
+
+- qd_setup(unit, base, config, QD6500_DEF_DATA,
+- QD6500_DEF_DATA, &qd6500_tune_drive);
++ qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA,
++ &qd6500_tune_drive);
+ return 1;
+ }
+
+@@ -448,25 +450,31 @@ int __init qd_probe (int base)
+
+ if (control & QD_CONTR_SEC_DISABLED) {
+ /* secondary disabled */
++
++ hwif = &ide_hwifs[unit];
+ printk(KERN_INFO "%s: qd6580: single IDE board\n",
+- ide_hwifs[unit].name);
+- qd_setup(unit, base, config | (control << 8),
+- QD6580_DEF_DATA, QD6580_DEF_DATA2,
+- &qd6580_tune_drive);
++ hwif->name);
++ qd_setup(hwif, base, config | (control << 8),
++ QD6580_DEF_DATA, QD6580_DEF_DATA2,
++ &qd6580_tune_drive);
+ qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
+
+ return 1;
+ } else {
++ ide_hwif_t *mate;
++
++ hwif = &ide_hwifs[0];
++ mate = &ide_hwifs[1];
+ /* secondary enabled */
+ printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
+- ide_hwifs[0].name,ide_hwifs[1].name);
++ hwif->name, mate->name);
+
+- qd_setup(0, base, config | (control << 8),
+- QD6580_DEF_DATA, QD6580_DEF_DATA,
+- &qd6580_tune_drive);
+- qd_setup(1, base, config | (control << 8),
+- QD6580_DEF_DATA2, QD6580_DEF_DATA2,
+- &qd6580_tune_drive);
++ qd_setup(hwif, base, config | (control << 8),
++ QD6580_DEF_DATA, QD6580_DEF_DATA,
++ &qd6580_tune_drive);
++ qd_setup(mate, base, config | (control << 8),
++ QD6580_DEF_DATA2, QD6580_DEF_DATA2,
++ &qd6580_tune_drive);
+ qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
+
+ return 0; /* no other qd65xx possible */
+@@ -476,38 +484,28 @@ int __init qd_probe (int base)
+ return 1;
+ }
+
+-#ifndef MODULE
+-/*
+- * init_qd65xx:
+- *
+- * called by ide.c when parsing command line
+- */
+-
+-void __init init_qd65xx (void)
+-{
+- if (qd_probe(0x30)) qd_probe(0xb0);
+-}
+-
+-#else
+-
+-MODULE_AUTHOR("Samuel Thibault");
+-MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
+-MODULE_LICENSE("GPL");
+-
+-static int __init qd65xx_mod_init(void)
++/* Can be called directly from ide.c. */
++int __init qd65xx_init(void)
+ {
+- if (qd_probe(0x30)) qd_probe(0xb0);
++ if (qd_probe(0x30))
++ qd_probe(0xb0);
+ if (ide_hwifs[0].chipset != ide_qd65xx &&
+ ide_hwifs[1].chipset != ide_qd65xx)
+ return -ENODEV;
+ return 0;
+ }
+-module_init(qd65xx_mod_init);
+
+-static void __exit qd65xx_mod_exit(void)
++#ifdef MODULE
++static void __exit qd65xx_exit(void)
+ {
+- qd_unsetup(0);
+- qd_unsetup(1);
++ qd_unsetup(&ide_hwifs[0]);
++ qd_unsetup(&ide_hwifs[1]);
+ }
+-module_exit(qd65xx_mod_exit);
++
++module_init(qd65xx_init);
++module_exit(qd65xx_exit);
+ #endif
++
++MODULE_AUTHOR("Samuel Thibault");
++MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/legacy/umc8672.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/legacy/umc8672.c 2003-10-05 00:33:24.000000000 -0700
+@@ -124,16 +124,16 @@ static void tune_umc (ide_drive_t *drive
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+
+-int __init probe_umc8672 (void)
++static int __init umc8672_probe(void)
+ {
+ unsigned long flags;
++ ide_hwif_t *hwif, *mate;
+
+- local_irq_save(flags);
+ if (!request_region(0x108, 2, "umc8672")) {
+- local_irq_restore(flags);
+ printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
+ return 1;
+ }
++ local_irq_save(flags);
+ outb_p(0x5A,0x108); /* enable umc */
+ if (in_umc (0xd5) != 0xa0) {
+ local_irq_restore(flags);
+@@ -146,82 +146,62 @@ int __init probe_umc8672 (void)
+ umc_set_speeds (current_speeds);
+ local_irq_restore(flags);
+
+- ide_hwifs[0].chipset = ide_umc8672;
+- ide_hwifs[1].chipset = ide_umc8672;
+- ide_hwifs[0].tuneproc = &tune_umc;
+- ide_hwifs[1].tuneproc = &tune_umc;
+- ide_hwifs[0].mate = &ide_hwifs[1];
+- ide_hwifs[1].mate = &ide_hwifs[0];
+- ide_hwifs[1].channel = 1;
++ hwif = &ide_hwifs[0];
++ mate = &ide_hwifs[1];
+
+- probe_hwif_init(&ide_hwifs[0]);
+- probe_hwif_init(&ide_hwifs[1]);
++ hwif->chipset = ide_umc8672;
++ hwif->tuneproc = &tune_umc;
++ hwif->mate = mate;
++
++ mate->chipset = ide_umc8672;
++ mate->tuneproc = &tune_umc;
++ mate->mate = hwif;
++ mate->channel = 1;
++
++ probe_hwif_init(hwif);
++ probe_hwif_init(mate);
+
+ return 0;
+ }
+
+-static void umc8672_release (void)
++/* Can be called directly from ide.c. */
++int __init umc8672_init(void)
+ {
+- unsigned long flags;
++ if (umc8672_probe())
++ return -ENODEV;
++ return 0;
++}
+
+- local_irq_save(flags);
+- if (ide_hwifs[0].chipset != ide_umc8672 &&
+- ide_hwifs[1].chipset != ide_umc8672) {
+- local_irq_restore(flags);
++#ifdef MODULE
++static void __exit umc8672_release_hwif(ide_hwif_t *hwif)
++{
++ if (hwif->chipset != ide_umc8672)
+ return;
+- }
+
+- ide_hwifs[0].chipset = ide_unknown;
+- ide_hwifs[1].chipset = ide_unknown;
+- ide_hwifs[0].tuneproc = NULL;
+- ide_hwifs[1].tuneproc = NULL;
+- ide_hwifs[0].mate = NULL;
+- ide_hwifs[1].mate = NULL;
+- ide_hwifs[0].channel = 0;
+- ide_hwifs[1].channel = 0;
+-
+- outb_p(0xa5,0x108); /* disable umc */
+-
+- release_region(0x108, 2);
+- local_irq_restore(flags);
++ hwif->chipset = ide_unknown;
++ hwif->tuneproc = NULL;
++ hwif->mate = NULL;
++ hwif->channel = 0;
+ }
+
+-#ifndef MODULE
+-/*
+- * init_umc8672:
+- *
+- * called by ide.c when parsing command line
+- */
+-
+-void __init init_umc8672 (void)
++static void __exit umc8672_exit(void)
+ {
+- if (probe_umc8672())
+- printk(KERN_ERR "init_umc8672: umc8672 controller not found.\n");
+-}
++ unsigned long flags;
+
+-#else
++ umc8672_release_hwif(&ide_hwifs[0]);
++ umc8672_release_hwif(&ide_hwifs[1]);
+
+-MODULE_AUTHOR("Wolfram Podien");
+-MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
+-MODULE_LICENSE("GPL");
++ local_irq_save(flags);
++ outb_p(0xa5, 0x108); /* disable umc */
++ local_irq_restore(flags);
+
+-static int __init umc8672_mod_init(void)
+-{
+- if (probe_umc8672())
+- return -ENODEV;
+- if (ide_hwifs[0].chipset != ide_umc8672 &&
+- ide_hwifs[1].chipset != ide_umc8672) {
+- umc8672_release();
+- return -ENODEV;
+- }
+- return 0;
++ release_region(0x108, 2);
+ }
+-module_init(umc8672_mod_init);
+
+-static void __exit umc8672_mod_exit(void)
+-{
+- umc8672_release();
+-}
+-module_exit(umc8672_mod_exit);
++module_init(umc8672_init);
++module_exit(umc8672_exit);
+ #endif
+
++MODULE_AUTHOR("Wolfram Podien");
++MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/pci/amd74xx.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/ide/pci/amd74xx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,5 +1,5 @@
+ /*
+- * Version 2.9
++ * Version 2.11
+ *
+ * AMD 755/756/766/8111 and nVidia nForce IDE driver for Linux.
+ *
+@@ -65,7 +65,6 @@ static struct amd_ide_chip {
+ };
+
+ static struct amd_ide_chip *amd_config;
+-static unsigned char amd_enabled;
+ static unsigned int amd_80w;
+ static unsigned int amd_clock;
+
+@@ -103,7 +102,7 @@ static int amd74xx_get_info(char *buffer
+
+ amd_print("----------AMD BusMastering IDE Configuration----------------");
+
+- amd_print("Driver Version: 2.9");
++ amd_print("Driver Version: 2.11");
+ amd_print("South Bridge: %s", pci_name(bmide_dev));
+
+ pci_read_config_byte(dev, PCI_REVISION_ID, &t);
+@@ -250,9 +249,6 @@ static int amd_set_drive(ide_drive_t *dr
+
+ static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
+ {
+- if (!((amd_enabled >> HWIF(drive)->channel) & 1))
+- return;
+-
+ if (pio == 255) {
+ amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ return;
+@@ -330,9 +326,6 @@ static unsigned int __init init_chipset_
+ break;
+ }
+
+- pci_read_config_dword(dev, AMD_IDE_ENABLE, &u);
+- amd_enabled = ((u & 1) ? 2 : 0) | ((u & 2) ? 1 : 0);
+-
+ /*
+ * Take care of prefetch & postwrite.
+ */
+@@ -408,8 +401,8 @@ static void __init init_hwif_amd74xx(ide
+ hwif->mwdma_mask = 0x07;
+ hwif->swdma_mask = 0x07;
+
+- if (!(hwif->udma_four))
+- hwif->udma_four = ((amd_enabled & amd_80w) >> hwif->channel) & 1;
++ if (!hwif->udma_four)
++ hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+ hwif->ide_dma_check = &amd74xx_ide_dma_check;
+ if (!noautodma)
+ hwif->autodma = 1;
+@@ -417,16 +410,6 @@ static void __init init_hwif_amd74xx(ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-/*
+- * We allow the BM-DMA driver only work on enabled interfaces.
+- */
+-
+-static void __init init_dma_amd74xx(ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- if ((amd_enabled >> hwif->channel) & 1)
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/amd74xx.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/ide/pci/amd74xx.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@ static ide_pci_host_proc_t amd74xx_procs
+
+ static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *);
+ static void init_hwif_amd74xx(ide_hwif_t *);
+-static void init_dma_amd74xx(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -35,9 +34,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_AMD_COBRA_7401,
+ .name = "AMD7401",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -48,9 +45,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_AMD_VIPER_7409,
+ .name = "AMD7409",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -61,9 +56,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_AMD_VIPER_7411,
+ .name = "AMD7411",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -74,9 +67,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_AMD_OPUS_7441,
+ .name = "AMD7441",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -87,9 +78,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_AMD_8111_IDE,
+ .name = "AMD8111",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .autodma = AUTODMA,
+ .channels = 2,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -101,9 +90,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,
+ .name = "NFORCE",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+@@ -115,9 +102,7 @@ static ide_pci_device_t amd74xx_chipsets
+ .device = PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,
+ .name = "NFORCE2",
+ .init_chipset = init_chipset_amd74xx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_amd74xx,
+- .init_dma = init_dma_amd74xx,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+--- linux-2.6.0-test6/drivers/ide/pci/cmd64x.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/cmd64x.c 2003-10-05 00:33:24.000000000 -0700
+@@ -742,11 +742,6 @@ static void __init init_hwif_cmd64x (ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/cmd64x.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/ide/pci/cmd64x.h 2003-10-05 00:33:24.000000000 -0700
+@@ -81,7 +81,6 @@ static ide_pci_host_proc_t cmd64x_procs[
+
+ static unsigned int init_chipset_cmd64x(struct pci_dev *, const char *);
+ static void init_hwif_cmd64x(ide_hwif_t *);
+-static void init_dma_cmd64x(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -91,7 +90,6 @@ static ide_pci_device_t cmd64x_chipsets[
+ .init_chipset = init_chipset_cmd64x,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cmd64x,
+- .init_dma = init_dma_cmd64x,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -104,7 +102,6 @@ static ide_pci_device_t cmd64x_chipsets[
+ .init_chipset = init_chipset_cmd64x,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cmd64x,
+- .init_dma = init_dma_cmd64x,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x51,0x80,0x80}},
+@@ -117,7 +114,6 @@ static ide_pci_device_t cmd64x_chipsets[
+ .init_chipset = init_chipset_cmd64x,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cmd64x,
+- .init_dma = init_dma_cmd64x,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -130,7 +126,6 @@ static ide_pci_device_t cmd64x_chipsets[
+ .init_chipset = init_chipset_cmd64x,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cmd64x,
+- .init_dma = init_dma_cmd64x,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/cs5530.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/cs5530.c 2003-10-05 00:33:24.000000000 -0700
+@@ -404,19 +404,6 @@ static void __init init_hwif_cs5530 (ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-/**
+- * init_dma_cs5530 - set up for DMA
+- * @hwif: interface
+- * @dmabase: DMA base address
+- *
+- * FIXME: this can go away
+- */
+-
+-static void __init init_dma_cs5530 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+--- linux-2.6.0-test6/drivers/ide/pci/cs5530.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/ide/pci/cs5530.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@ static ide_pci_host_proc_t cs5530_procs[
+
+ static unsigned int init_chipset_cs5530(struct pci_dev *, const char *);
+ static void init_hwif_cs5530(ide_hwif_t *);
+-static void init_dma_cs5530(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t cs5530_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -37,7 +36,6 @@ static ide_pci_device_t cs5530_chipsets[
+ .init_chipset = init_chipset_cs5530,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cs5530,
+- .init_dma = init_dma_cs5530,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/generic.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/generic.c 2003-10-05 00:33:24.000000000 -0700
+@@ -72,11 +72,6 @@ static void __init init_hwif_generic (id
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void init_dma_generic (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ #if 0
+--- linux-2.6.0-test6/drivers/ide/pci/generic.h 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/generic.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,7 +7,6 @@
+
+ static unsigned int init_chipset_generic(struct pci_dev *, const char *);
+ static void init_hwif_generic(ide_hwif_t *);
+-static void init_dma_generic(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t generic_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -17,7 +16,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}},
+@@ -30,7 +28,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -43,7 +40,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -56,7 +52,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = NODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -69,7 +64,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = NODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -82,7 +76,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = NODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -95,7 +88,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -108,7 +100,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -121,7 +112,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -134,7 +124,6 @@ static ide_pci_device_t generic_chipsets
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -157,7 +146,6 @@ static ide_pci_device_t unknown_chipset[
+ .init_chipset = init_chipset_generic,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_generic,
+- .init_dma = init_dma_generic,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/hpt34x.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/hpt34x.c 2003-10-05 00:33:24.000000000 -0700
+@@ -315,11 +315,6 @@ static void __init init_hwif_hpt34x (ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_hpt34x (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/hpt34x.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/drivers/ide/pci/hpt34x.h 2003-10-05 00:33:24.000000000 -0700
+@@ -33,7 +33,6 @@ static ide_pci_host_proc_t hpt34x_procs[
+
+ static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *);
+ static void init_hwif_hpt34x(ide_hwif_t *);
+-static void init_dma_hpt34x(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t hpt34x_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -43,7 +42,6 @@ static ide_pci_device_t hpt34x_chipsets[
+ .init_chipset = init_chipset_hpt34x,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_hpt34x,
+- .init_dma = init_dma_hpt34x,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/it8172.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/it8172.c 2003-10-05 00:33:24.000000000 -0700
+@@ -284,11 +284,6 @@ static void __init init_hwif_it8172 (ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_it8172 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/it8172.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/ide/pci/it8172.h 2003-10-05 00:33:24.000000000 -0700
+@@ -17,7 +17,6 @@ static int it8172_config_chipset_for_dma
+ static void init_setup_it8172(struct pci_dev *, ide_pci_device_t *);
+ static unsigned int init_chipset_it8172(struct pci_dev *, const char *);
+ static void init_hwif_it8172(ide_hwif_t *);
+-static void init_dma_it8172(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t it8172_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -28,7 +27,6 @@ static ide_pci_device_t it8172_chipsets[
+ .init_chipset = init_chipset_it8172,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_it8172,
+- .init_dma = init_dma_it8172,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x40,0x00,0x01}},
+--- linux-2.6.0-test6/drivers/ide/pci/Makefile 2003-06-14 12:17:59.000000000 -0700
++++ 25/drivers/ide/pci/Makefile 2003-10-05 00:36:28.000000000 -0700
+@@ -18,10 +18,10 @@ obj-$(CONFIG_BLK_DEV_NS87415) += ns8741
+ obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o
+ obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o
+ obj-$(CONFIG_BLK_DEV_PDC202XX_NEW) += pdc202xx_new.o
+-obj-$(CONFIG_BLK_DEV_PDC_ADMA) += pdcadma.o ide-adma.o
+ obj-$(CONFIG_BLK_DEV_PIIX) += piix.o
+ obj-$(CONFIG_BLK_DEV_RZ1000) += rz1000.o
+ obj-$(CONFIG_BLK_DEV_SVWKS) += serverworks.o
++obj-$(CONFIG_BLK_DEV_SGIIOC4) += sgiioc4.o
+ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o
+ obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o
+ obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o
+--- linux-2.6.0-test6/drivers/ide/pci/ns87415.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/ns87415.c 2003-10-05 00:33:24.000000000 -0700
+@@ -217,11 +217,6 @@ static void __init init_hwif_ns87415 (id
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_ns87415 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/ns87415.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/ide/pci/ns87415.h 2003-10-05 00:33:24.000000000 -0700
+@@ -6,7 +6,6 @@
+ #include <linux/ide.h>
+
+ static void init_hwif_ns87415(ide_hwif_t *);
+-static void init_dma_ns87415(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t ns87415_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -16,7 +15,6 @@ static ide_pci_device_t ns87415_chipsets
+ .init_chipset = NULL,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_ns87415,
+- .init_dma = init_dma_ns87415,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/opti621.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/opti621.c 2003-10-05 00:33:24.000000000 -0700
+@@ -348,11 +348,6 @@ static void __init init_hwif_opti621 (id
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static void __init init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d)
+--- linux-2.6.0-test6/drivers/ide/pci/opti621.h 2003-06-14 12:18:33.000000000 -0700
++++ 25/drivers/ide/pci/opti621.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,7 +7,6 @@
+
+ static void init_setup_opti621(struct pci_dev *, ide_pci_device_t *);
+ static void init_hwif_opti621(ide_hwif_t *);
+-static void init_dma_opti621(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t opti621_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -18,7 +17,6 @@ static ide_pci_device_t opti621_chipsets
+ .init_chipset = NULL,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_opti621,
+- .init_dma = init_dma_opti621,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+@@ -32,7 +30,6 @@ static ide_pci_device_t opti621_chipsets
+ .init_chipset = NULL,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_opti621,
+- .init_dma = init_dma_opti621,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x45,0x80,0x00}, {0x40,0x08,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/pdc202xx_new.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/pdc202xx_new.c 2003-10-05 00:33:24.000000000 -0700
+@@ -563,11 +563,6 @@ static void __init init_hwif_pdc202new (
+ #endif /* PDC202_DEBUG_CABLE */
+ }
+
+-static void __init init_dma_pdc202new (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+ extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *);
+
+--- linux-2.6.0-test6/drivers/ide/pci/pdc202xx_new.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/ide/pci/pdc202xx_new.h 2003-10-05 00:33:24.000000000 -0700
+@@ -188,7 +188,6 @@ static void init_setup_pdc20270(struct p
+ static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d);
+ static unsigned int init_chipset_pdcnew(struct pci_dev *, const char *);
+ static void init_hwif_pdc202new(ide_hwif_t *);
+-static void init_dma_pdc202new(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -199,7 +198,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -213,7 +211,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -227,7 +224,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ #ifdef CONFIG_PDC202XX_FORCE
+@@ -245,7 +241,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -259,7 +254,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -273,7 +267,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ #ifdef CONFIG_PDC202XX_FORCE
+@@ -291,7 +284,6 @@ static ide_pci_device_t pdcnew_chipsets[
+ .init_chipset = init_chipset_pdcnew,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_pdc202new,
+- .init_dma = init_dma_pdc202new,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/pdcadma.c 2003-09-08 13:58:57.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,162 +0,0 @@
+-/*
+- * linux/drivers/ide/pci/pdcadma.c Version 0.05 Sept 10, 2002
+- *
+- * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
+- * May be copied or modified under the terms of the GNU General Public License
+- *
+- */
+-
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+-#include <linux/hdreg.h>
+-
+-#include <linux/interrupt.h>
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/ide.h>
+-
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-
+-#include "pdcadma.h"
+-
+-#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS)
+-#include <linux/stat.h>
+-#include <linux/proc_fs.h>
+-
+-static u8 pdcadma_proc = 0;
+-#define PDC_MAX_DEVS 5
+-static struct pci_dev *pdc_devs[PDC_MAX_DEVS];
+-static int n_pdc_devs;
+-
+-static int pdcadma_get_info (char *buffer, char **addr, off_t offset, int count)
+-{
+- char *p = buffer;
+- int i;
+-
+- for (i = 0; i < n_pdc_devs; i++) {
+- struct pci_dev *dev = pdc_devs[i];
+- unsigned long bibma = pci_resource_start(dev, 4);
+-
+- p += sprintf(p, "\n "
+- "PDC ADMA %04X Chipset.\n", dev->device);
+- p += sprintf(p, "UDMA\n");
+- p += sprintf(p, "PIO\n");
+-
+- }
+- return p-buffer; /* => must be less than 4k! */
+-}
+-#endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */
+-
+-/*
+- * pdcadma_dma functions() initiates/aborts (U)DMA read/write
+- * operations on a drive.
+- */
+-#if 0
+- int (*ide_dma_read)(ide_drive_t *drive);
+- int (*ide_dma_write)(ide_drive_t *drive);
+- int (*ide_dma_begin)(ide_drive_t *drive);
+- int (*ide_dma_end)(ide_drive_t *drive);
+- int (*ide_dma_check)(ide_drive_t *drive);
+- int (*ide_dma_on)(ide_drive_t *drive);
+- int (*ide_dma_off)(ide_drive_t *drive);
+- int (*ide_dma_off_quietly)(ide_drive_t *drive);
+- int (*ide_dma_test_irq)(ide_drive_t *drive);
+- int (*ide_dma_host_on)(ide_drive_t *drive);
+- int (*ide_dma_host_off)(ide_drive_t *drive);
+- int (*ide_dma_bad_drive)(ide_drive_t *drive);
+- int (*ide_dma_good_drive)(ide_drive_t *drive);
+- int (*ide_dma_count)(ide_drive_t *drive);
+- int (*ide_dma_verbose)(ide_drive_t *drive);
+- int (*ide_dma_retune)(ide_drive_t *drive);
+- int (*ide_dma_lostirq)(ide_drive_t *drive);
+- int (*ide_dma_timeout)(ide_drive_t *drive);
+-
+-#endif
+-
+-static unsigned int __init init_chipset_pdcadma (struct pci_dev *dev, const char *name)
+-{
+-#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS)
+- pdc_devs[n_pdc_devs++] = dev;
+-
+- if (!pdcadma_proc) {
+- pdcadma_proc = 1;
+- ide_pci_register_host_proc(&pdcadma_procs[0]);
+- }
+-#endif /* DISPLAY_PDCADMA_TIMINGS && CONFIG_PROC_FS */
+- return 0;
+-}
+-
+-static void __init init_hwif_pdcadma (ide_hwif_t *hwif)
+-{
+- hwif->autodma = 0;
+- hwif->dma_base = 0;
+-
+-// hwif->tuneproc = &pdcadma_tune_drive;
+-// hwif->speedproc = &pdcadma_tune_chipset;
+-
+-// if (hwif->dma_base) {
+-// hwif->autodma = 1;
+-// }
+-
+- hwif->udma_four = 1;
+-
+-// hwif->atapi_dma = 1;
+-// hwif->ultra_mask = 0x7f;
+-// hwif->mwdma_mask = 0x07;
+-// hwif->swdma_mask = 0x07;
+-
+-}
+-
+-static void __init init_dma_pdcadma (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+-#if 0
+- ide_setup_dma(hwif, dmabase, 8);
+-#endif
+-}
+-
+-extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+-
+-static int __devinit pdcadma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+-{
+- ide_pci_device_t *d = &pdcadma_chipsets[id->driver_data];
+- if (dev->device != d->device)
+- BUG();
+- ide_setup_pci_device(dev, d);
+- MOD_INC_USE_COUNT;
+- return 1;
+-}
+-
+-static struct pci_device_id pdcadma_pci_tbl[] = {
+- { PCI_VENDOR_ID_PDC, PCI_DEVICE_ID_PDC_1841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+- { 0, },
+-};
+-
+-static struct pci_driver driver = {
+- .name = "PDCADMA-IDE",
+- .id_table = pdcadma_pci_tbl,
+- .probe = pdcadma_init_one,
+-};
+-
+-static int pdcadma_ide_init(void)
+-{
+- return ide_pci_register_driver(&driver);
+-}
+-
+-static void pdcadma_ide_exit(void)
+-{
+- ide_pci_unregister_driver(&driver);
+-}
+-
+-module_init(pdcadma_ide_init);
+-module_exit(pdcadma_ide_exit);
+-
+-MODULE_AUTHOR("Andre Hedrick");
+-MODULE_DESCRIPTION("PCI driver module for PDCADMA IDE");
+-MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/pci/pdcadma.h 2003-06-14 12:17:56.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,56 +0,0 @@
+-#ifndef PDC_ADMA_H
+-#define PDC_ADMA_H
+-
+-#include <linux/config.h>
+-#include <linux/pci.h>
+-#include <linux/ide.h>
+-
+-#undef DISPLAY_PDCADMA_TIMINGS
+-
+-#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS)
+-#include <linux/stat.h>
+-#include <linux/proc_fs.h>
+-
+-static u8 pdcadma_proc;
+-
+-static int pdcadma_get_info(char *, char **, off_t, int);
+-
+-static ide_pci_host_proc_t pdcadma_procs[] __initdata = {
+- {
+- .name = "pdcadma",
+- .set = 1,
+- .get_info = pdcadma_get_info,
+- .parent = NULL,
+- },
+-};
+-#endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */
+-
+-static void init_setup_pdcadma(struct pci_dev *, ide_pci_device_t *);
+-static unsigned int init_chipset_pdcadma(struct pci_dev *, const char *);
+-static void init_hwif_pdcadma(ide_hwif_t *);
+-static void init_dma_pdcadma(ide_hwif_t *, unsigned long);
+-
+-static ide_pci_device_t pdcadma_chipsets[] __devinitdata = {
+- { /* 0 */
+- .vendor = PCI_VENDOR_ID_PDC,
+- .device = PCI_DEVICE_ID_PDC_1841,
+- .name = "PDCADMA",
+- .init_setup = init_setup_pdcadma,
+- .init_chipset = init_chipset_pdcadma,
+- .init_iops = NULL,
+- .init_hwif = init_hwif_pdcadma,
+- .init_dma = init_dma_pdcadma,
+- .channels = 2,
+- .autodma = NODMA,
+- .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+- .bootable = OFF_BOARD,
+- .extra = 0,
+- },{
+- .vendor = 0,
+- .device = 0,
+- .channels = 0,
+- .bootable = EOL,
+- }
+-};
+-
+-#endif /* PDC_ADMA_H */
+--- linux-2.6.0-test6/drivers/ide/pci/piix.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/piix.c 2003-10-05 00:33:24.000000000 -0700
+@@ -709,21 +709,6 @@ static void __init init_hwif_piix (ide_h
+ hwif->drives[0].autodma = hwif->autodma;
+ }
+
+-/**
+- * init_dma_piix - set up the PIIX DMA
+- * @hwif: IDE interface
+- * @dmabase: DMA PCI base
+- *
+- * Set up the DMA on the PIIX controller, providing a DMA base is
+- * available. The PIIX follows the normal specs so we do nothing
+- * magical here.
+- */
+-
+-static void __init init_dma_piix (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ /**
+--- linux-2.6.0-test6/drivers/ide/pci/piix.h 2003-06-14 12:18:00.000000000 -0700
++++ 25/drivers/ide/pci/piix.h 2003-10-05 00:33:24.000000000 -0700
+@@ -30,8 +30,6 @@ static ide_pci_host_proc_t piix_procs[]
+ static void init_setup_piix(struct pci_dev *, ide_pci_device_t *);
+ static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *);
+ static void init_hwif_piix(ide_hwif_t *);
+-static void init_dma_piix(ide_hwif_t *, unsigned long);
+-
+
+ /*
+ * Table of the various PIIX capability blocks
+@@ -47,7 +45,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -61,7 +58,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -75,7 +71,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = NULL,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = NULL,
+ .channels = 2,
+ .autodma = NODMA,
+ .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},
+@@ -89,7 +84,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -103,7 +97,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -117,7 +110,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -131,7 +123,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -145,7 +136,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -159,7 +149,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -173,7 +162,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -187,7 +175,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -201,7 +188,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -215,7 +201,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -229,7 +214,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -243,7 +227,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -257,7 +240,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -271,7 +253,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -285,7 +266,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+@@ -299,7 +279,6 @@ static ide_pci_device_t piix_pci_info[]
+ .init_chipset = init_chipset_piix,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_piix,
+- .init_dma = init_dma_piix,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+--- linux-2.6.0-test6/drivers/ide/pci/sc1200.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/sc1200.c 2003-10-05 00:33:24.000000000 -0700
+@@ -396,44 +396,44 @@ typedef struct sc1200_saved_state_s {
+ __u32 regs[4];
+ } sc1200_saved_state_t;
+
+-static int sc1200_save_state (struct pci_dev *dev, u32 state)
++
++static int sc1200_suspend (struct pci_dev *dev, u32 state)
+ {
+ ide_hwif_t *hwif = NULL;
+
+-printk("SC1200: save_state(%u)\n", state);
+- if (state != 0)
+- return 0; // we only save state when going from full power to less
+- //
+- // Loop over all interfaces that are part of this PCI device:
+- //
+- while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+- sc1200_saved_state_t *ss;
+- unsigned int basereg, r;
+- //
+- // allocate a permanent save area, if not already allocated
+- //
+- ss = (sc1200_saved_state_t *)hwif->config_data;
+- if (ss == NULL) {
+- ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
+- if (ss == NULL)
+- return -ENOMEM;
+- (sc1200_saved_state_t *)hwif->config_data = ss;
+- }
+- ss = (sc1200_saved_state_t *)hwif->config_data;
++ printk("SC1200: suspend(%u)\n", state);
++
++ if (state == 0) {
++ // we only save state when going from full power to less
++
+ //
+- // Save timing registers: this may be unnecessary if BIOS also does it
++ // Loop over all interfaces that are part of this PCI device:
+ //
+- basereg = hwif->channel ? 0x50 : 0x40;
+- for (r = 0; r < 4; ++r) {
+- pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
++ while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
++ sc1200_saved_state_t *ss;
++ unsigned int basereg, r;
++ //
++ // allocate a permanent save area, if not already allocated
++ //
++ ss = (sc1200_saved_state_t *)hwif->config_data;
++ if (ss == NULL) {
++ ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
++ if (ss == NULL)
++ return -ENOMEM;
++ (sc1200_saved_state_t *)hwif->config_data = ss;
++ }
++ ss = (sc1200_saved_state_t *)hwif->config_data;
++ //
++ // Save timing registers: this may be unnecessary if
++ // BIOS also does it
++ //
++ basereg = hwif->channel ? 0x50 : 0x40;
++ for (r = 0; r < 4; ++r) {
++ pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
++ }
+ }
+ }
+- return 0;
+-}
+
+-static int sc1200_suspend (struct pci_dev *dev, u32 state)
+-{
+- printk("SC1200: suspend(%u)\n", state);
+ /* You don't need to iterate over disks -- sysfs should have done that for you already */
+
+ pci_disable_device(dev);
+@@ -545,11 +545,6 @@ static void __init init_hwif_sc1200 (ide
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-static void __init init_dma_sc1200 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+@@ -572,7 +567,6 @@ static struct pci_driver driver = {
+ .name = "SC1200 IDE",
+ .id_table = sc1200_pci_tbl,
+ .probe = sc1200_init_one,
+- .save_state = sc1200_save_state,
+ .suspend = sc1200_suspend,
+ .resume = sc1200_resume,
+ };
+--- linux-2.6.0-test6/drivers/ide/pci/sc1200.h 2003-06-14 12:18:05.000000000 -0700
++++ 25/drivers/ide/pci/sc1200.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@ static ide_pci_host_proc_t sc1200_procs[
+
+ static unsigned int init_chipset_sc1200(struct pci_dev *, const char *);
+ static void init_hwif_sc1200(ide_hwif_t *);
+-static void init_dma_sc1200(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t sc1200_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -37,7 +36,6 @@ static ide_pci_device_t sc1200_chipsets[
+ .init_chipset = init_chipset_sc1200,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_sc1200,
+- .init_dma = init_dma_sc1200,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/ide/pci/sgiioc4.c 2003-10-05 00:36:28.000000000 -0700
+@@ -0,0 +1,1053 @@
++/*
++ * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of version 2 of the GNU General Public License
++ * as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it would be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ * You should have received a copy of the GNU General Public
++ * License along with this program; if not, write the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ *
++ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
++ * Mountain View, CA 94043, or:
++ *
++ * http://www.sgi.com
++ *
++ * For further information regarding this notice, see:
++ *
++ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/hdreg.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/timer.h>
++#include <linux/mm.h>
++#include <linux/ioport.h>
++#include <linux/blkdev.h>
++#include <asm/io.h>
++
++#define IDE_ARCH_ACK_INTR 1
++#include <linux/ide.h>
++
++/* IOC4 Specific Definitions */
++#define IOC4_CMD_OFFSET 0x100
++#define IOC4_CTRL_OFFSET 0x120
++#define IOC4_DMA_OFFSET 0x140
++#define IOC4_INTR_OFFSET 0x0
++
++#define IOC4_TIMING 0x00
++#define IOC4_DMA_PTR_L 0x01
++#define IOC4_DMA_PTR_H 0x02
++#define IOC4_DMA_ADDR_L 0x03
++#define IOC4_DMA_ADDR_H 0x04
++#define IOC4_BC_DEV 0x05
++#define IOC4_BC_MEM 0x06
++#define IOC4_DMA_CTRL 0x07
++#define IOC4_DMA_END_ADDR 0x08
++
++/* Bits in the IOC4 Control/Status Register */
++#define IOC4_S_DMA_START 0x01
++#define IOC4_S_DMA_STOP 0x02
++#define IOC4_S_DMA_DIR 0x04
++#define IOC4_S_DMA_ACTIVE 0x08
++#define IOC4_S_DMA_ERROR 0x10
++#define IOC4_ATA_MEMERR 0x02
++
++/* Read/Write Directions */
++#define IOC4_DMA_WRITE 0x04
++#define IOC4_DMA_READ 0x00
++
++/* Interrupt Register Offsets */
++#define IOC4_INTR_REG 0x03
++#define IOC4_INTR_SET 0x05
++#define IOC4_INTR_CLEAR 0x07
++
++#define IOC4_IDE_CACHELINE_SIZE 128
++#define IOC4_CMD_CTL_BLK_SIZE 0x20
++#define IOC4_SUPPORTED_FIRMWARE_REV 46
++
++/* Weeds out non-IDE interrupts to the IOC4 */
++#define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
++
++#define SGIIOC4_MAX_DEVS 32
++
++#if defined(CONFIG_PROC_FS)
++#include <linux/stat.h>
++#include <linux/proc_fs.h>
++
++static u8 sgiioc4_proc;
++
++static struct pci_dev *sgiioc4_devs[SGIIOC4_MAX_DEVS];
++static int sgiioc4_get_info(char *, char **, off_t, int);
++
++static ide_pci_host_proc_t sgiioc4_procs[] __initdata = {
++ {
++ .name = "sgiioc4",
++ .set = 1,
++ .get_info = sgiioc4_get_info,
++ .parent = NULL,
++ }
++};
++#endif
++
++typedef struct {
++ u32 timing_reg0;
++ u32 timing_reg1;
++ u32 low_mem_ptr;
++ u32 high_mem_ptr;
++ u32 low_mem_addr;
++ u32 high_mem_addr;
++ u32 dev_byte_count;
++ u32 mem_byte_count;
++ u32 status;
++} ioc4_dma_regs_t;
++
++/* Each Physical Region Descriptor Entry size is 16 bytes (2 * 64 bits) */
++/* IOC4 has only 1 IDE channel */
++#define IOC4_PRD_BYTES 16
++#define IOC4_PRD_ENTRIES (PAGE_SIZE /(4*IOC4_PRD_BYTES))
++
++typedef enum pciio_endian_e {
++ PCIDMA_ENDIAN_BIG,
++ PCIDMA_ENDIAN_LITTLE
++} pciio_endian_t;
++
++static void sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
++ unsigned long ctrl_port,
++ unsigned long irq_port);
++static void sgiioc4_ide_setup_pci_device(struct pci_dev *dev,
++ ide_pci_device_t * d);
++static void sgiioc4_resetproc(ide_drive_t * drive);
++static void sgiioc4_maskproc(ide_drive_t * drive, int mask);
++static void sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive);
++static void __init ide_init_sgiioc4(ide_hwif_t * hwif);
++static void __init ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base);
++static int sgiioc4_checkirq(ide_hwif_t * hwif);
++static int sgiioc4_clearirq(ide_drive_t * drive);
++static int sgiioc4_get_info(char *buffer, char **addr, off_t offset, int count);
++static int sgiioc4_ide_dma_read(ide_drive_t * drive);
++static int sgiioc4_ide_dma_write(ide_drive_t * drive);
++static int sgiioc4_ide_dma_begin(ide_drive_t * drive);
++static int sgiioc4_ide_dma_end(ide_drive_t * drive);
++static int sgiioc4_ide_dma_check(ide_drive_t * drive);
++static int sgiioc4_ide_dma_on(ide_drive_t * drive);
++static int sgiioc4_ide_dma_off(ide_drive_t * drive);
++static int sgiioc4_ide_dma_off_quietly(ide_drive_t * drive);
++static int sgiioc4_ide_dma_test_irq(ide_drive_t * drive);
++static int sgiioc4_ide_dma_host_on(ide_drive_t * drive);
++static int sgiioc4_ide_dma_host_off(ide_drive_t * drive);
++static int sgiioc4_ide_dma_count(ide_drive_t * drive);
++static int sgiioc4_ide_dma_verbose(ide_drive_t * drive);
++static int sgiioc4_ide_dma_lostirq(ide_drive_t * drive);
++static int sgiioc4_ide_dma_timeout(ide_drive_t * drive);
++static int sgiioc4_ide_build_sglist(ide_drive_t * drive, struct request *rq);
++static int sgiioc4_ide_raw_build_sglist(ide_drive_t * drive,
++ struct request *rq);
++static u8 sgiioc4_INB(unsigned long port);
++static inline void xide_delay(long ticks);
++static unsigned int sgiioc4_build_dma_table(ide_drive_t * drive,
++ struct request *rq, int ddir);
++static unsigned int __init pci_init_sgiioc4(struct pci_dev *dev,
++ ide_pci_device_t * d);
++
++static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
++ {
++ /* Channel 0 */
++ .vendor = PCI_VENDOR_ID_SGI,
++ .device = PCI_DEVICE_ID_SGI_IOC4,
++ .name = "SGIIOC4",
++ .init_chipset = NULL,
++ .init_iops = NULL,
++ .init_hwif = ide_init_sgiioc4,
++ .init_dma = ide_dma_sgiioc4,
++ .channels = 1,
++ .autodma = AUTODMA,
++ .enablebits = {{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}},
++ .bootable = ON_BOARD,
++ .extra = 0,
++ }
++};
++
++#ifdef CONFIG_PROC_FS
++static u8 sgiioc4_proc;
++#endif /* CONFIG_PROC_FS */
++
++static int n_sgiioc4_devs;
++
++static inline void
++xide_delay(long ticks)
++{
++ if (!ticks)
++ return;
++
++ current->state = TASK_UNINTERRUPTIBLE;
++ schedule_timeout(ticks);
++}
++static void __init
++sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
++{
++ unsigned long base = 0, ctl = 0, dma_base = 0, irqport = 0;
++ ide_hwif_t *hwif = NULL;
++ int h = 0;
++
++ /* Get the CmdBlk and CtrlBlk Base Registers */
++ base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
++ ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
++ irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
++ dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
++
++ if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
++ printk(KERN_ERR
++ "%s : %s -- Warning, Port Addresses "
++ "0x%p to 0x%p ALREADY in use\n",
++ __FUNCTION__, hwif->name, (void *) base,
++ (void *) base + IOC4_CMD_CTL_BLK_SIZE);
++ }
++
++ for (h = 0; h < MAX_HWIFS; ++h) {
++ hwif = &ide_hwifs[h];
++ /* Find an empty HWIF */
++ if (hwif->chipset == ide_unknown)
++ break;
++ }
++
++ if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
++ /* Initialize the IO registers */
++ sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
++ memcpy(hwif->io_ports, hwif->hw.io_ports,
++ sizeof (hwif->io_ports));
++ hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
++ }
++
++ hwif->irq = dev->irq;
++ hwif->chipset = ide_pci;
++ hwif->pci_dev = dev;
++ hwif->channel = 0; /* Single Channel chip */
++ hwif->cds = (struct ide_pci_device_s *) d;
++ hwif->hw.ack_intr = &sgiioc4_checkirq; /* MultiFunction Chip */
++ hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
++
++ /* Initializing chipset IRQ Registers */
++ hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
++
++ (void) ide_init_sgiioc4(hwif);
++
++ if (dma_base)
++ ide_dma_sgiioc4(hwif, dma_base);
++ else
++ printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
++ hwif->name, d->name);
++
++ probe_hwif_init(hwif);
++}
++
++/* This ensures that we can build this for generic kernels without
++ * having all the SN2 code sync'd and merged.
++ */
++
++pciio_endian_t __attribute__ ((weak)) snia_pciio_endian_set(struct pci_dev
++ *pci_dev, pciio_endian_t device_end,
++ pciio_endian_t desired_end);
++
++static unsigned int __init
++pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
++{
++ if (pci_enable_device(dev)) {
++ printk(KERN_INFO
++ "Failed to enable device %s at slot %s\n",
++ d->name, dev->slot_name);
++ return 1;
++ }
++ pci_set_master(dev);
++
++ /* Enable Byte Swapping in the PIC... */
++ if (snia_pciio_endian_set) {
++ snia_pciio_endian_set(dev, PCIDMA_ENDIAN_LITTLE,
++ PCIDMA_ENDIAN_BIG);
++ } else {
++ printk(KERN_INFO
++ "Failed to set endianness for device %s at slot %s\n",
++ d->name, dev->slot_name);
++ return 1;
++ }
++
++#ifdef CONFIG_PROC_FS
++ sgiioc4_devs[n_sgiioc4_devs++] = dev;
++ if (!sgiioc4_proc) {
++ sgiioc4_proc = 1;
++ ide_pci_register_host_proc(&sgiioc4_procs[0]);
++ }
++#endif
++ sgiioc4_ide_setup_pci_device(dev, d);
++
++ return 0;
++}
++
++static void
++sgiioc4_init_hwif_ports(hw_regs_t * hw, unsigned long data_port,
++ unsigned long ctrl_port, unsigned long irq_port)
++{
++ unsigned long reg = data_port;
++ int i;
++
++ /* Registers are word (32 bit) aligned */
++ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
++ hw->io_ports[i] = reg + i * 4;
++
++ if (ctrl_port)
++ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
++
++ if (irq_port)
++ hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
++}
++
++static void
++sgiioc4_resetproc(ide_drive_t * drive)
++{
++ sgiioc4_ide_dma_end(drive);
++ sgiioc4_clearirq(drive);
++}
++
++static void
++sgiioc4_maskproc(ide_drive_t * drive, int mask)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2),
++ IDE_CONTROL_REG);
++}
++
++static void __init
++ide_init_sgiioc4(ide_hwif_t * hwif)
++{
++ hwif->mmio = 2;
++ hwif->autodma = 1;
++ hwif->atapi_dma = 1;
++ hwif->ultra_mask = 0x0; /* Disable Ultra DMA */
++ hwif->mwdma_mask = 0x2; /* Multimode-2 DMA */
++ hwif->swdma_mask = 0x2;
++ hwif->identify = NULL;
++ hwif->tuneproc = NULL; /* Sets timing for PIO mode */
++ hwif->speedproc = NULL; /* Sets timing for DMA &/or PIO modes */
++ hwif->selectproc = NULL;/* Use the default routine to select drive */
++ hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */
++ hwif->pre_reset = NULL; /* No HBA specific pre_set needed */
++ hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
++ clear interrupts */
++ hwif->intrproc = NULL; /* Enable or Disable interrupt from drive */
++ hwif->maskproc = &sgiioc4_maskproc; /* Mask on/off NIEN register */
++ hwif->quirkproc = NULL;
++ hwif->busproc = NULL;
++
++ hwif->ide_dma_read = &sgiioc4_ide_dma_read;
++ hwif->ide_dma_write = &sgiioc4_ide_dma_write;
++ hwif->ide_dma_begin = &sgiioc4_ide_dma_begin;
++ hwif->ide_dma_end = &sgiioc4_ide_dma_end;
++ hwif->ide_dma_check = &sgiioc4_ide_dma_check;
++ hwif->ide_dma_on = &sgiioc4_ide_dma_on;
++ hwif->ide_dma_off = &sgiioc4_ide_dma_off;
++ hwif->ide_dma_off_quietly = &sgiioc4_ide_dma_off_quietly;
++ hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
++ hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
++ hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
++ hwif->ide_dma_bad_drive = &__ide_dma_bad_drive;
++ hwif->ide_dma_good_drive = &__ide_dma_good_drive;
++ hwif->ide_dma_count = &sgiioc4_ide_dma_count;
++ hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose;
++ hwif->ide_dma_retune = &__ide_dma_retune;
++ hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
++ hwif->ide_dma_timeout = &sgiioc4_ide_dma_timeout;
++ hwif->INB = &sgiioc4_INB;
++}
++
++static int
++sgiioc4_ide_dma_read(ide_drive_t * drive)
++{
++ struct request *rq = HWGROUP(drive)->rq;
++ unsigned int count = 0;
++
++ if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) {
++ /* try PIO instead of DMA */
++ return 1;
++ }
++ /* Writes FROM the IOC4 TO Main Memory */
++ sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive);
++
++ return 0;
++}
++
++static int
++sgiioc4_ide_dma_write(ide_drive_t * drive)
++{
++ struct request *rq = HWGROUP(drive)->rq;
++ unsigned int count = 0;
++
++ if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) {
++ /* try PIO instead of DMA */
++ return 1;
++ }
++
++ sgiioc4_configure_for_dma(IOC4_DMA_READ, drive);
++ /* Writes TO the IOC4 FROM Main Memory */
++
++ return 0;
++}
++
++static int
++sgiioc4_ide_dma_begin(ide_drive_t * drive)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ unsigned int reg = hwif->INL(hwif->dma_base + IOC4_DMA_CTRL * 4);
++ unsigned int temp_reg = reg | IOC4_S_DMA_START;
++
++ hwif->OUTL(temp_reg, hwif->dma_base + IOC4_DMA_CTRL * 4);
++
++ return 0;
++}
++
++/* Stops the IOC4 DMA Engine */
++static int
++sgiioc4_ide_dma_end(ide_drive_t * drive)
++{
++ u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
++ ide_hwif_t *hwif = HWIF(drive);
++ uint64_t dma_base = hwif->dma_base;
++ int dma_stat = 0, count;
++ unsigned long *ending_dma = (unsigned long *) hwif->dma_base2;
++
++ hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
++
++ count = 0;
++ do {
++ xide_delay(count);
++ ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
++ count += 10;
++ } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100));
++
++ if (ioc4_dma & IOC4_S_DMA_STOP) {
++ printk(KERN_ERR
++ "%s(%s): IOC4 DMA STOP bit is still 1 :"
++ "ioc4_dma_reg 0x%x\n",
++ __FUNCTION__, drive->name, ioc4_dma);
++ dma_stat = 1;
++ }
++
++ if (ending_dma) {
++ do {
++ for (num = 0; num < 16; num++) {
++ if (ending_dma[num] & (~0ul)) {
++ valid = 1;
++ break;
++ }
++ }
++ xide_delay(cnt);
++ } while ((cnt++ < 100) && (!valid));
++ }
++
++ if (!valid)
++ printk(KERN_INFO "%s(%s) : Stale DMA Data in Memory\n",
++ __FUNCTION__, drive->name);
++
++ bc_dev = hwif->INL(dma_base + IOC4_BC_DEV * 4);
++ bc_mem = hwif->INL(dma_base + IOC4_BC_MEM * 4);
++
++ if ((bc_dev & 0x01FF) || (bc_mem & 0x1FF)) {
++ if (bc_dev > bc_mem + 8) {
++ printk(KERN_ERR
++ "%s(%s): WARNING!! byte_count_dev %d "
++ "!= byte_count_mem %d\n",
++ __FUNCTION__, drive->name, bc_dev, bc_mem);
++ }
++ }
++
++ drive->waiting_for_dma = 0;
++ ide_destroy_dmatable(drive);
++
++ return dma_stat;
++}
++
++static int
++sgiioc4_ide_dma_check(ide_drive_t * drive)
++{
++ if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) {
++ printk(KERN_INFO
++ "Couldnot set %s in Multimode-2 DMA mode | "
++ "Drive %s using PIO instead\n",
++ drive->name, drive->name);
++ drive->using_dma = 0;
++ } else
++ drive->using_dma = 1;
++
++ return 0;
++}
++
++static int
++sgiioc4_ide_dma_on(ide_drive_t * drive)
++{
++ drive->using_dma = 1;
++
++ return HWIF(drive)->ide_dma_host_on(drive);
++}
++
++static int
++sgiioc4_ide_dma_off(ide_drive_t * drive)
++{
++ printk(KERN_INFO "%s: DMA disabled\n", drive->name);
++
++ return HWIF(drive)->ide_dma_off_quietly(drive);
++}
++
++static int
++sgiioc4_ide_dma_off_quietly(ide_drive_t * drive)
++{
++ drive->using_dma = 0;
++
++ return HWIF(drive)->ide_dma_host_off(drive);
++}
++
++/* returns 1 if dma irq issued, 0 otherwise */
++static int
++sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
++{
++ return sgiioc4_checkirq(HWIF(drive));
++}
++
++static int
++sgiioc4_ide_dma_host_on(ide_drive_t * drive)
++{
++ if (drive->using_dma)
++ return 0;
++
++ return 1;
++}
++
++static int
++sgiioc4_ide_dma_host_off(ide_drive_t * drive)
++{
++ sgiioc4_clearirq(drive);
++
++ return 0;
++}
++
++static int
++sgiioc4_ide_dma_count(ide_drive_t * drive)
++{
++ return HWIF(drive)->ide_dma_begin(drive);
++}
++
++static int
++sgiioc4_ide_dma_verbose(ide_drive_t * drive)
++{
++ if (drive->using_dma == 1)
++ printk(", UDMA(16)");
++ else
++ printk(", PIO");
++
++ return 1;
++}
++
++static int
++sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
++{
++ HWIF(drive)->resetproc(drive);
++
++ return __ide_dma_lostirq(drive);
++}
++
++static int
++sgiioc4_ide_dma_timeout(ide_drive_t * drive)
++{
++ printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
++ if (HWIF(drive)->ide_dma_test_irq(drive))
++ return 0;
++
++ return HWIF(drive)->ide_dma_end(drive);
++}
++
++static u8
++sgiioc4_INB(unsigned long port)
++{
++ u8 reg = (u8) inb(port);
++
++ if ((port & 0xFFF) == 0x11C) { /* Status register of IOC4 */
++ if (reg & 0x51) { /* Not busy...check for interrupt */
++ unsigned long other_ir = port - 0x110;
++ unsigned int intr_reg = (u32) inl(other_ir);
++
++ /* Clear the Interrupt, Error bits on the IOC4 */
++ if (intr_reg & 0x03) {
++ outl(0x03, other_ir);
++ intr_reg = (u32) inl(other_ir);
++ }
++ }
++ }
++
++ return reg;
++}
++
++/* Creates a dma map for the scatter-gather list entries */
++static void __init
++ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
++{
++ int num_ports = sizeof (ioc4_dma_regs_t);
++
++ printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
++ dma_base, dma_base + num_ports - 1);
++
++ if (!request_region(dma_base, num_ports, hwif->name)) {
++ printk(KERN_ERR
++ "%s(%s) -- WARNING, Addresses 0x%p to 0x%p "
++ "ALREADY in use\n",
++ __FUNCTION__, hwif->name, (void *) dma_base,
++ (void *) dma_base + num_ports - 1);
++ }
++
++ hwif->dma_base = dma_base;
++ hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
++ IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
++ &hwif->dmatable_dma);
++
++ if (!hwif->dmatable_cpu)
++ goto dma_alloc_failure;
++
++ hwif->sg_table =
++ kmalloc(sizeof (struct scatterlist) * IOC4_PRD_ENTRIES, GFP_KERNEL);
++
++ if (!hwif->sg_table) {
++ pci_free_consistent(hwif->pci_dev,
++ IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
++ hwif->dmatable_cpu, hwif->dmatable_dma);
++ goto dma_alloc_failure;
++ }
++
++ hwif->dma_base2 = (unsigned long)
++ pci_alloc_consistent(hwif->pci_dev,
++ IOC4_IDE_CACHELINE_SIZE,
++ (dma_addr_t *) &(hwif->dma_status));
++
++ if (!hwif->dma_base2) {
++ pci_free_consistent(hwif->pci_dev,
++ IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
++ hwif->dmatable_cpu, hwif->dmatable_dma);
++ kfree(hwif->sg_table);
++ goto dma_alloc_failure;
++ }
++
++ return;
++
++ dma_alloc_failure:
++ printk(KERN_INFO
++ "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
++ __FUNCTION__, hwif->name);
++ printk(KERN_INFO
++ "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
++
++ /* Disable DMA because we couldnot allocate any DMA maps */
++ hwif->autodma = 0;
++ hwif->atapi_dma = 0;
++}
++
++/* Initializes the IOC4 DMA Engine */
++static void
++sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
++{
++ u32 ioc4_dma;
++ int count;
++ ide_hwif_t *hwif = HWIF(drive);
++ uint64_t dma_base = hwif->dma_base;
++ uint32_t dma_addr, ending_dma_addr;
++
++ ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
++
++ if (ioc4_dma & IOC4_S_DMA_ACTIVE) {
++ printk(KERN_WARNING
++ "%s(%s):Warning!! DMA from previous transfer was still active\n",
++ __FUNCTION__, drive->name);
++ hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
++ count = 0;
++ do {
++ xide_delay(count);
++ ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
++ count += 10;
++ } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100));
++
++ if (ioc4_dma & IOC4_S_DMA_STOP)
++ printk(KERN_ERR
++ "%s(%s) : IOC4 Dma STOP bit is still 1\n",
++ __FUNCTION__, drive->name);
++ }
++
++ ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
++ if (ioc4_dma & IOC4_S_DMA_ERROR) {
++ printk(KERN_WARNING
++ "%s(%s) : Warning!! - DMA Error during Previous"
++ " transfer | status 0x%x\n",
++ __FUNCTION__, drive->name, ioc4_dma);
++ hwif->OUTL(IOC4_S_DMA_STOP, dma_base + IOC4_DMA_CTRL * 4);
++ count = 0;
++ do {
++ ioc4_dma = hwif->INL(dma_base + IOC4_DMA_CTRL * 4);
++ xide_delay(count);
++ count += 10;
++ } while ((ioc4_dma & IOC4_S_DMA_STOP) && (count < 100));
++
++ if (ioc4_dma & IOC4_S_DMA_STOP)
++ printk(KERN_ERR
++ "%s(%s) : IOC4 DMA STOP bit is still 1\n",
++ __FUNCTION__, drive->name);
++ }
++
++ /* Address of the Scatter Gather List */
++ dma_addr = cpu_to_le32(hwif->dmatable_dma);
++ hwif->OUTL(dma_addr, dma_base + IOC4_DMA_PTR_L * 4);
++
++ /* Address of the Ending DMA */
++ memset((unsigned int *) hwif->dma_base2, 0, IOC4_IDE_CACHELINE_SIZE);
++ ending_dma_addr = cpu_to_le32(hwif->dma_status);
++ hwif->OUTL(ending_dma_addr, dma_base + IOC4_DMA_END_ADDR * 4);
++
++ hwif->OUTL(dma_direction, dma_base + IOC4_DMA_CTRL * 4);
++ drive->waiting_for_dma = 1;
++}
++
++/* IOC4 Scatter Gather list Format */
++/* 128 Bit entries to support 64 bit addresses in the future */
++/* The Scatter Gather list Entry should be in the BIG-ENDIAN Format */
++/* --------------------------------------------------------------------- */
++/* | Upper 32 bits - Zero | Lower 32 bits- address | */
++/* --------------------------------------------------------------------- */
++/* | Upper 32 bits - Zero |EOL| 15 unused | 16 Bit Length| */
++/* --------------------------------------------------------------------- */
++/* Creates the scatter gather list, DMA Table */
++static unsigned int
++sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ unsigned int *table = hwif->dmatable_cpu;
++ unsigned int count = 0, i = 1;
++ struct scatterlist *sg;
++
++ if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
++ hwif->sg_nents = i = sgiioc4_ide_raw_build_sglist(drive, rq);
++ else
++ hwif->sg_nents = i = sgiioc4_ide_build_sglist(drive, rq);
++
++ if (!i)
++ return 0; /* sglist of length Zero */
++
++ sg = hwif->sg_table;
++ while (i && sg_dma_len(sg)) {
++ dma_addr_t cur_addr;
++ int cur_len;
++ cur_addr = sg_dma_address(sg);
++ cur_len = sg_dma_len(sg);
++
++ while (cur_len) {
++ if (count++ >= IOC4_PRD_ENTRIES) {
++ printk(KERN_WARNING
++ "%s: DMA table too small\n",
++ drive->name);
++ goto use_pio_instead;
++ } else {
++ uint32_t xcount, bcount =
++ 0x10000 - (cur_addr & 0xffff);
++
++ if (bcount > cur_len)
++ bcount = cur_len;
++
++ /* put the addr, length in
++ * the IOC4 dma-table format */
++ *table = 0x0;
++ table++;
++ *table = cpu_to_be32(cur_addr);
++ table++;
++ *table = 0x0;
++ table++;
++
++ xcount = bcount & 0xffff;
++ *table = cpu_to_be32(xcount);
++ table++;
++
++ cur_addr += bcount;
++ cur_len -= bcount;
++ }
++ }
++
++ sg++;
++ i--;
++ }
++
++ if (count) {
++ table--;
++ *table |= cpu_to_be32(0x80000000);
++ return count;
++ }
++
++ use_pio_instead:
++ pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
++ hwif->sg_dma_direction);
++ hwif->sg_dma_active = 0;
++
++ return 0; /* revert to PIO for this request */
++}
++
++static int
++sgiioc4_checkirq(ide_hwif_t * hwif)
++{
++ uint8_t intr_reg =
++ hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + IOC4_INTR_REG * 4);
++
++ if (intr_reg & 0x03)
++ return 1;
++
++ return 0;
++}
++
++static int
++sgiioc4_clearirq(ide_drive_t * drive)
++{
++ u32 intr_reg;
++ ide_hwif_t *hwif = HWIF(drive);
++ unsigned long other_ir =
++ hwif->io_ports[IDE_IRQ_OFFSET] + (IOC4_INTR_REG << 2);
++
++ /* Code to check for PCI error conditions */
++ intr_reg = hwif->INL(other_ir);
++ if (intr_reg & 0x03) {
++ /* Valid IOC4-IDE interrupt */
++ u8 stat = hwif->INB(IDE_STATUS_REG);
++ int count = 0;
++ do {
++ xide_delay(count);
++ stat = hwif->INB(IDE_STATUS_REG);
++ /* Removes Interrupt from IDE Device */
++ } while ((stat & 0x80) && (count++ < 1024));
++
++ if (intr_reg & 0x02) {
++ /* Error when transferring DMA data on PCI bus */
++ uint32_t pci_err_addr_low, pci_err_addr_high,
++ pci_stat_cmd_reg;
++
++ pci_err_addr_low =
++ hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET]);
++ pci_err_addr_high =
++ hwif->INL(hwif->io_ports[IDE_IRQ_OFFSET] + 4);
++ pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
++ &pci_stat_cmd_reg);
++ printk(KERN_ERR
++ "%s(%s) : PCI Bus Error when doing DMA:"
++ " status-cmd reg is 0x%x\n",
++ __FUNCTION__, drive->name, pci_stat_cmd_reg);
++ printk(KERN_ERR
++ "%s(%s) : PCI Error Address is 0x%x%x\n",
++ __FUNCTION__, drive->name,
++ pci_err_addr_high, pci_err_addr_low);
++ /* Clear the PCI Error indicator */
++ pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
++ 0x00000146);
++ }
++
++ /* Clear the Interrupt, Error bits on the IOC4 */
++ hwif->OUTL(0x03, other_ir);
++
++ intr_reg = hwif->INL(other_ir);
++ }
++
++ return intr_reg;
++}
++
++/**
++ * "Copied from drivers/ide/ide-dma.c"
++ * sgiioc4_ide_build_sglist - map IDE scatter gather for DMA I/O
++ * @hwif: the interface to build the DMA table for
++ * @rq: the request holding the sg list
++ * @ddir: data direction
++ *
++ * Perform the PCI mapping magic neccessary to access the source
++ * or target buffers of a request via PCI DMA. The lower layers
++ * of the kernel provide the neccessary cache management so that
++ * we can operate in a portable fashion.
++ *
++ * This code is identical to ide_build_sglist in ide-dma.c
++ * however that is not exported.
++ */
++
++static int
++sgiioc4_ide_build_sglist(ide_drive_t * drive, struct request *rq)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ struct scatterlist *sg = hwif->sg_table;
++ int nents;
++
++ if (hwif->sg_dma_active)
++ BUG();
++
++ nents = blk_rq_map_sg(drive->queue, rq, hwif->sg_table);
++
++ if (rq_data_dir(rq) == READ)
++ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
++ else
++ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
++
++ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
++}
++
++/**
++ * Copied from drivers/ide/ide-dma.c
++ * sgiioc4_ide_raw_build_sglist - map IDE scatter gather for DMA
++ * @hwif: the interface to build the DMA table for
++ * @rq: the request holding the sg list
++ *
++ * Perform the PCI mapping magic neccessary to access the source or
++ * target buffers of a taskfile request via PCI DMA. The lower layers
++ * of the kernel provide the neccessary cache management so that we can
++ * operate in a portable fashion
++ *
++ * This code is identical to ide_raw_build_sglist in ide-dma.c
++ * however that is not exported
++ */
++
++static int
++sgiioc4_ide_raw_build_sglist(ide_drive_t * drive, struct request *rq)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ struct scatterlist *sg = hwif->sg_table;
++ int nents = 0;
++ ide_task_t *args = rq->special;
++ u8 *virt_addr = rq->buffer;
++ int sector_count = rq->nr_sectors;
++
++ if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
++ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
++ else
++ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
++
++#if 1
++ if (sector_count > 256)
++ BUG();
++
++ if (sector_count > 128) {
++#else
++ while (sector_count > 128) {
++#endif
++ memset(&sg[nents], 0, sizeof (*sg));
++ sg[nents].page = virt_to_page(virt_addr);
++ sg[nents].offset = offset_in_page(virt_addr);
++ sg[nents].length = 128 * SECTOR_SIZE;
++ nents++;
++ virt_addr = virt_addr + (128 * SECTOR_SIZE);
++ sector_count -= 128;
++ }
++ memset(&sg[nents], 0, sizeof (*sg));
++ sg[nents].page = virt_to_page(virt_addr);
++ sg[nents].offset = offset_in_page(virt_addr);
++ sg[nents].length = sector_count * SECTOR_SIZE;
++ nents++;
++
++ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
++}
++
++#ifdef CONFIG_PROC_FS
++
++static int
++sgiioc4_get_info(char *buffer, char **addr, off_t offset, int count)
++{
++ char *p = buffer;
++ unsigned int class_rev;
++ int i = 0;
++
++ while (i < n_sgiioc4_devs) {
++ pci_read_config_dword(sgiioc4_devs[i], PCI_CLASS_REVISION, &class_rev);
++ class_rev &= 0xff;
++
++ if (sgiioc4_devs[i]->device == PCI_DEVICE_ID_SGI_IOC4) {
++ p += sprintf(p,
++ "\n\tSGI IOC4 Chipset rev %d.\n\t"
++ "Chipset has 1 IDE channel and supports 2 devices on that channel.\n\t"
++ "Chipset supports DMA in MultiMode-2 data transfer protocol.\n",
++ class_rev);
++ /* Do we need more info. here? */
++ }
++ i++;
++ }
++
++ return p - buffer;
++}
++
++#endif /* CONFIG_PROC_FS */
++
++static int __devinit
++sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id)
++{
++ unsigned int class_rev;
++ ide_pci_device_t *d = &sgiioc4_chipsets[id->driver_data];
++ if (dev->device != d->device) {
++ printk(KERN_ERR "Error in %s(dev 0x%p | id 0x%p )\n",
++ __FUNCTION__, (void *) dev, (void *) id);
++ BUG();
++ }
++
++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
++ class_rev &= 0xff;
++
++ if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
++ printk(KERN_INFO
++ "Disabling IOC4 IDE Part due to "
++ "unsupported Firmware Rev (%d)",
++ class_rev);
++ printk(KERN_INFO
++ "\nPlease upgrade to Firmware Rev 46 or higher\n");
++ return 0;
++ }
++
++ printk(KERN_INFO "%s: IDE controller at PCI slot %s\n", d->name,
++ dev->slot_name);
++
++ if (pci_init_sgiioc4(dev, d))
++ return 0;
++
++ MOD_INC_USE_COUNT;
++
++ return 0;
++}
++
++static struct pci_device_id sgiioc4_pci_tbl[] = {
++ {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0},
++ {0}
++};
++
++static struct pci_driver driver = {
++ .name = "SGI-IOC4 IDE",
++ .id_table = sgiioc4_pci_tbl,
++ .probe = sgiioc4_init_one,
++};
++
++static int
++sgiioc4_ide_init(void)
++{
++ return ide_pci_register_driver(&driver);
++}
++
++static void
++sgiioc4_ide_exit(void)
++{
++ ide_pci_unregister_driver(&driver);
++}
++
++module_init(sgiioc4_ide_init);
++module_exit(sgiioc4_ide_exit);
++
++MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
++MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/ide/pci/siimage.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/siimage.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1150,20 +1150,6 @@ static void __init init_hwif_siimage (id
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-/**
+- * init_dma_siimage - set up IDE DMA
+- * @hwif: interface
+- * @dmabase: DMA base address to use
+- *
+- * For the SI chips this requires no special set up so we can just
+- * let the IDE DMA core do the usual work.
+- */
+-
+-static void __init init_dma_siimage (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+--- linux-2.6.0-test6/drivers/ide/pci/siimage.h 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/siimage.h 2003-10-05 00:33:24.000000000 -0700
+@@ -44,7 +44,6 @@ static ide_pci_host_proc_t siimage_procs
+ static unsigned int init_chipset_siimage(struct pci_dev *, const char *);
+ static void init_iops_siimage(ide_hwif_t *);
+ static void init_hwif_siimage(ide_hwif_t *);
+-static void init_dma_siimage(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t siimage_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -54,7 +53,6 @@ static ide_pci_device_t siimage_chipsets
+ .init_chipset = init_chipset_siimage,
+ .init_iops = init_iops_siimage,
+ .init_hwif = init_hwif_siimage,
+- .init_dma = init_dma_siimage,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -67,7 +65,6 @@ static ide_pci_device_t siimage_chipsets
+ .init_chipset = init_chipset_siimage,
+ .init_iops = init_iops_siimage,
+ .init_hwif = init_hwif_siimage,
+- .init_dma = init_dma_siimage,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+@@ -80,7 +77,6 @@ static ide_pci_device_t siimage_chipsets
+ .init_chipset = init_chipset_siimage,
+ .init_iops = init_iops_siimage,
+ .init_hwif = init_hwif_siimage,
+- .init_dma = init_dma_siimage,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
+--- linux-2.6.0-test6/drivers/ide/pci/sis5513.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/sis5513.c 2003-10-05 00:33:24.000000000 -0700
+@@ -942,11 +942,6 @@ static void __init init_hwif_sis5513 (id
+ return;
+ }
+
+-static void __init init_dma_sis5513 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+--- linux-2.6.0-test6/drivers/ide/pci/sis5513.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/drivers/ide/pci/sis5513.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@ static ide_pci_host_proc_t sis_procs[] _
+
+ static unsigned int init_chipset_sis5513(struct pci_dev *, const char *);
+ static void init_hwif_sis5513(ide_hwif_t *);
+-static void init_dma_sis5513(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t sis5513_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -37,7 +36,6 @@ static ide_pci_device_t sis5513_chipsets
+ .init_chipset = init_chipset_sis5513,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_sis5513,
+- .init_dma = init_dma_sis5513,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+--- linux-2.6.0-test6/drivers/ide/pci/slc90e66.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/ide/pci/slc90e66.c 2003-10-05 00:33:24.000000000 -0700
+@@ -362,11 +362,6 @@ static void __init init_hwif_slc90e66 (i
+ #endif /* !CONFIG_BLK_DEV_IDEDMA */
+ }
+
+-static void __init init_dma_slc90e66 (ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+
+--- linux-2.6.0-test6/drivers/ide/pci/slc90e66.h 2003-06-14 12:18:05.000000000 -0700
++++ 25/drivers/ide/pci/slc90e66.h 2003-10-05 00:33:24.000000000 -0700
+@@ -29,7 +29,6 @@ static ide_pci_host_proc_t slc90e66_proc
+
+ static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *);
+ static void init_hwif_slc90e66(ide_hwif_t *);
+-static void init_dma_slc90e66(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t slc90e66_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -39,7 +38,6 @@ static ide_pci_device_t slc90e66_chipset
+ .init_chipset = init_chipset_slc90e66,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_slc90e66,
+- .init_dma = init_dma_slc90e66,
+ .channels = 2,
+ .autodma = AUTODMA,
+ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
+--- linux-2.6.0-test6/drivers/ide/pci/via82cxxx.c 2003-08-08 22:55:11.000000000 -0700
++++ 25/drivers/ide/pci/via82cxxx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,6 +1,6 @@
+ /*
+ *
+- * Version 3.37
++ * Version 3.38
+ *
+ * VIA IDE driver for Linux. Supported southbridges:
+ *
+@@ -96,7 +96,6 @@ static struct via_isa_bridge {
+ };
+
+ static struct via_isa_bridge *via_config;
+-static unsigned char via_enabled;
+ static unsigned int via_80w;
+ static unsigned int via_clock;
+ static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+@@ -146,7 +145,7 @@ static int via_get_info(char *buffer, ch
+ via_print("----------VIA BusMastering IDE Configuration"
+ "----------------");
+
+- via_print("Driver Version: 3.37");
++ via_print("Driver Version: 3.38");
+ via_print("South Bridge: VIA %s",
+ via_config->name);
+
+@@ -370,9 +369,6 @@ static int via_set_drive(ide_drive_t *dr
+
+ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
+ {
+- if (!((via_enabled >> HWIF(drive)->channel) & 1))
+- return;
+-
+ if (pio == 255) {
+ via_set_drive(drive,
+ ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+@@ -506,7 +502,6 @@ static unsigned int __init init_chipset_
+ */
+
+ pci_read_config_byte(dev, VIA_IDE_ENABLE, &v);
+- via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0);
+
+ /*
+ * Set up FIFO sizes and thresholds.
+@@ -523,9 +518,9 @@ static unsigned int __init init_chipset_
+ /* Fix FIFO split between channels */
+ if (via_config->flags & VIA_SET_FIFO) {
+ t &= (t & 0x9f);
+- switch (via_enabled) {
+- case 1: t |= 0x00; break; /* 16 on primary */
+- case 2: t |= 0x60; break; /* 16 on secondary */
++ switch (v & 3) {
++ case 2: t |= 0x00; break; /* 16 on primary */
++ case 1: t |= 0x60; break; /* 16 on secondary */
+ case 3: t |= 0x20; break; /* 8 pri 8 sec */
+ }
+ }
+@@ -603,8 +598,8 @@ static void __init init_hwif_via82cxxx(i
+ hwif->mwdma_mask = 0x07;
+ hwif->swdma_mask = 0x07;
+
+- if (!(hwif->udma_four))
+- hwif->udma_four = ((via_enabled & via_80w) >> hwif->channel) & 1;
++ if (!hwif->udma_four)
++ hwif->udma_four = (via_80w >> hwif->channel) & 1;
+ hwif->ide_dma_check = &via82cxxx_ide_dma_check;
+ if (!noautodma)
+ hwif->autodma = 1;
+@@ -612,20 +607,6 @@ static void __init init_hwif_via82cxxx(i
+ hwif->drives[1].autodma = hwif->autodma;
+ }
+
+-/**
+- * init_dma_via82cxxx - set up for IDE DMA
+- * @hwif: IDE interface
+- * @dmabase: DMA base address
+- *
+- * We allow the BM-DMA driver to only work on enabled interfaces.
+- */
+-
+-static void __init init_dma_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase)
+-{
+- if ((via_enabled >> hwif->channel) & 1)
+- ide_setup_dma(hwif, dmabase, 8);
+-}
+-
+ extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
+
+ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+--- linux-2.6.0-test6/drivers/ide/pci/via82cxxx.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/drivers/ide/pci/via82cxxx.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@ static ide_pci_host_proc_t via_procs[] _
+
+ static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *);
+ static void init_hwif_via82cxxx(ide_hwif_t *);
+-static void init_dma_via82cxxx(ide_hwif_t *, unsigned long);
+
+ static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = {
+ { /* 0 */
+@@ -35,9 +34,7 @@ static ide_pci_device_t via82cxxx_chipse
+ .device = PCI_DEVICE_ID_VIA_82C576_1,
+ .name = "VP_IDE",
+ .init_chipset = init_chipset_via82cxxx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_via82cxxx,
+- .init_dma = init_dma_via82cxxx,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+@@ -48,9 +45,7 @@ static ide_pci_device_t via82cxxx_chipse
+ .device = PCI_DEVICE_ID_VIA_82C586_1,
+ .name = "VP_IDE",
+ .init_chipset = init_chipset_via82cxxx,
+- .init_iops = NULL,
+ .init_hwif = init_hwif_via82cxxx,
+- .init_dma = init_dma_via82cxxx,
+ .channels = 2,
+ .autodma = NOAUTODMA,
+ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
+--- linux-2.6.0-test6/drivers/input/input.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/input.c 2003-10-05 00:34:14.000000000 -0700
+@@ -447,9 +447,10 @@ void input_register_device(struct input_
+ list_add_tail(&dev->node, &input_dev_list);
+
+ list_for_each_entry(handler, &input_handler_list, node)
+- if ((id = input_match_device(handler->id_table, dev)))
+- if ((handle = handler->connect(handler, dev, id)))
+- input_link_handle(handle);
++ if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
++ if ((id = input_match_device(handler->id_table, dev)))
++ if ((handle = handler->connect(handler, dev, id)))
++ input_link_handle(handle);
+
+ #ifdef CONFIG_HOTPLUG
+ input_call_hotplug("add", dev);
+@@ -507,9 +508,10 @@ void input_register_handler(struct input
+ list_add_tail(&handler->node, &input_handler_list);
+
+ list_for_each_entry(dev, &input_dev_list, node)
+- if ((id = input_match_device(handler->id_table, dev)))
+- if ((handle = handler->connect(handler, dev, id)))
+- input_link_handle(handle);
++ if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
++ if ((id = input_match_device(handler->id_table, dev)))
++ if ((handle = handler->connect(handler, dev, id)))
++ input_link_handle(handle);
+
+ #ifdef CONFIG_PROC_FS
+ input_devices_state++;
+--- linux-2.6.0-test6/drivers/input/joydev.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/input/joydev.c 2003-10-05 00:34:14.000000000 -0700
+@@ -380,10 +380,6 @@ static struct input_handle *joydev_conne
+ struct joydev *joydev;
+ int i, j, t, minor;
+
+- /* Avoid tablets */
+- if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
+- return NULL;
+-
+ for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
+ if (minor == JOYDEV_MINORS) {
+ printk(KERN_ERR "joydev: no more free joydev devices\n");
+@@ -464,6 +460,15 @@ static void joydev_disconnect(struct inp
+ joydev_free(joydev);
+ }
+
++static struct input_device_id joydev_blacklist[] = {
++ {
++ .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
++ .evbit = { BIT(EV_KEY) },
++ .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
++ }, /* Avoid itouchpads, touchscreens and tablets */
++ { }, /* Terminating entry */
++};
++
+ static struct input_device_id joydev_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+@@ -493,6 +498,7 @@ static struct input_handler joydev_handl
+ .minor = JOYDEV_MINOR_BASE,
+ .name = "joydev",
+ .id_table = joydev_ids,
++ .blacklist = joydev_blacklist,
+ };
+
+ static int __init joydev_init(void)
+--- linux-2.6.0-test6/drivers/input/joystick/analog.c 2003-06-16 22:32:21.000000000 -0700
++++ 25/drivers/input/joystick/analog.c 2003-10-05 00:33:24.000000000 -0700
+@@ -159,7 +159,7 @@ static unsigned int get_time_pit(void)
+ #define DELTA(x,y) ((y)-(x))
+ #define TIME_NAME "TSC"
+ #elif __alpha__
+-#define GET_TIME(x) do { x = get_cycles(x); } while (0)
++#define GET_TIME(x) do { x = get_cycles(); } while (0)
+ #define DELTA(x,y) ((y)-(x))
+ #define TIME_NAME "PCC"
+ #else
+--- linux-2.6.0-test6/drivers/input/keyboard/atkbd.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/keyboard/atkbd.c 2003-10-05 00:36:37.000000000 -0700
+@@ -369,10 +369,11 @@ static int atkbd_command(struct atkbd *a
+ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+ {
+ struct atkbd *atkbd = dev->private;
+- struct { int p; u8 v; } period[] =
+- { {30, 0x00}, {25, 0x02}, {20, 0x04}, {15, 0x08}, {10, 0x0c}, {7, 0x10}, {5, 0x14}, {0, 0x14} };
+- struct { int d; u8 v; } delay[] =
+- { {1000, 0x60}, {750, 0x40}, {500, 0x20}, {250, 0x00}, {0, 0x00} };
++ const short period[32] =
++ { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
++ 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
++ const short delay[4] =
++ { 250, 500, 750, 1000 };
+ char param[2];
+ int i, j;
+
+@@ -406,11 +407,11 @@ static int atkbd_event(struct input_dev
+ if (atkbd_softrepeat) return 0;
+
+ i = j = 0;
+- while (period[i].p > dev->rep[REP_PERIOD]) i++;
+- while (delay[j].d > dev->rep[REP_DELAY]) j++;
+- dev->rep[REP_PERIOD] = period[i].p;
+- dev->rep[REP_DELAY] = delay[j].d;
+- param[0] = period[i].v | delay[j].v;
++ while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
++ while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
++ dev->rep[REP_PERIOD] = period[i];
++ dev->rep[REP_DELAY] = delay[j];
++ param[0] = i | (j << 5);
+ atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
+
+ return 0;
+@@ -576,6 +577,7 @@ static void atkbd_disconnect(struct seri
+ struct atkbd *atkbd = serio->private;
+ input_unregister_device(&atkbd->dev);
+ serio_close(serio);
++ serio->private = NULL;
+ kfree(atkbd);
+ }
+
+@@ -634,6 +636,7 @@ static void atkbd_connect(struct serio *
+ serio->private = atkbd;
+
+ if (serio_open(serio, dev)) {
++ serio->private = NULL;
+ kfree(atkbd);
+ return;
+ }
+@@ -642,6 +645,7 @@ static void atkbd_connect(struct serio *
+
+ if (atkbd_probe(atkbd)) {
+ serio_close(serio);
++ serio->private = NULL;
+ kfree(atkbd);
+ return;
+ }
+--- linux-2.6.0-test6/drivers/input/keyboard/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/keyboard/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -12,10 +12,11 @@ config INPUT_KEYBOARD
+ If unsure, say Y.
+
+ config KEYBOARD_ATKBD
+- tristate "AT keyboard support" if EMBEDDED || !X86
++ tristate "AT keyboard support" if !PC
+ default y
+ depends on INPUT && INPUT_KEYBOARD
+- select SERIO_I8042
++ select SERIO
++ select SERIO_I8042 if PC
+ help
+ Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
+ you'll need this, unless you have a different type keyboard (USB, ADB
+--- linux-2.6.0-test6/drivers/input/mouse/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/mouse/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -15,7 +15,8 @@ config MOUSE_PS2
+ tristate "PS/2 mouse"
+ default y
+ depends on INPUT && INPUT_MOUSE
+- select SERIO_I8042
++ select SERIO
++ select SERIO_I8042 if PC
+ ---help---
+ Say Y here if you have a PS/2 mouse connected to your system. This
+ includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
+--- linux-2.6.0-test6/drivers/input/mouse/logips2pp.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/drivers/input/mouse/logips2pp.c 2003-10-05 00:34:15.000000000 -0700
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/input.h>
++#include <linux/serio.h>
+ #include "psmouse.h"
+ #include "logips2pp.h"
+
+--- linux-2.6.0-test6/drivers/input/mouse/psmouse-base.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/mouse/psmouse-base.c 2003-10-05 00:34:15.000000000 -0700
+@@ -141,7 +141,8 @@ static irqreturn_t psmouse_interrupt(str
+ goto out;
+ }
+
+- if (psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
++ if (psmouse->state == PSMOUSE_ACTIVATED &&
++ psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
+ printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
+ psmouse->pktcnt = 0;
+@@ -276,24 +277,18 @@ static int psmouse_extensions(struct psm
+ return PSMOUSE_PS2;
+
+ /*
+- * Try Synaptics TouchPad magic ID
++ * Try Synaptics TouchPad
+ */
+-
+- param[0] = 0;
+- psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+- psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+- psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+- psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+- psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+-
+- if (param[1] == 0x47) {
++ if (synaptics_detect(psmouse) == 0) {
+ psmouse->vendor = "Synaptics";
+ psmouse->name = "TouchPad";
+- if (!synaptics_init(psmouse))
++
++#if CONFIG_MOUSE_PS2_SYNAPTICS
++ if (synaptics_init(psmouse) == 0)
+ return PSMOUSE_SYNAPTICS;
+- else
+- return PSMOUSE_PS2;
+- }
++#endif
++ return PSMOUSE_PS2;
++ }
+
+ /*
+ * Try Genius NetMouse magic init.
+@@ -519,7 +514,18 @@ static void psmouse_disconnect(struct se
+ struct psmouse *psmouse = serio->private;
+
+ psmouse->state = PSMOUSE_IGNORE;
+- synaptics_disconnect(psmouse);
++
++ if (psmouse->ptport) {
++ if (psmouse->ptport->deactivate)
++ psmouse->ptport->deactivate(psmouse);
++ __serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */
++ kfree(psmouse->ptport);
++ psmouse->ptport = NULL;
++ }
++
++ if (psmouse->disconnect)
++ psmouse->disconnect(psmouse);
++
+ input_unregister_device(&psmouse->dev);
+ serio_close(serio);
+ kfree(psmouse);
+@@ -532,20 +538,10 @@ static void psmouse_disconnect(struct se
+ static int psmouse_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
+ {
+ struct psmouse *psmouse = dev->data;
+- struct serio_dev *ser_dev = psmouse->serio->dev;
+-
+- synaptics_disconnect(psmouse);
+-
+- /* We need to reopen the serio port to reinitialize the i8042 controller */
+- serio_close(psmouse->serio);
+- serio_open(psmouse->serio, ser_dev);
+-
+- /* Probe and re-initialize the mouse */
+- psmouse_probe(psmouse);
+- psmouse_initialize(psmouse);
+- synaptics_pt_init(psmouse);
+- psmouse_activate(psmouse);
+
++ psmouse->state = PSMOUSE_IGNORE;
++ serio_reconnect(psmouse->serio);
++
+ return 0;
+ }
+
+@@ -553,7 +549,6 @@ static int psmouse_pm_callback(struct pm
+ * psmouse_connect() is a callback from the serio module when
+ * an unhandled serio port is found.
+ */
+-
+ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
+ {
+ struct psmouse *psmouse;
+@@ -578,7 +573,6 @@ static void psmouse_connect(struct serio
+ psmouse->dev.private = psmouse;
+
+ serio->private = psmouse;
+-
+ if (serio_open(serio, dev)) {
+ kfree(psmouse);
+ return;
+@@ -590,10 +584,12 @@ static void psmouse_connect(struct serio
+ return;
+ }
+
+- pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
+- if (pmdev) {
+- psmouse->dev.pm_dev = pmdev;
+- pmdev->data = psmouse;
++ if (serio->type != SERIO_PS_PSTHRU) {
++ pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
++ if (pmdev) {
++ psmouse->dev.pm_dev = pmdev;
++ pmdev->data = psmouse;
++ }
+ }
+
+ sprintf(psmouse->devname, "%s %s %s",
+@@ -614,14 +610,70 @@ static void psmouse_connect(struct serio
+
+ psmouse_initialize(psmouse);
+
+- synaptics_pt_init(psmouse);
++ if (psmouse->ptport) {
++ printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys);
++ __serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */
++ if (psmouse->ptport->activate)
++ psmouse->ptport->activate(psmouse);
++ }
++
++ psmouse_activate(psmouse);
++}
+
++
++static int psmouse_reconnect(struct serio *serio)
++{
++ struct psmouse *psmouse = serio->private;
++ struct serio_dev *dev = serio->dev;
++ int old_type = psmouse->type;
++
++ if (!dev) {
++ printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
++ return -1;
++ }
++
++ /* We need to reopen the serio port to reinitialize the i8042 controller */
++ serio_close(serio);
++ if (serio_open(serio, dev)) {
++ /* do a disconnect here as serio_open leaves dev as NULL so disconnect
++ * will not be called automatically later
++ */
++ psmouse_disconnect(serio);
++ return -1;
++ }
++
++ psmouse->state = PSMOUSE_NEW_DEVICE;
++ psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0;
++ if (psmouse->reconnect) {
++ if (psmouse->reconnect(psmouse))
++ return -1;
++ } else if (psmouse_probe(psmouse) != old_type)
++ return -1;
++
++ /* ok, the device type (and capabilities) match the old one,
++ * we can continue using it, complete intialization
++ */
++ psmouse->type = old_type;
++ psmouse_initialize(psmouse);
++
++ if (psmouse->ptport) {
++ if (psmouse_reconnect(&psmouse->ptport->serio)) {
++ __serio_unregister_port(&psmouse->ptport->serio);
++ __serio_register_port(&psmouse->ptport->serio);
++ if (psmouse->ptport->activate)
++ psmouse->ptport->activate(psmouse);
++ }
++ }
++
+ psmouse_activate(psmouse);
++ return 0;
+ }
+
++
+ static struct serio_dev psmouse_dev = {
+ .interrupt = psmouse_interrupt,
+ .connect = psmouse_connect,
++ .reconnect = psmouse_reconnect,
+ .disconnect = psmouse_disconnect,
+ .cleanup = psmouse_cleanup,
+ };
+--- linux-2.6.0-test6/drivers/input/mouse/psmouse.h 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/mouse/psmouse.h 2003-10-05 00:34:15.000000000 -0700
+@@ -22,10 +22,20 @@
+ #define PSMOUSE_ACTIVATED 1
+ #define PSMOUSE_IGNORE 2
+
++struct psmouse;
++
++struct psmouse_ptport {
++ struct serio serio;
++
++ void (*activate)(struct psmouse *parent);
++ void (*deactivate)(struct psmouse *parent);
++};
++
+ struct psmouse {
+ void *private;
+ struct input_dev dev;
+ struct serio *serio;
++ struct psmouse_ptport *ptport;
+ char *vendor;
+ char *name;
+ unsigned char cmdbuf[8];
+@@ -41,6 +51,9 @@ struct psmouse {
+ char error;
+ char devname[64];
+ char phys[32];
++
++ int (*reconnect)(struct psmouse *psmouse);
++ void (*disconnect)(struct psmouse *psmouse);
+ };
+
+ #define PSMOUSE_PS2 1
+--- linux-2.6.0-test6/drivers/input/mouse/synaptics.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/mouse/synaptics.c 2003-10-05 00:34:15.000000000 -0700
+@@ -2,7 +2,8 @@
+ * Synaptics TouchPad PS/2 mouse driver
+ *
+ * 2003 Dmitry Torokhov <dtor@mail.ru>
+- * Added support for pass-through port
++ * Added support for pass-through port. Special thanks to Peter Berg Larsen
++ * for explaining various Synaptics quirks.
+ *
+ * 2003 Peter Osterlund <petero2@telia.com>
+ * Ported to 2.5 input device infrastructure.
+@@ -194,9 +195,7 @@ static void print_ident(struct synaptics
+
+ static int synaptics_query_hardware(struct psmouse *psmouse)
+ {
+- struct synaptics_data *priv = psmouse->private;
+ int retries = 0;
+- int mode;
+
+ while ((retries++ < 3) && synaptics_reset(psmouse))
+ printk(KERN_ERR "synaptics reset failed\n");
+@@ -207,8 +206,15 @@ static int synaptics_query_hardware(stru
+ return -1;
+ if (synaptics_capability(psmouse))
+ return -1;
++
++ return 0;
++}
+
+- mode = SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
++static int synaptics_set_mode(struct psmouse *psmouse, int mode)
++{
++ struct synaptics_data *priv = psmouse->private;
++
++ mode |= SYN_BIT_ABSOLUTE_MODE | SYN_BIT_HIGH_RATE;
+ if (SYN_ID_MAJOR(priv->identity) >= 4)
+ mode |= SYN_BIT_DISABLE_GESTURE;
+ if (SYN_CAP_EXTENDED(priv->capabilities))
+@@ -265,49 +271,38 @@ static void synaptics_pass_pt_packet(str
+ }
+ }
+
+-int synaptics_pt_init(struct psmouse *psmouse)
++static void synaptics_pt_activate(struct psmouse *psmouse)
+ {
+- struct synaptics_data *priv = psmouse->private;
+- struct serio *port;
+- struct psmouse *child;
++ struct psmouse *child = psmouse->ptport->serio.private;
++
++ /* adjust the touchpad to child's choice of protocol */
++ if (child && child->type >= PSMOUSE_GENPS) {
++ if (synaptics_set_mode(psmouse, SYN_BIT_FOUR_BYTE_CLIENT))
++ printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
++ }
++}
+
+- if (psmouse->type != PSMOUSE_SYNAPTICS)
+- return -1;
+- if (!SYN_CAP_EXTENDED(priv->capabilities))
+- return -1;
+- if (!SYN_CAP_PASS_THROUGH(priv->capabilities))
+- return -1;
++static void synaptics_pt_create(struct psmouse *psmouse)
++{
++ struct psmouse_ptport *port;
+
+- priv->ptport = port = kmalloc(sizeof(struct serio), GFP_KERNEL);
++ psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
+ if (!port) {
+- printk(KERN_ERR "synaptics: not enough memory to allocate serio port\n");
+- return -1;
++ printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
++ return;
+ }
+
+- memset(port, 0, sizeof(struct serio));
+- port->type = SERIO_PS_PSTHRU;
+- port->name = "Synaptics pass-through";
+- port->phys = "synaptics-pt/serio0";
+- port->write = synaptics_pt_write;
+- port->open = synaptics_pt_open;
+- port->close = synaptics_pt_close;
+- port->driver = psmouse;
++ memset(port, 0, sizeof(struct psmouse_ptport));
+
+- printk(KERN_INFO "serio: %s port at %s\n", port->name, psmouse->phys);
+- serio_register_slave_port(port);
++ port->serio.type = SERIO_PS_PSTHRU;
++ port->serio.name = "Synaptics pass-through";
++ port->serio.phys = "synaptics-pt/serio0";
++ port->serio.write = synaptics_pt_write;
++ port->serio.open = synaptics_pt_open;
++ port->serio.close = synaptics_pt_close;
++ port->serio.driver = psmouse;
+
+- /* adjust the touchpad to child's choice of protocol */
+- child = port->private;
+- if (child && child->type >= PSMOUSE_GENPS) {
+- if (synaptics_mode_cmd(psmouse, (SYN_BIT_ABSOLUTE_MODE |
+- SYN_BIT_HIGH_RATE |
+- SYN_BIT_DISABLE_GESTURE |
+- SYN_BIT_FOUR_BYTE_CLIENT |
+- SYN_BIT_W_MODE)))
+- printk(KERN_INFO "synaptics: failed to enable 4-byte guest protocol\n");
+- }
+-
+- return 0;
++ port->activate = synaptics_pt_activate;
+ }
+
+ /*****************************************************************************
+@@ -371,27 +366,82 @@ static void set_input_params(struct inpu
+ clear_bit(REL_Y, dev->relbit);
+ }
+
++static void synaptics_disconnect(struct psmouse *psmouse)
++{
++ synaptics_mode_cmd(psmouse, 0);
++ kfree(psmouse->private);
++}
++
++static int synaptics_reconnect(struct psmouse *psmouse)
++{
++ struct synaptics_data *priv = psmouse->private;
++ struct synaptics_data old_priv = *priv;
++
++ if (synaptics_detect(psmouse))
++ return -1;
++
++ if (synaptics_query_hardware(psmouse)) {
++ printk(KERN_ERR "Unable to query Synaptics hardware.\n");
++ return -1;
++ }
++
++ if (old_priv.identity != priv->identity ||
++ old_priv.model_id != priv->model_id ||
++ old_priv.capabilities != priv->capabilities ||
++ old_priv.ext_cap != priv->ext_cap)
++ return -1;
++
++ if (synaptics_set_mode(psmouse, 0)) {
++ printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
++ return -1;
++ }
++
++ return 0;
++}
++
++int synaptics_detect(struct psmouse *psmouse)
++{
++ unsigned char param[4];
++
++ param[0] = 0;
++
++ psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
++ psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
++ psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
++ psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
++ psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
++
++ return param[1] == 0x47 ? 0 : -1;
++}
++
+ int synaptics_init(struct psmouse *psmouse)
+ {
+ struct synaptics_data *priv;
+
+-#ifndef CONFIG_MOUSE_PS2_SYNAPTICS
+- return -1;
+-#endif
+-
+ psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL);
+ if (!priv)
+ return -1;
+ memset(priv, 0, sizeof(struct synaptics_data));
+
+ if (synaptics_query_hardware(psmouse)) {
+- printk(KERN_ERR "Unable to query/initialize Synaptics hardware.\n");
++ printk(KERN_ERR "Unable to query Synaptics hardware.\n");
++ goto init_fail;
++ }
++
++ if (synaptics_set_mode(psmouse, 0)) {
++ printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
+ goto init_fail;
+ }
+
++ if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
++ synaptics_pt_create(psmouse);
++
+ print_ident(priv);
+ set_input_params(&psmouse->dev, priv);
+
++ psmouse->disconnect = synaptics_disconnect;
++ psmouse->reconnect = synaptics_reconnect;
++
+ return 0;
+
+ init_fail:
+@@ -399,36 +449,13 @@ int synaptics_init(struct psmouse *psmou
+ return -1;
+ }
+
+-void synaptics_disconnect(struct psmouse *psmouse)
+-{
+- struct synaptics_data *priv = psmouse->private;
+-
+- if (psmouse->type == PSMOUSE_SYNAPTICS && priv) {
+- synaptics_mode_cmd(psmouse, 0);
+- if (priv->ptport) {
+- serio_unregister_slave_port(priv->ptport);
+- kfree(priv->ptport);
+- }
+- kfree(priv);
+- }
+-}
+-
+ /*****************************************************************************
+ * Functions to interpret the absolute mode packets
+ ****************************************************************************/
+
+ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
+ {
+- hw->up = 0;
+- hw->down = 0;
+- hw->b0 = 0;
+- hw->b1 = 0;
+- hw->b2 = 0;
+- hw->b3 = 0;
+- hw->b4 = 0;
+- hw->b5 = 0;
+- hw->b6 = 0;
+- hw->b7 = 0;
++ memset(hw, 0, sizeof(struct synaptics_hw_state));
+
+ if (SYN_MODEL_NEWABS(priv->model_id)) {
+ hw->x = (((buf[3] & 0x10) << 8) |
+@@ -570,64 +597,47 @@ static void synaptics_process_packet(str
+ input_sync(dev);
+ }
+
++static int synaptics_validate_byte(struct psmouse *psmouse)
++{
++ static unsigned char newabs_mask[] = { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
++ static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
++ static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
++ static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
++ struct synaptics_data *priv = psmouse->private;
++ int idx = psmouse->pktcnt - 1;
++
++ if (SYN_MODEL_NEWABS(priv->model_id))
++ return (psmouse->packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
++ else
++ return (psmouse->packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
++}
++
+ void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
+ {
+ struct input_dev *dev = &psmouse->dev;
+ struct synaptics_data *priv = psmouse->private;
+- unsigned char data = psmouse->packet[psmouse->pktcnt - 1];
+- int newabs = SYN_MODEL_NEWABS(priv->model_id);
+
+ input_regs(dev, regs);
+
+- switch (psmouse->pktcnt) {
+- case 1:
+- if (newabs ? ((data & 0xC8) != 0x80) : ((data & 0xC0) != 0xC0)) {
+- printk(KERN_WARNING "Synaptics driver lost sync at 1st byte\n");
+- goto bad_sync;
+- }
+- break;
+- case 2:
+- if (!newabs && ((data & 0x60) != 0x00)) {
+- printk(KERN_WARNING "Synaptics driver lost sync at 2nd byte\n");
+- goto bad_sync;
+- }
+- break;
+- case 4:
+- if (newabs ? ((data & 0xC8) != 0xC0) : ((data & 0xC0) != 0x80)) {
+- printk(KERN_WARNING "Synaptics driver lost sync at 4th byte\n");
+- goto bad_sync;
+- }
+- break;
+- case 5:
+- if (!newabs && ((data & 0x60) != 0x00)) {
+- printk(KERN_WARNING "Synaptics driver lost sync at 5th byte\n");
+- goto bad_sync;
+- }
+- break;
+- default:
+- if (psmouse->pktcnt < 6)
+- break; /* Wait for full packet */
+-
++ if (psmouse->pktcnt >= 6) { /* Full packet received */
+ if (priv->out_of_sync) {
+ priv->out_of_sync = 0;
+ printk(KERN_NOTICE "Synaptics driver resynced.\n");
+ }
+
+- if (priv->ptport && synaptics_is_pt_packet(psmouse->packet))
+- synaptics_pass_pt_packet(priv->ptport, psmouse->packet);
++ if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
++ synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
+ else
+ synaptics_process_packet(psmouse);
+-
+ psmouse->pktcnt = 0;
+- break;
+- }
+- return;
+
+- bad_sync:
+- priv->out_of_sync++;
+- psmouse->pktcnt = 0;
+- if (psmouse_resetafter > 0 && priv->out_of_sync == psmouse_resetafter) {
+- psmouse->state = PSMOUSE_IGNORE;
+- serio_rescan(psmouse->serio);
++ } else if (psmouse->pktcnt && !synaptics_validate_byte(psmouse)) {
++ printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
++ psmouse->pktcnt = 0;
++ if (++priv->out_of_sync == psmouse_resetafter) {
++ psmouse->state = PSMOUSE_IGNORE;
++ printk(KERN_NOTICE "synaptics: issuing reconnect request\n");
++ serio_reconnect(psmouse->serio);
++ }
+ }
+ }
+--- linux-2.6.0-test6/drivers/input/mouse/synaptics.h 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/mouse/synaptics.h 2003-10-05 00:34:15.000000000 -0700
+@@ -9,11 +9,9 @@
+ #ifndef _SYNAPTICS_H
+ #define _SYNAPTICS_H
+
+-
+ extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
++extern int synaptics_detect(struct psmouse *psmouse);
+ extern int synaptics_init(struct psmouse *psmouse);
+-extern int synaptics_pt_init(struct psmouse *psmouse);
+-extern void synaptics_disconnect(struct psmouse *psmouse);
+
+ /* synaptics queries */
+ #define SYN_QUE_IDENTIFY 0x00
+@@ -105,8 +103,6 @@ struct synaptics_data {
+ /* Data for normal processing */
+ unsigned int out_of_sync; /* # of packets out of sync */
+ int old_w; /* Previous w value */
+-
+- struct serio *ptport; /* pass-through port */
+ };
+
+ #endif /* _SYNAPTICS_H */
+--- linux-2.6.0-test6/drivers/input/serio/serio.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/input/serio/serio.c 2003-10-05 00:34:15.000000000 -0700
+@@ -49,14 +49,15 @@ MODULE_LICENSE("GPL");
+
+ EXPORT_SYMBOL(serio_interrupt);
+ EXPORT_SYMBOL(serio_register_port);
+-EXPORT_SYMBOL(serio_register_slave_port);
++EXPORT_SYMBOL(__serio_register_port);
+ EXPORT_SYMBOL(serio_unregister_port);
+-EXPORT_SYMBOL(serio_unregister_slave_port);
++EXPORT_SYMBOL(__serio_unregister_port);
+ EXPORT_SYMBOL(serio_register_device);
+ EXPORT_SYMBOL(serio_unregister_device);
+ EXPORT_SYMBOL(serio_open);
+ EXPORT_SYMBOL(serio_close);
+ EXPORT_SYMBOL(serio_rescan);
++EXPORT_SYMBOL(serio_reconnect);
+
+ struct serio_event {
+ int type;
+@@ -83,10 +84,20 @@ static void serio_find_dev(struct serio
+ }
+
+ #define SERIO_RESCAN 1
++#define SERIO_RECONNECT 2
+
+ static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
+ static DECLARE_COMPLETION(serio_exited);
+
++static void serio_invalidate_pending_events(struct serio *serio)
++{
++ struct serio_event *event;
++
++ list_for_each_entry(event, &serio_event_list, node)
++ if (event->serio == serio)
++ event->serio = NULL;
++}
++
+ void serio_handle_events(void)
+ {
+ struct list_head *node, *next;
+@@ -95,17 +106,27 @@ void serio_handle_events(void)
+ list_for_each_safe(node, next, &serio_event_list) {
+ event = container_of(node, struct serio_event, node);
+
++ down(&serio_sem);
++ if (event->serio == NULL)
++ goto event_done;
++
+ switch (event->type) {
++ case SERIO_RECONNECT :
++ if (event->serio->dev && event->serio->dev->reconnect)
++ if (event->serio->dev->reconnect(event->serio) == 0)
++ break;
++ /* reconnect failed - fall through to rescan */
++
+ case SERIO_RESCAN :
+- down(&serio_sem);
+ if (event->serio->dev && event->serio->dev->disconnect)
+ event->serio->dev->disconnect(event->serio);
+ serio_find_dev(event->serio);
+- up(&serio_sem);
+ break;
+ default:
+ break;
+ }
++event_done:
++ up(&serio_sem);
+ list_del_init(node);
+ kfree(event);
+ }
+@@ -130,18 +151,27 @@ static int serio_thread(void *nothing)
+ complete_and_exit(&serio_exited, 0);
+ }
+
+-void serio_rescan(struct serio *serio)
++static void serio_queue_event(struct serio *serio, int event_type)
+ {
+ struct serio_event *event;
+
+- if (!(event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC)))
+- return;
++ if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
++ event->type = event_type;
++ event->serio = serio;
+
+- event->type = SERIO_RESCAN;
+- event->serio = serio;
++ list_add_tail(&event->node, &serio_event_list);
++ wake_up(&serio_wait);
++ }
++}
+
+- list_add_tail(&event->node, &serio_event_list);
+- wake_up(&serio_wait);
++void serio_rescan(struct serio *serio)
++{
++ serio_queue_event(serio, SERIO_RESCAN);
++}
++
++void serio_reconnect(struct serio *serio)
++{
++ serio_queue_event(serio, SERIO_RECONNECT);
+ }
+
+ irqreturn_t serio_interrupt(struct serio *serio,
+@@ -163,17 +193,16 @@ irqreturn_t serio_interrupt(struct serio
+ void serio_register_port(struct serio *serio)
+ {
+ down(&serio_sem);
+- list_add_tail(&serio->node, &serio_list);
+- serio_find_dev(serio);
++ __serio_register_port(serio);
+ up(&serio_sem);
+ }
+
+ /*
+- * Same as serio_register_port but does not try to acquire serio_sem.
+- * Should be used when registering a serio from other input device's
++ * Should only be called directly if serio_sem has already been taken,
++ * for example when unregistering a serio from other input device's
+ * connect() function.
+ */
+-void serio_register_slave_port(struct serio *serio)
++void __serio_register_port(struct serio *serio)
+ {
+ list_add_tail(&serio->node, &serio_list);
+ serio_find_dev(serio);
+@@ -182,19 +211,18 @@ void serio_register_slave_port(struct se
+ void serio_unregister_port(struct serio *serio)
+ {
+ down(&serio_sem);
+- list_del_init(&serio->node);
+- if (serio->dev && serio->dev->disconnect)
+- serio->dev->disconnect(serio);
++ __serio_unregister_port(serio);
+ up(&serio_sem);
+ }
+
+ /*
+- * Same as serio_unregister_port but does not try to acquire serio_sem.
+- * Should be used when unregistering a serio from other input device's
++ * Should only be called directly if serio_sem has already been taken,
++ * for example when unregistering a serio from other input device's
+ * disconnect() function.
+ */
+-void serio_unregister_slave_port(struct serio *serio)
++void __serio_unregister_port(struct serio *serio)
+ {
++ serio_invalidate_pending_events(serio);
+ list_del_init(&serio->node);
+ if (serio->dev && serio->dev->disconnect)
+ serio->dev->disconnect(serio);
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/debuglib.h 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/debuglib.h 2003-10-05 00:33:24.000000000 -0700
+@@ -103,28 +103,28 @@
+ #define DL_TO_KERNEL 0x40000000
+
+ #ifdef DIVA_NO_DEBUGLIB
+-#define myDbgPrint_LOG(x,...) do { } while(0);
+-#define myDbgPrint_FTL(x,...) do { } while(0);
+-#define myDbgPrint_ERR(x,...) do { } while(0);
+-#define myDbgPrint_TRC(x,...) do { } while(0);
+-#define myDbgPrint_MXLOG(x,...) do { } while(0);
+-#define myDbgPrint_EVL(x,...) do { } while(0);
+-#define myDbgPrint_REG(x,...) do { } while(0);
+-#define myDbgPrint_MEM(x,...) do { } while(0);
+-#define myDbgPrint_SPL(x,...) do { } while(0);
+-#define myDbgPrint_IRP(x,...) do { } while(0);
+-#define myDbgPrint_TIM(x,...) do { } while(0);
+-#define myDbgPrint_BLK(x,...) do { } while(0);
+-#define myDbgPrint_TAPI(x,...) do { } while(0);
+-#define myDbgPrint_NDIS(x,...) do { } while(0);
+-#define myDbgPrint_CONN(x,...) do { } while(0);
+-#define myDbgPrint_STAT(x,...) do { } while(0);
+-#define myDbgPrint_SEND(x,...) do { } while(0);
+-#define myDbgPrint_RECV(x,...) do { } while(0);
+-#define myDbgPrint_PRV0(x,...) do { } while(0);
+-#define myDbgPrint_PRV1(x,...) do { } while(0);
+-#define myDbgPrint_PRV2(x,...) do { } while(0);
+-#define myDbgPrint_PRV3(x,...) do { } while(0);
++#define myDbgPrint_LOG(x...) do { } while(0);
++#define myDbgPrint_FTL(x...) do { } while(0);
++#define myDbgPrint_ERR(x...) do { } while(0);
++#define myDbgPrint_TRC(x...) do { } while(0);
++#define myDbgPrint_MXLOG(x...) do { } while(0);
++#define myDbgPrint_EVL(x...) do { } while(0);
++#define myDbgPrint_REG(x...) do { } while(0);
++#define myDbgPrint_MEM(x...) do { } while(0);
++#define myDbgPrint_SPL(x...) do { } while(0);
++#define myDbgPrint_IRP(x...) do { } while(0);
++#define myDbgPrint_TIM(x...) do { } while(0);
++#define myDbgPrint_BLK(x...) do { } while(0);
++#define myDbgPrint_TAPI(x...) do { } while(0);
++#define myDbgPrint_NDIS(x...) do { } while(0);
++#define myDbgPrint_CONN(x...) do { } while(0);
++#define myDbgPrint_STAT(x...) do { } while(0);
++#define myDbgPrint_SEND(x...) do { } while(0);
++#define myDbgPrint_RECV(x...) do { } while(0);
++#define myDbgPrint_PRV0(x...) do { } while(0);
++#define myDbgPrint_PRV1(x...) do { } while(0);
++#define myDbgPrint_PRV2(x...) do { } while(0);
++#define myDbgPrint_PRV3(x...) do { } while(0);
+ #define DBG_TEST(func,args) do { } while(0);
+ #define DBG_EVL_ID(args) do { } while(0);
+
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/divamnt.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/divamnt.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * Driver for Eicon DIVA Server ISDN cards.
+ * Maint module
+@@ -24,10 +24,9 @@
+ #include "platform.h"
+ #include "di_defs.h"
+ #include "divasync.h"
+-#include "di_defs.h"
+ #include "debug_if.h"
+
+-static char *main_revision = "$Revision: 1.1.4.1 $";
++static char *main_revision = "$Revision: 1.1.4.1 $";
+
+ static int major;
+
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/divasmain.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/divasmain.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * Low level driver for Eicon DIVA Server ISDN cards.
+ *
+@@ -9,13 +9,11 @@
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+-#define __KERNEL_SYSCALLS__
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+-#include <linux/unistd.h>
+ #include <linux/devfs_fs_kernel.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -43,7 +41,7 @@
+ #include "diva_dma.h"
+ #include "diva_pci.h"
+
+-static char *main_revision = "$Revision: 1.1.4.1 $";
++static char *main_revision = "$Revision: 1.1.4.1 $";
+
+ static int major;
+
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/dqueue.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/dqueue.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,10 +1,10 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * Driver for Eicon DIVA Server ISDN cards.
+ * User Mode IDI Interface
+ *
+- * Copyright 2000,2001 by Armin Schindler (mac@melware.de)
+- * Copyright 2000,2001 Cytronics & Melware (info@melware.de)
++ * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
++ * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/mntfunc.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/mntfunc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * Driver for Eicon DIVA Server ISDN cards.
+ * Maint module
+@@ -14,7 +14,6 @@
+ #include "platform.h"
+ #include "di_defs.h"
+ #include "divasync.h"
+-#include "di_defs.h"
+ #include "debug_if.h"
+
+ extern char *DRIVERRELEASE_MNT;
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/os_capi.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/os_capi.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,10 +1,10 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * ISDN interface module for Eicon active cards DIVA.
+ * CAPI Interface OS include files
+ *
+- * Copyright 2000-2002 by Armin Schindler (mac@melware.de)
+- * Copyright 2000-2002 Cytronics & Melware (info@melware.de)
++ * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
++ * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+--- linux-2.6.0-test6/drivers/isdn/hardware/eicon/platform.h 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/hardware/eicon/platform.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,4 +1,4 @@
+-/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
++/* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ *
+ * platform.h
+ *
+@@ -19,7 +19,6 @@
+ #endif
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/drivers/isdn/i4l/isdn_common.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/isdn/i4l/isdn_common.c 2003-10-05 00:33:24.000000000 -0700
+@@ -2229,8 +2229,10 @@ static int __init isdn_init(void)
+ isdn_info_update();
+ return 0;
+
+-/* err_tty_modem:*/
++#ifdef CONFIG_ISDN_PPP
++ err_tty_modem:
+ isdn_tty_exit();
++#endif
+ err_cleanup_devfs:
+ isdn_cleanup_devfs();
+ unregister_chrdev(ISDN_MAJOR, "isdn");
+--- linux-2.6.0-test6/drivers/mca/mca-legacy.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/mca/mca-legacy.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,7 @@
+
+ #include <linux/module.h>
+ #include <linux/device.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <asm/io.h>
+
+ /* NOTE: This structure is stack allocated */
+--- linux-2.6.0-test6/drivers/mca/mca-proc.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/mca/mca-proc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -120,12 +120,13 @@ static int mca_default_procfn(char* buf,
+ len += sprintf(buf+len, "Id: %02x%02x\n",
+ mca_dev->pos[1], mca_dev->pos[0]);
+ len += sprintf(buf+len, "Enabled: %s\nPOS: ",
+- mca_isenabled(slot) ? "Yes" : "No");
++ mca_device_status(mca_dev) == MCA_ADAPTER_NORMAL ?
++ "Yes" : "No");
+ for(i=0; i<8; i++) {
+ len += sprintf(buf+len, "%02x ", mca_dev->pos[i]);
+ }
+ len += sprintf(buf+len, "\nDriver Installed: %s",
+- mca_is_adapter_used(slot) ? "Yes" : "No");
++ mca_device_claimed(mca_dev) ? "Yes" : "No");
+ buf[len++] = '\n';
+ buf[len] = 0;
+
+@@ -189,6 +190,7 @@ void __init mca_do_proc_init(void)
+ /* Initialize /proc/mca entries for existing adapters */
+
+ for(i = 0; i < MCA_NUMADAPTERS; i++) {
++ enum MCA_AdapterStatus status;
+ mca_dev = mca_find_device_by_slot(i);
+ if(!mca_dev)
+ continue;
+@@ -200,7 +202,10 @@ void __init mca_do_proc_init(void)
+ else if(i == MCA_INTEGSCSI) sprintf(mca_dev->procname,"scsi");
+ else if(i == MCA_MOTHERBOARD) sprintf(mca_dev->procname,"planar");
+
+- if(!mca_isadapter(i)) continue;
++ status = mca_device_status(mca_dev);
++ if (status != MCA_ADAPTER_NORMAL &&
++ status != MCA_ADAPTER_DISABLED)
++ continue;
+
+ node = create_proc_read_entry(mca_dev->procname, 0, proc_mca,
+ mca_read_proc, (void *)mca_dev);
+--- linux-2.6.0-test6/drivers/md/dm.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/md/dm.c 2003-10-05 00:34:01.000000000 -0700
+@@ -160,20 +160,16 @@ static void __exit dm_exit(void)
+ /*
+ * Block device functions
+ */
+-static int dm_blk_open(struct inode *inode, struct file *file)
++static int dm_blk_open(struct block_device *bdev, struct file *file)
+ {
+- struct mapped_device *md;
+-
+- md = inode->i_bdev->bd_disk->private_data;
++ struct mapped_device *md = bdev->bd_disk->private_data;
+ dm_get(md);
+ return 0;
+ }
+
+-static int dm_blk_close(struct inode *inode, struct file *file)
++static int dm_blk_close(struct gendisk *disk)
+ {
+- struct mapped_device *md;
+-
+- md = inode->i_bdev->bd_disk->private_data;
++ struct mapped_device *md = disk->private_data;
+ dm_put(md);
+ return 0;
+ }
+--- linux-2.6.0-test6/drivers/md/md.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/md/md.c 2003-10-05 00:34:01.000000000 -0700
+@@ -2360,11 +2360,10 @@ static int set_disk_faulty(mddev_t *mdde
+ return 1;
+ }
+
+-static int md_ioctl(struct inode *inode, struct file *file,
++static int md_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+ char b[BDEVNAME_SIZE];
+- unsigned int minor = iminor(inode);
+ int err = 0;
+ struct hd_geometry *loc = (struct hd_geometry *) arg;
+ mddev_t *mddev = NULL;
+@@ -2372,11 +2371,6 @@ static int md_ioctl(struct inode *inode,
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+- if (minor >= MAX_MD_DEVS) {
+- MD_BUG();
+- return -EINVAL;
+- }
+-
+ /*
+ * Commands dealing with the RAID driver but not any
+ * particular array:
+@@ -2405,7 +2399,7 @@ static int md_ioctl(struct inode *inode,
+ * Commands creating/starting a new array:
+ */
+
+- mddev = inode->i_bdev->bd_inode->u.generic_ip;
++ mddev = bdev->bd_inode->u.generic_ip;
+
+ if (!mddev) {
+ BUG();
+@@ -2527,7 +2521,7 @@ static int md_ioctl(struct inode *inode,
+ (short *) &loc->cylinders);
+ if (err)
+ goto abort_unlock;
+- err = put_user (get_start_sect(inode->i_bdev),
++ err = put_user (get_start_sect(bdev),
+ (long *) &loc->start);
+ goto done_unlock;
+ }
+@@ -2605,12 +2599,12 @@ abort:
+ return err;
+ }
+
+-static int md_open(struct inode *inode, struct file *file)
++static int md_open(struct block_device *bdev, struct file *file)
+ {
+ /*
+ * Succeed if we can find or allocate a mddev structure.
+ */
+- mddev_t *mddev = mddev_find(iminor(inode));
++ mddev_t *mddev = mddev_find(MINOR(bdev->bd_dev));
+ int err = -ENOMEM;
+
+ if (!mddev)
+@@ -2621,16 +2615,16 @@ static int md_open(struct inode *inode,
+
+ err = 0;
+ mddev_unlock(mddev);
+- inode->i_bdev->bd_inode->u.generic_ip = mddev_get(mddev);
++ bdev->bd_inode->u.generic_ip = mddev_get(mddev);
+ put:
+ mddev_put(mddev);
+ out:
+ return err;
+ }
+
+-static int md_release(struct inode *inode, struct file * file)
++static int md_release(struct gendisk *disk)
+ {
+- mddev_t *mddev = inode->i_bdev->bd_inode->u.generic_ip;
++ mddev_t *mddev = disk->private_data;
+
+ if (!mddev)
+ BUG();
+--- linux-2.6.0-test6/drivers/media/common/saa7146_i2c.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/common/saa7146_i2c.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,3 +1,4 @@
++#include <linux/version.h>
+ #include <media/saa7146_vv.h>
+
+ /* helper function */
+--- linux-2.6.0-test6/drivers/media/dvb/dvb-core/dvbdev.h 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/dvb-core/dvbdev.h 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ #include <linux/poll.h>
+ #include <linux/fs.h>
+ #include <linux/list.h>
+-#include <linux/version.h>
+ #include <linux/devfs_fs_kernel.h>
+
+ #define DVB_MAJOR 250
+--- linux-2.6.0-test6/drivers/media/dvb/dvb-core/dvb_functions.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/dvb-core/dvb_functions.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1,4 +1,3 @@
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+ #include <linux/string.h>
+--- linux-2.6.0-test6/drivers/media/dvb/dvb-core/dvb_functions.h 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/dvb-core/dvb_functions.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,8 +1,6 @@
+ #ifndef __DVB_FUNCTIONS_H__
+ #define __DVB_FUNCTIONS_H__
+
+-#include <linux/version.h>
+-
+ /**
+ * a sleeping delay function, waits i ms
+ *
+--- linux-2.6.0-test6/drivers/media/dvb/ttpci/av7110.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/ttpci/av7110.c 2003-10-05 00:33:24.000000000 -0700
+@@ -55,10 +55,8 @@
+ #include <linux/ptrace.h>
+ #include <linux/ioport.h>
+ #include <linux/in.h>
+-#include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/pci.h>
+-#include <linux/init.h>
+ #include <linux/vmalloc.h>
+ #include <linux/netdevice.h>
+ #include <linux/inetdevice.h>
+@@ -4745,12 +4743,19 @@ static struct saa7146_extension av7110_e
+
+ static int __init av7110_init(void)
+ {
+- if (saa7146_register_extension(&av7110_extension))
+- return -ENODEV;
++ int retval;
++ retval = saa7146_register_extension(&av7110_extension);
++ if (retval)
++ goto failed_saa7146_register;
+
+- av7110_ir_init();
+-
++ retval = av7110_ir_init();
++ if (retval)
++ goto failed_av7110_ir_init;
+ return 0;
++failed_av7110_ir_init:
++ saa7146_unregister_extension(&av7110_extension);
++failed_saa7146_register:
++ return retval;
+ }
+
+
+--- linux-2.6.0-test6/drivers/media/dvb/ttpci/budget.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/ttpci/budget.c 2003-10-05 00:33:24.000000000 -0700
+@@ -228,10 +228,7 @@ static struct saa7146_extension budget_e
+
+ static int __init budget_init(void)
+ {
+- if (saa7146_register_extension(&budget_extension))
+- return -ENODEV;
+-
+- return 0;
++ return saa7146_register_extension(&budget_extension);
+ }
+
+
+--- linux-2.6.0-test6/drivers/media/dvb/ttpci/budget-ci.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/media/dvb/ttpci/budget-ci.c 2003-10-05 00:33:24.000000000 -0700
+@@ -384,10 +384,7 @@ static struct saa7146_extension budget_e
+
+ static int __init budget_ci_init(void)
+ {
+- if (saa7146_register_extension(&budget_extension))
+- return -ENODEV;
+-
+- return 0;
++ return saa7146_register_extension(&budget_extension);
+ }
+
+
+--- linux-2.6.0-test6/drivers/media/dvb/ttpci/budget-patch.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/dvb/ttpci/budget-patch.c 2003-10-05 00:33:24.000000000 -0700
+@@ -247,10 +247,7 @@ static int budget_patch_detach (struct s
+
+ static int __init budget_patch_init(void)
+ {
+- if (saa7146_register_extension(&budget_extension))
+- return -ENODEV;
+-
+- return 0;
++ return saa7146_register_extension(&budget_extension);
+ }
+
+
+--- linux-2.6.0-test6/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c 2003-10-05 00:33:24.000000000 -0700
+@@ -9,6 +9,7 @@
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
++#include <linux/version.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/wait.h>
+@@ -27,7 +28,6 @@
+ #include <linux/dvb/frontend.h>
+ #include <linux/dvb/dmx.h>
+ #include <linux/pci.h>
+-#include <linux/usb.h>
+
+ #include "dvb_functions.h"
+
+@@ -1055,7 +1055,8 @@ static ssize_t stc_read(struct file *fil
+ if (tc < 0)
+ return 0;
+
+- copy_to_user(buf, stc_firmware + *offset, tc);
++ if (copy_to_user(buf, stc_firmware + *offset, tc))
++ return -EFAULT;
+
+ *offset += tc;
+
+--- linux-2.6.0-test6/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/dvb/ttusb-dec/ttusb_dec.c 2003-10-05 00:33:24.000000000 -0700
+@@ -19,6 +19,7 @@
+ *
+ */
+
++#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+--- linux-2.6.0-test6/drivers/media/radio/radio-gemtek-pci.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/media/radio/radio-gemtek-pci.c 2003-10-05 00:33:24.000000000 -0700
+@@ -37,7 +37,6 @@
+ ***************************************************************************
+ */
+
+-#include <linux/version.h>
+ #include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/list.h>
+--- linux-2.6.0-test6/drivers/media/video/adv7170.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/adv7170.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,8 +28,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -49,7 +47,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
+--- linux-2.6.0-test6/drivers/media/video/adv7175.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/adv7175.c 2003-10-05 00:33:24.000000000 -0700
+@@ -24,8 +24,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -45,7 +43,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
+--- linux-2.6.0-test6/drivers/media/video/bt819.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/bt819.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,8 +28,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -49,7 +47,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
+--- linux-2.6.0-test6/drivers/media/video/bt856.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/bt856.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,8 +28,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -49,7 +47,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
+--- linux-2.6.0-test6/drivers/media/video/bttvp.h 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/media/video/bttvp.h 2003-10-05 00:33:24.000000000 -0700
+@@ -25,6 +25,7 @@
+ #define _BTTVP_H_
+
+
++#include <linux/version.h>
+ #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,11)
+
+ #include <linux/types.h>
+--- linux-2.6.0-test6/drivers/media/video/bw-qcam.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/bw-qcam.c 2003-10-05 00:33:24.000000000 -0700
+@@ -72,7 +72,6 @@ OTHER DEALINGS IN THE SOFTWARE.
+ #include <linux/mm.h>
+ #include <linux/parport.h>
+ #include <linux/sched.h>
+-#include <linux/version.h>
+ #include <linux/videodev.h>
+ #include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+--- linux-2.6.0-test6/drivers/media/video/cpia.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/cpia.c 2003-10-05 00:33:24.000000000 -0700
+@@ -29,7 +29,6 @@
+ #include <linux/config.h>
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/init.h>
+ #include <linux/fs.h>
+ #include <linux/vmalloc.h>
+--- linux-2.6.0-test6/drivers/media/video/cpia_pp.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/drivers/media/video/cpia_pp.c 2003-10-05 00:33:24.000000000 -0700
+@@ -26,7 +26,6 @@
+ /* #define _CPIA_DEBUG_ 1 */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+
+ #include <linux/module.h>
+ #include <linux/init.h>
+--- linux-2.6.0-test6/drivers/media/video/c-qcam.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/c-qcam.c 2003-10-05 00:33:24.000000000 -0700
+@@ -33,7 +33,6 @@
+ #include <linux/mm.h>
+ #include <linux/parport.h>
+ #include <linux/sched.h>
+-#include <linux/version.h>
+ #include <linux/videodev.h>
+ #include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+--- linux-2.6.0-test6/drivers/media/video/meye.h 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/meye.h 2003-10-05 00:33:24.000000000 -0700
+@@ -36,8 +36,6 @@
+ #include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/sonypi.h>
+-#include <linux/meye.h>
+
+ /****************************************************************************/
+ /* Motion JPEG chip registers */
+--- linux-2.6.0-test6/drivers/media/video/planb.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/planb.c 2003-10-05 00:33:24.000000000 -0700
+@@ -27,7 +27,6 @@
+
+ /* $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $ */
+
+-#include <linux/version.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/media/video/pms.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/pms.c 2003-10-05 00:33:24.000000000 -0700
+@@ -30,7 +30,6 @@
+ #include <asm/io.h>
+ #include <linux/sched.h>
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+
+--- linux-2.6.0-test6/drivers/media/video/saa7110.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/saa7110.c 2003-10-05 00:33:24.000000000 -0700
+@@ -25,8 +25,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/types.h>
+--- linux-2.6.0-test6/drivers/media/video/saa7111.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/saa7111.c 2003-10-05 00:33:24.000000000 -0700
+@@ -24,8 +24,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -45,7 +43,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
+--- linux-2.6.0-test6/drivers/media/video/saa7114.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/saa7114.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,8 +28,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -51,7 +49,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
+--- linux-2.6.0-test6/drivers/media/video/saa7134/saa7134.h 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/saa7134/saa7134.h 2003-10-05 00:33:24.000000000 -0700
+@@ -18,6 +18,7 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
++#include <linux/version.h>
+ #include <linux/pci.h>
+ #include <linux/i2c.h>
+ #include <linux/videodev.h>
+--- linux-2.6.0-test6/drivers/media/video/saa7185.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/saa7185.c 2003-10-05 00:33:24.000000000 -0700
+@@ -24,8 +24,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+-
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+@@ -45,7 +43,6 @@
+ #include <linux/types.h>
+
+ #include <linux/videodev.h>
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
+--- linux-2.6.0-test6/drivers/media/video/stradis.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/stradis.c 2003-10-05 00:33:24.000000000 -0700
+@@ -20,7 +20,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
+--- linux-2.6.0-test6/drivers/media/video/tuner-3036.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/tuner-3036.c 2003-10-05 00:33:24.000000000 -0700
+@@ -21,7 +21,6 @@
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/slab.h>
+-#include <linux/version.h>
+ #include <linux/init.h>
+
+ #include <linux/i2c.h>
+--- linux-2.6.0-test6/drivers/media/video/v4l2-common.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/media/video/v4l2-common.c 2003-10-05 00:33:24.000000000 -0700
+@@ -45,7 +45,6 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/drivers/media/video/videocodec.c 2003-08-22 19:23:40.000000000 -0700
++++ 25/drivers/media/video/videocodec.c 2003-10-05 00:33:24.000000000 -0700
+@@ -29,7 +29,6 @@
+
+ #define VIDEOCODEC_VERSION "v0.2"
+
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+--- linux-2.6.0-test6/drivers/media/video/videodev.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/videodev.c 2003-10-05 00:33:24.000000000 -0700
+@@ -15,7 +15,6 @@
+ * - Added procfs support
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -27,7 +26,6 @@
+ #include <linux/init.h>
+ #include <linux/kmod.h>
+ #include <linux/slab.h>
+-#include <linux/types.h>
+ #include <linux/devfs_fs_kernel.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -52,7 +50,7 @@ static ssize_t show_dev(struct class_dev
+ {
+ struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+ dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor);
+- return sprintf(buf,"%04x\n",old_encode_dev(dev));
++ return print_dev_t(buf,dev);
+ }
+
+ static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+--- linux-2.6.0-test6/drivers/media/video/vpx3220.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/vpx3220.c 2003-10-05 00:33:24.000000000 -0700
+@@ -18,7 +18,6 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+--- linux-2.6.0-test6/drivers/media/video/zoran_card.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/zoran_card.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/media/video/zoran_device.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/zoran_device.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/media/video/zoran_procfs.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/media/video/zoran_procfs.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+
+ #include <linux/config.h>
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/media/video/zr36120.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/media/video/zr36120.c 2003-10-05 00:33:24.000000000 -0700
+@@ -36,7 +36,6 @@
+ #include <linux/sched.h>
+ #include <linux/video_decoder.h>
+
+-#include <linux/version.h>
+ #include <asm/uaccess.h>
+
+ #include "tuner.h"
+--- linux-2.6.0-test6/drivers/media/video/zr36120_i2c.c 2003-06-14 12:18:52.000000000 -0700
++++ 25/drivers/media/video/zr36120_i2c.c 2003-10-05 00:33:24.000000000 -0700
+@@ -22,7 +22,6 @@
+ #include <linux/delay.h>
+ #include <asm/io.h>
+
+-#include <linux/version.h>
+ #include <linux/video_decoder.h>
+ #include <asm/uaccess.h>
+
+--- linux-2.6.0-test6/drivers/message/i2o/i2o_block.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/message/i2o/i2o_block.c 2003-10-05 00:34:01.000000000 -0700
+@@ -885,10 +885,10 @@ static void i2o_block_biosparam(
+ * Issue device specific ioctl calls.
+ */
+
+-static int i2ob_ioctl(struct inode *inode, struct file *file,
++static int i2ob_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct i2ob_device *dev = disk->private_data;
+
+ /* Anyone capable of this syscall can do *real bad* things */
+@@ -901,7 +901,7 @@ static int i2ob_ioctl(struct inode *inod
+ struct hd_geometry g;
+ i2o_block_biosparam(get_capacity(disk),
+ &g.cylinders, &g.heads, &g.sectors);
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0;
+ }
+
+@@ -927,9 +927,8 @@ static int i2ob_ioctl(struct inode *inod
+ * Close the block device down
+ */
+
+-static int i2ob_release(struct inode *inode, struct file *file)
++static int i2ob_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct i2ob_device *dev = disk->private_data;
+
+ /*
+@@ -999,9 +998,9 @@ static int i2ob_release(struct inode *in
+ * Open the block device.
+ */
+
+-static int i2ob_open(struct inode *inode, struct file *file)
++static int i2ob_open(struct block_device *bdev, struct file *file)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct i2ob_device *dev = disk->private_data;
+
+ if(!dev->i2odev)
+--- linux-2.6.0-test6/drivers/mtd/chips/cfi_cmdset_0020.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/drivers/mtd/chips/cfi_cmdset_0020.c 2003-10-05 00:33:24.000000000 -0700
+@@ -17,6 +17,7 @@
+ * - added a writev function
+ */
+
++#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -26,7 +27,6 @@
+ #include <asm/byteorder.h>
+
+ #include <linux/errno.h>
+-#include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+@@ -208,6 +208,7 @@ static struct mtd_info *cfi_staa_setup(s
+ if (!mtd->eraseregions) {
+ printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
+ kfree(cfi->cmdset_priv);
++ kfree(mtd);
+ return NULL;
+ }
+
+@@ -232,6 +233,7 @@ static struct mtd_info *cfi_staa_setup(s
+ printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
+ kfree(mtd->eraseregions);
+ kfree(cfi->cmdset_priv);
++ kfree(mtd);
+ return NULL;
+ }
+
+--- linux-2.6.0-test6/drivers/mtd/chips/gen_probe.c 2003-07-02 14:53:14.000000000 -0700
++++ 25/drivers/mtd/chips/gen_probe.c 2003-10-05 00:33:24.000000000 -0700
+@@ -11,7 +11,6 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/cfi.h>
+-#include <linux/mtd/mtd.h>
+ #include <linux/mtd/gen_probe.h>
+
+ static struct mtd_info *check_cmd_set(struct map_info *, int);
+--- linux-2.6.0-test6/drivers/mtd/chips/map_rom.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/drivers/mtd/chips/map_rom.c 2003-10-05 00:33:24.000000000 -0700
+@@ -4,7 +4,6 @@
+ * $Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/drivers/mtd/chips/sharp.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/mtd/chips/sharp.c 2003-10-05 00:33:24.000000000 -0700
+@@ -22,7 +22,6 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/types.h>
+ #include <linux/sched.h>
+ #include <linux/errno.h>
+--- linux-2.6.0-test6/drivers/mtd/devices/lart.c 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/mtd/devices/lart.c 2003-10-05 00:33:24.000000000 -0700
+@@ -42,7 +42,6 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+-#include <linux/version.h>
+ #include <linux/errno.h>
+ #include <linux/mtd/mtd.h>
+ #ifdef HAVE_PARTITIONS
+--- linux-2.6.0-test6/drivers/mtd/devices/pmc551.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/drivers/mtd/devices/pmc551.c 2003-10-05 00:33:24.000000000 -0700
+@@ -82,6 +82,7 @@
+ * * Comb the init routine. It's still a bit cludgy on a few things.
+ */
+
++#include <linux/version.h>
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/mtd/maps/integrator-flash.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/drivers/mtd/maps/integrator-flash.c 2003-10-05 00:33:24.000000000 -0700
+@@ -31,223 +31,181 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/ioport.h>
++#include <linux/device.h>
+ #include <linux/init.h>
+
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/partitions.h>
+
++#include <asm/mach/flash.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+
+-// board specific stuff - sorry, it should be in arch/arm/mach-*.
+-#ifdef CONFIG_ARCH_INTEGRATOR
+-
+-#define FLASH_BASE INTEGRATOR_FLASH_BASE
+-#define FLASH_SIZE INTEGRATOR_FLASH_SIZE
+-
+-#define FLASH_PART_SIZE 0x400000
+-
+-#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
+-#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
+-#define EBI_CSR1 (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_CSR1_OFFSET)
+-#define EBI_LOCK (IO_ADDRESS(INTEGRATOR_EBI_BASE) + INTEGRATOR_EBI_LOCK_OFFSET)
+-
+-/*
+- * Initialise the flash access systems:
+- * - Disable VPP
+- * - Assert WP
+- * - Set write enable bit in EBI reg
+- */
+-static void armflash_flash_init(void)
+-{
+- unsigned int tmp;
+-
+- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+-
+- tmp = __raw_readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
+- __raw_writel(tmp, EBI_CSR1);
+-
+- if (!(__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
+- __raw_writel(0xa05f, EBI_LOCK);
+- __raw_writel(tmp, EBI_CSR1);
+- __raw_writel(0, EBI_LOCK);
+- }
+-}
+-
+-/*
+- * Shutdown the flash access systems:
+- * - Disable VPP
+- * - Assert WP
+- * - Clear write enable bit in EBI reg
+- */
+-static void armflash_flash_exit(void)
+-{
+- unsigned int tmp;
+-
+- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
+-
+- /*
+- * Clear the write enable bit in system controller EBI register.
+- */
+- tmp = __raw_readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
+- __raw_writel(tmp, EBI_CSR1);
+-
+- if (__raw_readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
+- __raw_writel(0xa05f, EBI_LOCK);
+- __raw_writel(tmp, EBI_CSR1);
+- __raw_writel(0, EBI_LOCK);
+- }
+-}
+-
+-static void armflash_flash_wp(int on)
+-{
+- unsigned int reg;
+-
+- if (on)
+- reg = SC_CTRLC;
+- else
+- reg = SC_CTRLS;
+-
+- __raw_writel(INTEGRATOR_SC_CTRL_nFLWP, reg);
+-}
+-
+-static void armflash_set_vpp(struct map_info *map, int on)
+-{
+- unsigned int reg;
+-
+- if (on)
+- reg = SC_CTRLS;
+- else
+- reg = SC_CTRLC;
+-
+- __raw_writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
+-}
+-#endif
+-
+ #ifdef CONFIG_ARCH_P720T
+-
+ #define FLASH_BASE (0x04000000)
+ #define FLASH_SIZE (64*1024*1024)
++#endif
+
+-#define FLASH_PART_SIZE (4*1024*1024)
+-#define FLASH_BLOCK_SIZE (128*1024)
++struct armflash_info {
++ struct flash_platform_data *plat;
++ struct resource *res;
++ struct mtd_partition *parts;
++ struct mtd_info *mtd;
++ struct map_info map;
++};
+
+-static void armflash_flash_init(void)
++static void armflash_set_vpp(struct map_info *map, int on)
+ {
+-}
++ struct armflash_info *info = container_of(map, struct armflash_info, map);
+
+-static void armflash_flash_exit(void)
+-{
++ if (info->plat && info->plat->set_vpp)
++ info->plat->set_vpp(on);
+ }
+
+-static void armflash_flash_wp(int on)
+-{
+-}
++static const char *probes[] = { "RedBoot", "afs", NULL };
+
+-static void armflash_set_vpp(struct map_info *map, int on)
++static int armflash_probe(struct device *_dev)
+ {
+-}
+-#endif
++ struct platform_device *dev = to_platform_device(_dev);
++ struct flash_platform_data *plat = dev->dev.platform_data;
++ struct resource *res = dev->resource;
++ unsigned int size = res->end - res->start + 1;
++ struct armflash_info *info;
++ int err;
++ void *base;
+
++ info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
++ if (!info) {
++ err = -ENOMEM;
++ goto out;
++ }
+
+-static struct map_info armflash_map =
+-{
+- .name = "AFS",
+- .set_vpp = armflash_set_vpp,
+- .phys = FLASH_BASE,
+-};
++ memset(info, 0, sizeof(struct armflash_info));
+
+-static struct mtd_info *mtd;
+-static struct mtd_partition *parts;
+-static const char *probes[] = { "RedBoot", "afs", NULL };
++ info->plat = plat;
++ if (plat && plat->init) {
++ err = plat->init();
++ if (err)
++ goto no_resource;
++ }
+
+-static int __init armflash_cfi_init(void *base, u_int size)
+-{
+- int ret;
++ info->res = request_mem_region(res->start, size, "armflash");
++ if (!info->res) {
++ err = -EBUSY;
++ goto no_resource;
++ }
+
+- armflash_flash_init();
+- armflash_flash_wp(1);
++ base = ioremap(res->start, size);
++ if (!base) {
++ err = -ENOMEM;
++ goto no_mem;
++ }
+
+ /*
+ * look for CFI based flash parts fitted to this board
+ */
+- armflash_map.size = size;
+- armflash_map.buswidth = 4;
+- armflash_map.virt = (unsigned long) base;
++ info->map.size = size;
++ info->map.buswidth = plat->width;
++ info->map.phys = res->start;
++ info->map.virt = (unsigned long) base;
++ info->map.name = dev->dev.bus_id;
++ info->map.set_vpp = armflash_set_vpp;
+
+- simple_map_init(&armflash_map);
++ simple_map_init(&info->map);
+
+ /*
+ * Also, the CFI layer automatically works out what size
+ * of chips we have, and does the necessary identification
+ * for us automatically.
+ */
+- mtd = do_map_probe("cfi_probe", &armflash_map);
+- if (!mtd)
+- return -ENXIO;
+-
+- mtd->owner = THIS_MODULE;
+-
+- ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0);
+- if (ret > 0) {
+- ret = add_mtd_partitions(mtd, parts, ret);
+- if (ret)
+- printk(KERN_ERR "mtd partition registration "
+- "failed: %d\n", ret);
++ info->mtd = do_map_probe(plat->map_name, &info->map);
++ if (!info->mtd) {
++ err = -ENXIO;
++ goto no_device;
+ }
+
++ info->mtd->owner = THIS_MODULE;
++
++ err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
++ if (err > 0) {
++ err = add_mtd_partitions(info->mtd, info->parts, err);
++ if (err)
++ printk(KERN_ERR
++ "mtd partition registration failed: %d\n", err);
++ }
++
++ if (err == 0)
++ dev_set_drvdata(&dev->dev, info);
++
+ /*
+ * If we got an error, free all resources.
+ */
+- if (ret < 0) {
+- del_mtd_partitions(mtd);
+- map_destroy(mtd);
+- }
++ if (err < 0) {
++ if (info->mtd) {
++ del_mtd_partitions(info->mtd);
++ map_destroy(info->mtd);
++ }
++ if (info->parts)
++ kfree(info->parts);
+
+- return ret;
+-}
+-
+-static void armflash_cfi_exit(void)
+-{
+- if (mtd) {
+- del_mtd_partitions(mtd);
+- map_destroy(mtd);
++ no_device:
++ iounmap(base);
++ no_mem:
++ release_mem_region(res->start, size);
++ no_resource:
++ if (plat && plat->exit)
++ plat->exit();
++ kfree(info);
+ }
+- if (parts)
+- kfree(parts);
++ out:
++ return err;
+ }
+
+-static int __init armflash_init(void)
++static int armflash_remove(struct device *_dev)
+ {
+- int err = -EBUSY;
+- void *base;
++ struct platform_device *dev = to_platform_device(_dev);
++ struct armflash_info *info = dev_get_drvdata(&dev->dev);
+
+- if (request_mem_region(FLASH_BASE, FLASH_SIZE, "flash") == NULL)
+- goto out;
++ dev_set_drvdata(&dev->dev, NULL);
+
+- base = ioremap(FLASH_BASE, FLASH_SIZE);
+- err = -ENOMEM;
+- if (base == NULL)
+- goto release;
++ if (info) {
++ if (info->mtd) {
++ del_mtd_partitions(info->mtd);
++ map_destroy(info->mtd);
++ }
++ if (info->parts)
++ kfree(info->parts);
+
+- err = armflash_cfi_init(base, FLASH_SIZE);
+- if (err) {
+- iounmap(base);
+-release:
+- release_mem_region(FLASH_BASE, FLASH_SIZE);
++ iounmap((void *)info->map.virt);
++ release_resource(info->res);
++ kfree(info->res);
++
++ if (info->plat && info->plat->exit)
++ info->plat->exit();
++
++ kfree(info);
+ }
+-out:
+- return err;
++
++ return 0;
++}
++
++static struct device_driver armflash_driver = {
++ .name = "armflash",
++ .bus = &platform_bus_type,
++ .probe = armflash_probe,
++ .remove = armflash_remove,
++};
++
++static int __init armflash_init(void)
++{
++ return driver_register(&armflash_driver);
+ }
+
+ static void __exit armflash_exit(void)
+ {
+- armflash_cfi_exit();
+- iounmap((void *)armflash_map.virt);
+- release_mem_region(FLASH_BASE, FLASH_SIZE);
+- armflash_flash_exit();
++ driver_unregister(&armflash_driver);
+ }
+
+ module_init(armflash_init);
+--- linux-2.6.0-test6/drivers/mtd/maps/sun_uflash.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/mtd/maps/sun_uflash.c 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/fs.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+--- linux-2.6.0-test6/drivers/mtd/mtd_blkdevs.c 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/mtd/mtd_blkdevs.c 2003-10-05 00:34:01.000000000 -0700
+@@ -141,14 +141,12 @@ static void mtd_blktrans_request(struct
+ }
+
+
+-int blktrans_open(struct inode *i, struct file *f)
++static int blktrans_open(struct block_device *bdev, struct file *f)
+ {
+- struct mtd_blktrans_dev *dev;
+- struct mtd_blktrans_ops *tr;
++ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
++ struct mtd_blktrans_ops *tr = dev->tr;
+ int ret = -ENODEV;
+
+- dev = i->i_bdev->bd_disk->private_data;
+- tr = dev->tr;
+
+ if (!try_module_get(dev->mtd->owner))
+ goto out;
+@@ -172,15 +170,12 @@ int blktrans_open(struct inode *i, struc
+ return ret;
+ }
+
+-int blktrans_release(struct inode *i, struct file *f)
++static int blktrans_release(struct gendisk *disk)
+ {
+- struct mtd_blktrans_dev *dev;
+- struct mtd_blktrans_ops *tr;
++ struct mtd_blktrans_dev *dev = disk->private_data;
++ struct mtd_blktrans_ops *tr = dev->tr;
+ int ret = 0;
+
+- dev = i->i_bdev->bd_disk->private_data;
+- tr = dev->tr;
+-
+ if (tr->release)
+ ret = tr->release(dev);
+
+@@ -194,10 +189,10 @@ int blktrans_release(struct inode *i, st
+ }
+
+
+-static int blktrans_ioctl(struct inode *inode, struct file *file,
++static int blktrans_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
++ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+ struct mtd_blktrans_ops *tr = dev->tr;
+
+ switch (cmd) {
+@@ -217,7 +212,7 @@ static int blktrans_ioctl(struct inode *
+ if (ret)
+ return ret;
+
+- g.start = get_start_sect(inode->i_bdev);
++ g.start = get_start_sect(bdev);
+ if (copy_to_user((void *)arg, &g, sizeof(g)))
+ return -EFAULT;
+ return 0;
+--- linux-2.6.0-test6/drivers/mtd/mtdcore.c 2003-06-14 12:18:20.000000000 -0700
++++ 25/drivers/mtd/mtdcore.c 2003-10-05 00:33:24.000000000 -0700
+@@ -6,6 +6,7 @@
+ *
+ */
+
++#include <linux/version.h>
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/drivers/mtd/nand/autcpu12.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/mtd/nand/autcpu12.c 2003-10-05 00:33:24.000000000 -0700
+@@ -27,6 +27,7 @@
+ * 10-06-2002 TG 128K card support added
+ */
+
++#include <linux/version.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+--- linux-2.6.0-test6/drivers/net/3c523.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/3c523.c 2003-10-05 00:33:24.000000000 -0700
+@@ -102,7 +102,7 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/ethtool.h>
+
+ #include <asm/uaccess.h>
+--- linux-2.6.0-test6/drivers/net/3c527.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/3c527.c 2003-10-05 00:33:24.000000000 -0700
+@@ -92,7 +92,7 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELD
+ #include <linux/types.h>
+ #include <linux/fcntl.h>
+ #include <linux/interrupt.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/ioport.h>
+ #include <linux/in.h>
+ #include <linux/skbuff.h>
+--- linux-2.6.0-test6/drivers/net/3c59x.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/3c59x.c 2003-10-05 00:33:46.000000000 -0700
+@@ -1063,6 +1063,22 @@ static int __devinit vortex_init_one (st
+ return rc;
+ }
+
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void vortex_rx_poll(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ vortex_interrupt(dev->irq, (void *)dev, 0);
++ enable_irq(dev->irq);
++}
++
++static void boomerang_rx_poll(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ boomerang_interrupt(dev->irq, (void *)dev, 0);
++ enable_irq(dev->irq);
++}
++#endif
++
+ /*
+ * Start up the PCI/EISA device which is described by *gendev.
+ * Return 0 on success.
+@@ -1450,6 +1466,13 @@ static int __devinit vortex_probe1(struc
+ dev->set_multicast_list = set_rx_mode;
+ dev->tx_timeout = vortex_tx_timeout;
+ dev->watchdog_timeo = (watchdog * HZ) / 1000;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ if (vp->full_bus_master_tx)
++ dev->poll_controller = boomerang_rx_poll;
++ else
++ dev->poll_controller = vortex_rx_poll;
++#endif
++
+ if (pdev) {
+ vp->pm_state_valid = 1;
+ pci_save_state(VORTEX_PCI(vp), vp->power_state);
+--- linux-2.6.0-test6/drivers/net/8139too.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/8139too.c 2003-10-05 00:34:34.000000000 -0700
+@@ -248,6 +248,7 @@ static struct pci_device_id rtl8139_pci_
+ {0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+ {0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+ {0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
++ {0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+
+ #ifdef CONFIG_SH_SECUREEDGE5410
+ /* Bogus 8139 silicon reports 8129 without external PROM :-( */
+--- linux-2.6.0-test6/drivers/net/arcnet/com20020.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/net/arcnet/com20020.c 2003-10-05 00:33:24.000000000 -0700
+@@ -180,10 +180,6 @@ int com20020_found(struct net_device *de
+ if (!dev->dev_addr[0])
+ dev->dev_addr[0] = inb(ioaddr + 8); /* FIXME: do this some other way! */
+
+- /* reserve the I/O region */
+- if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)"))
+- return -EBUSY;
+-
+ SET_SUBADR(SUB_SETUP1);
+ outb(lp->setup, _XREG);
+
+@@ -207,7 +203,6 @@ int com20020_found(struct net_device *de
+ if (request_irq(dev->irq, &arcnet_interrupt, shared,
+ "arcnet (COM20020)", dev)) {
+ BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
+- release_region(ioaddr, ARCNET_TOTAL_SIZE);
+ return -ENODEV;
+ }
+
+@@ -227,7 +222,6 @@ int com20020_found(struct net_device *de
+ clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
+
+ if (!dev->init && register_netdev(dev)) {
+- release_region(ioaddr, ARCNET_TOTAL_SIZE);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+@@ -342,7 +336,6 @@ void com20020_remove(struct net_device *
+ {
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
+ kfree(dev->priv);
+ free_netdev(dev);
+ }
+--- linux-2.6.0-test6/drivers/net/arcnet/com20020-isa.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/net/arcnet/com20020-isa.c 2003-10-05 00:33:24.000000000 -0700
+@@ -53,6 +53,7 @@ static int __init com20020isa_probe(stru
+ int ioaddr;
+ unsigned long airqmask;
+ struct arcnet_local *lp = dev->priv;
++ int err;
+
+ BUGLVL(D_NORMAL) printk(VERSION);
+
+@@ -62,17 +63,20 @@ static int __init com20020isa_probe(stru
+ "must specify the base address!\n");
+ return -ENODEV;
+ }
+- if (check_region(ioaddr, ARCNET_TOTAL_SIZE)) {
++ if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
+ BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n",
+ ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
+ return -ENXIO;
+ }
+ if (ASTATUS() == 0xFF) {
+ BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr);
+- return -ENODEV;
++ err = -ENODEV;
++ goto out;
++ }
++ if (com20020_check(dev)) {
++ err = -ENODEV;
++ goto out;
+ }
+- if (com20020_check(dev))
+- return -ENODEV;
+
+ if (!dev->irq) {
+ /* if we do this, we're sure to get an IRQ since the
+@@ -96,13 +100,21 @@ static int __init com20020isa_probe(stru
+ dev->irq = probe_irq_off(airqmask);
+ if (dev->irq <= 0) {
+ BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n");
+- return -ENODEV;
++ err = -ENODEV;
++ goto out;
+ }
+ }
+ }
+
+ lp->card_name = "ISA COM20020";
+- return com20020_found(dev, 0);
++ if ((err = com20020_found(dev, 0)) != 0)
++ goto out;
++
++ return 0;
++
++out:
++ release_region(ioaddr, ARCNET_TOTAL_SIZE);
++ return err;
+ }
+
+
+@@ -170,6 +182,7 @@ int init_module(void)
+ void cleanup_module(void)
+ {
+ com20020_remove(my_dev);
++ release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
+ }
+
+ #else
+--- linux-2.6.0-test6/drivers/net/arcnet/com20020-pci.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/net/arcnet/com20020-pci.c 2003-10-05 00:33:24.000000000 -0700
+@@ -115,20 +115,20 @@ static int __devinit com20020pci_probe(s
+ BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
+ "but seems empty!\n", ioaddr);
+ err = -EIO;
+- goto out_priv;
++ goto out_port;
+ }
+ if (com20020_check(dev)) {
+ err = -EIO;
+- goto out_priv;
++ goto out_port;
+ }
+
+- release_region(ioaddr, ARCNET_TOTAL_SIZE);
+-
+ if ((err = com20020_found(dev, SA_SHIRQ)) != 0)
+- goto out_priv;
++ goto out_port;
+
+ return 0;
+
++out_port:
++ release_region(ioaddr, ARCNET_TOTAL_SIZE);
+ out_priv:
+ kfree(dev->priv);
+ out_dev:
+@@ -138,7 +138,9 @@ out_dev:
+
+ static void __devexit com20020pci_remove(struct pci_dev *pdev)
+ {
+- com20020_remove(pci_get_drvdata(pdev));
++ struct net_device *dev = pci_get_drvdata(pdev);
++ com20020_remove(dev);
++ release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
+ }
+
+ static struct pci_device_id com20020pci_id_table[] = {
+--- linux-2.6.0-test6/drivers/net/at1700.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/drivers/net/at1700.c 2003-10-05 00:33:24.000000000 -0700
+@@ -43,7 +43,7 @@
+ #include <linux/errno.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+--- linux-2.6.0-test6/drivers/net/e100/e100_main.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/e100/e100_main.c 2003-10-05 00:33:46.000000000 -0700
+@@ -539,6 +539,15 @@ e100_trigger_SWI(struct e100_private *bd
+ readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */
+ }
+
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void e100_rx_poll(struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ e100intr(dev->irq, (void *)dev, 0);
++ enable_irq(dev->irq);
++}
++#endif
++
+ static int __devinit
+ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
+ {
+@@ -631,7 +640,9 @@ e100_found1(struct pci_dev *pcid, const
+ dev->set_multicast_list = &e100_set_multi;
+ dev->set_mac_address = &e100_set_mac;
+ dev->do_ioctl = &e100_ioctl;
+-
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = e100_rx_poll;
++#endif
+ if (bdp->flags & USE_IPCB)
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+--- linux-2.6.0-test6/drivers/net/eepro100.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/eepro100.c 2003-10-05 00:33:47.000000000 -0700
+@@ -543,6 +543,7 @@ static void speedo_refill_rx_buffers(str
+ static int speedo_rx(struct net_device *dev);
+ static void speedo_tx_buffer_gc(struct net_device *dev);
+ static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
++static void poll_speedo (struct net_device *dev);
+ static int speedo_close(struct net_device *dev);
+ static struct net_device_stats *speedo_get_stats(struct net_device *dev);
+ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+@@ -885,6 +886,9 @@ static int __devinit speedo_found1(struc
+ dev->get_stats = &speedo_get_stats;
+ dev->set_multicast_list = &set_rx_mode;
+ dev->do_ioctl = &speedo_ioctl;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = &poll_speedo;
++#endif
+
+ if (register_netdevice(dev))
+ goto err_free_unlock;
+@@ -1675,6 +1679,22 @@ static irqreturn_t speedo_interrupt(int
+ return IRQ_RETVAL(handled);
+ }
+
++#ifdef CONFIG_NET_POLL_CONTROLLER
++
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++
++static void poll_speedo (struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ speedo_interrupt (dev->irq, dev, NULL);
++ enable_irq(dev->irq);
++}
++#endif
++
+ static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
+ {
+ struct speedo_private *sp = (struct speedo_private *)dev->priv;
+--- linux-2.6.0-test6/drivers/net/eexpress.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/net/eexpress.c 2003-10-05 00:33:24.000000000 -0700
+@@ -113,7 +113,6 @@
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+ #include <linux/slab.h>
+-#include <linux/mca.h>
+ #include <linux/mca-legacy.h>
+ #include <linux/spinlock.h>
+
+--- linux-2.6.0-test6/drivers/net/ibmlana.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/ibmlana.c 2003-10-05 00:33:24.000000000 -0700
+@@ -82,7 +82,7 @@ History:
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/time.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+--- linux-2.6.0-test6/drivers/net/irda/act200l.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/act200l.c 2003-10-05 00:33:24.000000000 -0700
+@@ -84,12 +84,12 @@ static int act200l_change_speed(struct
+ #define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_ACT200L_DONGLE,
+- act200l_open,
+- act200l_close,
+- act200l_reset,
+- act200l_change_speed,
++ .type = IRDA_ACT200L_DONGLE,
++ .open = act200l_open,
++ .close = act200l_close,
++ .reset = act200l_reset,
++ .change_speed = act200l_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init act200l_init(void)
+@@ -112,8 +112,6 @@ static void act200l_open(dongle_t *self,
+ /* Set the speeds we can accept */
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x03;
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void act200l_close(dongle_t *self)
+@@ -122,8 +120,6 @@ static void act200l_close(dongle_t *self
+
+ /* Power off the dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/actisys.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/actisys.c 2003-10-05 00:33:24.000000000 -0700
+@@ -64,21 +64,21 @@ static __u32 baud_rates[] = { 9600, 1920
+ #define MAX_SPEEDS 5
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_ACTISYS_DONGLE,
+- actisys_open,
+- actisys_close,
+- actisys_reset,
+- actisys_change_speed,
++ .type = IRDA_ACTISYS_DONGLE,
++ .open = actisys_open,
++ .close = actisys_close,
++ .reset = actisys_reset,
++ .change_speed = actisys_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ static struct dongle_reg dongle_plus = {
+- Q_NULL,
+- IRDA_ACTISYS_PLUS_DONGLE,
+- actisys_open,
+- actisys_close,
+- actisys_reset,
+- actisys_change_speed,
++ .type = IRDA_ACTISYS_PLUS_DONGLE,
++ .open = actisys_open,
++ .close = actisys_close,
++ .reset = actisys_reset,
++ .change_speed = actisys_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ /*
+@@ -128,16 +128,12 @@ static void actisys_open(dongle_t *self,
+ qos->baud_rate.bits &= ~IR_38400;
+
+ qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void actisys_close(dongle_t *self)
+ {
+ /* Power off the dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/ali-ircc.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/ali-ircc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -254,7 +254,7 @@ static int ali_ircc_open(int i, chipio_t
+ if ((ali_ircc_setup(info)) == -1)
+ return -1;
+
+- dev = alloc_netdev(sizeof(*self), "irda%d", irda_device_setup);
++ dev = alloc_irdadev(sizeof(*self));
+ if (dev == NULL) {
+ ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
+ return -ENOMEM;
+--- linux-2.6.0-test6/drivers/net/irda/donauboe.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/donauboe.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1598,8 +1598,7 @@ toshoboe_open (struct pci_dev *pci_dev,
+ if ((err=pci_enable_device(pci_dev)))
+ return err;
+
+- dev = alloc_netdev(sizeof (struct toshoboe_cb), "irda%d",
+- irda_device_setup);
++ dev = alloc_irdadev(sizeof (struct toshoboe_cb));
+ if (dev == NULL)
+ {
+ printk (KERN_ERR DRIVER_NAME ": can't allocate memory for "
+--- linux-2.6.0-test6/drivers/net/irda/ep7211_ir.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/ep7211_ir.c 2003-10-05 00:33:24.000000000 -0700
+@@ -24,12 +24,12 @@ static int ep7211_ir_change_speed(struc
+ static int ep7211_ir_reset(struct irda_task *task);
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_EP7211_IR,
+- ep7211_ir_open,
+- ep7211_ir_close,
+- ep7211_ir_reset,
+- ep7211_ir_change_speed,
++ .type = IRDA_EP7211_IR,
++ .open = ep7211_ir_open,
++ .close = ep7211_ir_close,
++ .reset = ep7211_ir_reset,
++ .change_speed = ep7211_ir_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
+@@ -47,8 +47,6 @@ static void ep7211_ir_open(dongle_t *sel
+ UART (interrupt #14). */
+
+ restore_flags(flags);
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void ep7211_ir_close(dongle_t *self)
+@@ -66,8 +64,6 @@ static void ep7211_ir_close(dongle_t *se
+ reset them back to their original state. */
+
+ restore_flags(flags);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/esi.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/esi.c 2003-10-05 00:33:24.000000000 -0700
+@@ -44,12 +44,12 @@ static int esi_change_speed(struct irda
+ static int esi_reset(struct irda_task *task);
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_ESI_DONGLE,
+- esi_open,
+- esi_close,
+- esi_reset,
+- esi_change_speed,
++ .type = IRDA_ESI_DONGLE,
++ .open = esi_open,
++ .close = esi_close,
++ .reset = esi_reset,
++ .change_speed = esi_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init esi_init(void)
+@@ -66,16 +66,12 @@ static void esi_open(dongle_t *self, str
+ {
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+ qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void esi_close(dongle_t *dongle)
+ {
+ /* Power off dongle */
+ dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/girbil.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/girbil.c 2003-10-05 00:33:24.000000000 -0700
+@@ -63,12 +63,12 @@ static int girbil_change_speed(struct i
+ #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_GIRBIL_DONGLE,
+- girbil_open,
+- girbil_close,
+- girbil_reset,
+- girbil_change_speed,
++ .type = IRDA_GIRBIL_DONGLE,
++ .open = girbil_open,
++ .close = girbil_close,
++ .reset = girbil_reset,
++ .change_speed = girbil_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init girbil_init(void)
+@@ -85,16 +85,12 @@ static void girbil_open(dongle_t *self,
+ {
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x03;
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void girbil_close(dongle_t *self)
+ {
+ /* Power off dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/irda-usb.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/irda-usb.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1176,7 +1176,7 @@ static inline int irda_usb_open(struct i
+ memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
+
+ /* Create a network device for us */
+- netdev = alloc_netdev(0, "irda%d", irda_device_setup);
++ netdev = alloc_irdadev(0);
+ if (!netdev) {
+ ERROR("%s(), alloc_net_dev() failed!\n", __FUNCTION__);
+ return -ENOMEM;
+--- linux-2.6.0-test6/drivers/net/irda/irport.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/net/irda/irport.c 2003-10-05 00:33:24.000000000 -0700
+@@ -78,7 +78,6 @@ static inline void irport_write_wakeup(s
+ static inline int irport_write(int iobase, int fifo_size, __u8 *buf, int len);
+ static inline void irport_receive(struct irport_cb *self);
+
+-static int irport_net_init(struct net_device *dev);
+ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq,
+ int cmd);
+ static inline int irport_is_receiving(struct irport_cb *self);
+@@ -136,30 +135,27 @@ irport_open(int i, unsigned int iobase,
+ {
+ struct net_device *dev;
+ struct irport_cb *self;
+- void *ret;
+- int err;
+
+ IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
+
+ /* Lock the port that we need */
+- ret = request_region(iobase, IO_EXTENT, driver_name);
+- if (!ret) {
++ if (!request_region(iobase, IO_EXTENT, driver_name)) {
+ IRDA_DEBUG(0, "%s(), can't get iobase of 0x%03x\n",
+ __FUNCTION__, iobase);
+- return NULL;
++ goto err_out1;
+ }
+
+ /*
+ * Allocate new instance of the driver
+ */
+- self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
+- if (!self) {
++ dev = alloc_irdadev(sizeof(struct irport_cb));
++ if (!dev) {
+ ERROR("%s(), can't allocate memory for "
+- "control block!\n", __FUNCTION__);
+- release_region(iobase, IO_EXTENT);
+- return NULL;
++ "irda device!\n", __FUNCTION__);
++ goto err_out2;
+ }
+- memset(self, 0, sizeof(struct irport_cb));
++
++ self = dev->priv;
+ spin_lock_init(&self->lock);
+
+ /* Need to store self somewhere */
+@@ -189,8 +185,11 @@ irport_open(int i, unsigned int iobase,
+ self->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+ self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize,
+ GFP_KERNEL);
+- if (self->rx_buff.skb == NULL)
+- return NULL;
++ if (self->rx_buff.skb == NULL) {
++ ERROR("%s(), can't allocate memory for "
++ "receive buffer!\n", __FUNCTION__);
++ goto err_out3;
++ }
+ skb_reserve(self->rx_buff.skb, 1);
+ self->rx_buff.head = self->rx_buff.skb->data;
+ /* No need to memset the buffer, unless you are really pedantic */
+@@ -208,30 +207,23 @@ irport_open(int i, unsigned int iobase,
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ GFP_KERNEL);
+ if (self->tx_buff.head == NULL) {
+- kfree_skb(self->rx_buff.skb);
+- self->rx_buff.skb = NULL;
+- self->rx_buff.head = NULL;
+- return NULL;
++ ERROR("%s(), can't allocate memory for "
++ "transmit buffer!\n", __FUNCTION__);
++ goto err_out4;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ }
+ self->tx_buff.data = self->tx_buff.head;
+
+- if (!(dev = dev_alloc("irda%d", &err))) {
+- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
+- return NULL;
+- }
+ self->netdev = dev;
+ /* Keep track of module usage */
+ SET_MODULE_OWNER(dev);
+
+ /* May be overridden by piggyback drivers */
+- dev->priv = (void *) self;
+ self->interrupt = irport_interrupt;
+ self->change_speed = irport_change_speed;
+
+ /* Override the network functions we need to use */
+- dev->init = irport_net_init;
+ dev->hard_start_xmit = irport_hard_xmit;
+ dev->tx_timeout = irport_timeout;
+ dev->watchdog_timeo = HZ; /* Allow time enough for speed change */
+@@ -244,17 +236,25 @@ irport_open(int i, unsigned int iobase,
+ dev->base_addr = iobase;
+ dev->irq = irq;
+
+- rtnl_lock();
+- err = register_netdevice(dev);
+- rtnl_unlock();
+- if (err) {
++ if (register_netdev(dev)) {
+ ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+- return NULL;
++ goto err_out5;
+ }
+ MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
+ dev->name, iobase, irq);
+
+ return self;
++ err_out5:
++ kfree(self->tx_buff.head);
++ err_out4:
++ kfree_skb(self->rx_buff.skb);
++ err_out3:
++ free_netdev(dev);
++ dev_self[i] = NULL;
++ err_out2:
++ release_region(iobase, IO_EXTENT);
++ err_out1:
++ return NULL;
+ }
+
+ int irport_close(struct irport_cb *self)
+@@ -267,8 +267,7 @@ int irport_close(struct irport_cb *self)
+ self->dongle = NULL;
+
+ /* Remove netdevice */
+- if (self->netdev)
+- unregister_netdev(self->netdev);
++ unregister_netdev(self->netdev);
+
+ /* Release the IO-port that this driver is using */
+ IRDA_DEBUG(0 , "%s(), Releasing Region %03x\n",
+@@ -284,7 +283,7 @@ int irport_close(struct irport_cb *self)
+
+ /* Remove ourselves */
+ dev_self[self->index] = NULL;
+- kfree(self);
++ free_netdev(self->netdev);
+
+ return 0;
+ }
+@@ -886,16 +885,6 @@ irqreturn_t irport_interrupt(int irq, vo
+ return IRQ_RETVAL(handled);
+ }
+
+-static int irport_net_init(struct net_device *dev)
+-{
+- /* Set up to be a normal IrDA network device driver */
+- irda_device_setup(dev);
+-
+- /* Insert overrides below this line! */
+-
+- return 0;
+-}
+-
+ /*
+ * Function irport_net_open (dev)
+ *
+--- linux-2.6.0-test6/drivers/net/irda/litelink.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/litelink.c 2003-10-05 00:33:24.000000000 -0700
+@@ -48,12 +48,12 @@ static int litelink_reset(struct irda_t
+ static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_LITELINK_DONGLE,
+- litelink_open,
+- litelink_close,
+- litelink_reset,
+- litelink_change_speed,
++ .type = IRDA_LITELINK_DONGLE,
++ .open = litelink_open,
++ .close = litelink_close,
++ .reset = litelink_reset,
++ .change_speed = litelink_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init litelink_init(void)
+@@ -70,16 +70,12 @@ static void litelink_open(dongle_t *self
+ {
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void litelink_close(dongle_t *self)
+ {
+ /* Power off dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/ma600.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/ma600.c 2003-10-05 00:33:24.000000000 -0700
+@@ -74,12 +74,12 @@ static int ma600_reset(struct irda_task
+ #define MA600_2400 0x08
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_MA600_DONGLE,
+- ma600_open,
+- ma600_close,
+- ma600_reset,
+- ma600_change_speed,
++ .type = IRDA_MA600_DONGLE,
++ .open = ma600_open,
++ .close = ma600_close,
++ .reset = ma600_reset,
++ .change_speed = ma600_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init ma600_init(void)
+@@ -115,8 +115,6 @@ static void ma600_open(dongle_t *self, s
+
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ // should wait 1 second
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void ma600_close(dongle_t *self)
+@@ -125,8 +123,6 @@ static void ma600_close(dongle_t *self)
+
+ /* Power off dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ static __u8 get_control_byte(__u32 speed)
+--- linux-2.6.0-test6/drivers/net/irda/mcp2120.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/mcp2120.c 2003-10-05 00:33:24.000000000 -0700
+@@ -40,12 +40,12 @@ static int mcp2120_change_speed(struct
+ #define MCP2120_COMMIT 0x11
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_MCP2120_DONGLE,
+- mcp2120_open,
+- mcp2120_close,
+- mcp2120_reset,
+- mcp2120_change_speed,
++ .type = IRDA_MCP2120_DONGLE,
++ .open = mcp2120_open,
++ .close = mcp2120_close,
++ .reset = mcp2120_reset,
++ .change_speed = mcp2120_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init mcp2120_init(void)
+@@ -62,8 +62,6 @@ static void mcp2120_open(dongle_t *self,
+ {
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x01;
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void mcp2120_close(dongle_t *self)
+@@ -72,8 +70,6 @@ static void mcp2120_close(dongle_t *self
+ /* reset and inhibit mcp2120 */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ //self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/nsc-ircc.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/nsc-ircc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -260,8 +260,7 @@ static int __init nsc_ircc_open(int i, c
+
+ MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
+- dev = alloc_netdev(sizeof(struct nsc_ircc_cb), "irda%d",
+- irda_device_setup);
++ dev = alloc_irdadev(sizeof(struct nsc_ircc_cb));
+ if (dev == NULL) {
+ ERROR("%s(), can't allocate memory for "
+ "control block!\n", __FUNCTION__);
+--- linux-2.6.0-test6/drivers/net/irda/old_belkin.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/old_belkin.c 2003-10-05 00:33:24.000000000 -0700
+@@ -74,12 +74,12 @@ static int old_belkin_reset(struct irda
+ /* static __u32 baud_rates[] = { 9600 }; */
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_OLD_BELKIN_DONGLE,
+- old_belkin_open,
+- old_belkin_close,
+- old_belkin_reset,
+- old_belkin_change_speed,
++ .type = IRDA_OLD_BELKIN_DONGLE,
++ .open = old_belkin_open,
++ .close = old_belkin_close,
++ .reset = old_belkin_reset,
++ .change_speed = old_belkin_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init old_belkin_init(void)
+@@ -98,16 +98,12 @@ static void old_belkin_open(dongle_t *se
+ qos->baud_rate.bits &= IR_9600;
+ /* Needs at least 10 ms (totally wild guess, can do probably better) */
+ qos->min_turn_time.bits = 0x01;
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void old_belkin_close(dongle_t *self)
+ {
+ /* Power off dongle */
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/sir_dev.c 2003-07-10 18:50:31.000000000 -0700
++++ 25/drivers/net/irda/sir_dev.c 2003-10-05 00:33:24.000000000 -0700
+@@ -538,28 +538,6 @@ out:
+
+ /* ----------------------------------------------------------------------------- */
+
+-static int sirdev_init(struct net_device *ndev)
+-{
+- struct sir_dev *dev = ndev->priv;
+-
+- SET_MODULE_OWNER(ndev);
+-
+- /* Set up to be a normal IrDA network device driver */
+- irda_device_setup(ndev);
+-
+- dev->flags = IFF_SIR | IFF_PIO;
+-
+- /* Override the network functions we need to use */
+- ndev->hard_start_xmit = sirdev_hard_xmit;
+- ndev->open = sirdev_open;
+- ndev->stop = sirdev_close;
+- ndev->get_stats = sirdev_get_stats;
+- ndev->do_ioctl = sirdev_ioctl;
+-
+- return 0;
+-}
+-
+-
+ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name)
+ {
+ struct net_device *ndev;
+@@ -577,12 +555,12 @@ struct sir_dev * sirdev_get_instance(con
+ /*
+ * Allocate new instance of the device
+ */
+- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+- if (dev == NULL) {
++ ndev = alloc_irdadev(sizeof(*dev));
++ if (ndev == NULL) {
+ ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
+ goto out;
+ }
+- memset(dev, 0, sizeof(*dev));
++ dev = ndev->priv;
+
+ irda_init_max_qos_capabilies(&dev->qos);
+ dev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+@@ -591,11 +569,6 @@ struct sir_dev * sirdev_get_instance(con
+
+ strncpy(dev->hwname, name, sizeof(dev->hwname)-1);
+
+- ndev = kmalloc(sizeof(*ndev), GFP_KERNEL);
+- if (ndev == NULL)
+- goto out_freedev;
+- memset(ndev, 0, sizeof(*ndev));
+-
+ atomic_set(&dev->enable_rx, 0);
+ dev->tx_skb = NULL;
+
+@@ -609,10 +582,17 @@ struct sir_dev * sirdev_get_instance(con
+ dev->drv = drv;
+ dev->netdev = ndev;
+
+- ndev->priv = (void *) dev;
+- ndev->init = sirdev_init;
++ SET_MODULE_OWNER(ndev);
++
++ dev->flags = IFF_SIR | IFF_PIO;
++
++ /* Override the network functions we need to use */
++ ndev->hard_start_xmit = sirdev_hard_xmit;
++ ndev->open = sirdev_open;
++ ndev->stop = sirdev_close;
++ ndev->get_stats = sirdev_get_stats;
++ ndev->do_ioctl = sirdev_ioctl;
+
+- strcpy(ndev->name, "irda%d");
+ if (register_netdev(ndev)) {
+ ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+ goto out_freenetdev;
+@@ -621,9 +601,7 @@ struct sir_dev * sirdev_get_instance(con
+ return dev;
+
+ out_freenetdev:
+- kfree(ndev);
+-out_freedev:
+- kfree(dev);
++ free_netdev(ndev);
+ out:
+ return NULL;
+ }
+@@ -653,10 +631,9 @@ int sirdev_put_instance(struct sir_dev *
+ up(&dev->fsm.sem);
+
+ /* Remove netdevice */
+- if (dev->netdev)
+- unregister_netdev(dev->netdev);
++ unregister_netdev(dev->netdev);
+
+- kfree(dev);
++ free_netdev(dev->netdev);
+
+ return 0;
+ }
+--- linux-2.6.0-test6/drivers/net/irda/smsc-ircc2.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/drivers/net/irda/smsc-ircc2.c 2003-10-05 00:33:24.000000000 -0700
+@@ -140,10 +140,8 @@ static const char *driver_name = "smsc-i
+
+ static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq);
+ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base);
+-static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq);
+-static int smsc_ircc_setup_buffers(struct smsc_ircc_cb *self);
++static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq);
+ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self);
+-static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self);
+ static void smsc_ircc_init_chip(struct smsc_ircc_cb *self);
+ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self);
+ static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase);
+@@ -163,7 +161,6 @@ static void smsc_ircc_sir_stop(struct sm
+ #endif
+ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self);
+ static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len);
+-static int smsc_ircc_net_init(struct net_device *dev);
+ static int smsc_ircc_net_open(struct net_device *dev);
+ static int smsc_ircc_net_close(struct net_device *dev);
+ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+@@ -366,38 +363,81 @@ int __init smsc_ircc_init(void)
+ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+ {
+ struct smsc_ircc_cb *self;
++ struct net_device *dev;
+ int err;
+
+ IRDA_DEBUG(1, "%s\n", __FUNCTION__);
+
+- err= smsc_ircc_present(fir_base, sir_base);
+- if(err) return -ENODEV;
++ err = smsc_ircc_present(fir_base, sir_base);
++ if(err)
++ goto err_out;
+
+- if (dev_count>DIM(dev_self)) {
++ err = -ENOMEM;
++ if (dev_count > DIM(dev_self)) {
+ WARNING("%s(), too many devices!\n", __FUNCTION__);
+- return -ENOMEM;
++ goto err_out1;
+ }
+
+ /*
+ * Allocate new instance of the driver
+ */
+- self = kmalloc(sizeof(struct smsc_ircc_cb), GFP_KERNEL);
+- if (self == NULL) {
+- ERROR("%s, Can't allocate memory for control block!\n",
+- driver_name);
+- return -ENOMEM;
++ dev = alloc_irdadev(sizeof(struct smsc_ircc_cb));
++ if (!dev) {
++ WARNING("%s() can't allocate net device\n", __FUNCTION__);
++ goto err_out1;
+ }
+- memset(self, 0, sizeof(struct smsc_ircc_cb));
++
++ SET_MODULE_OWNER(dev);
++
++ dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
++#if SMSC_IRCC2_C_NET_TIMEOUT
++ dev->tx_timeout = smsc_ircc_timeout;
++ dev->watchdog_timeo = HZ*2; /* Allow enough time for speed change */
++#endif
++ dev->open = smsc_ircc_net_open;
++ dev->stop = smsc_ircc_net_close;
++ dev->do_ioctl = smsc_ircc_net_ioctl;
++ dev->get_stats = smsc_ircc_net_get_stats;
++
++ self = dev->priv;
++ self->netdev = dev;
++
++ /* Make ifconfig display some details */
++ dev->base_addr = self->io.fir_base = fir_base;
++ dev->irq = self->io.irq = irq;
+
+ /* Need to store self somewhere */
+ dev_self[dev_count++] = self;
+ spin_lock_init(&self->lock);
+
+- err = smsc_ircc_setup_buffers(self);
+- if(err) return err;
++ self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
++ self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
++
++ self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize,
++ GFP_KERNEL|GFP_DMA);
++ if (self->rx_buff.head == NULL) {
++ ERROR("%s, Can't allocate memory for receive buffer!\n",
++ driver_name);
++ goto err_out2;
++ }
++
++ self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize,
++ GFP_KERNEL|GFP_DMA);
++ if (self->tx_buff.head == NULL) {
++ ERROR("%s, Can't allocate memory for transmit buffer!\n",
++ driver_name);
++ goto err_out3;
++ }
++
++ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
++ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
++
++ self->rx_buff.in_frame = FALSE;
++ self->rx_buff.state = OUTSIDE_FRAME;
++ self->tx_buff.data = self->tx_buff.head;
++ self->rx_buff.data = self->rx_buff.head;
+
+- err= smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
+- if(err) return err;
++ smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq);
+
+ smsc_ircc_setup_qos(self);
+
+@@ -405,17 +445,38 @@ static int __init smsc_ircc_open(unsigne
+
+ smsc_ircc_init_chip(self);
+
+- if(ircc_transceiver > 0 && ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) self->transceiver = ircc_transceiver;
+- else smsc_ircc_probe_transceiver(self);
++ if(ircc_transceiver > 0 &&
++ ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS)
++ self->transceiver = ircc_transceiver;
++ else
++ smsc_ircc_probe_transceiver(self);
+
+- err = smsc_ircc_setup_netdev(self);
+- if(err) return err;
++ err = register_netdev(self->netdev);
++ if(err) {
++ ERROR("%s, Network device registration failed!\n",
++ driver_name);
++ goto err_out4;
++ }
+
+ self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc);
+ if (self->pmdev)
+ self->pmdev->data = self;
+
++ MESSAGE("IrDA: Registered device %s\n", dev->name);
++
+ return 0;
++ err_out4:
++ kfree(self->tx_buff.head);
++ err_out3:
++ kfree(self->rx_buff.head);
++ err_out2:
++ free_netdev(self->netdev);
++ dev_self[--dev_count] = NULL;
++ err_out1:
++ release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
++ release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
++ err_out:
++ return err;
+ }
+
+ /*
+@@ -428,18 +489,19 @@ static int smsc_ircc_present(unsigned in
+ {
+ unsigned char low, high, chip, config, dma, irq, version;
+
+- if (check_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT) < 0) {
++ if (!request_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT,
++ driver_name)) {
+ WARNING("%s: can't get fir_base of 0x%03x\n",
+ __FUNCTION__, fir_base);
+- return -ENODEV;
++ goto out1;
+ }
+-#if POSSIBLE_USED_BY_SERIAL_DRIVER
+- if (check_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT) < 0) {
++
++ if (!request_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT,
++ driver_name)) {
+ WARNING("%s: can't get sir_base of 0x%03x\n",
+ __FUNCTION__, sir_base);
+- return -ENODEV;
++ goto out2;
+ }
+-#endif
+
+ register_bank(fir_base, 3);
+
+@@ -454,54 +516,19 @@ static int smsc_ircc_present(unsigned in
+ if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
+ WARNING("%s(), addr 0x%04x - no device found!\n",
+ __FUNCTION__, fir_base);
+- return -ENODEV;
++ goto out3;
+ }
+ MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, "
+ "firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+ chip & 0x0f, version, fir_base, sir_base, dma, irq);
+
+ return 0;
+-}
+-
+-/*
+- * Function smsc_ircc_setup_buffers(self)
+- *
+- * Setup RX/TX buffers
+- *
+- */
+-static int smsc_ircc_setup_buffers(struct smsc_ircc_cb *self)
+-{
+- self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE;
+- self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE;
+-
+- self->rx_buff.head = (u8 *) kmalloc(self->rx_buff.truesize,
+- GFP_KERNEL|GFP_DMA);
+- if (self->rx_buff.head == NULL) {
+- ERROR("%s, Can't allocate memory for receive buffer!\n",
+- driver_name);
+- kfree(self);
+- return -ENOMEM;
+- }
+-
+- self->tx_buff.head = (u8 *) kmalloc(self->tx_buff.truesize,
+- GFP_KERNEL|GFP_DMA);
+- if (self->tx_buff.head == NULL) {
+- ERROR("%s, Can't allocate memory for transmit buffer!\n",
+- driver_name);
+- kfree(self->rx_buff.head);
+- kfree(self);
+- return -ENOMEM;
+- }
+-
+- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+-
+- self->rx_buff.in_frame = FALSE;
+- self->rx_buff.state = OUTSIDE_FRAME;
+- self->tx_buff.data = self->tx_buff.head;
+- self->rx_buff.data = self->rx_buff.head;
+-
+- return 0;
++ out3:
++ release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
++ out2:
++ release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
++ out1:
++ return -ENODEV;
+ }
+
+ /*
+@@ -510,10 +537,11 @@ static int smsc_ircc_setup_buffers(struc
+ * Setup I/O
+ *
+ */
+-static int smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
++static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
++ unsigned int fir_base, unsigned int sir_base,
++ u8 dma, u8 irq)
+ {
+ unsigned char config, chip_dma, chip_irq;
+- void *ret;
+
+ register_bank(fir_base, 3);
+ config = inb(fir_base+IRCC_INTERFACE);
+@@ -545,27 +573,6 @@ static int smsc_ircc_setup_io(struct sms
+ else
+ self->io.dma = chip_dma;
+
+- ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
+- if (!ret) {
+- WARNING("%s(), can't get iobase of 0x%03x\n",
+- __FUNCTION__, self->io.fir_base);
+- kfree(self->tx_buff.head);
+- kfree(self->rx_buff.head);
+- kfree(self);
+- return -ENODEV;
+- }
+- ret = request_region(self->io.sir_base, self->io.sir_ext, driver_name);
+- if (!ret) {
+- WARNING("%s(), can't get iobase of 0x%03x\n",
+- __FUNCTION__, self->io.sir_base);
+- release_region(self->io.fir_base, self->io.fir_ext);
+- kfree(self->tx_buff.head);
+- kfree(self->rx_buff.head);
+- kfree(self);
+- return -ENODEV;
+- }
+-
+- return 0;
+ }
+
+ /*
+@@ -635,59 +642,6 @@ static void smsc_ircc_init_chip(struct s
+ }
+
+ /*
+- * Function smsc_ircc_setup_netdev(self)
+- *
+- * Alloc and setup network device
+- *
+- */
+-static int smsc_ircc_setup_netdev(struct smsc_ircc_cb *self)
+-{
+- struct net_device *dev;
+- int err;
+- /* Alloc netdev */
+-
+- if (!(dev = dev_alloc("irda%d", &err))) {
+- ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
+- kfree(self->tx_buff.head);
+- kfree(self->rx_buff.head);
+- kfree(self);
+- return -ENOMEM;
+- }
+-
+- dev->priv = (void *) self;
+- self->netdev = dev;
+-
+- dev->init = smsc_ircc_net_init;
+- dev->hard_start_xmit = smsc_ircc_hard_xmit_sir;
+- #if SMSC_IRCC2_C_NET_TIMEOUT
+- dev->tx_timeout = smsc_ircc_timeout;
+- dev->watchdog_timeo = HZ*2; /* Allow enough time for speed change */
+- #endif
+- dev->open = smsc_ircc_net_open;
+- dev->stop = smsc_ircc_net_close;
+- dev->do_ioctl = smsc_ircc_net_ioctl;
+- dev->get_stats = smsc_ircc_net_get_stats;
+-
+- /* Make ifconfig display some details */
+- dev->base_addr = self->io.fir_base;
+- dev->irq = self->io.irq;
+-
+- rtnl_lock();
+- err = register_netdevice(dev);
+- rtnl_unlock();
+- if (err) {
+- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+- kfree(self->tx_buff.head);
+- kfree(self->rx_buff.head);
+- kfree(self);
+- return -ENODEV;
+- }
+- MESSAGE("IrDA: Registered device %s\n", dev->name);
+-
+- return 0;
+-}
+-
+-/*
+ * Function smsc_ircc_net_ioctl (dev, rq, cmd)
+ *
+ * Process IOCTL commands for this device
+@@ -1571,18 +1525,6 @@ static int ircc_is_receiving(struct smsc
+ }
+ #endif /* unused */
+
+-static int smsc_ircc_net_init(struct net_device *dev)
+-{
+- /* Keep track of module usage */
+- SET_MODULE_OWNER(dev);
+-
+- /* Set up to be a normal IrDA network device driver */
+- irda_device_setup(dev);
+-
+- /* Insert overrides below this line! */
+-
+- return 0;
+-}
+
+ /*
+ * Function smsc_ircc_net_open (dev)
+@@ -1745,11 +1687,7 @@ static int __exit smsc_ircc_close(struct
+ pm_unregister(self->pmdev);
+
+ /* Remove netdevice */
+- if (self->netdev) {
+- rtnl_lock();
+- unregister_netdevice(self->netdev);
+- rtnl_unlock();
+- }
++ unregister_netdev(self->netdev);
+
+ /* Make sure the irq handler is not exectuting */
+ spin_lock_irqsave(&self->lock, flags);
+@@ -1784,7 +1722,7 @@ static int __exit smsc_ircc_close(struct
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
+
+- kfree(self);
++ free_netdev(self->netdev);
+
+ return 0;
+ }
+@@ -2269,32 +2207,36 @@ static const smsc_chip_t * __init smsc_i
+
+ static int __init smsc_superio_fdc(unsigned short cfg_base)
+ {
+- if (check_region(cfg_base, 2) < 0) {
++ int ret = -1;
++
++ if (!request_region(cfg_base, 2, driver_name)) {
+ WARNING("%s: can't get cfg_base of 0x%03x\n",
+ __FUNCTION__, cfg_base);
+- return -1;
+- }
++ } else {
++ if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")
++ ||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
++ ret = 0;
+
+- if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
+- return 0;
++ release_region(cfg_base, 2);
++ }
+
+- return -1;
++ return ret;
+ }
+
+ static int __init smsc_superio_lpc(unsigned short cfg_base)
+ {
+-#if 0
+- if (check_region(cfg_base, 2) < 0) {
+- IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
+- cfg_base);
+- return -1;
+- }
+-#endif
+-
+- if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
+- return 0;
++ int ret = -1;
+
+- return -1;
++ if (!request_region(cfg_base, 2, driver_name)) {
++ WARNING("%s: can't get cfg_base of 0x%03x\n",
++ __FUNCTION__, cfg_base);
++ } else {
++ if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")
++ ||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
++ ret = 0;
++ release_region(cfg_base, 2);
++ }
++ return ret;
+ }
+
+ /************************************************
+--- linux-2.6.0-test6/drivers/net/irda/tekram.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/tekram.c 2003-10-05 00:33:24.000000000 -0700
+@@ -44,12 +44,12 @@ static int tekram_reset(struct irda_tas
+ #define TEKRAM_PW 0x10 /* Pulse select bit */
+
+ static struct dongle_reg dongle = {
+- Q_NULL,
+- IRDA_TEKRAM_DONGLE,
+- tekram_open,
+- tekram_close,
+- tekram_reset,
+- tekram_change_speed,
++ .type = IRDA_TEKRAM_DONGLE,
++ .open = tekram_open,
++ .close = tekram_close,
++ .reset = tekram_reset,
++ .change_speed = tekram_change_speed,
++ .owner = THIS_MODULE,
+ };
+
+ int __init tekram_init(void)
+@@ -69,8 +69,6 @@ static void tekram_open(dongle_t *self,
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
+ irda_qos_bits_to_value(qos);
+-
+- MOD_INC_USE_COUNT;
+ }
+
+ static void tekram_close(dongle_t *self)
+@@ -84,8 +82,6 @@ static void tekram_close(dongle_t *self)
+ irda_task_delete(self->reset_task);
+ if (self->speed_task)
+ irda_task_delete(self->speed_task);
+-
+- MOD_DEC_USE_COUNT;
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/net/irda/via-ircc.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/via-ircc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -335,8 +335,7 @@ static __devinit int via_ircc_open(int i
+ return -1;
+
+ /* Allocate new instance of the driver */
+- dev = alloc_netdev(sizeof(struct via_ircc_cb), "irda%d",
+- irda_device_setup);
++ dev = alloc_irdadev(sizeof(struct via_ircc_cb));
+ if (dev == NULL)
+ return -ENOMEM;
+
+--- linux-2.6.0-test6/drivers/net/irda/vlsi_ir.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/irda/vlsi_ir.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1859,15 +1859,6 @@ static void __devexit vlsi_irda_remove(s
+ * otherwise we might get cheated by pci-pm.
+ */
+
+-static int vlsi_irda_save_state(struct pci_dev *pdev, u32 state)
+-{
+- if (state < 1 || state > 3 ) {
+- ERROR("%s - %s: invalid pm state request: %u\n",
+- __FUNCTION__, PCIDEV_NAME(pdev), state);
+- return -1;
+- }
+- return 0;
+-}
+
+ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state)
+ {
+@@ -1970,7 +1961,6 @@ static struct pci_driver vlsi_irda_drive
+ .probe = vlsi_irda_probe,
+ .remove = __devexit_p(vlsi_irda_remove),
+ #ifdef CONFIG_PM
+- .save_state = vlsi_irda_save_state,
+ .suspend = vlsi_irda_suspend,
+ .resume = vlsi_irda_resume,
+ #endif
+--- linux-2.6.0-test6/drivers/net/irda/w83977af_ir.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/irda/w83977af_ir.c 2003-10-05 00:33:24.000000000 -0700
+@@ -170,8 +170,7 @@ int w83977af_open(int i, unsigned int io
+ /*
+ * Allocate new instance of the driver
+ */
+- dev = alloc_netdev(sizeof(struct w83977af_ir), "irda%d",
+- irda_device_setup);
++ dev = alloc_irdadev(sizeof(struct w83977af_ir));
+ if (dev == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+--- linux-2.6.0-test6/drivers/net/Kconfig 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/net/Kconfig 2003-10-05 00:33:46.000000000 -0700
+@@ -8,32 +8,18 @@ config NETDEVICES
+ bool "Network device support"
+ ---help---
+ You can say N here if you don't intend to connect your Linux box to
+- any other computer at all or if all your connections will be over a
+- telephone line with a modem either via UUCP (UUCP is a protocol to
+- forward mail and news between unix hosts over telephone lines; read
+- the UUCP-HOWTO, available from
+- <http://www.tldp.org/docs.html#howto>) or dialing up a shell
+- account or a BBS, even using term (term is a program which gives you
+- almost full Internet connectivity if you have a regular dial up
+- shell account on some Internet connected Unix computer. Read
+- <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
++ any other computer at all.
+
+ You'll have to say Y if your computer contains a network card that
+- you want to use under Linux (make sure you know its name because you
+- will be asked for it and read the Ethernet-HOWTO (especially if you
+- plan to use more than one network card under Linux)) or if you want
+- to use SLIP (Serial Line Internet Protocol is the protocol used to
+- send Internet traffic over telephone lines or null modem cables) or
+- CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better
+- and newer replacement for SLIP) or PLIP (Parallel Line Internet
+- Protocol is mainly used to create a mini network by connecting the
+- parallel ports of two local machines) or AX.25/KISS (protocol for
+- sending Internet traffic over amateur radio links).
+-
+- Make sure to read the NET-3-HOWTO. Eventually, you will have to read
+- Olaf Kirch's excellent and free book "Network Administrator's
+- Guide", to be found in <http://www.tldp.org/docs.html#guide>. If
+- unsure, say Y.
++ you want to use under Linux. If you are going to run SLIP or PPP over
++ telephone line or null modem cable you need say Y here. Connecting
++ two machines with parallel ports using PLIP needs this, as well as
++ AX.25/KISS for sending Internet traffic over amateur radio links.
++
++ See also "The Linux Network Administrator's Guide" by Olaf Kirch and
++ Terry Dawson. Available at <http://www.tldp.org/guides.html>.
++
++ If unsure, say Y.
+
+ if NETDEVICES
+ source "drivers/net/arcnet/Kconfig"
+@@ -332,7 +318,7 @@ config MAC8390
+
+ config MAC89x0
+ tristate "Macintosh CS89x0 based ethernet cards"
+- depends on NETDEVICES && MAC
++ depends on NETDEVICES && MAC && BROKEN
+ ---help---
+ Support for CS89x0 chipset based Ethernet cards. If you have a
+ Nubus or LC-PDS network (Ethernet) card of this type, say Y and
+@@ -405,7 +391,7 @@ config ATARILANCE
+
+ config ATARI_BIONET
+ tristate "BioNet-100 support"
+- depends on NETDEVICES && ATARI && ATARI_ACSI!=n
++ depends on NETDEVICES && ATARI && ATARI_ACSI!=n && BROKEN
+ help
+ Say Y to include support for BioData's BioNet-100 Ethernet adapter
+ for the ACSI port. The driver works (has to work...) with a polled
+@@ -413,7 +399,7 @@ config ATARI_BIONET
+
+ config ATARI_PAMSNET
+ tristate "PAMsNet support"
+- depends on NETDEVICES && ATARI && ATARI_ACSI!=n
++ depends on NETDEVICES && ATARI && ATARI_ACSI!=n && BROKEN
+ help
+ Say Y to include support for the PAMsNet Ethernet adapter for the
+ ACSI port ("ACSI node"). The driver works (has to work...) with a
+@@ -808,7 +794,7 @@ config ULTRA32
+
+ config SMC9194
+ tristate "SMC 9194 support"
+- depends on NET_VENDOR_SMC && (ISA || MAC)
++ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+@@ -2455,6 +2441,9 @@ config SHAPER
+ To compile this driver as a module, choose M here: the module
+ will be called shaper. If unsure, say N.
+
++config NET_POLL_CONTROLLER
++ def_bool KGDB
++
+ source "drivers/net/wan/Kconfig"
+
+ source "drivers/net/pcmcia/Kconfig"
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/net/kgdb_eth.c 2003-10-05 00:33:51.000000000 -0700
+@@ -0,0 +1,517 @@
++/*
++ * Network interface GDB stub
++ *
++ * Written by San Mehat (nettwerk@biodome.org)
++ * Based upon 'gdbserial' by David Grothe (dave@gcom.com)
++ * and Scott Foehner (sfoehner@engr.sgi.com)
++ *
++ * Twiddled for 2.6 by Robert Walsh <rjwalsh@durables.org>
++ * and wangdi <wangdi@clusterfs.com>.
++ */
++
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <linux/config.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/termios.h>
++#include <asm/kgdb.h>
++#include <linux/if_ether.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/delay.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/segment.h>
++#include <asm/bitops.h>
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/atomic.h>
++
++#define GDB_BUF_SIZE 512 /* power of 2, please */
++
++static char kgdb_buf[GDB_BUF_SIZE] ;
++static int kgdb_buf_in_inx ;
++static atomic_t kgdb_buf_in_cnt ;
++static int kgdb_buf_out_inx ;
++
++extern void set_debug_traps(void) ; /* GDB routine */
++extern void breakpoint(void);
++
++unsigned int kgdb_remoteip = 0;
++unsigned short kgdb_listenport = 6443;
++unsigned short kgdb_sendport= 6442;
++int kgdb_eth = -1; /* Default tty mode */
++unsigned char kgdb_remotemac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
++unsigned char kgdb_localmac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
++volatile int kgdb_eth_is_initializing = 0;
++int kgdb_eth_need_breakpoint[NR_CPUS];
++
++struct net_device *kgdb_netdevice = NULL;
++
++/*
++ * Get a char if available, return -1 if nothing available.
++ * Empty the receive buffer first, then look at the interface hardware.
++ */
++static int
++read_char(void)
++{
++ /* intr routine has queued chars */
++ if (atomic_read(&kgdb_buf_in_cnt) != 0)
++ {
++ int chr;
++
++ chr = kgdb_buf[kgdb_buf_out_inx++] ;
++ kgdb_buf_out_inx &= (GDB_BUF_SIZE - 1) ;
++ atomic_dec(&kgdb_buf_in_cnt) ;
++ return chr;
++ }
++
++ return -1; /* no data */
++}
++
++/*
++ * Wait until the interface can accept a char, then write it.
++ */
++static void
++write_buffer(char *buf, int len)
++{
++ int total_len, eth_len, ip_len, udp_len;
++ struct in_device *in_dev;
++ struct sk_buff *skb;
++ struct udphdr *udph;
++ struct iphdr *iph;
++ struct ethhdr *eth;
++
++ if (!(in_dev = (struct in_device *) kgdb_netdevice->ip_ptr)) {
++ panic("No in_device available for interface!\n");
++ }
++
++ if (!(in_dev->ifa_list)) {
++ panic("No interface address set for interface!\n");
++ }
++
++ udp_len = len + sizeof(struct udphdr);
++ ip_len = eth_len = udp_len + sizeof(struct iphdr);
++ total_len = eth_len + ETH_HLEN;
++
++ if (!(skb = alloc_skb(total_len, GFP_ATOMIC))) {
++ return;
++ }
++
++ atomic_set(&skb->users, 1);
++ skb_reserve(skb, total_len - len);
++
++ memcpy(skb->data, (unsigned char *) buf, len);
++ skb->len += len;
++
++ udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
++ udph->source = htons(kgdb_listenport);
++ udph->dest = htons(kgdb_sendport);
++ udph->len = htons(udp_len);
++ udph->check = 0;
++
++ iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
++ iph->version = 4;
++ iph->ihl = 5;
++ iph->tos = 0;
++ iph->tot_len = htons(ip_len);
++ iph->id = 0;
++ iph->frag_off = 0;
++ iph->ttl = 64;
++ iph->protocol = IPPROTO_UDP;
++ iph->check = 0;
++ iph->saddr = in_dev->ifa_list->ifa_address;
++ iph->daddr = kgdb_remoteip;
++ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
++
++ eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
++ eth->h_proto = htons(ETH_P_IP);
++ memcpy(eth->h_source, kgdb_localmac, kgdb_netdevice->addr_len);
++ memcpy(eth->h_dest, kgdb_remotemac, kgdb_netdevice->addr_len);
++
++repeat:
++ spin_lock(&kgdb_netdevice->xmit_lock);
++ kgdb_netdevice->xmit_lock_owner = smp_processor_id();
++
++ if (netif_queue_stopped(kgdb_netdevice)) {
++ kgdb_netdevice->xmit_lock_owner = -1;
++ spin_unlock(&kgdb_netdevice->xmit_lock);
++
++ kgdb_netdevice->poll_controller(kgdb_netdevice);
++ goto repeat;
++ }
++
++ kgdb_netdevice->hard_start_xmit(skb, kgdb_netdevice);
++ kgdb_netdevice->xmit_lock_owner = -1;
++ spin_unlock(&kgdb_netdevice->xmit_lock);
++}
++
++/*
++ * In the interrupt state the target machine will not respond to any
++ * arp requests, so handle them here.
++ */
++
++static struct sk_buff *send_skb = NULL;
++
++void
++kgdb_eth_reply_arp(void)
++{
++ if (send_skb) {
++ spin_lock(&kgdb_netdevice->xmit_lock);
++ kgdb_netdevice->xmit_lock_owner = smp_processor_id();
++ kgdb_netdevice->hard_start_xmit(send_skb, kgdb_netdevice);
++ kgdb_netdevice->xmit_lock_owner = -1;
++ spin_unlock(&kgdb_netdevice->xmit_lock);
++ send_skb = NULL;
++ }
++}
++
++static int
++make_arp_request(struct sk_buff *skb)
++{
++ struct arphdr *arp;
++ unsigned char *arp_ptr;
++ int type = ARPOP_REPLY;
++ int ptype = ETH_P_ARP;
++ u32 sip, tip;
++ unsigned char *sha, *tha;
++ struct in_device *in_dev = (struct in_device *) kgdb_netdevice->ip_ptr;
++
++ /* No arp on this interface */
++
++ if (kgdb_netdevice->flags & IFF_NOARP) {
++ return 0;
++ }
++
++ if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
++ (2 * kgdb_netdevice->addr_len) +
++ (2 * sizeof(u32))))) {
++ return 0;
++ }
++
++ skb->h.raw = skb->nh.raw = skb->data;
++ arp = skb->nh.arph;
++
++ if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
++ arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
++ arp->ar_pro != htons(ETH_P_IP)) {
++ return 0;
++ }
++
++ /* Understand only these message types */
++
++ if (arp->ar_op != htons(ARPOP_REQUEST)) {
++ return 0;
++ }
++
++ /* Extract fields */
++
++ arp_ptr= (unsigned char *)(arp+1);
++ sha = arp_ptr;
++ arp_ptr += kgdb_netdevice->addr_len;
++ memcpy(&sip, arp_ptr, 4);
++ arp_ptr += 4;
++ tha = arp_ptr;
++ arp_ptr += kgdb_netdevice->addr_len;
++ memcpy(&tip, arp_ptr, 4);
++
++ if (tip != in_dev->ifa_list->ifa_address) {
++ return 0;
++ }
++
++ if (kgdb_remoteip != sip) {
++ return 0;
++ }
++
++ /*
++ * Check for bad requests for 127.x.x.x and requests for multicast
++ * addresses. If this is one such, delete it.
++ */
++
++ if (LOOPBACK(tip) || MULTICAST(tip)) {
++ return 0;
++ }
++
++ /* reply to the ARP request */
++
++ send_skb = alloc_skb(sizeof(struct arphdr) + 2 * (kgdb_netdevice->addr_len + 4) + LL_RESERVED_SPACE(kgdb_netdevice), GFP_ATOMIC);
++
++ if (send_skb == NULL) {
++ return 0;
++ }
++
++ skb_reserve(send_skb, LL_RESERVED_SPACE(kgdb_netdevice));
++ send_skb->nh.raw = send_skb->data;
++ arp = (struct arphdr *) skb_put(send_skb, sizeof(struct arphdr) + 2 * (kgdb_netdevice->addr_len + 4));
++ send_skb->dev = kgdb_netdevice;
++ send_skb->protocol = htons(ETH_P_ARP);
++
++ /* Fill the device header for the ARP frame */
++
++ if (kgdb_netdevice->hard_header &&
++ kgdb_netdevice->hard_header(send_skb, kgdb_netdevice, ptype,
++ kgdb_remotemac, kgdb_localmac,
++ send_skb->len) < 0) {
++ kfree_skb(send_skb);
++ return 0;
++ }
++
++ /*
++ * Fill out the arp protocol part.
++ *
++ * we only support ethernet device type,
++ * which (according to RFC 1390) should always equal 1 (Ethernet).
++ */
++
++ arp->ar_hrd = htons(kgdb_netdevice->type);
++ arp->ar_pro = htons(ETH_P_IP);
++
++ arp->ar_hln = kgdb_netdevice->addr_len;
++ arp->ar_pln = 4;
++ arp->ar_op = htons(type);
++
++ arp_ptr=(unsigned char *)(arp + 1);
++
++ memcpy(arp_ptr, kgdb_netdevice->dev_addr, kgdb_netdevice->addr_len);
++ arp_ptr += kgdb_netdevice->addr_len;
++ memcpy(arp_ptr, &tip, 4);
++ arp_ptr += 4;
++ memcpy(arp_ptr, kgdb_localmac, kgdb_netdevice->addr_len);
++ arp_ptr += kgdb_netdevice->addr_len;
++ memcpy(arp_ptr, &sip, 4);
++ return 0;
++}
++
++
++/*
++ * Accept an skbuff from net_device layer and add the payload onto
++ * kgdb buffer
++ *
++ * When the kgdb stub routine getDebugChar() is called it draws characters
++ * out of the buffer until it is empty and then reads directly from the
++ * serial port.
++ *
++ * We do not attempt to write chars from the interrupt routine since
++ * the stubs do all of that via putDebugChar() which writes one byte
++ * after waiting for the interface to become ready.
++ *
++ * The debug stubs like to run with interrupts disabled since, after all,
++ * they run as a consequence of a breakpoint in the kernel.
++ *
++ * NOTE: Return value of 1 means it was for us and is an indication to
++ * the calling driver to destroy the sk_buff and not send it up the stack.
++ */
++int
++kgdb_net_interrupt(struct sk_buff *skb)
++{
++ unsigned char chr;
++ struct iphdr *iph = (struct iphdr*)skb->data;
++ struct udphdr *udph= (struct udphdr*)(skb->data+(iph->ihl<<2));
++ unsigned char *data = (unsigned char *) udph + sizeof(struct udphdr);
++ int len;
++ int i;
++
++ if ((kgdb_eth != -1) && (!kgdb_netdevice) &&
++ (iph->protocol == IPPROTO_UDP) &&
++ (be16_to_cpu(udph->dest) == kgdb_listenport)) {
++ kgdb_sendport = be16_to_cpu(udph->source);
++
++ while (kgdb_eth_is_initializing)
++ ;
++ if (!kgdb_netdevice)
++ kgdb_eth_hook();
++ if (!kgdb_netdevice) {
++ /* Lets not even try again. */
++ kgdb_eth = -1;
++ return 0;
++ }
++ }
++ if (!kgdb_netdevice) {
++ return 0;
++ }
++ if (skb->protocol == __constant_htons(ETH_P_ARP) && !send_skb) {
++ make_arp_request(skb);
++ return 0;
++ }
++ if (iph->protocol != IPPROTO_UDP) {
++ return 0;
++ }
++
++ if (be16_to_cpu(udph->dest) != kgdb_listenport) {
++ return 0;
++ }
++
++ len = (be16_to_cpu(iph->tot_len) -
++ (sizeof(struct udphdr) + sizeof(struct iphdr)));
++
++ for (i = 0; i < len; i++) {
++ chr = data[i];
++ if (chr == 3) {
++ kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
++ continue;
++ }
++ if (atomic_read(&kgdb_buf_in_cnt) >= GDB_BUF_SIZE) {
++ /* buffer overflow, clear it */
++ kgdb_buf_in_inx = 0;
++ atomic_set(&kgdb_buf_in_cnt, 0);
++ kgdb_buf_out_inx = 0;
++ break;
++ }
++ kgdb_buf[kgdb_buf_in_inx++] = chr;
++ kgdb_buf_in_inx &= (GDB_BUF_SIZE - 1);
++ atomic_inc(&kgdb_buf_in_cnt);
++ }
++
++ if (!kgdb_netdevice->kgdb_is_trapped) {
++ /*
++ * If a new gdb instance is trying to attach, we need to
++ * break here.
++ */
++ if (!strncmp(data, "$Hc-1#09", 8))
++ kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
++ }
++ return 1;
++}
++EXPORT_SYMBOL(kgdb_net_interrupt);
++
++int
++kgdb_eth_hook(void)
++{
++ char kgdb_netdev[16];
++ extern void kgdb_respond_ok(void);
++
++ if (kgdb_remotemac[0] == 0xff) {
++ panic("ERROR! 'gdbeth_remotemac' option not set!\n");
++ }
++ if (kgdb_localmac[0] == 0xff) {
++ panic("ERROR! 'gdbeth_localmac' option not set!\n");
++ }
++ if (kgdb_remoteip == 0) {
++ panic("ERROR! 'gdbeth_remoteip' option not set!\n");
++ }
++
++ sprintf(kgdb_netdev,"eth%d",kgdb_eth);
++
++#ifdef CONFIG_SMP
++ if (num_online_cpus() > CONFIG_NO_KGDB_CPUS) {
++ printk("kgdb: too manu cpus. Cannot enable debugger with more than %d cpus\n", CONFIG_NO_KGDB_CPUS);
++ return -1;
++ }
++#endif
++ for (kgdb_netdevice = dev_base;
++ kgdb_netdevice != NULL;
++ kgdb_netdevice = kgdb_netdevice->next) {
++ if (strncmp(kgdb_netdevice->name, kgdb_netdev, IFNAMSIZ) == 0) {
++ break;
++ }
++ }
++ if (!kgdb_netdevice) {
++ printk("KGDB NET : Unable to find interface %s\n",kgdb_netdev);
++ return -ENODEV;
++ }
++
++ /*
++ * Call GDB routine to setup the exception vectors for the debugger
++ */
++ set_debug_traps();
++
++ /*
++ * Call the breakpoint() routine in GDB to start the debugging
++ * session.
++ */
++ kgdb_eth_is_initializing = 1;
++ kgdb_eth_need_breakpoint[smp_processor_id()] = 1;
++ return 0;
++}
++
++/*
++ * getDebugChar
++ *
++ * This is a GDB stub routine. It waits for a character from the
++ * serial interface and then returns it. If there is no serial
++ * interface connection then it returns a bogus value which will
++ * almost certainly cause the system to hang.
++ */
++int
++eth_getDebugChar(void)
++{
++ volatile int chr;
++
++ while ((chr = read_char()) < 0) {
++ if (send_skb) {
++ kgdb_eth_reply_arp();
++ }
++ if (kgdb_netdevice->poll_controller) {
++ kgdb_netdevice->poll_controller(kgdb_netdevice);
++ } else {
++ printk("KGDB NET: Error - Device %s is not supported!\n", kgdb_netdevice->name);
++ panic("Please add support for kgdb net to this driver");
++ }
++ }
++ return chr;
++}
++
++#define ETH_QUEUE_SIZE 256
++static char eth_queue[ETH_QUEUE_SIZE];
++static int outgoing_queue;
++
++void
++eth_flushDebugChar(void)
++{
++ if(outgoing_queue) {
++ write_buffer(eth_queue, outgoing_queue);
++
++ outgoing_queue = 0;
++ }
++}
++
++static void
++put_char_on_queue(int chr)
++{
++ eth_queue[outgoing_queue++] = chr;
++ if(outgoing_queue == ETH_QUEUE_SIZE)
++ {
++ eth_flushDebugChar();
++ }
++}
++
++/*
++ * eth_putDebugChar
++ *
++ * This is a GDB stub routine. It waits until the interface is ready
++ * to transmit a char and then sends it.
++ */
++void
++eth_putDebugChar(int chr)
++{
++ put_char_on_queue(chr); /* this routine will wait */
++}
++
++void
++kgdb_eth_set_trapmode(int mode)
++{
++ if (!kgdb_netdevice) {
++ return;
++ }
++ kgdb_netdevice->kgdb_is_trapped = mode;
++}
++
++int
++kgdb_eth_is_trapped()
++{
++ if (!kgdb_netdevice) {
++ return 0;
++ }
++ return kgdb_netdevice->kgdb_is_trapped;
++}
++EXPORT_SYMBOL(kgdb_eth_is_trapped);
+--- linux-2.6.0-test6/drivers/net/loopback.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/loopback.c 2003-10-05 00:33:24.000000000 -0700
+@@ -30,6 +30,7 @@
+ */
+ #include <linux/kernel.h>
+ #include <linux/jiffies.h>
++#include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/fs.h>
+ #include <linux/types.h>
+@@ -202,3 +203,5 @@ int __init loopback_init(void)
+
+ return register_netdev(&loopback_dev);
+ };
++
++EXPORT_SYMBOL(loopback_dev);
+--- linux-2.6.0-test6/drivers/net/mac8390.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/net/mac8390.c 2003-10-05 00:33:24.000000000 -0700
+@@ -442,14 +442,14 @@ int __init mac8390_initdev(struct net_de
+ ei_status.tx_start_page = CABLETRON_TX_START_PG;
+ ei_status.rx_start_page = CABLETRON_RX_START_PG;
+ ei_status.stop_page = CABLETRON_RX_STOP_PG;
+- dev->rmem_start = dev->mem_start;
+- dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
++ ei_status.rmem_start = dev->mem_start;
++ ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+ } else {
+ ei_status.tx_start_page = WD_START_PG;
+ ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+ ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+- dev->rmem_start = dev->mem_start + TX_PAGES*256;
+- dev->rmem_end = dev->mem_end;
++ ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
++ ei_status.rmem_end = dev->mem_end;
+ }
+
+ /* Fill in model-specific information and functions */
+@@ -621,12 +621,12 @@ static void sane_block_input(struct net_
+ unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+ unsigned long xfer_start = xfer_base + dev->mem_start;
+
+- if (xfer_start + count > dev->rmem_end) {
++ if (xfer_start + count > ei_status.rmem_end) {
+ /* We must wrap the input move. */
+- int semi_count = dev->rmem_end - xfer_start;
++ int semi_count = ei_status.rmem_end - xfer_start;
+ memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, semi_count);
+ count -= semi_count;
+- memcpy_toio(skb->data + semi_count, (char *)dev->rmem_start, count);
++ memcpy_toio(skb->data + semi_count, (char *)ei_status.rmem_start, count);
+ } else {
+ memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, count);
+ }
+@@ -657,15 +657,16 @@ static void dayna_block_input(struct net
+
+ /* Note the offset math is done in card memory space which is word
+ per long onto our space. */
+-
+- if (xfer_start + count > dev->rmem_end)
++
++ if (xfer_start + count > ei_status.rmem_end)
+ {
+ /* We must wrap the input move. */
+- int semi_count = dev->rmem_end - xfer_start;
++ int semi_count = ei_status.rmem_end - xfer_start;
+ dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
+ count -= semi_count;
+- dayna_memcpy_fromcard(dev, skb->data + semi_count,
+- dev->rmem_start - dev->mem_start, count);
++ dayna_memcpy_fromcard(dev, skb->data + semi_count,
++ ei_status.rmem_start - dev->mem_start,
++ count);
+ }
+ else
+ {
+@@ -697,15 +698,15 @@ static void slow_sane_block_input(struct
+ unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+ unsigned long xfer_start = xfer_base+dev->mem_start;
+
+- if (xfer_start + count > dev->rmem_end)
++ if (xfer_start + count > ei_status.rmem_end)
+ {
+ /* We must wrap the input move. */
+- int semi_count = dev->rmem_end - xfer_start;
++ int semi_count = ei_status.rmem_end - xfer_start;
+ word_memcpy_fromcard(skb->data, (char *)dev->mem_start +
+ xfer_base, semi_count);
+ count -= semi_count;
+ word_memcpy_fromcard(skb->data + semi_count,
+- (char *)dev->rmem_start, count);
++ (char *)ei_status.rmem_start, count);
+ }
+ else
+ {
+--- linux-2.6.0-test6/drivers/net/Makefile 2003-09-27 18:57:44.000000000 -0700
++++ 25/drivers/net/Makefile 2003-10-05 00:33:44.000000000 -0700
+@@ -32,6 +32,8 @@ obj-$(CONFIG_BMAC) += bmac.o
+
+ obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
+
++obj-$(CONFIG_KGDB) += kgdb_eth.o
++
+ obj-$(CONFIG_DGRS) += dgrs.o
+ obj-$(CONFIG_RCPCI) += rcpci.o
+ obj-$(CONFIG_VORTEX) += 3c59x.o
+--- linux-2.6.0-test6/drivers/net/ne2.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/ne2.c 2003-10-05 00:33:24.000000000 -0700
+@@ -70,7 +70,7 @@ static const char *version = "ne2.c:v0.9
+ #include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+--- linux-2.6.0-test6/drivers/net/ne3210.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/ne3210.c 2003-10-05 00:33:24.000000000 -0700
+@@ -23,6 +23,7 @@
+ This driver WILL NOT WORK FOR THE NE3200 - it is completely different
+ and does not use an 8390 at all.
+
++ Updated to EISA probing API 5/2003 by Marc Zyngier.
+ */
+
+ static const char *version =
+@@ -44,9 +45,6 @@ static const char *version =
+
+ #include "8390.h"
+
+-int ne3210_probe(struct net_device *dev);
+-static int ne3210_probe1(struct net_device *dev, int ioaddr);
+-
+ static int ne3210_open(struct net_device *dev);
+ static int ne3210_close(struct net_device *dev);
+
+@@ -59,7 +57,6 @@ static void ne3210_block_output(struct n
+ #define NE3210_START_PG 0x00 /* First page of TX buffer */
+ #define NE3210_STOP_PG 0x80 /* Last page +1 of RX ring */
+
+-#define NE3210_ID_PORT 0xc80 /* Same for all EISA cards */
+ #define NE3210_IO_EXTENT 0x20
+ #define NE3210_SA_PROM 0x16 /* Start of e'net addr. */
+ #define NE3210_RESET_PORT 0xc84
+@@ -69,10 +66,9 @@ static void ne3210_block_output(struct n
+ #define NE3210_ADDR1 0x00
+ #define NE3210_ADDR2 0x1b
+
+-#define NE3210_ID 0x0118cc3a /* 0x3acc = 1110 10110 01100 = nvl */
+-
+ #define NE3210_CFG1 0xc84 /* NB: 0xc84 is also "reset" port. */
+ #define NE3210_CFG2 0xc90
++#define NE3210_CFG_EXTENT (NE3210_CFG2 - NE3210_CFG1 + 1)
+
+ /*
+ * You can OR any of the following bits together and assign it
+@@ -89,152 +85,108 @@ static void ne3210_block_output(struct n
+
+ static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+ static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0};
++static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"};
++static int ifmap_val[] __initdata = {
++ IF_PORT_10BASET,
++ IF_PORT_UNKNOWN,
++ IF_PORT_10BASE2,
++ IF_PORT_AUI,
++};
+
+-/*
+- * Probe for the card. The best way is to read the EISA ID if it
+- * is known. Then we can check the prefix of the station address
+- * PROM for a match against the value assigned to Novell.
+- */
+-
+-int __init ne3210_probe(struct net_device *dev)
++static int __init ne3210_eisa_probe (struct device *device)
+ {
+- unsigned short ioaddr = dev->base_addr;
+-
+- SET_MODULE_OWNER(dev);
++ unsigned long ioaddr, phys_mem;
++ int i, retval, port_index;
++ struct eisa_device *edev = to_eisa_device (device);
++ struct net_device *dev;
+
+- if (ioaddr > 0x1ff) /* Check a single specified location. */
+- return ne3210_probe1(dev, ioaddr);
+- else if (ioaddr > 0) /* Don't probe at all. */
+- return -ENXIO;
+-
+- if (!EISA_bus) {
+-#if NE3210_DEBUG & NE3210_D_PROBE
+- printk("ne3210-debug: Not an EISA bus. Not probing high ports.\n");
+-#endif
+- return -ENXIO;
++ /* Allocate dev->priv and fill in 8390 specific dev fields. */
++ if (!(dev = alloc_ei_netdev ())) {
++ printk ("ne3210.c: unable to allocate memory for dev!\n");
++ return -ENOMEM;
+ }
+
+- /* EISA spec allows for up to 16 slots, but 8 is typical. */
+- for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000)
+- if (ne3210_probe1(dev, ioaddr) == 0)
+- return 0;
+-
+- return -ENODEV;
+-}
+-
+-static int __init ne3210_probe1(struct net_device *dev, int ioaddr)
+-{
+- int i, retval;
+- unsigned long eisa_id;
+- const char *ifmap[] = {"UTP", "?", "BNC", "AUI"};
+-
+- if (!request_region(dev->base_addr, NE3210_IO_EXTENT, dev->name))
+- return -EBUSY;
++ SET_MODULE_OWNER(dev);
++ SET_NETDEV_DEV(dev, device);
++ device->driver_data = dev;
++ ioaddr = edev->base_addr;
+
+- if (inb_p(ioaddr + NE3210_ID_PORT) == 0xff) {
+- retval = -ENODEV;
++ if (ethdev_init (dev)) {
++ printk ("ne3210.c: unable to allocate memory for dev->priv!\n");
++ retval = -ENOMEM;
+ goto out;
+ }
+
+-#if NE3210_DEBUG & NE3210_D_PROBE
+- printk("ne3210-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + NE3210_ID_PORT));
+- printk("ne3210-debug: config regs: %#x %#x\n",
+- inb(ioaddr + NE3210_CFG1), inb(ioaddr + NE3210_CFG2));
+-#endif
+-
+-
+-/* Check the EISA ID of the card. */
+- eisa_id = inl(ioaddr + NE3210_ID_PORT);
+- if (eisa_id != NE3210_ID) {
+- retval = -ENODEV;
++ if (!request_region(ioaddr, NE3210_IO_EXTENT, dev->name)) {
++ retval = -EBUSY;
+ goto out;
+ }
+
+-
+-#if 0
+-/* Check the vendor ID as well. Not really required. */
+- if (inb(ioaddr + NE3210_SA_PROM + 0) != NE3210_ADDR0
+- || inb(ioaddr + NE3210_SA_PROM + 1) != NE3210_ADDR1
+- || inb(ioaddr + NE3210_SA_PROM + 2) != NE3210_ADDR2 ) {
+- printk("ne3210.c: card not found");
+- for(i = 0; i < ETHER_ADDR_LEN; i++)
+- printk(" %02x", inb(ioaddr + NE3210_SA_PROM + i));
+- printk(" (invalid prefix).\n");
+- retval = -ENODEV;
+- goto out;
++ if (!request_region(ioaddr + NE3210_CFG1,
++ NE3210_CFG_EXTENT, dev->name)) {
++ retval = -EBUSY;
++ goto out1;
+ }
++
++#if NE3210_DEBUG & NE3210_D_PROBE
++ printk("ne3210-debug: probe at %#x, ID %s\n", ioaddr, edev->id.sig);
++ printk("ne3210-debug: config regs: %#x %#x\n",
++ inb(ioaddr + NE3210_CFG1), inb(ioaddr + NE3210_CFG2));
+ #endif
+
+- /* Allocate dev->priv and fill in 8390 specific dev fields. */
+- if (ethdev_init(dev)) {
+- printk ("ne3210.c: unable to allocate memory for dev->priv!\n");
+- retval = -ENOMEM;
+- goto out;
+- }
+
++ port_index = inb(ioaddr + NE3210_CFG2) >> 6;
+ printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr:",
+- ioaddr/0x1000, ifmap[inb(ioaddr + NE3210_CFG2) >> 6]);
++ edev->slot, ifmap[port_index]);
+ for(i = 0; i < ETHER_ADDR_LEN; i++)
+ printk(" %02x", (dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i)));
+- printk(".\nne3210.c: ");
++
+
+ /* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
+- if (dev->irq == 0) {
+- unsigned char irq_reg = inb(ioaddr + NE3210_CFG2) >> 3;
+- dev->irq = irq_map[irq_reg & 0x07];
+- printk("using");
+- } else {
+- /* This is useless unless we reprogram the card here too */
+- if (dev->irq == 2) dev->irq = 9; /* Doh! */
+- printk("assigning");
+- }
+- printk(" IRQ %d,", dev->irq);
++ dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
++ printk(".\nne3210.c: using IRQ %d, ", dev->irq);
+
+ retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+ if (retval) {
+ printk (" unable to get IRQ %d.\n", dev->irq);
+- goto out1;
+- }
+-
+- if (dev->mem_start == 0) {
+- unsigned char mem_reg = inb(ioaddr + NE3210_CFG2) & 0x07;
+- dev->mem_start = shmem_map[mem_reg] * 0x1000;
+- printk(" using ");
+- } else {
+- /* Should check for value in shmem_map and reprogram the card to use it */
+- dev->mem_start &= 0xfff8000;
+- printk(" assigning ");
++ goto out2;
+ }
+
+- printk("%dkB memory at physical address %#lx\n",
+- NE3210_STOP_PG/4, dev->mem_start);
++ phys_mem = shmem_map[inb(ioaddr + NE3210_CFG2) & 0x07] * 0x1000;
+
+ /*
+ BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+ the card mem within the region covered by `normal' RAM !!!
+ */
+- if (dev->mem_start > 1024*1024) { /* phys addr > 1MB */
+- if (dev->mem_start < virt_to_phys(high_memory)) {
++ if (phys_mem > 1024*1024) { /* phys addr > 1MB */
++ if (phys_mem < virt_to_phys(high_memory)) {
+ printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
+ printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
+ printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_phys(high_memory));
+ printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
+ retval = -EINVAL;
+- goto out2;
++ goto out3;
+ }
+- dev->mem_start = (unsigned long)ioremap(dev->mem_start, NE3210_STOP_PG*0x100);
+- if (dev->mem_start == 0) {
+- printk(KERN_ERR "ne3210.c: Unable to remap card memory above 1MB !!\n");
+- printk(KERN_ERR "ne3210.c: Try using EISA SCU to set memory below 1MB.\n");
+- printk(KERN_ERR "ne3210.c: Driver NOT installed.\n");
+- retval = -EAGAIN;
+- goto out2;
+- }
+- ei_status.reg0 = 1; /* Use as remap flag */
+- printk("ne3210.c: remapped %dkB card memory to virtual address %#lx\n",
+- NE3210_STOP_PG/4, dev->mem_start);
+ }
++
++ if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, dev->name)) {
++ printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n",
++ phys_mem);
++ goto out3;
++ }
++
++ printk("%dkB memory at physical address %#lx\n",
++ NE3210_STOP_PG/4, phys_mem);
+
++ dev->mem_start = (unsigned long)ioremap(phys_mem, NE3210_STOP_PG*0x100);
++ if (dev->mem_start == 0) {
++ printk(KERN_ERR "ne3210.c: Unable to remap card memory !!\n");
++ printk(KERN_ERR "ne3210.c: Driver NOT installed.\n");
++ retval = -EAGAIN;
++ goto out4;
++ }
++ printk("ne3210.c: remapped %dkB card memory to virtual address %#lx\n",
++ NE3210_STOP_PG/4, dev->mem_start);
+ dev->mem_end = ei_status.rmem_end = dev->mem_start
+ + (NE3210_STOP_PG - NE3210_START_PG)*256;
+ ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+@@ -247,6 +199,7 @@ static int __init ne3210_probe1(struct n
+ ei_status.rx_start_page = NE3210_START_PG + TX_PAGES;
+ ei_status.stop_page = NE3210_STOP_PG;
+ ei_status.word16 = 1;
++ ei_status.priv = phys_mem;
+
+ if (ei_debug > 0)
+ printk(version);
+@@ -258,18 +211,46 @@ static int __init ne3210_probe1(struct n
+
+ dev->open = &ne3210_open;
+ dev->stop = &ne3210_close;
++ dev->if_port = ifmap_val[port_index];
++
++ if ((retval = register_netdev (dev)))
++ goto out5;
++
+ NS8390_init(dev, 0);
+ return 0;
+-out2:
+- free_irq(dev->irq, dev);
+-out1:
+- kfree(dev->priv);
+- dev->priv = NULL;
+-out:
+- release_region(ioaddr, NE3210_IO_EXTENT);
++
++ out5:
++ iounmap((void *)dev->mem_start);
++ out4:
++ release_mem_region (phys_mem, NE3210_STOP_PG*0x100);
++ out3:
++ free_irq (dev->irq, dev);
++ out2:
++ release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
++ out1:
++ release_region (ioaddr, NE3210_IO_EXTENT);
++ out:
++ free_netdev (dev);
++
+ return retval;
+ }
+
++static int __devexit ne3210_eisa_remove (struct device *device)
++{
++ struct net_device *dev = device->driver_data;
++ unsigned long ioaddr = to_eisa_device (device)->base_addr;
++
++ unregister_netdev (dev);
++ iounmap((void *)dev->mem_start);
++ release_mem_region (ei_status.priv, NE3210_STOP_PG*0x100);
++ free_irq (dev->irq, dev);
++ release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
++ release_region (ioaddr, NE3210_IO_EXTENT);
++ free_netdev (dev);
++
++ return 0;
++}
++
+ /*
+ * Reset by toggling the "Board Enable" bits (bit 2 and 0).
+ */
+@@ -309,7 +290,7 @@ static void
+ ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+ {
+ unsigned long hdr_start = dev->mem_start + ((ring_page - NE3210_START_PG)<<8);
+- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
++ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */
+ }
+
+@@ -327,12 +308,12 @@ static void ne3210_block_input(struct ne
+ if (xfer_start + count > ei_status.rmem_end) {
+ /* Packet wraps over end of ring buffer. */
+ int semi_count = ei_status.rmem_end - xfer_start;
+- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
++ memcpy_fromio(skb->data, xfer_start, semi_count);
+ count -= semi_count;
+- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
++ memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ } else {
+ /* Packet is in one chunk. */
+- isa_memcpy_fromio(skb->data, xfer_start, count);
++ memcpy_fromio(skb->data, xfer_start, count);
+ }
+ }
+
+@@ -342,7 +323,7 @@ static void ne3210_block_output(struct n
+ unsigned long shmem = dev->mem_start + ((start_page - NE3210_START_PG)<<8);
+
+ count = (count + 3) & ~3; /* Round up to doubleword */
+- isa_memcpy_toio(shmem, buf, count);
++ memcpy_toio(shmem, buf, count);
+ }
+
+ static int ne3210_open(struct net_device *dev)
+@@ -361,7 +342,23 @@ static int ne3210_close(struct net_devic
+ return 0;
+ }
+
++static struct eisa_device_id ne3210_ids[] = {
++ { "EGL0101" },
++ { "NVL1801" },
++ { "" },
++};
++
++static struct eisa_driver ne3210_eisa_driver = {
++ .id_table = ne3210_ids,
++ .driver = {
++ .name = "ne3210",
++ .probe = ne3210_eisa_probe,
++ .remove = __devexit_p (ne3210_eisa_remove),
++ },
++};
++
+ #ifdef MODULE
++#if 0
+ #define MAX_NE3210_CARDS 4 /* Max number of NE3210 cards per module */
+ static struct net_device dev_ne3210[MAX_NE3210_CARDS];
+ static int io[MAX_NE3210_CARDS];
+@@ -374,50 +371,22 @@ MODULE_PARM(mem, "1-" __MODULE_STRING(MA
+ MODULE_PARM_DESC(io, "I/O base address(es)");
+ MODULE_PARM_DESC(irq, "IRQ number(s)");
+ MODULE_PARM_DESC(mem, "memory base address(es)");
++#endif
++#endif /* MODULE */
++
++
+ MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
+ MODULE_LICENSE("GPL");
+
+-int init_module(void)
++int ne3210_init(void)
+ {
+- int this_dev, found = 0;
+-
+- for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) {
+- struct net_device *dev = &dev_ne3210[this_dev];
+- dev->irq = irq[this_dev];
+- dev->base_addr = io[this_dev];
+- dev->mem_start = mem[this_dev];
+- dev->init = ne3210_probe;
+- /* Default is to only install one card. */
+- if (io[this_dev] == 0 && this_dev != 0) break;
+- if (register_netdev(dev) != 0) {
+- printk(KERN_WARNING "ne3210.c: No NE3210 card found (i/o = 0x%x).\n", io[this_dev]);
+- if (found != 0) { /* Got at least one. */
+- return 0;
+- }
+- return -ENXIO;
+- }
+- found++;
+- }
+- return 0;
++ return eisa_driver_register (&ne3210_eisa_driver);
+ }
+
+-void cleanup_module(void)
++void ne3210_cleanup(void)
+ {
+- int this_dev;
+-
+- for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) {
+- struct net_device *dev = &dev_ne3210[this_dev];
+- if (dev->priv != NULL) {
+- free_irq(dev->irq, dev);
+- release_region(dev->base_addr, NE3210_IO_EXTENT);
+- if (ei_status.reg0)
+- iounmap((void *)dev->mem_start);
+- unregister_netdev(dev);
+- kfree(dev->priv);
+- dev->priv = NULL;
+- }
+- }
++ eisa_driver_unregister (&ne3210_eisa_driver);
+ }
+
+-#endif /* MODULE */
+-
++module_init (ne3210_init);
++module_exit (ne3210_cleanup);
+--- linux-2.6.0-test6/drivers/net/sk_mca.c 2003-09-08 13:58:57.000000000 -0700
++++ 25/drivers/net/sk_mca.c 2003-10-05 00:33:24.000000000 -0700
+@@ -89,7 +89,7 @@ History:
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/time.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/version.h>
+--- linux-2.6.0-test6/drivers/net/slip.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/slip.c 2003-10-05 00:36:15.000000000 -0700
+@@ -1307,7 +1307,7 @@ static int sl_ioctl(struct net_device *d
+ /* Resolve race condition, when ioctl'ing hanged up
+ and opened by another process device.
+ */
+- if (sl->tty != current->tty && sl->pid != current->pid) {
++ if (sl->tty != process_tty(current) && sl->pid != current->pid) {
+ spin_unlock_bh(&sl->lock);
+ return -EPERM;
+ }
+--- linux-2.6.0-test6/drivers/net/Space.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/Space.c 2003-10-05 00:33:24.000000000 -0700
+@@ -67,7 +67,6 @@ extern int elplus_probe(struct net_devic
+ extern int ac3200_probe(struct net_device *);
+ extern int es_probe(struct net_device *);
+ extern int lne390_probe(struct net_device *);
+-extern int ne3210_probe(struct net_device *);
+ extern int e2100_probe(struct net_device *);
+ extern int ni5010_probe(struct net_device *);
+ extern int ni52_probe(struct net_device *);
+@@ -155,9 +154,6 @@ static struct devprobe eisa_probes[] __i
+ #ifdef CONFIG_LNE390
+ {lne390_probe, 0},
+ #endif
+-#ifdef CONFIG_NE3210
+- {ne3210_probe, 0},
+-#endif
+ {NULL, 0},
+ };
+
+@@ -480,3 +476,5 @@ void __init probe_old_netdevs(void)
+ struct net_device *dev_base;
+ rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
+
++EXPORT_SYMBOL(dev_base);
++EXPORT_SYMBOL(dev_base_lock);
+--- linux-2.6.0-test6/drivers/net/tlan.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/tlan.c 2003-10-05 00:33:48.000000000 -0700
+@@ -297,6 +297,7 @@ static int TLan_ioctl( struct net_device
+ static int TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent);
+ static void TLan_tx_timeout( struct net_device *dev);
+ static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
++static void TLan_Poll(struct net_device *dev);
+
+ static u32 TLan_HandleInvalid( struct net_device *, u16 );
+ static u32 TLan_HandleTxEOF( struct net_device *, u16 );
+@@ -453,6 +454,25 @@ static void __devexit tlan_remove_one( s
+ pci_set_drvdata( pdev, NULL );
+ }
+
++#ifdef CONFIG_NET_POLL_CONTROLLER
++
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++
++static void TLan_Poll (struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ TLan_HandleInterrupt(dev->irq, dev, NULL);
++ enable_irq(dev->irq);
++}
++
++#endif
++
++
++
+ static struct pci_driver tlan_driver = {
+ .name = "tlan",
+ .id_table = tlan_pci_tbl,
+@@ -895,6 +915,9 @@ static int TLan_Init( struct net_device
+ dev->do_ioctl = &TLan_ioctl;
+ dev->tx_timeout = &TLan_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = &TLan_Poll;
++#endif
+
+ return 0;
+
+--- linux-2.6.0-test6/drivers/net/tokenring/madgemc.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/net/tokenring/madgemc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -20,7 +20,7 @@
+ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
+
+ #include <linux/module.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/pci.h>
+--- linux-2.6.0-test6/drivers/net/tokenring/smctr.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/tokenring/smctr.c 2003-10-05 00:33:24.000000000 -0700
+@@ -43,7 +43,7 @@
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+-#include <linux/mca.h>
++#include <linux/mca-legacy.h>
+ #include <linux/delay.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+--- linux-2.6.0-test6/drivers/net/tulip/interrupt.c 2003-06-14 12:18:04.000000000 -0700
++++ 25/drivers/net/tulip/interrupt.c 2003-10-05 00:36:07.000000000 -0700
+@@ -19,13 +19,13 @@
+ #include <linux/etherdevice.h>
+ #include <linux/pci.h>
+
+-
+ int tulip_rx_copybreak;
+ unsigned int tulip_max_interrupt_work;
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+-
++#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+ #define MIT_SIZE 15
++#define MIT_TABLE 15 /* We use 0 or max */
++
+ unsigned int mit_table[MIT_SIZE+1] =
+ {
+ /* CRS11 21143 hardware Mitigation Control Interrupt
+@@ -99,16 +99,28 @@ int tulip_refill_rx(struct net_device *d
+ return refilled;
+ }
+
++#ifdef CONFIG_TULIP_NAPI
+
+-static int tulip_rx(struct net_device *dev)
++void oom_timer(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ netif_rx_schedule(dev);
++}
++
++int tulip_poll(struct net_device *dev, int *budget)
+ {
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int entry = tp->cur_rx % RX_RING_SIZE;
+- int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
++ int rx_work_limit = *budget;
+ int received = 0;
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- int drop = 0, mit_sel = 0;
++ if (!netif_running(dev))
++ goto done;
++
++ if (rx_work_limit > dev->quota)
++ rx_work_limit = dev->quota;
++
++#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
+
+ /* that one buffer is needed for mit activation; or might be a
+ bug in the ring buffer code; check later -- JHS*/
+@@ -119,6 +131,237 @@ static int tulip_rx(struct net_device *d
+ if (tulip_debug > 4)
+ printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
+ tp->rx_ring[entry].status);
++
++ do {
++ /* Acknowledge current RX interrupt sources. */
++ outl((RxIntr | RxNoBuf), dev->base_addr + CSR5);
++
++
++ /* If we own the next entry, it is a new packet. Send it up. */
++ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
++ s32 status = le32_to_cpu(tp->rx_ring[entry].status);
++
++
++ if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
++ break;
++
++ if (tulip_debug > 5)
++ printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
++ dev->name, entry, status);
++ if (--rx_work_limit < 0)
++ goto not_done;
++
++ if ((status & 0x38008300) != 0x0300) {
++ if ((status & 0x38000300) != 0x0300) {
++ /* Ingore earlier buffers. */
++ if ((status & 0xffff) != 0x7fff) {
++ if (tulip_debug > 1)
++ printk(KERN_WARNING "%s: Oversized Ethernet frame "
++ "spanned multiple buffers, status %8.8x!\n",
++ dev->name, status);
++ tp->stats.rx_length_errors++;
++ }
++ } else if (status & RxDescFatalErr) {
++ /* There was a fatal error. */
++ if (tulip_debug > 2)
++ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
++ dev->name, status);
++ tp->stats.rx_errors++; /* end of a packet.*/
++ if (status & 0x0890) tp->stats.rx_length_errors++;
++ if (status & 0x0004) tp->stats.rx_frame_errors++;
++ if (status & 0x0002) tp->stats.rx_crc_errors++;
++ if (status & 0x0001) tp->stats.rx_fifo_errors++;
++ }
++ } else {
++ /* Omit the four octet CRC from the length. */
++ short pkt_len = ((status >> 16) & 0x7ff) - 4;
++ struct sk_buff *skb;
++
++#ifndef final_version
++ if (pkt_len > 1518) {
++ printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
++ dev->name, pkt_len, pkt_len);
++ pkt_len = 1518;
++ tp->stats.rx_length_errors++;
++ }
++#endif
++ /* Check if the packet is long enough to accept without copying
++ to a minimally-sized skbuff. */
++ if (pkt_len < tulip_rx_copybreak
++ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
++ skb->dev = dev;
++ skb_reserve(skb, 2); /* 16 byte align the IP header */
++ pci_dma_sync_single(tp->pdev,
++ tp->rx_buffers[entry].mapping,
++ pkt_len, PCI_DMA_FROMDEVICE);
++#if ! defined(__alpha__)
++ eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail,
++ pkt_len, 0);
++ skb_put(skb, pkt_len);
++#else
++ memcpy(skb_put(skb, pkt_len),
++ tp->rx_buffers[entry].skb->tail,
++ pkt_len);
++#endif
++ } else { /* Pass up the skb already on the Rx ring. */
++ char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
++ pkt_len);
++
++#ifndef final_version
++ if (tp->rx_buffers[entry].mapping !=
++ le32_to_cpu(tp->rx_ring[entry].buffer1)) {
++ printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
++ "do not match in tulip_rx: %08x vs. %08x %p / %p.\n",
++ dev->name,
++ le32_to_cpu(tp->rx_ring[entry].buffer1),
++ tp->rx_buffers[entry].mapping,
++ skb->head, temp);
++ }
++#endif
++
++ pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
++ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
++
++ tp->rx_buffers[entry].skb = NULL;
++ tp->rx_buffers[entry].mapping = 0;
++ }
++ skb->protocol = eth_type_trans(skb, dev);
++
++ netif_receive_skb(skb);
++
++ dev->last_rx = jiffies;
++ tp->stats.rx_packets++;
++ tp->stats.rx_bytes += pkt_len;
++ }
++ received++;
++
++ entry = (++tp->cur_rx) % RX_RING_SIZE;
++ if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
++ tulip_refill_rx(dev);
++
++ }
++
++ /* New ack strategy... irq does not ack Rx any longer
++ hopefully this helps */
++
++ /* Really bad things can happen here... If new packet arrives
++ * and an irq arrives (tx or just due to occasionally unset
++ * mask), it will be acked by irq handler, but new thread
++ * is not scheduled. It is major hole in design.
++ * No idea how to fix this if "playing with fire" will fail
++ * tomorrow (night 011029). If it will not fail, we won
++ * finally: amount of IO did not increase at all. */
++ } while ((inl(dev->base_addr + CSR5) & RxIntr));
++
++done:
++
++ #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
++
++ /* We use this simplistic scheme for IM. It's proven by
++ real life installations. We can have IM enabled
++ continuesly but this would cause unnecessary latency.
++ Unfortunely we can't use all the NET_RX_* feedback here.
++ This would turn on IM for devices that is not contributing
++ to backlog congestion with unnecessary latency.
++
++ We monitor the the device RX-ring and have:
++
++ HW Interrupt Mitigation either ON or OFF.
++
++ ON: More then 1 pkt received (per intr.) OR we are dropping
++ OFF: Only 1 pkt received
++
++ Note. We only use min and max (0, 15) settings from mit_table */
++
++
++ if( tp->flags & HAS_INTR_MITIGATION) {
++ if( received > 1 ) {
++ if( ! tp->mit_on ) {
++ tp->mit_on = 1;
++ outl(mit_table[MIT_TABLE], dev->base_addr + CSR11);
++ }
++ }
++ else {
++ if( tp->mit_on ) {
++ tp->mit_on = 0;
++ outl(0, dev->base_addr + CSR11);
++ }
++ }
++ }
++
++#endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
++
++ dev->quota -= received;
++ *budget -= received;
++
++ tulip_refill_rx(dev);
++
++ /* If RX ring is not full we are out of memory. */
++ if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
++
++ /* Remove us from polling list and enable RX intr. */
++
++ netif_rx_complete(dev);
++ outl(tulip_tbl[tp->chip_id].valid_intrs, dev->base_addr+CSR7);
++
++ /* The last op happens after poll completion. Which means the following:
++ * 1. it can race with disabling irqs in irq handler
++ * 2. it can race with dise/enabling irqs in other poll threads
++ * 3. if an irq raised after beginning loop, it will be immediately
++ * triggered here.
++ *
++ * Summarizing: the logic results in some redundant irqs both
++ * due to races in masking and due to too late acking of already
++ * processed irqs. But it must not result in losing events.
++ */
++
++ return 0;
++
++ not_done:
++ if (!received) {
++
++ received = dev->quota; /* Not to happen */
++ }
++ dev->quota -= received;
++ *budget -= received;
++
++ if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
++ tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
++ tulip_refill_rx(dev);
++
++ if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
++
++ return 1;
++
++
++ oom: /* Executed with RX ints disabled */
++
++
++ /* Start timer, stop polling, but do not enable rx interrupts. */
++ mod_timer(&tp->oom_timer, jiffies+1);
++
++ /* Think: timer_pending() was an explicit signature of bug.
++ * Timer can be pending now but fired and completed
++ * before we did netif_rx_complete(). See? We would lose it. */
++
++ /* remove ourselves from the polling list */
++ netif_rx_complete(dev);
++
++ return 0;
++}
++
++#else /* CONFIG_TULIP_NAPI */
++
++static int tulip_rx(struct net_device *dev)
++{
++ struct tulip_private *tp = (struct tulip_private *)dev->priv;
++ int entry = tp->cur_rx % RX_RING_SIZE;
++ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
++ int received = 0;
++
++ if (tulip_debug > 4)
++ printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
++ tp->rx_ring[entry].status);
+ /* If we own the next entry, it is a new packet. Send it up. */
+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
+ s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+@@ -163,11 +406,6 @@ static int tulip_rx(struct net_device *d
+ }
+ #endif
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- drop = atomic_read(&netdev_dropping);
+- if (drop)
+- goto throttle;
+-#endif
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < tulip_rx_copybreak
+@@ -209,44 +447,9 @@ static int tulip_rx(struct net_device *d
+ tp->rx_buffers[entry].mapping = 0;
+ }
+ skb->protocol = eth_type_trans(skb, dev);
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- mit_sel =
+-#endif
+- netif_rx(skb);
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- switch (mit_sel) {
+- case NET_RX_SUCCESS:
+- case NET_RX_CN_LOW:
+- case NET_RX_CN_MOD:
+- break;
+-
+- case NET_RX_CN_HIGH:
+- rx_work_limit -= NET_RX_CN_HIGH; /* additional*/
+- break;
+- case NET_RX_DROP:
+- rx_work_limit = -1;
+- break;
+- default:
+- printk("unknown feedback return code %d\n", mit_sel);
+- break;
+- }
++ netif_rx(skb);
+
+- drop = atomic_read(&netdev_dropping);
+- if (drop) {
+-throttle:
+- rx_work_limit = -1;
+- mit_sel = NET_RX_DROP;
+-
+- if (tp->fc_bit) {
+- long ioaddr = dev->base_addr;
+-
+- /* disable Rx & RxNoBuf ints. */
+- outl(tulip_tbl[tp->chip_id].valid_intrs&RX_A_NBF_STOP, ioaddr + CSR7);
+- set_bit(tp->fc_bit, &netdev_fc_xoff);
+- }
+- }
+-#endif
+ dev->last_rx = jiffies;
+ tp->stats.rx_packets++;
+ tp->stats.rx_bytes += pkt_len;
+@@ -254,42 +457,9 @@ throttle:
+ received++;
+ entry = (++tp->cur_rx) % RX_RING_SIZE;
+ }
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+-
+- /* We use this simplistic scheme for IM. It's proven by
+- real life installations. We can have IM enabled
+- continuesly but this would cause unnecessary latency.
+- Unfortunely we can't use all the NET_RX_* feedback here.
+- This would turn on IM for devices that is not contributing
+- to backlog congestion with unnecessary latency.
+-
+- We monitor the device RX-ring and have:
+-
+- HW Interrupt Mitigation either ON or OFF.
+-
+- ON: More then 1 pkt received (per intr.) OR we are dropping
+- OFF: Only 1 pkt received
+-
+- Note. We only use min and max (0, 15) settings from mit_table */
+-
+-
+- if( tp->flags & HAS_INTR_MITIGATION) {
+- if((received > 1 || mit_sel == NET_RX_DROP)
+- && tp->mit_sel != 15 ) {
+- tp->mit_sel = 15;
+- tp->mit_change = 1; /* Force IM change */
+- }
+- if((received <= 1 && mit_sel != NET_RX_DROP) && tp->mit_sel != 0 ) {
+- tp->mit_sel = 0;
+- tp->mit_change = 1; /* Force IM change */
+- }
+- }
+-
+- return RX_RING_SIZE+1; /* maxrx+1 */
+-#else
+ return received;
+-#endif
+ }
++#endif /* CONFIG_TULIP_NAPI */
+
+ static inline unsigned int phy_interrupt (struct net_device *dev)
+ {
+@@ -323,7 +493,6 @@ irqreturn_t tulip_interrupt(int irq, voi
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr5;
+- int entry;
+ int missed;
+ int rx = 0;
+ int tx = 0;
+@@ -331,6 +500,11 @@ irqreturn_t tulip_interrupt(int irq, voi
+ int maxrx = RX_RING_SIZE;
+ int maxtx = TX_RING_SIZE;
+ int maxoi = TX_RING_SIZE;
++#ifdef CONFIG_TULIP_NAPI
++ int rxd = 0;
++#else
++ int entry;
++#endif
+ unsigned int work_count = tulip_max_interrupt_work;
+ unsigned int handled = 0;
+
+@@ -346,22 +520,41 @@ irqreturn_t tulip_interrupt(int irq, voi
+ tp->nir++;
+
+ do {
++
++#ifdef CONFIG_TULIP_NAPI
++
++ if (!rxd && (csr5 & (RxIntr | RxNoBuf))) {
++ rxd++;
++ /* Mask RX intrs and add the device to poll list. */
++ outl(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
++ netif_rx_schedule(dev);
++
++ if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
++ break;
++ }
++
++ /* Acknowledge the interrupt sources we handle here ASAP
++ the poll function does Rx and RxNoBuf acking */
++
++ outl(csr5 & 0x0001ff3f, ioaddr + CSR5);
++
++#else
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ outl(csr5 & 0x0001ffff, ioaddr + CSR5);
+
+- if (tulip_debug > 4)
+- printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
+- dev->name, csr5, inl(dev->base_addr + CSR5));
+
+ if (csr5 & (RxIntr | RxNoBuf)) {
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if ((!tp->fc_bit) ||
+- (!test_bit(tp->fc_bit, &netdev_fc_xoff)))
+-#endif
+ rx += tulip_rx(dev);
+ tulip_refill_rx(dev);
+ }
+
++#endif /* CONFIG_TULIP_NAPI */
++
++ if (tulip_debug > 4)
++ printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
++ dev->name, csr5, inl(dev->base_addr + CSR5));
++
++
+ if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
+ unsigned int dirty_tx;
+
+@@ -462,15 +655,8 @@ irqreturn_t tulip_interrupt(int irq, voi
+ }
+ if (csr5 & RxDied) { /* Missed a Rx frame. */
+ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
+- tp->stats.rx_errors++;
+- tulip_start_rxtx(tp);
+- }
+-#else
+ tp->stats.rx_errors++;
+ tulip_start_rxtx(tp);
+-#endif
+ }
+ /*
+ * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this
+@@ -504,10 +690,6 @@ irqreturn_t tulip_interrupt(int irq, voi
+ if (tulip_debug > 2)
+ printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
+ dev->name, csr5);
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if (tp->fc_bit && (test_bit(tp->fc_bit, &netdev_fc_xoff)))
+- if (net_ratelimit()) printk("BUG!! enabling interrupt when FC off (timerintr.) \n");
+-#endif
+ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ tp->ttimer = 0;
+ oi++;
+@@ -520,16 +702,9 @@ irqreturn_t tulip_interrupt(int irq, voi
+ /* Acknowledge all interrupt sources. */
+ outl(0x8001ffff, ioaddr + CSR5);
+ if (tp->flags & HAS_INTR_MITIGATION) {
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if(tp->mit_change) {
+- outl(mit_table[tp->mit_sel], ioaddr + CSR11);
+- tp->mit_change = 0;
+- }
+-#else
+ /* Josip Loncaric at ICASE did extensive experimentation
+ to develop a good interrupt mitigation setting.*/
+ outl(0x8b240000, ioaddr + CSR11);
+-#endif
+ } else if (tp->chip_id == LC82C168) {
+ /* the LC82C168 doesn't have a hw timer.*/
+ outl(0x00, ioaddr + CSR7);
+@@ -537,10 +712,8 @@ irqreturn_t tulip_interrupt(int irq, voi
+ } else {
+ /* Mask all interrupting sources, set timer to
+ re-enable. */
+-#ifndef CONFIG_NET_HW_FLOWCONTROL
+ outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
+ outl(0x0012, ioaddr + CSR11);
+-#endif
+ }
+ break;
+ }
+@@ -550,6 +723,21 @@ irqreturn_t tulip_interrupt(int irq, voi
+ break;
+
+ csr5 = inl(ioaddr + CSR5);
++
++#ifdef CONFIG_TULIP_NAPI
++ if (rxd)
++ csr5 &= ~RxPollInt;
++ } while ((csr5 & (TxNoBuf |
++ TxDied |
++ TxIntr |
++ TimerInt |
++ /* Abnormal intr. */
++ RxDied |
++ TxFIFOUnderflow |
++ TxJabber |
++ TPLnkFail |
++ SytemError )) != 0);
++#else
+ } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
+
+ tulip_refill_rx(dev);
+@@ -574,6 +762,7 @@ irqreturn_t tulip_interrupt(int irq, voi
+ }
+ }
+ }
++#endif /* CONFIG_TULIP_NAPI */
+
+ if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
+ tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+--- linux-2.6.0-test6/drivers/net/tulip/Kconfig 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/tulip/Kconfig 2003-10-05 00:34:49.000000000 -0700
+@@ -68,6 +68,26 @@ config TULIP_MMIO
+ obscure bugs if your mainboard has memory controller timing issues.
+ If in doubt, say N.
+
++config TULIP_NAPI
++ bool "Use NAPI RX polling "
++ depends on TULIP
++ ---help---
++ This is of useful for servers and routers dealing with high network loads.
++
++ See <file:Documentation/networking/NAPI_HOWTO.txt>.
++
++ If in doubt, say N.
++
++config TULIP_NAPI_HW_MITIGATION
++ bool "Use Interrupt Mitigation "
++ depends on TULIP_NAPI
++ ---help---
++ Use HW to reduce RX interrupts. Not strict necessary since NAPI reduces
++ RX interrupts but itself. Although this reduces RX interrupts even at
++ low levels traffic at the cost of a small latency.
++
++ If in doubt, say Y.
++
+ config DE4X5
+ tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
+ depends on NET_TULIP && (PCI || EISA)
+--- linux-2.6.0-test6/drivers/net/tulip/tulip_core.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/net/tulip/tulip_core.c 2003-10-05 00:34:49.000000000 -0700
+@@ -14,11 +14,17 @@
+
+ */
+
++#include <linux/config.h>
++
+ #define DRV_NAME "tulip"
++#ifdef CONFIG_TULIP_NAPI
++#define DRV_VERSION "1.1.13-NAPI" /* Keep at least for test */
++#else
+ #define DRV_VERSION "1.1.13"
++#endif
+ #define DRV_RELDATE "May 11, 2002"
+
+-#include <linux/config.h>
++
+ #include <linux/module.h>
+ #include "tulip.h"
+ #include <linux/pci.h>
+@@ -246,6 +252,7 @@ static void tulip_down(struct net_device
+ static struct net_device_stats *tulip_get_stats(struct net_device *dev);
+ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+ static void set_rx_mode(struct net_device *dev);
++static void poll_tulip(struct net_device *dev);
+
+
+
+@@ -465,29 +472,16 @@ media_picked:
+ to an alternate media type. */
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+-}
+-
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+-/* Enable receiver */
+-void tulip_xon(struct net_device *dev)
+-{
+- struct tulip_private *tp = (struct tulip_private *)dev->priv;
+-
+- clear_bit(tp->fc_bit, &netdev_fc_xoff);
+- if (netif_running(dev)){
+-
+- tulip_refill_rx(dev);
+- outl(tulip_tbl[tp->chip_id].valid_intrs, dev->base_addr+CSR7);
+- }
+-}
++#ifdef CONFIG_TULIP_NAPI
++ init_timer(&tp->oom_timer);
++ tp->oom_timer.data = (unsigned long)dev;
++ tp->oom_timer.function = oom_timer;
+ #endif
++}
+
+ static int
+ tulip_open(struct net_device *dev)
+ {
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- struct tulip_private *tp = (struct tulip_private *)dev->priv;
+-#endif
+ int retval;
+
+ if ((retval = request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)))
+@@ -497,10 +491,6 @@ tulip_open(struct net_device *dev)
+
+ tulip_up (dev);
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- tp->fc_bit = netdev_register_fc(dev, tulip_xon);
+-#endif
+-
+ netif_start_queue (dev);
+
+ return 0;
+@@ -581,10 +571,7 @@ static void tulip_tx_timeout(struct net_
+ #endif
+
+ /* Stop and restart the chip's Tx processes . */
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if (tp->fc_bit && test_bit(tp->fc_bit,&netdev_fc_xoff))
+- printk("BUG tx_timeout restarting rx when fc on\n");
+-#endif
++
+ tulip_restart_rxtx(tp);
+ /* Trigger an immediate transmit demand. */
+ outl(0, ioaddr + CSR1);
+@@ -741,7 +728,9 @@ static void tulip_down (struct net_devic
+ unsigned long flags;
+
+ del_timer_sync (&tp->timer);
+-
++#ifdef CONFIG_TULIP_NAPI
++ del_timer_sync (&tp->oom_timer);
++#endif
+ spin_lock_irqsave (&tp->lock, flags);
+
+ /* Disable interrupts by clearing the interrupt mask. */
+@@ -780,13 +769,6 @@ static int tulip_close (struct net_devic
+
+ netif_stop_queue (dev);
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+- if (tp->fc_bit) {
+- int bit = tp->fc_bit;
+- tp->fc_bit = 0;
+- netdev_unregister_fc(bit);
+- }
+-#endif
+ tulip_down (dev);
+
+ if (tulip_debug > 1)
+@@ -1627,10 +1609,17 @@ static int __devinit tulip_init_one (str
+ dev->hard_start_xmit = tulip_start_xmit;
+ dev->tx_timeout = tulip_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
++#ifdef CONFIG_TULIP_NAPI
++ dev->poll = tulip_poll;
++ dev->weight = 16;
++#endif
+ dev->stop = tulip_close;
+ dev->get_stats = tulip_get_stats;
+ dev->do_ioctl = private_ioctl;
+ dev->set_multicast_list = set_rx_mode;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ dev->poll_controller = &poll_tulip;
++#endif
+
+ if (register_netdev(dev))
+ goto err_out_free_ring;
+@@ -1788,6 +1777,24 @@ static void __devexit tulip_remove_one (
+ }
+
+
++#ifdef CONFIG_NET_POLL_CONTROLLER
++
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++
++static void poll_tulip (struct net_device *dev)
++{
++ disable_irq(dev->irq);
++ tulip_interrupt (dev->irq, dev, NULL);
++ enable_irq(dev->irq);
++}
++
++#endif
++
++
+ static struct pci_driver tulip_driver = {
+ .name = DRV_NAME,
+ .id_table = tulip_pci_tbl,
+--- linux-2.6.0-test6/drivers/net/tulip/tulip.h 2003-06-14 12:18:34.000000000 -0700
++++ 25/drivers/net/tulip/tulip.h 2003-10-05 00:34:49.000000000 -0700
+@@ -126,6 +126,7 @@ enum pci_cfg_driver_reg {
+ CFDD_Snooze = (1 << 30),
+ };
+
++#define RxPollInt (RxIntr|RxNoBuf|RxDied|RxJabber)
+
+ /* The bits in the CSR5 status registers, mostly interrupt sources. */
+ enum status_bits {
+@@ -251,9 +252,9 @@ enum t21143_csr6_bits {
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+-#define TX_RING_SIZE 16
+-#define RX_RING_SIZE 32
+
++#define TX_RING_SIZE 32
++#define RX_RING_SIZE 128
+ #define MEDIA_MASK 31
+
+ #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
+@@ -343,17 +344,15 @@ struct tulip_private {
+ int flags;
+ struct net_device_stats stats;
+ struct timer_list timer; /* Media selection timer. */
++ struct timer_list oom_timer; /* Out of memory timer. */
+ u32 mc_filter[2];
+ spinlock_t lock;
+ spinlock_t mii_lock;
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+-#define RX_A_NBF_STOP 0xffffff3f /* To disable RX and RX-NOBUF ints. */
+- int fc_bit;
+- int mit_sel;
+- int mit_change; /* Signal for Interrupt Mitigtion */
++#ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
++ int mit_on;
+ #endif
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int full_duplex_lock:1;
+@@ -415,6 +414,10 @@ extern unsigned int tulip_max_interrupt_
+ extern int tulip_rx_copybreak;
+ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+ int tulip_refill_rx(struct net_device *dev);
++#ifdef CONFIG_TULIP_NAPI
++int tulip_poll(struct net_device *dev, int *budget);
++#endif
++
+
+ /* media.c */
+ int tulip_mdio_read(struct net_device *dev, int phy_id, int location);
+@@ -438,6 +441,7 @@ extern int tulip_debug;
+ extern const char * const medianame[];
+ extern const char tulip_media_cap[];
+ extern struct tulip_chip_table tulip_tbl[];
++void oom_timer(unsigned long data);
+ extern u8 t21040_csr13[];
+
+ #ifndef USE_IO_OPS
+--- linux-2.6.0-test6/drivers/net/wan/comx-hw-munich.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/wan/comx-hw-munich.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1849,7 +1849,7 @@ static int MUNICH_open(struct net_device
+ if (board->isx21)
+ {
+ init_timer(&board->modemline_timer);
+- board->modemline_timer.data = (unsigned int)board;
++ board->modemline_timer.data = (unsigned long)board;
+ board->modemline_timer.function = pcicom_modemline;
+ board->modemline_timer.expires = jiffies + HZ;
+ add_timer((struct timer_list *)&board->modemline_timer);
+--- linux-2.6.0-test6/drivers/net/wan/dscc4.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/wan/dscc4.c 2003-10-05 00:36:13.000000000 -0700
+@@ -107,7 +107,7 @@
+ #include <linux/hdlc.h>
+
+ /* Version */
+-static const char version[] = "$Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $ for Linux\n";
++static const char version[] = "$Id: 2.6.0-test6-mm4.patch,v 1.1.4.1 2003/10/10 09:31:08 ericm Exp $ for Linux\n";
+ static int debug;
+ static int quartz;
+
+@@ -592,6 +592,7 @@ static inline int dscc4_xpr_ack(struct d
+ return (i >= 0 ) ? i : -EAGAIN;
+ }
+
++#if 0 /* dscc4_{rx/tx}_reset are both unreliable - more tweak needed */
+ static void dscc4_rx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+ {
+ unsigned long flags;
+@@ -606,6 +607,9 @@ static void dscc4_rx_reset(struct dscc4_
+ spin_unlock_irqrestore(&dpriv->pci_priv->lock, flags);
+ }
+
++#endif
++
++#if 0
+ static void dscc4_tx_reset(struct dscc4_dev_priv *dpriv, struct net_device *dev)
+ {
+ u16 i = 0;
+@@ -625,6 +629,7 @@ static void dscc4_tx_reset(struct dscc4_
+ if (dscc4_do_action(dev, "Rdt") < 0)
+ printk(KERN_ERR "%s: Tx reset failed\n", dev->name);
+ }
++#endif
+
+ /* TODO: (ab)use this function to refill a completely depleted RX ring. */
+ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
+@@ -859,7 +864,7 @@ static int dscc4_found1(struct pci_dev *
+ {
+ struct dscc4_pci_priv *ppriv;
+ struct dscc4_dev_priv *root;
+- int i = 0;
++ int i, ret = -ENOMEM;
+
+ root = (struct dscc4_dev_priv *)
+ kmalloc(dev_per_card*sizeof(*root), GFP_KERNEL);
+@@ -900,7 +905,8 @@ static int dscc4_found1(struct pci_dev *
+ hdlc->xmit = dscc4_start_xmit;
+ hdlc->attach = dscc4_hdlc_attach;
+
+- if (register_hdlc_device(hdlc)) {
++ ret = register_hdlc_device(hdlc);
++ if (ret < 0) {
+ printk(KERN_ERR "%s: unable to register\n", DRV_NAME);
+ goto err_unregister;
+ }
+@@ -908,17 +914,20 @@ static int dscc4_found1(struct pci_dev *
+ dscc4_init_registers(dpriv, d);
+ dpriv->parity = PARITY_CRC16_PR0_CCITT;
+ dpriv->encoding = ENCODING_NRZ;
+- if (dscc4_init_ring(d)) {
++
++ ret = dscc4_init_ring(d);
++ if (ret < 0) {
+ unregister_hdlc_device(hdlc);
+ goto err_unregister;
+ }
+ }
+- if (dscc4_set_quartz(root, quartz) < 0)
++ ret = dscc4_set_quartz(root, quartz);
++ if (ret < 0)
+ goto err_unregister;
+ ppriv->root = root;
+ spin_lock_init(&ppriv->lock);
+ pci_set_drvdata(pdev, ppriv);
+- return 0;
++ return ret;
+
+ err_unregister:
+ while (--i >= 0) {
+@@ -929,7 +938,7 @@ err_unregister:
+ err_free_dev:
+ kfree(root);
+ err_out:
+- return -1;
++ return ret;
+ };
+
+ /* FIXME: get rid of the unneeded code */
+@@ -1092,9 +1101,7 @@ done:
+
+ err_disable_scc_events:
+ scc_writel(0xffffffff, dpriv, dev, IMR);
+-err_free_ring:
+ scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0);
+- dscc4_release_ring(dpriv);
+ err_out:
+ hdlc_close(hdlc);
+ err:
+@@ -1160,7 +1167,6 @@ static int dscc4_close(struct net_device
+ dpriv->flags |= FakeReset;
+
+ hdlc_close(hdlc);
+- dscc4_release_ring(dpriv);
+
+ return 0;
+ }
+@@ -2006,6 +2012,7 @@ static int dscc4_hdlc_attach(hdlc_device
+ return 0;
+ }
+
++#ifndef MODULE
+ static int __init dscc4_setup(char *str)
+ {
+ int *args[] = { &debug, &quartz, NULL }, **p = args;
+@@ -2016,6 +2023,7 @@ static int __init dscc4_setup(char *str)
+ }
+
+ __setup("dscc4.setup=", dscc4_setup);
++#endif
+
+ static struct pci_device_id dscc4_pci_tbl[] = {
+ { PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4,
+--- linux-2.6.0-test6/drivers/net/wan/sbni.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/wan/sbni.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1300,12 +1300,9 @@ sbni_ioctl( struct net_device *dev, st
+
+ switch( cmd ) {
+ case SIOCDEVGETINSTATS :
+- error = verify_area( VERIFY_WRITE, ifr->ifr_data,
+- sizeof(struct sbni_in_stats) );
+- if( !error )
+- if (copy_to_user( ifr->ifr_data, &nl->in_stats,
+- sizeof(struct sbni_in_stats) ))
+- return -EFAULT;
++ if (copy_to_user( ifr->ifr_data, &nl->in_stats,
++ sizeof(struct sbni_in_stats) ))
++ error = -EFAULT;
+ break;
+
+ case SIOCDEVRESINSTATS :
+@@ -1321,11 +1318,8 @@ sbni_ioctl( struct net_device *dev, st
+ flags.rxl = nl->cur_rxl_index;
+ flags.fixed_rxl = nl->delta_rxl == 0;
+
+- error = verify_area( VERIFY_WRITE, ifr->ifr_data,
+- sizeof flags );
+- if( !error )
+- if (copy_to_user( ifr->ifr_data, &flags, sizeof flags ))
+- return -EFAULT;
++ if (copy_to_user( ifr->ifr_data, &flags, sizeof flags ))
++ error = -EFAULT;
+ break;
+
+ case SIOCDEVSHWSTATE :
+@@ -1353,10 +1347,6 @@ sbni_ioctl( struct net_device *dev, st
+ if( current->euid != 0 ) /* root only */
+ return -EPERM;
+
+- if( (error = verify_area( VERIFY_READ, ifr->ifr_data,
+- sizeof slave_name )) != 0 )
+- return error;
+-
+ if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name ))
+ return -EFAULT;
+ slave_dev = dev_get_by_name( slave_name );
+--- linux-2.6.0-test6/drivers/net/wan/syncppp.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/wan/syncppp.c 2003-10-05 00:33:24.000000000 -0700
+@@ -236,7 +236,7 @@ void sppp_input (struct net_device *dev,
+ sp->ipkts++;
+ }
+
+- if (skb->len <= PPP_HEADER_LEN) {
++ if (!pskb_may_pull(skb, PPP_HEADER_LEN)) {
+ /* Too small packet, drop it. */
+ if (sp->pp_flags & PP_DEBUG)
+ printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n",
+@@ -473,7 +473,7 @@ static void sppp_lcp_input (struct sppp
+ u8 *p, opt[6];
+ u32 rmagic;
+
+- if (len < 4) {
++ if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
+ if (sp->pp_flags & PP_DEBUG)
+ printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n",
+ dev->name, len);
+@@ -707,7 +707,9 @@ static void sppp_cisco_input (struct spp
+ struct cisco_packet *h;
+ struct net_device *dev = sp->pp_if;
+
+- if (skb->len != CISCO_PACKET_LEN && skb->len != CISCO_BIG_PACKET_LEN) {
++ if (!pskb_may_pull(skb, sizeof(struct cisco_packet))
++ || (skb->len != CISCO_PACKET_LEN
++ && skb->len != CISCO_BIG_PACKET_LEN)) {
+ if (sp->pp_flags & PP_DEBUG)
+ printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n",
+ dev->name, skb->len);
+@@ -1211,8 +1213,7 @@ static void sppp_ipcp_input (struct sppp
+ struct net_device *dev = sp->pp_if;
+ int len = skb->len;
+
+- if (len < 4)
+- {
++ if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
+ if (sp->pp_flags & PP_DEBUG)
+ printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n",
+ dev->name, len);
+--- linux-2.6.0-test6/drivers/net/wireless/arlan-main.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/net/wireless/arlan-main.c 2003-10-05 00:33:24.000000000 -0700
+@@ -5,7 +5,6 @@
+ * This module provides support for the Arlan 655 card made by Aironet
+ */
+
+-#include <linux/version.h>
+ #include <linux/config.h>
+ #include "arlan.h"
+
+@@ -721,9 +720,9 @@ static int arlan_hw_tx(struct net_device
+ else
+ {
+ netif_stop_queue (dev);
+- return -1;
+ IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+ printk(KERN_ERR "TX TAIL & HEAD full, return, tailStart %d headEnd %d\n", tailStarts, headEnds);
++ return -1;
+ }
+ priv->out_bytes += length;
+ priv->out_bytes10 += length;
+@@ -1881,6 +1880,8 @@ int __init arlan_probe(struct net_device
+
+ #ifdef MODULE
+
++static int probe = probeUNKNOWN;
++
+ static int __init arlan_find_devices(void)
+ {
+ int m;
+--- linux-2.6.0-test6/drivers/parisc/superio.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/parisc/superio.c 2003-10-05 00:33:24.000000000 -0700
+@@ -530,11 +530,6 @@ static struct pci_driver superio_driver
+
+ static int __init superio_modinit(void)
+ {
+-#ifdef CONFIG_SERIAL_8250
+- extern int serial8250_init(void);
+- serial8250_init();
+-#endif
+-
+ return pci_module_init(&superio_driver);
+ }
+
+@@ -543,5 +538,10 @@ static void __exit superio_exit(void)
+ pci_unregister_driver(&superio_driver);
+ }
+
+-module_init(superio_modinit);
++/* Make late initcall to ensure the serial and tty layers are initialised
++ * before we start superio.
++ *
++ * FIXME: does this break the superio console?
++ */
++late_initcall(superio_modinit);
+ module_exit(superio_exit);
+--- linux-2.6.0-test6/drivers/pci/hotplug/cpqphp.h 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/pci/hotplug/cpqphp.h 2003-10-05 00:33:24.000000000 -0700
+@@ -766,7 +766,6 @@ static inline int wait_for_ctrl_irq (str
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* Sleep for up to 1 second to wait for the LED to change. */
+ schedule_timeout(1*HZ);
+- set_current_state(TASK_RUNNING);
+ remove_wait_queue(&ctrl->queue, &wait);
+ if (signal_pending(current))
+ retval = -EINTR;
+--- linux-2.6.0-test6/drivers/pci/hotplug/pci_hotplug_core.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/pci/hotplug/pci_hotplug_core.c 2003-10-05 00:33:24.000000000 -0700
+@@ -69,7 +69,7 @@ static int debug;
+
+ static LIST_HEAD(pci_hotplug_slot_list);
+
+-static struct subsystem hotplug_slots_subsys;
++struct subsystem pci_hotplug_slots_subsys;
+
+ static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+@@ -104,7 +104,7 @@ static struct kobj_type hotplug_slot_kty
+ .release = &hotplug_slot_release,
+ };
+
+-static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL);
++decl_subsys(pci_hotplug_slots, &hotplug_slot_ktype, NULL);
+
+
+ /* these strings match up with the values in pci_bus_speed */
+@@ -534,7 +534,7 @@ int pci_hp_register (struct hotplug_slot
+ return -EINVAL;
+
+ strlcpy(slot->kobj.name, slot->name, KOBJ_NAME_LEN);
+- kobj_set_kset_s(slot, hotplug_slots_subsys);
++ kobj_set_kset_s(slot, pci_hotplug_slots_subsys);
+
+ /* this can fail if we have already registered a slot with the same name */
+ if (kobject_register(&slot->kobj)) {
+@@ -629,8 +629,8 @@ static int __init pci_hotplug_init (void
+ {
+ int result;
+
+- kset_set_kset_s(&hotplug_slots_subsys, pci_bus_type.subsys);
+- result = subsystem_register(&hotplug_slots_subsys);
++ kset_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
++ result = subsystem_register(&pci_hotplug_slots_subsys);
+ if (result) {
+ err("Register subsys with error %d\n", result);
+ goto exit;
+@@ -645,7 +645,7 @@ static int __init pci_hotplug_init (void
+ goto exit;
+
+ err_subsys:
+- subsystem_unregister(&hotplug_slots_subsys);
++ subsystem_unregister(&pci_hotplug_slots_subsys);
+ exit:
+ return result;
+ }
+@@ -653,7 +653,7 @@ exit:
+ static void __exit pci_hotplug_exit (void)
+ {
+ cpci_hotplug_exit();
+- subsystem_unregister(&hotplug_slots_subsys);
++ subsystem_unregister(&pci_hotplug_slots_subsys);
+ }
+
+ module_init(pci_hotplug_init);
+@@ -665,6 +665,7 @@ MODULE_LICENSE("GPL");
+ MODULE_PARM(debug, "i");
+ MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
++EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys);
+ EXPORT_SYMBOL_GPL(pci_hp_register);
+ EXPORT_SYMBOL_GPL(pci_hp_deregister);
+ EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
+--- linux-2.6.0-test6/drivers/pci/hotplug/pci_hotplug.h 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/pci/hotplug/pci_hotplug.h 2003-10-05 00:33:24.000000000 -0700
+@@ -145,6 +145,7 @@ extern int pci_hp_register (struct hotp
+ extern int pci_hp_deregister (struct hotplug_slot *slot);
+ extern int pci_hp_change_slot_info (struct hotplug_slot *slot,
+ struct hotplug_slot_info *info);
++extern struct subsystem pci_hotplug_slots_subsys;
+
+ #endif
+
+--- linux-2.6.0-test6/drivers/pci/Makefile 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/pci/Makefile 2003-10-05 00:36:20.000000000 -0700
+@@ -4,7 +4,6 @@
+
+ obj-y += access.o bus.o probe.o remove.o pci.o pool.o quirks.o \
+ names.o pci-driver.o search.o pci-sysfs.o
+-obj-$(CONFIG_PM) += power.o
+ obj-$(CONFIG_PROC_FS) += proc.o
+
+ ifndef CONFIG_SPARC64
+@@ -28,6 +27,7 @@ obj-$(CONFIG_PPC64) += setup-bus.o
+ obj-$(CONFIG_SGI_IP27) += setup-irq.o
+ obj-$(CONFIG_SGI_IP32) += setup-irq.o
+ obj-$(CONFIG_X86_VISWS) += setup-irq.o
++obj-$(CONFIG_PCI_USE_VECTOR) += msi.o
+
+ # Cardbus & CompactPCI use setup-bus
+ obj-$(CONFIG_HOTPLUG) += setup-bus.o
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/pci/msi.c 2003-10-05 00:36:21.000000000 -0700
+@@ -0,0 +1,1062 @@
++/*
++ * linux/drivers/pci/msi.c
++ */
++
++#include <linux/mm.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/ioport.h>
++#include <linux/smp_lock.h>
++#include <linux/pci.h>
++#include <linux/proc_fs.h>
++#include <linux/acpi.h>
++
++#include <asm/errno.h>
++#include <asm/io.h>
++#include <asm/smp.h>
++#include <asm/desc.h>
++#include <asm/io_apic.h>
++#include <mach_apic.h>
++
++#include <linux/pci_msi.h>
++
++_DEFINE_DBG_BUFFER
++
++static spinlock_t msi_lock = SPIN_LOCK_UNLOCKED;
++static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
++static kmem_cache_t* msi_cachep;
++
++static int pci_msi_enable = 1;
++static int nr_alloc_vectors = 0;
++static int nr_released_vectors = 0;
++static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;
++static int nr_msix_devices = 0;
++
++#ifndef CONFIG_X86_IO_APIC
++int vector_irq[NR_IRQS] = { [0 ... NR_IRQS -1] = -1};
++int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
++#endif
++
++static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
++{
++ memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
++}
++
++static int msi_cache_init(void)
++{
++ msi_cachep = kmem_cache_create("msi_cache",
++ NR_IRQS * sizeof(struct msi_desc),
++ 0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
++ if (!msi_cachep)
++ return -ENOMEM;
++
++ return 0;
++}
++
++static void msi_set_mask_bit(unsigned int vector, int flag)
++{
++ struct msi_desc *entry;
++
++ entry = (struct msi_desc *)msi_desc[vector];
++ if (!entry || !entry->dev || !entry->mask_base)
++ return;
++ switch (entry->msi_attrib.type) {
++ case PCI_CAP_ID_MSI:
++ {
++ int pos;
++ unsigned int mask_bits;
++
++ pos = entry->mask_base;
++ entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
++ pos, 4, &mask_bits);
++ mask_bits &= ~(1);
++ mask_bits |= flag;
++ entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
++ pos, 4, mask_bits);
++ break;
++ }
++ case PCI_CAP_ID_MSIX:
++ {
++ int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
++ PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
++ writel(flag, entry->mask_base + offset);
++ break;
++ }
++ default:
++ break;
++ }
++}
++
++#ifdef CONFIG_SMP
++static void set_msi_affinity(unsigned int vector, unsigned long cpu_mask)
++{
++ struct msi_desc *entry;
++ struct msg_address address;
++ unsigned int dest_id;
++
++ entry = (struct msi_desc *)msi_desc[vector];
++ if (!entry || !entry->dev)
++ return;
++
++ switch (entry->msi_attrib.type) {
++ case PCI_CAP_ID_MSI:
++ {
++ int pos;
++
++ if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
++ return;
++
++ entry->dev->bus->ops->read(entry->dev->bus, entry->dev->devfn,
++ msi_lower_address_reg(pos), 4,
++ &address.lo_address.value);
++ dest_id = (address.lo_address.u.dest_id &
++ MSI_ADDRESS_HEADER_MASK) |
++ (cpu_mask_to_apicid(cpu_mask) << MSI_TARGET_CPU_SHIFT);
++ address.lo_address.u.dest_id = dest_id;
++ entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
++ entry->dev->bus->ops->write(entry->dev->bus, entry->dev->devfn,
++ msi_lower_address_reg(pos), 4,
++ address.lo_address.value);
++ break;
++ }
++ case PCI_CAP_ID_MSIX:
++ {
++ int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
++ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
++
++ address.lo_address.value = readl(entry->mask_base + offset);
++ dest_id = (address.lo_address.u.dest_id &
++ MSI_ADDRESS_HEADER_MASK) |
++ (cpu_mask_to_apicid(cpu_mask) << MSI_TARGET_CPU_SHIFT);
++ address.lo_address.u.dest_id = dest_id;
++ entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
++ writel(address.lo_address.value, entry->mask_base + offset);
++ break;
++ }
++ default:
++ break;
++ }
++}
++
++static inline void move_msi(int vector)
++{
++ if (unlikely(pending_irq_balance_cpumask[vector])) {
++ set_msi_affinity(vector, pending_irq_balance_cpumask[vector]);
++ pending_irq_balance_cpumask[vector] = 0;
++ }
++}
++#endif
++
++static void mask_MSI_irq(unsigned int vector)
++{
++ msi_set_mask_bit(vector, 1);
++}
++
++static void unmask_MSI_irq(unsigned int vector)
++{
++ msi_set_mask_bit(vector, 0);
++}
++
++static unsigned int startup_msi_irq_wo_maskbit(unsigned int vector)
++{
++ return 0; /* never anything pending */
++}
++
++static void pci_disable_msi(unsigned int vector);
++static void shutdown_msi_irq(unsigned int vector)
++{
++ pci_disable_msi(vector);
++}
++
++#define shutdown_msi_irq_wo_maskbit shutdown_msi_irq
++static void enable_msi_irq_wo_maskbit(unsigned int vector) {}
++static void disable_msi_irq_wo_maskbit(unsigned int vector) {}
++static void ack_msi_irq_wo_maskbit(unsigned int vector) {}
++static void end_msi_irq_wo_maskbit(unsigned int vector)
++{
++ move_msi(vector);
++ ack_APIC_irq();
++}
++
++static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)
++{
++ unmask_MSI_irq(vector);
++ return 0; /* never anything pending */
++}
++
++#define shutdown_msi_irq_w_maskbit shutdown_msi_irq
++#define enable_msi_irq_w_maskbit unmask_MSI_irq
++#define disable_msi_irq_w_maskbit mask_MSI_irq
++#define ack_msi_irq_w_maskbit mask_MSI_irq
++
++static void end_msi_irq_w_maskbit(unsigned int vector)
++{
++ move_msi(vector);
++ unmask_MSI_irq(vector);
++ ack_APIC_irq();
++}
++
++/*
++ * Interrupt Type for MSI-X PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI-X Capability Structure.
++ */
++static struct hw_interrupt_type msix_irq_type = {
++ .typename = "PCI MSI-X",
++ .startup = startup_msi_irq_w_maskbit,
++ .shutdown = shutdown_msi_irq_w_maskbit,
++ .enable = enable_msi_irq_w_maskbit,
++ .disable = disable_msi_irq_w_maskbit,
++ .ack = ack_msi_irq_w_maskbit,
++ .end = end_msi_irq_w_maskbit,
++ .set_affinity = set_msi_irq_affinity
++};
++
++/*
++ * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI Capability Structure with
++ * Mask-and-Pending Bits.
++ */
++static struct hw_interrupt_type msi_irq_w_maskbit_type = {
++ .typename = "PCI MSI",
++ .startup = startup_msi_irq_w_maskbit,
++ .shutdown = shutdown_msi_irq_w_maskbit,
++ .enable = enable_msi_irq_w_maskbit,
++ .disable = disable_msi_irq_w_maskbit,
++ .ack = ack_msi_irq_w_maskbit,
++ .end = end_msi_irq_w_maskbit,
++ .set_affinity = set_msi_irq_affinity
++};
++
++/*
++ * Interrupt Type for MSI PCI/PCI-X/PCI-Express Devices,
++ * which implement the MSI Capability Structure without
++ * Mask-and-Pending Bits.
++ */
++static struct hw_interrupt_type msi_irq_wo_maskbit_type = {
++ .typename = "PCI MSI",
++ .startup = startup_msi_irq_wo_maskbit,
++ .shutdown = shutdown_msi_irq_wo_maskbit,
++ .enable = enable_msi_irq_wo_maskbit,
++ .disable = disable_msi_irq_wo_maskbit,
++ .ack = ack_msi_irq_wo_maskbit,
++ .end = end_msi_irq_wo_maskbit,
++ .set_affinity = set_msi_irq_affinity
++};
++
++static void msi_data_init(struct msg_data *msi_data,
++ unsigned int vector)
++{
++ memset(msi_data, 0, sizeof(struct msg_data));
++ msi_data->vector = (u8)vector;
++ msi_data->delivery_mode = MSI_DELIVERY_MODE;
++ msi_data->level = MSI_LEVEL_MODE;
++ msi_data->trigger = MSI_TRIGGER_MODE;
++}
++
++static void msi_address_init(struct msg_address *msi_address)
++{
++ unsigned int dest_id;
++
++ memset(msi_address, 0, sizeof(struct msg_address));
++ msi_address->hi_address = (u32)0;
++ dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT) |
++ (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT);
++ msi_address->lo_address.u.dest_mode = MSI_LOGICAL_MODE;
++ msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
++ msi_address->lo_address.u.dest_id = dest_id;
++}
++
++static int pci_vector_resources(void)
++{
++ static int res = -EINVAL;
++ int nr_free_vectors;
++
++ if (res == -EINVAL) {
++ int i, repeat;
++ for (i = NR_REPEATS; i > 0; i--) {
++ if ((FIRST_DEVICE_VECTOR + i * 8) > FIRST_SYSTEM_VECTOR)
++ continue;
++ break;
++ }
++ i++;
++ repeat = (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR)/i;
++ res = i * repeat - NR_RESERVED_VECTORS + 1;
++ }
++
++ nr_free_vectors = res + nr_released_vectors - nr_alloc_vectors;
++
++ return nr_free_vectors;
++}
++
++int assign_irq_vector(int irq)
++{
++ static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
++
++ if (irq != MSI_AUTO && IO_APIC_VECTOR(irq) > 0)
++ return IO_APIC_VECTOR(irq);
++next:
++ current_vector += 8;
++ if (current_vector == SYSCALL_VECTOR)
++ goto next;
++
++ if (current_vector > FIRST_SYSTEM_VECTOR) {
++ offset++;
++ current_vector = FIRST_DEVICE_VECTOR + offset;
++ }
++
++ if (current_vector == FIRST_SYSTEM_VECTOR)
++ return -ENOSPC;
++
++ vector_irq[current_vector] = irq;
++ if (irq != MSI_AUTO)
++ IO_APIC_VECTOR(irq) = current_vector;
++
++ nr_alloc_vectors++;
++
++ return current_vector;
++}
++
++static int assign_msi_vector(void)
++{
++ static int new_vector_avail = 1;
++ int vector;
++ unsigned long flags;
++
++ /*
++ * msi_lock is provided to ensure that successful allocation of MSI
++ * vector is assigned unique among drivers.
++ */
++ spin_lock_irqsave(&msi_lock, flags);
++ if (!(pci_vector_resources() > 0)) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EBUSY;
++ }
++
++ if (!new_vector_avail) {
++ /*
++ * vector_irq[] = -1 indicates that this specific vector is:
++ * - assigned for MSI (since MSI have no associated IRQ) or
++ * - assigned for legacy if less than 16, or
++ * - having no corresponding 1:1 vector-to-IOxAPIC IRQ mapping
++ * vector_irq[] = 0 indicates that this vector, previously
++ * assigned for MSI, is freed by hotplug removed operations.
++ * This vector will be reused for any subsequent hotplug added
++ * operations.
++ * vector_irq[] > 0 indicates that this vector is assigned for
++ * IOxAPIC IRQs. This vector and its value provides a 1-to-1
++ * vector-to-IOxAPIC IRQ mapping.
++ */
++ for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
++ if (vector_irq[vector] != 0)
++ continue;
++ vector_irq[vector] = -1;
++ nr_released_vectors--;
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return vector;
++ }
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EBUSY;
++ }
++
++ vector = assign_irq_vector(MSI_AUTO);
++ if (vector == (FIRST_SYSTEM_VECTOR - 8))
++ new_vector_avail = 0;
++
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return vector;
++}
++
++static int get_new_vector(void)
++{
++ int vector;
++
++ if ((vector = assign_msi_vector()) > 0)
++ set_intr_gate(vector, interrupt[vector]);
++
++ return vector;
++}
++
++static int msi_init(void)
++{
++ static int status = -ENOMEM;
++
++ if (!status)
++ return status;
++
++ if ((status = msi_cache_init()) < 0) {
++ pci_msi_enable = 0;
++ printk(KERN_INFO "WARNING: MSI INIT FAILURE\n");
++ return status;
++ }
++ printk(KERN_INFO "MSI INIT SUCCESS\n");
++
++ return status;
++}
++
++static int get_msi_vector(struct pci_dev *dev)
++{
++ return get_new_vector();
++}
++
++static struct msi_desc* alloc_msi_entry(void)
++{
++ struct msi_desc *entry;
++
++ entry = (struct msi_desc*) kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
++ if (!entry)
++ return NULL;
++
++ memset(entry, 0, sizeof(struct msi_desc));
++ entry->link.tail = entry->link.head = 0; /* single message */
++ entry->dev = NULL;
++
++ return entry;
++}
++
++static void attach_msi_entry(struct msi_desc *entry, int vector)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ msi_desc[vector] = entry;
++ spin_unlock_irqrestore(&msi_lock, flags);
++}
++
++static void irq_handler_init(int cap_id, int pos, int mask)
++{
++ spin_lock(&irq_desc[pos].lock);
++ if (cap_id == PCI_CAP_ID_MSIX)
++ irq_desc[pos].handler = &msix_irq_type;
++ else {
++ if (!mask)
++ irq_desc[pos].handler = &msi_irq_wo_maskbit_type;
++ else
++ irq_desc[pos].handler = &msi_irq_w_maskbit_type;
++ }
++ spin_unlock(&irq_desc[pos].lock);
++}
++
++static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
++{
++ u32 control;
++
++ dev->bus->ops->read(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, &control);
++ if (type == PCI_CAP_ID_MSI) {
++ /* Set enabled bits to single MSI & enable MSI_enable bit */
++ msi_enable(control, 1);
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, control);
++ } else {
++ msix_enable(control);
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, control);
++ }
++ if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
++ /* PCI Express Endpoint device detected */
++ u32 cmd;
++ dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
++ cmd |= PCI_COMMAND_INTX_DISABLE;
++ dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
++ }
++}
++
++static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
++{
++ u32 control;
++
++ dev->bus->ops->read(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, &control);
++ if (type == PCI_CAP_ID_MSI) {
++ /* Set enabled bits to single MSI & enable MSI_enable bit */
++ msi_disable(control);
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, control);
++ } else {
++ msix_disable(control);
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_control_reg(pos), 2, control);
++ }
++ if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
++ /* PCI Express Endpoint device detected */
++ u32 cmd;
++ dev->bus->ops->read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd);
++ cmd &= ~PCI_COMMAND_INTX_DISABLE;
++ dev->bus->ops->write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd);
++ }
++}
++
++static int msi_lookup_vector(struct pci_dev *dev)
++{
++ int vector;
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ for (vector = FIRST_DEVICE_VECTOR; vector < NR_IRQS; vector++) {
++ if (!msi_desc[vector] || msi_desc[vector]->dev != dev ||
++ msi_desc[vector]->msi_attrib.entry_nr ||
++ msi_desc[vector]->msi_attrib.default_vector != dev->irq)
++ continue; /* not entry 0, skip */
++ spin_unlock_irqrestore(&msi_lock, flags);
++ /* This pre-assigned entry-0 MSI vector for this device
++ already exits. Override dev->irq with this vector */
++ dev->irq = vector;
++ return 0;
++ }
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ return -EACCES;
++}
++
++void pci_scan_msi_device(struct pci_dev *dev)
++{
++ if (!dev)
++ return;
++
++ if (pci_find_capability(dev, PCI_CAP_ID_MSIX) > 0) {
++ nr_reserved_vectors++;
++ nr_msix_devices++;
++ } else if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0)
++ nr_reserved_vectors++;
++}
++
++/**
++ * msi_capability_init - configure device's MSI capability structure
++ * @dev: pointer to the pci_dev data structure of MSI device function
++ *
++ * Setup the MSI capability structure of device funtion with a single
++ * MSI vector, regardless of device function is capable of handling
++ * multiple messages. A return of zero indicates the successful setup
++ * of an entry zero with the new MSI vector or non-zero for otherwise.
++ **/
++static int msi_capability_init(struct pci_dev *dev)
++{
++ struct msi_desc *entry;
++ struct msg_address address;
++ struct msg_data data;
++ int pos, vector;
++ u32 control;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
++ if (!pos)
++ return -EINVAL;
++
++ dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
++ 2, &control);
++ if (control & PCI_MSI_FLAGS_ENABLE)
++ return 0;
++
++ vector = dev->irq;
++ if (vector > 0 && !msi_lookup_vector(dev)) {
++ /* Lookup Sucess */
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++ return 0;
++ }
++ /* MSI Entry Initialization */
++ if (!(entry = alloc_msi_entry()))
++ return -ENOMEM;
++
++ if ((vector = get_msi_vector(dev)) < 0) {
++ kmem_cache_free(msi_cachep, entry);
++ return -EBUSY;
++ }
++ entry->msi_attrib.type = PCI_CAP_ID_MSI;
++ entry->msi_attrib.entry_nr = 0;
++ entry->msi_attrib.maskbit = is_mask_bit_support(control);
++ entry->msi_attrib.default_vector = dev->irq;
++ dev->irq = vector; /* save default pre-assigned ioapic vector */
++ entry->dev = dev;
++ if (is_mask_bit_support(control)) {
++ entry->mask_base = msi_mask_bits_reg(pos,
++ is_64bit_address(control));
++ }
++ /* Replace with MSI handler */
++ irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
++ /* Configure MSI capability structure */
++ msi_address_init(&address);
++ msi_data_init(&data, vector);
++ entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
++ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
++ dev->bus->ops->write(dev->bus, dev->devfn, msi_lower_address_reg(pos),
++ 4, address.lo_address.value);
++ if (is_64bit_address(control)) {
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_upper_address_reg(pos), 4, address.hi_address);
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_data_reg(pos, 1), 2, *((u32*)&data));
++ } else
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_data_reg(pos, 0), 2, *((u32*)&data));
++ if (entry->msi_attrib.maskbit) {
++ unsigned int maskbits, temp;
++ /* All MSIs are unmasked by default, Mask them all */
++ dev->bus->ops->read(dev->bus, dev->devfn,
++ msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
++ &maskbits);
++ temp = (1 << multi_msi_capable(control));
++ temp = ((temp - 1) & ~temp);
++ maskbits |= temp;
++ dev->bus->ops->write(dev->bus, dev->devfn,
++ msi_mask_bits_reg(pos, is_64bit_address(control)), 4,
++ maskbits);
++ }
++ attach_msi_entry(entry, vector);
++ /* Set MSI enabled bits */
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
++
++ return 0;
++}
++
++/**
++ * msix_capability_init - configure device's MSI-X capability
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ *
++ * Setup the MSI-X capability structure of device funtion with a
++ * single MSI-X vector. A return of zero indicates the successful setup
++ * of an entry zero with the new MSI-X vector or non-zero for otherwise.
++ * To request for additional MSI-X vectors, the device drivers are
++ * required to utilize the following supported APIs:
++ * 1) msi_alloc_vectors(...) for requesting one or more MSI-X vectors
++ * 2) msi_free_vectors(...) for releasing one or more MSI-X vectors
++ * back to PCI subsystem before calling free_irq(...)
++ **/
++static int msix_capability_init(struct pci_dev *dev)
++{
++ struct msi_desc *entry;
++ struct msg_address address;
++ struct msg_data data;
++ int vector, pos, dev_msi_cap;
++ u32 phys_addr, table_offset;
++ u32 control;
++ u8 bir;
++ void *base;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ if (!pos)
++ return -EINVAL;
++
++ /* Request & Map MSI-X table region */
++ dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2,
++ &control);
++ if (control & PCI_MSIX_FLAGS_ENABLE)
++ return 0;
++
++ vector = dev->irq;
++ if (vector > 0 && !msi_lookup_vector(dev)) {
++ /* Lookup Sucess */
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++ return 0;
++ }
++
++ dev_msi_cap = multi_msix_capable(control);
++ dev->bus->ops->read(dev->bus, dev->devfn,
++ msix_table_offset_reg(pos), 4, &table_offset);
++ bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
++ phys_addr = pci_resource_start (dev, bir);
++ phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
++ if (!request_mem_region(phys_addr,
++ dev_msi_cap * PCI_MSIX_ENTRY_SIZE,
++ "MSI-X iomap Failure"))
++ return -ENOMEM;
++ base = ioremap_nocache(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
++ if (base == NULL)
++ goto free_region;
++ /* MSI Entry Initialization */
++ entry = alloc_msi_entry();
++ if (!entry)
++ goto free_iomap;
++ if ((vector = get_msi_vector(dev)) < 0)
++ goto free_entry;
++
++ entry->msi_attrib.type = PCI_CAP_ID_MSIX;
++ entry->msi_attrib.entry_nr = 0;
++ entry->msi_attrib.maskbit = 1;
++ entry->msi_attrib.default_vector = dev->irq;
++ dev->irq = vector; /* save default pre-assigned ioapic vector */
++ entry->dev = dev;
++ entry->mask_base = (unsigned long)base;
++ /* Replace with MSI handler */
++ irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
++ /* Configure MSI-X capability structure */
++ msi_address_init(&address);
++ msi_data_init(&data, vector);
++ entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
++ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
++ writel(address.lo_address.value, base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++ writel(address.hi_address, base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
++ writel(*(u32*)&data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
++ /* Initialize all entries from 1 up to 0 */
++ for (pos = 1; pos < dev_msi_cap; pos++) {
++ writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
++ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++ writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
++ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
++ writel(0, base + pos * PCI_MSIX_ENTRY_SIZE +
++ PCI_MSIX_ENTRY_DATA_OFFSET);
++ }
++ attach_msi_entry(entry, vector);
++ /* Set MSI enabled bits */
++ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
++
++ return 0;
++
++free_entry:
++ kmem_cache_free(msi_cachep, entry);
++free_iomap:
++ iounmap(base);
++free_region:
++ release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
++
++ return ((vector < 0) ? -EBUSY : -ENOMEM);
++}
++
++/**
++ * pci_enable_msi - configure device's MSI(X) capability structure
++ * @dev: pointer to the pci_dev data structure of MSI(X) device function
++ *
++ * Setup the MSI/MSI-X capability structure of device function with
++ * a single MSI(X) vector upon its software driver call to request for
++ * MSI(X) mode enabled on its hardware device function. A return of zero
++ * indicates the successful setup of an entry zero with the new MSI(X)
++ * vector or non-zero for otherwise.
++ **/
++int pci_enable_msi(struct pci_dev* dev)
++{
++ int status = -EINVAL;
++
++ if (!pci_msi_enable || !dev)
++ return status;
++
++ if (msi_init() < 0)
++ return -ENOMEM;
++
++ if ((status = msix_capability_init(dev)) == -EINVAL)
++ status = msi_capability_init(dev);
++ if (!status)
++ nr_reserved_vectors--;
++
++ return status;
++}
++
++static int msi_free_vector(struct pci_dev* dev, int vector);
++static void pci_disable_msi(unsigned int vector)
++{
++ int head, tail, type, default_vector;
++ struct msi_desc *entry;
++ struct pci_dev *dev;
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[vector];
++ if (!entry || !entry->dev) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return;
++ }
++ dev = entry->dev;
++ type = entry->msi_attrib.type;
++ head = entry->link.head;
++ tail = entry->link.tail;
++ default_vector = entry->msi_attrib.default_vector;
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ disable_msi_mode(dev, pci_find_capability(dev, type), type);
++ /* Restore dev->irq to its default pin-assertion vector */
++ dev->irq = default_vector;
++ if (type == PCI_CAP_ID_MSIX && head != tail) {
++ /* Bad driver, which do not call msi_free_vectors before exit.
++ We must do a cleanup here */
++ while (1) {
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[vector];
++ head = entry->link.head;
++ tail = entry->link.tail;
++ spin_unlock_irqrestore(&msi_lock, flags);
++ if (tail == head)
++ break;
++ if (msi_free_vector(dev, entry->link.tail))
++ break;
++ }
++ }
++}
++
++static int msi_alloc_vector(struct pci_dev* dev, int head)
++{
++ struct msi_desc *entry;
++ struct msg_address address;
++ struct msg_data data;
++ int i, offset, pos, dev_msi_cap, vector;
++ u32 low_address, control;
++ unsigned long base = 0L;
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[dev->irq];
++ if (!entry) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EINVAL;
++ }
++ base = entry->mask_base;
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos),
++ 2, &control);
++ dev_msi_cap = multi_msix_capable(control);
++ for (i = 1; i < dev_msi_cap; i++) {
++ if (!(low_address = readl(base + i * PCI_MSIX_ENTRY_SIZE)))
++ break;
++ }
++ if (i >= dev_msi_cap)
++ return -EINVAL;
++
++ /* MSI Entry Initialization */
++ if (!(entry = alloc_msi_entry()))
++ return -ENOMEM;
++
++ if ((vector = get_new_vector()) < 0) {
++ kmem_cache_free(msi_cachep, entry);
++ return vector;
++ }
++ entry->msi_attrib.type = PCI_CAP_ID_MSIX;
++ entry->msi_attrib.entry_nr = i;
++ entry->msi_attrib.maskbit = 1;
++ entry->dev = dev;
++ entry->link.head = head;
++ entry->mask_base = base;
++ irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
++ /* Configure MSI-X capability structure */
++ msi_address_init(&address);
++ msi_data_init(&data, vector);
++ entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
++ MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
++ offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
++ writel(address.lo_address.value, base + offset +
++ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++ writel(address.hi_address, base + offset +
++ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
++ writel(*(u32*)&data, base + offset + PCI_MSIX_ENTRY_DATA_OFFSET);
++ writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
++ attach_msi_entry(entry, vector);
++
++ return vector;
++}
++
++static int msi_free_vector(struct pci_dev* dev, int vector)
++{
++ struct msi_desc *entry;
++ int entry_nr, type;
++ unsigned long base = 0L;
++ unsigned long flags;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[vector];
++ if (!entry || entry->dev != dev) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EINVAL;
++ }
++ type = entry->msi_attrib.type;
++ entry_nr = entry->msi_attrib.entry_nr;
++ base = entry->mask_base;
++ if (entry->link.tail != entry->link.head) {
++ msi_desc[entry->link.head]->link.tail = entry->link.tail;
++ if (entry->link.tail)
++ msi_desc[entry->link.tail]->link.head = entry->link.head;
++ }
++ entry->dev = NULL;
++ vector_irq[vector] = 0;
++ nr_released_vectors++;
++ msi_desc[vector] = NULL;
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ kmem_cache_free(msi_cachep, entry);
++ if (type == PCI_CAP_ID_MSIX) {
++ int offset;
++
++ offset = entry_nr * PCI_MSIX_ENTRY_SIZE;
++ writel(1, base + offset + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
++ writel(0, base + offset + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
++ }
++
++ return 0;
++}
++
++/**
++ * msi_alloc_vectors - allocate additional MSI-X vectors
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ * @vector: pointer to an array of new allocated MSI-X vectors
++ * @nvec: number of MSI-X vectors requested for allocation by device driver
++ *
++ * Allocate additional MSI-X vectors requested by device driver. A
++ * return of zero indicates the successful setup of MSI-X capability
++ * structure with new allocated MSI-X vectors or non-zero for otherwise.
++ **/
++int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec)
++{
++ struct msi_desc *entry;
++ int i, head, pos, vec, free_vectors, alloc_vectors;
++ int *vectors = (int *)vector;
++ u32 control;
++ unsigned long flags;
++
++ if (!pci_msi_enable || !dev)
++ return -EINVAL;
++
++ if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)))
++ return -EINVAL;
++
++ dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2, &control);
++ if (nvec > multi_msix_capable(control))
++ return -EINVAL;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[dev->irq];
++ if (!entry || entry->dev != dev || /* legal call */
++ entry->msi_attrib.type != PCI_CAP_ID_MSIX || /* must be MSI-X */
++ entry->link.head != entry->link.tail) { /* already multi */
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EINVAL;
++ }
++ /*
++ * msi_lock is provided to ensure that enough vectors resources are
++ * available before granting.
++ */
++ free_vectors = pci_vector_resources();
++ /* Ensure that each MSI/MSI-X device has one vector reserved by
++ default to avoid any MSI-X driver to take all available
++ resources */
++ free_vectors -= nr_reserved_vectors;
++ /* Find the average of free vectors among MSI-X devices */
++ if (nr_msix_devices > 0)
++ free_vectors /= nr_msix_devices;
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ if (nvec > free_vectors)
++ return -EBUSY;
++
++ alloc_vectors = 0;
++ head = dev->irq;
++ for (i = 0; i < nvec; i++) {
++ if ((vec = msi_alloc_vector(dev, head)) < 0)
++ break;
++ *(vectors + i) = vec;
++ head = vec;
++ alloc_vectors++;
++ }
++ if (alloc_vectors != nvec) {
++ for (i = 0; i < alloc_vectors; i++) {
++ vec = *(vectors + i);
++ msi_free_vector(dev, vec);
++ }
++ spin_lock_irqsave(&msi_lock, flags);
++ msi_desc[dev->irq]->link.tail = msi_desc[dev->irq]->link.head;
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EBUSY;
++ }
++ if (nr_msix_devices > 0)
++ nr_msix_devices--;
++
++ return 0;
++}
++
++/**
++ * msi_free_vectors - reclaim MSI-X vectors to unused state
++ * @dev: pointer to the pci_dev data structure of MSI-X device function
++ * @vector: pointer to an array of released MSI-X vectors
++ * @nvec: number of MSI-X vectors requested for release by device driver
++ *
++ * Reclaim MSI-X vectors released by device driver to unused state,
++ * which may be used later on. A return of zero indicates the
++ * success or non-zero for otherwise. Device driver should call this
++ * before calling function free_irq.
++ **/
++int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec)
++{
++ struct msi_desc *entry;
++ int i;
++ unsigned long flags;
++
++ if (!pci_msi_enable)
++ return -EINVAL;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[dev->irq];
++ if (!entry || entry->dev != dev ||
++ entry->msi_attrib.type != PCI_CAP_ID_MSIX ||
++ entry->link.head == entry->link.tail) { /* Nothing to free */
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return -EINVAL;
++ }
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ for (i = 0; i < nvec; i++) {
++ if (*(vector + i) == dev->irq)
++ continue;/* Don't free entry 0 if mistaken by driver */
++ msi_free_vector(dev, *(vector + i));
++ }
++
++ return 0;
++}
++
++/**
++ * msi_remove_pci_irq_vectors - reclaim MSI(X) vectors to unused state
++ * @dev: pointer to the pci_dev data structure of MSI(X) device function
++ *
++ * Being called during hotplug remove, from which the device funciton
++ * is hot-removed. All previous assigned MSI/MSI-X vectors, if
++ * allocated for this device function, are reclaimed to unused state,
++ * which may be used later on.
++ **/
++void msi_remove_pci_irq_vectors(struct pci_dev* dev)
++{
++ struct msi_desc *entry;
++ int type;
++ unsigned long flags;
++
++ if (!pci_msi_enable)
++ return;
++
++ spin_lock_irqsave(&msi_lock, flags);
++ entry = msi_desc[dev->irq];
++ if (!entry || entry->dev != dev) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ return;
++ }
++ type = entry->msi_attrib.type;
++ spin_unlock_irqrestore(&msi_lock, flags);
++
++ msi_free_vector(dev, dev->irq);
++ if (type == PCI_CAP_ID_MSIX) {
++ int i, pos, dev_msi_cap;
++ u32 phys_addr, table_offset;
++ u32 control;
++ u8 bir;
++
++ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
++ dev->bus->ops->read(dev->bus, dev->devfn, msi_control_reg(pos), 2, &control);
++ dev_msi_cap = multi_msix_capable(control);
++ dev->bus->ops->read(dev->bus, dev->devfn,
++ msix_table_offset_reg(pos), 4, &table_offset);
++ bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
++ phys_addr = pci_resource_start (dev, bir);
++ phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
++ for (i = FIRST_DEVICE_VECTOR; i < NR_IRQS; i++) {
++ spin_lock_irqsave(&msi_lock, flags);
++ if (!msi_desc[i] || msi_desc[i]->dev != dev) {
++ spin_unlock_irqrestore(&msi_lock, flags);
++ continue;
++ }
++ spin_unlock_irqrestore(&msi_lock, flags);
++ msi_free_vector(dev, i);
++ }
++ writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
++ iounmap((void*)entry->mask_base);
++ release_mem_region(phys_addr, dev_msi_cap * PCI_MSIX_ENTRY_SIZE);
++ }
++ nr_reserved_vectors++;
++}
++
++EXPORT_SYMBOL(pci_enable_msi);
++EXPORT_SYMBOL(msi_alloc_vectors);
++EXPORT_SYMBOL(msi_free_vectors);
+--- linux-2.6.0-test6/drivers/pci/pci.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/pci/pci.c 2003-10-05 00:36:10.000000000 -0700
+@@ -126,11 +126,13 @@ pci_find_capability(struct pci_dev *dev,
+
+ /**
+ * pci_bus_find_capability - query for devices' capabilities
+- * @dev: PCI device to query
+- * @cap: capability code
++ * @bus: the PCI bus to query
++ * @devfn: PCI device to query
++ * @cap: capability code
+ *
+ * Like pci_find_capability() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
++ *
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.
+--- linux-2.6.0-test6/drivers/pci/pool.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/pci/pool.c 2003-10-05 00:33:24.000000000 -0700
+@@ -296,7 +296,6 @@ restart:
+
+ schedule_timeout (POOL_TIMEOUT_JIFFIES);
+
+- current->state = TASK_RUNNING;
+ remove_wait_queue (&pool->waitq, &wait);
+ goto restart;
+ }
+--- linux-2.6.0-test6/drivers/pci/power.c 2003-06-14 12:18:25.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,159 +0,0 @@
+-#include <linux/pci.h>
+-#include <linux/pm.h>
+-#include <linux/init.h>
+-
+-/*
+- * PCI Power management..
+- *
+- * This needs to be done centralized, so that we power manage PCI
+- * devices in the right order: we should not shut down PCI bridges
+- * before we've shut down the devices behind them, and we should
+- * not wake up devices before we've woken up the bridge to the
+- * device.. Eh?
+- *
+- * We do not touch devices that don't have a driver that exports
+- * a suspend/resume function. That is just too dangerous. If the default
+- * PCI suspend/resume functions work for a device, the driver can
+- * easily implement them (ie just have a suspend function that calls
+- * the pci_set_power_state() function).
+- */
+-
+-static int pci_pm_save_state_device(struct pci_dev *dev, u32 state)
+-{
+- int error = 0;
+- if (dev) {
+- struct pci_driver *driver = dev->driver;
+- if (driver && driver->save_state)
+- error = driver->save_state(dev,state);
+- }
+- return error;
+-}
+-
+-static int pci_pm_suspend_device(struct pci_dev *dev, u32 state)
+-{
+- int error = 0;
+- if (dev) {
+- struct pci_driver *driver = dev->driver;
+- if (driver && driver->suspend)
+- error = driver->suspend(dev,state);
+- }
+- return error;
+-}
+-
+-static int pci_pm_resume_device(struct pci_dev *dev)
+-{
+- int error = 0;
+- if (dev) {
+- struct pci_driver *driver = dev->driver;
+- if (driver && driver->resume)
+- error = driver->resume(dev);
+- }
+- return error;
+-}
+-
+-static int pci_pm_save_state_bus(struct pci_bus *bus, u32 state)
+-{
+- struct list_head *list;
+- int error = 0;
+-
+- list_for_each(list, &bus->children) {
+- error = pci_pm_save_state_bus(pci_bus_b(list),state);
+- if (error) return error;
+- }
+- list_for_each(list, &bus->devices) {
+- error = pci_pm_save_state_device(pci_dev_b(list),state);
+- if (error) return error;
+- }
+- return 0;
+-}
+-
+-static int pci_pm_suspend_bus(struct pci_bus *bus, u32 state)
+-{
+- struct list_head *list;
+-
+- /* Walk the bus children list */
+- list_for_each(list, &bus->children)
+- pci_pm_suspend_bus(pci_bus_b(list),state);
+-
+- /* Walk the device children list */
+- list_for_each(list, &bus->devices)
+- pci_pm_suspend_device(pci_dev_b(list),state);
+- return 0;
+-}
+-
+-static int pci_pm_resume_bus(struct pci_bus *bus)
+-{
+- struct list_head *list;
+-
+- /* Walk the device children list */
+- list_for_each(list, &bus->devices)
+- pci_pm_resume_device(pci_dev_b(list));
+-
+- /* And then walk the bus children */
+- list_for_each(list, &bus->children)
+- pci_pm_resume_bus(pci_bus_b(list));
+- return 0;
+-}
+-
+-static int pci_pm_save_state(u32 state)
+-{
+- struct pci_bus *bus = NULL;
+- int error = 0;
+-
+- while ((bus = pci_find_next_bus(bus)) != NULL) {
+- error = pci_pm_save_state_bus(bus,state);
+- if (!error)
+- error = pci_pm_save_state_device(bus->self,state);
+- }
+- return error;
+-}
+-
+-static int pci_pm_suspend(u32 state)
+-{
+- struct pci_bus *bus = NULL;
+-
+- while ((bus = pci_find_next_bus(bus)) != NULL) {
+- pci_pm_suspend_bus(bus,state);
+- pci_pm_suspend_device(bus->self,state);
+- }
+- return 0;
+-}
+-
+-static int pci_pm_resume(void)
+-{
+- struct pci_bus *bus = NULL;
+-
+- while ((bus = pci_find_next_bus(bus)) != NULL) {
+- pci_pm_resume_device(bus->self);
+- pci_pm_resume_bus(bus);
+- }
+- return 0;
+-}
+-
+-static int
+-pci_pm_callback(struct pm_dev *pm_device, pm_request_t rqst, void *data)
+-{
+- int error = 0;
+-
+- switch (rqst) {
+- case PM_SAVE_STATE:
+- error = pci_pm_save_state((unsigned long)data);
+- break;
+- case PM_SUSPEND:
+- error = pci_pm_suspend((unsigned long)data);
+- break;
+- case PM_RESUME:
+- error = pci_pm_resume();
+- break;
+- default: break;
+- }
+- return error;
+-}
+-
+-static int __init pci_pm_init(void)
+-{
+- pm_register(PM_PCI_DEV, 0, pci_pm_callback);
+- return 0;
+-}
+-
+-subsys_initcall(pci_pm_init);
+--- linux-2.6.0-test6/drivers/pci/probe.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/pci/probe.c 2003-10-05 00:36:20.000000000 -0700
+@@ -176,7 +176,7 @@ void __devinit pci_read_bridge_bases(str
+ limit |= (io_limit_hi << 16);
+ }
+
+- if (base && base <= limit) {
++ if (base <= limit) {
+ res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+ res->start = base;
+ res->end = limit + 0xfff;
+@@ -187,7 +187,7 @@ void __devinit pci_read_bridge_bases(str
+ pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+- if (base && base <= limit) {
++ if (base <= limit) {
+ res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
+ res->start = base;
+ res->end = limit + 0xfffff;
+@@ -213,7 +213,7 @@ void __devinit pci_read_bridge_bases(str
+ }
+ #endif
+ }
+- if (base && base <= limit) {
++ if (base <= limit) {
+ res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+ res->start = base;
+ res->end = limit + 0xfffff;
+@@ -552,6 +552,7 @@ int __devinit pci_scan_slot(struct pci_b
+ struct pci_dev *dev;
+
+ dev = pci_scan_device(bus, devfn);
++ pci_scan_msi_device(dev);
+ if (func == 0) {
+ if (!dev)
+ break;
+--- linux-2.6.0-test6/drivers/pci/quirks.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/pci/quirks.c 2003-10-05 00:33:24.000000000 -0700
+@@ -750,6 +750,9 @@ static void __init quirk_sis_96x_compati
+
+ /*
+ * The main table of quirks.
++ *
++ * Note: any hooks for hotpluggable devices in this table must _NOT_
++ * be declared __init.
+ */
+
+ static struct pci_fixup pci_fixups[] __devinitdata = {
+--- linux-2.6.0-test6/drivers/pci/remove.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/pci/remove.c 2003-10-05 00:36:20.000000000 -0700
+@@ -14,6 +14,8 @@ static void pci_free_resources(struct pc
+ {
+ int i;
+
++ msi_remove_pci_irq_vectors(dev);
++
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *res = dev->resource + i;
+ if (res->parent)
+--- linux-2.6.0-test6/drivers/s390/block/dasd.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/s390/block/dasd.c 2003-10-05 00:34:01.000000000 -0700
+@@ -1643,9 +1643,9 @@ dasd_flush_request_queue(struct dasd_dev
+ }
+
+ static int
+-dasd_open(struct inode *inp, struct file *filp)
++dasd_open(struct block_device *bdev, struct file *filp)
+ {
+- struct gendisk *disk = inp->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct dasd_device *device = disk->private_data;
+ int rc;
+
+@@ -1676,10 +1676,8 @@ out:
+ return rc;
+ }
+
+-static int
+-dasd_release(struct inode *inp, struct file *filp)
++static int dasd_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inp->i_bdev->bd_disk;
+ struct dasd_device *device = disk->private_data;
+
+ if (device->state < DASD_STATE_BASIC) {
+--- linux-2.6.0-test6/drivers/s390/block/dasd_int.h 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/s390/block/dasd_int.h 2003-10-05 00:33:54.000000000 -0700
+@@ -493,7 +493,7 @@ int dasd_ioctl_init(void);
+ void dasd_ioctl_exit(void);
+ int dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t);
+ int dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t);
+-int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
++int dasd_ioctl(struct block_device *, struct file *, unsigned int, unsigned long);
+
+ /* externals in dasd_proc.c */
+ int dasd_proc_init(void);
+--- linux-2.6.0-test6/drivers/s390/block/dasd_ioctl.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/s390/block/dasd_ioctl.c 2003-10-05 00:33:54.000000000 -0700
+@@ -78,10 +78,9 @@ dasd_ioctl_no_unregister(struct module *
+ }
+
+ int
+-dasd_ioctl(struct inode *inp, struct file *filp,
++dasd_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int no, unsigned long data)
+ {
+- struct block_device *bdev = inp->i_bdev;
+ struct dasd_device *device = bdev->bd_disk->private_data;
+ struct dasd_ioctl *ioctl;
+ const char *dir;
+--- linux-2.6.0-test6/drivers/s390/block/xpram.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/s390/block/xpram.c 2003-10-05 00:33:54.000000000 -0700
+@@ -328,7 +328,7 @@ fail:
+ return 0;
+ }
+
+-static int xpram_ioctl (struct inode *inode, struct file *filp,
++static int xpram_ioctl (struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+ {
+ struct hd_geometry *geo;
+--- linux-2.6.0-test6/drivers/s390/char/tape_block.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/s390/char/tape_block.c 2003-10-05 00:34:01.000000000 -0700
+@@ -27,8 +27,8 @@
+ /*
+ * file operation structure for tape block frontend
+ */
+-static int tapeblock_open(struct inode *, struct file *);
+-static int tapeblock_release(struct inode *, struct file *);
++static int tapeblock_open(block_device *, struct file *);
++static int tapeblock_release(struct gendisk *);
+
+ static struct block_device_operations tapeblock_fops = {
+ .owner = THIS_MODULE,
+@@ -299,9 +299,9 @@ static int tapeblock_mediumdetect(struct
+ * Block frontend tape device open function.
+ */
+ static int
+-tapeblock_open(struct inode *inode, struct file *filp)
++tapeblock_open(struct block_device *bdev, struct file *filp)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct tape_device *device = disk->private_data;
+ int rc;
+
+@@ -336,9 +336,8 @@ tapeblock_open(struct inode *inode, stru
+ * Block frontend tape device release function.
+ */
+ static int
+-tapeblock_release(struct inode *inode, struct file *filp)
++tapeblock_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct tape_device *device = disk->private_data;
+
+ tape_release(device);
+--- linux-2.6.0-test6/drivers/sbus/char/bbc_envctrl.c 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/sbus/char/bbc_envctrl.c 2003-10-05 00:33:24.000000000 -0700
+@@ -59,7 +59,7 @@ static int errno;
+ * before the hardware based power-off event is triggered.
+ */
+
+-/* These settings are in celcius. We use these defaults only
++/* These settings are in Celsius. We use these defaults only
+ * if we cannot interrogate the cpu-fru SEEPROM.
+ */
+ struct temp_limits {
+--- linux-2.6.0-test6/drivers/sbus/char/cpwatchdog.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/sbus/char/cpwatchdog.c 2003-10-05 00:33:24.000000000 -0700
+@@ -539,7 +539,7 @@ static void wd_toggleintr(struct wd_time
+ static void wd_pingtimer(struct wd_timer* pTimer)
+ {
+ if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+- wd_readb(&pTimer->regs->dcntr);
++ wd_readw(&pTimer->regs->dcntr);
+ }
+ }
+
+--- linux-2.6.0-test6/drivers/sbus/char/jsflash.c 2003-08-08 22:55:12.000000000 -0700
++++ 25/drivers/sbus/char/jsflash.c 2003-10-05 00:33:24.000000000 -0700
+@@ -37,6 +37,7 @@
+ #include <linux/string.h>
+ #include <linux/smp_lock.h>
+ #include <linux/genhd.h>
++#include <linux/blkdev.h>
+
+ #define MAJOR_NR JSFD_MAJOR
+
+@@ -187,7 +188,7 @@ static void jsfd_read(char *buf, unsigne
+ static void jsfd_do_request(request_queue_t *q)
+ {
+ struct request *req;
+-
++
+ while ((req = elv_next_request(q)) != NULL) {
+ struct jsfd_part *jdp = req->rq_disk->private_data;
+ unsigned long offset = req->sector << 9;
+@@ -198,16 +199,11 @@ static void jsfd_do_request(request_queu
+ continue;
+ }
+
+- if (req->cmd == WRITE) {
++ if (rq_data_dir(req) != READ) {
+ printk(KERN_ERR "jsfd: write\n");
+ end_request(req, 0);
+ continue;
+ }
+- if (req->cmd != READ) {
+- printk(KERN_ERR "jsfd: bad req->cmd %d\n", req->cmd);
+- end_request(req, 0);
+- continue;
+- }
+
+ if ((jdp->dbase & 0xff000000) != 0x20000000) {
+ printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase);
+@@ -215,7 +211,6 @@ static void jsfd_do_request(request_queu
+ continue;
+ }
+
+-/* printk("%s: read buf %p off %x len %x\n", req->rq_disk->disk_name, req->buffer, (int)offset, (int)len); */ /* P3 */
+ jsfd_read(req->buffer, jdp->dbase + offset, len);
+
+ end_request(req, 1);
+@@ -265,9 +260,6 @@ static ssize_t jsf_read(struct file * fi
+ unsigned int n;
+ } b;
+
+- if (verify_area(VERIFY_WRITE, buf, togo))
+- return -EFAULT;
+-
+ if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) {
+ return 0;
+ }
+@@ -298,7 +290,8 @@ static ssize_t jsf_read(struct file * fi
+ while (togo >= 4) {
+ togo -= 4;
+ b.n = jsf_inl(p);
+- copy_to_user(tmp, b.s, 4);
++ if (copy_to_user(tmp, b.s, 4))
++ return -EFAULT;
+ tmp += 4;
+ p += 4;
+ }
+@@ -374,19 +367,17 @@ static int jsf_ioctl_program(unsigned lo
+ char s[4];
+ } b;
+
+- if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ))
++ if (copy_from_user(&abuf, (char *)arg, JSFPRGSZ))
+ return -EFAULT;
+- copy_from_user(&abuf, (char *)arg, JSFPRGSZ);
+ p = abuf.off;
+ togo = abuf.size;
+ if ((togo & 3) || (p & 3)) return -EINVAL;
+
+ uptr = (char *) (unsigned long) abuf.data;
+- if (verify_area(VERIFY_READ, uptr, togo))
+- return -EFAULT;
+ while (togo != 0) {
+ togo -= 4;
+- copy_from_user(&b.s[0], uptr, 4);
++ if (copy_from_user(&b.s[0], uptr, 4))
++ return -EFAULT;
+ jsf_write4(p, b.n);
+ p += 4;
+ uptr += 4;
+@@ -404,10 +395,8 @@ static int jsf_ioctl(struct inode *inode
+ return -EPERM;
+ switch (cmd) {
+ case JSFLASH_IDENT:
+- if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ))
+- return -EFAULT;
+- copy_to_user(arg, &jsf0.id, JSFIDSZ);
+- error = 0;
++ if (copy_to_user((void *)arg, &jsf0.id, JSFIDSZ))
++ return -EFAULT;
+ break;
+ case JSFLASH_ERASE:
+ error = jsf_ioctl_erase(arg);
+--- linux-2.6.0-test6/drivers/scsi/a2091.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/scsi/a2091.c 2003-10-05 00:33:24.000000000 -0700
+@@ -25,31 +25,20 @@
+ #define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
+ #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
+
+-static struct Scsi_Host *first_instance = NULL;
+-static Scsi_Host_Template *a2091_template;
+-
+-static irqreturn_t a2091_intr (int irq, void *dummy, struct pt_regs *fp)
++static irqreturn_t a2091_intr (int irq, void *_instance, struct pt_regs *fp)
+ {
+ unsigned long flags;
+ unsigned int status;
+- struct Scsi_Host *instance;
+- int handled = 0;
++ struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
+
+- for (instance = first_instance; instance &&
+- instance->hostt == a2091_template; instance = instance->next)
+- {
+- status = DMA(instance)->ISTR;
+- if (!(status & (ISTR_INT_F|ISTR_INT_P)))
+- continue;
+-
+- if (status & ISTR_INTS) {
+- spin_lock_irqsave(instance->host_lock, flags);
+- wd33c93_intr (instance);
+- spin_unlock_irqrestore(instance->host_lock, flags);
+- handled = 1;
+- }
+- }
+- return IRQ_RETVAL(handled);
++ status = DMA(instance)->ISTR;
++ if (!(status & (ISTR_INT_F|ISTR_INT_P)) || !(status & ISTR_INTS))
++ return IRQ_NONE;
++
++ spin_lock_irqsave(instance->host_lock, flags);
++ wd33c93_intr(instance);
++ spin_unlock_irqrestore(instance->host_lock, flags);
++ return IRQ_HANDLED;
+ }
+
+ static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
+@@ -184,8 +173,6 @@ static void dma_stop (struct Scsi_Host *
+ }
+ }
+
+-static int num_a2091 = 0;
+-
+ int __init a2091_detect(Scsi_Host_Template *tpnt)
+ {
+ static unsigned char called = 0;
+@@ -193,6 +180,7 @@ int __init a2091_detect(Scsi_Host_Templa
+ unsigned long address;
+ struct zorro_dev *z = NULL;
+ wd33c93_regs regs;
++ int num_a2091 = 0;
+
+ if (!MACH_IS_AMIGA || called)
+ return 0;
+@@ -221,13 +209,10 @@ int __init a2091_detect(Scsi_Host_Templa
+ regs.SASR = &(DMA(instance)->SASR);
+ regs.SCMD = &(DMA(instance)->SCMD);
+ wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
+- if (num_a2091++ == 0) {
+- first_instance = instance;
+- a2091_template = instance->hostt;
+- request_irq(IRQ_AMIGA_PORTS, a2091_intr, SA_SHIRQ, "A2091 SCSI",
+- a2091_intr);
+- }
++ request_irq(IRQ_AMIGA_PORTS, a2091_intr, SA_SHIRQ, "A2091 SCSI",
++ instance);
+ DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
++ num_a2091++;
+ }
+
+ return num_a2091;
+@@ -266,8 +251,7 @@ int a2091_release(struct Scsi_Host *inst
+ #ifdef MODULE
+ DMA(instance)->CNTR = 0;
+ release_mem_region(ZTWO_PADDR(instance->base), 256);
+- if (--num_a2091 == 0)
+- free_irq(IRQ_AMIGA_PORTS, a2091_intr);
++ free_irq(IRQ_AMIGA_PORTS, instance);
+ wd33c93_release();
+ #endif
+ return 1;
+--- linux-2.6.0-test6/drivers/scsi/aic7xxx/aicasm/Makefile 2003-06-14 12:18:32.000000000 -0700
++++ 25/drivers/scsi/aic7xxx/aicasm/Makefile 2003-10-05 00:34:29.000000000 -0700
+@@ -49,14 +49,18 @@ aicdb.h:
+ clean:
+ rm -f $(clean-files)
+
+-aicasm_gram.c aicasm_gram.h: aicasm_gram.y
++aicasm_gram.c: aicasm_gram.h
++ mv $(<:.h=).tab.c $(<:.h=.c)
++
++aicasm_gram.h: aicasm_gram.y
+ $(YACC) $(YFLAGS) -b $(<:.y=) $<
+- mv $(<:.y=).tab.c $(<:.y=.c)
+ mv $(<:.y=).tab.h $(<:.y=.h)
+
+-aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y
++aicasm_macro_gram.c: aicasm_macro_gram.h
++ mv $(<:.h=).tab.c $(<:.h=.c)
++
++aicasm_macro_gram.h: aicasm_macro_gram.y
+ $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $<
+- mv $(<:.y=).tab.c $(<:.y=.c)
+ mv $(<:.y=).tab.h $(<:.y=.h)
+
+ aicasm_scan.c: aicasm_scan.l
+--- linux-2.6.0-test6/drivers/scsi/aic7xxx/Makefile 2003-06-14 12:18:48.000000000 -0700
++++ 25/drivers/scsi/aic7xxx/Makefile 2003-10-05 00:34:29.000000000 -0700
+@@ -58,7 +58,9 @@ aicasm-7xxx-opts-$(CONFIG_AIC7XXX_REG_PR
+ -p $(obj)/aic7xxx_reg_print.c -i aic7xxx_osm.h
+
+ ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y)
+-$(aic7xxx-gen-y): $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm
++$(aic7xxx-gen-y): $(src)/aic7xxx.seq
++
++$(src)/aic7xxx.seq: $(obj)/aicasm/aicasm $(src)/aic7xxx.reg
+ $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \
+ $(aicasm-7xxx-opts-y) -o $(obj)/aic7xxx_seq.h \
+ $(src)/aic7xxx.seq
+@@ -72,7 +74,9 @@ aicasm-79xx-opts-$(CONFIG_AIC79XX_REG_PR
+ -p $(obj)/aic79xx_reg_print.c -i aic79xx_osm.h
+
+ ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y)
+-$(aic79xx-gen-y): $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm
++$(aic79xx-gen-y): $(src)/aic79xx.seq
++
++$(src)/aic79xx.seq: $(obj)/aicasm/aicasm $(src)/aic79xx.reg
+ $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \
+ $(aicasm-79xx-opts-y) -o $(obj)/aic79xx_seq.h \
+ $(src)/aic79xx.seq
+--- linux-2.6.0-test6/drivers/scsi/aic7xxx_old/aic7xxx_proc.c 2003-06-14 12:18:33.000000000 -0700
++++ 25/drivers/scsi/aic7xxx_old/aic7xxx_proc.c 2003-10-05 00:36:51.000000000 -0700
+@@ -92,7 +92,7 @@ aic7xxx_proc_info ( struct Scsi_Host *HB
+
+ HBAptr = NULL;
+
+- for(p=first_aic7xxx; p->host != HBAptr; p=p->next)
++ for(p=first_aic7xxx; p && p->host != HBAptr; p=p->next)
+ ;
+
+ if (!p)
+--- linux-2.6.0-test6/drivers/scsi/g_NCR5380.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/scsi/g_NCR5380.c 2003-10-05 00:33:24.000000000 -0700
+@@ -527,8 +527,9 @@ int generic_NCR5380_release_resources(st
+ * Locks: none
+ */
+
+-int generic_NCR5380_biosparam(struct scsi_device *sdev,
+- struct block_device *bdev, sector_t capacity, int *ip)
++static int
++generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
++ sector_t capacity, int *ip)
+ {
+ ip[0] = 64;
+ ip[1] = 32;
+--- linux-2.6.0-test6/drivers/scsi/g_NCR5380.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/drivers/scsi/g_NCR5380.h 2003-10-05 00:33:24.000000000 -0700
+@@ -52,7 +52,6 @@ static int generic_NCR5380_bus_reset(Scs
+ static int generic_NCR5380_host_reset(Scsi_Cmnd *);
+ static int generic_NCR5380_device_reset(Scsi_Cmnd *);
+ static const char* generic_NCR5380_info(struct Scsi_Host *);
+-static int generic_NCR5380_biosparam(struct scsi_device *, struct block_device *, sector_t, int *);
+
+ #ifndef CMD_PER_LUN
+ #define CMD_PER_LUN 2
+--- linux-2.6.0-test6/drivers/scsi/gvp11.c 2003-07-27 12:14:39.000000000 -0700
++++ 25/drivers/scsi/gvp11.c 2003-10-05 00:33:24.000000000 -0700
+@@ -25,29 +25,20 @@
+ #define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base))
+ #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
+
+-static struct Scsi_Host *first_instance = NULL;
+-static Scsi_Host_Template *gvp11_template;
+-
+-static irqreturn_t gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
++static irqreturn_t gvp11_intr (int irq, void *_instance, struct pt_regs *fp)
+ {
+ unsigned long flags;
+ unsigned int status;
+- struct Scsi_Host *instance;
+- int handled = 0;
+-
+- for (instance = first_instance; instance &&
+- instance->hostt == gvp11_template; instance = instance->next)
+- {
+- status = DMA(instance)->CNTR;
+- if (!(status & GVP11_DMAC_INT_PENDING))
+- continue;
++ struct Scsi_Host *instance = (struct Scsi_Host *)_instance;
+
+- spin_lock_irqsave(instance->host_lock, flags);
+- wd33c93_intr (instance);
+- spin_unlock_irqrestore(instance->host_lock, flags);
+- handled = 1;
+- }
+- return IRQ_RETVAL(handled);
++ status = DMA(instance)->CNTR;
++ if (!(status & GVP11_DMAC_INT_PENDING))
++ return IRQ_NONE;
++
++ spin_lock_irqsave(instance->host_lock, flags);
++ wd33c93_intr(instance);
++ spin_unlock_irqrestore(instance->host_lock, flags);
++ return IRQ_HANDLED;
+ }
+
+ static int gvp11_xfer_mask = 0;
+@@ -177,8 +168,6 @@ static void dma_stop (struct Scsi_Host *
+ }
+ }
+
+-static int num_gvp11 = 0;
+-
+ #define CHECK_WD33C93
+
+ int __init gvp11_detect(Scsi_Host_Template *tpnt)
+@@ -190,6 +179,7 @@ int __init gvp11_detect(Scsi_Host_Templa
+ struct zorro_dev *z = NULL;
+ unsigned int default_dma_xfer_mask;
+ wd33c93_regs regs;
++ int num_gvp11 = 0;
+ #ifdef CHECK_WD33C93
+ volatile unsigned char *sasr_3393, *scmd_3393;
+ unsigned char save_sasr;
+@@ -339,13 +329,10 @@ int __init gvp11_detect(Scsi_Host_Templa
+ (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
+ : WD33C93_FS_12_15);
+
+- if (num_gvp11++ == 0) {
+- first_instance = instance;
+- gvp11_template = instance->hostt;
+- request_irq(IRQ_AMIGA_PORTS, gvp11_intr, SA_SHIRQ,
+- "GVP11 SCSI", gvp11_intr);
+- }
++ request_irq(IRQ_AMIGA_PORTS, gvp11_intr, SA_SHIRQ, "GVP11 SCSI",
++ instance);
+ DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
++ num_gvp11++;
+ continue;
+
+ release:
+@@ -391,8 +378,7 @@ int gvp11_release(struct Scsi_Host *inst
+ #ifdef MODULE
+ DMA(instance)->CNTR = 0;
+ release_mem_region(ZTWO_PADDR(instance->base), 256);
+- if (--num_gvp11 == 0)
+- free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
++ free_irq(IRQ_AMIGA_PORTS, instance);
+ wd33c93_release();
+ #endif
+ return 1;
+--- linux-2.6.0-test6/drivers/scsi/ide-scsi.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/scsi/ide-scsi.c 2003-10-05 00:34:01.000000000 -0700
+@@ -635,24 +635,23 @@ static ide_driver_t idescsi_driver = {
+ .drives = LIST_HEAD_INIT(idescsi_driver.drives),
+ };
+
+-static int idescsi_ide_open(struct inode *inode, struct file *filp)
++static int idescsi_ide_open(struct block_device *bdev, struct file *filp)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = bdev->bd_disk->private_data;
+ drive->usage++;
+ return 0;
+ }
+
+-static int idescsi_ide_release(struct inode *inode, struct file *filp)
++static int idescsi_ide_release(struct gendisk *disk)
+ {
+- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
++ ide_drive_t *drive = disk->private_data;
+ drive->usage--;
+ return 0;
+ }
+
+-static int idescsi_ide_ioctl(struct inode *inode, struct file *file,
++static int idescsi_ide_ioctl(struct block_device *bdev, struct file *file,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ return generic_ide_ioctl(bdev, cmd, arg);
+ }
+
+--- linux-2.6.0-test6/drivers/scsi/Kconfig 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/scsi/Kconfig 2003-10-05 00:36:26.000000000 -0700
+@@ -55,6 +55,14 @@ config BLK_DEV_SD
+ In this case, do not compile the driver for your SCSI host adapter
+ (below) as a module either.
+
++config MAX_SD_DISKS
++ int "Maximum number of SCSI disks to support (256-8192)"
++ depends on BLK_DEV_SD
++ default "256"
++ help
++ The maximum number SCSI disks to support. Default is 256.
++ Change this value if you want kernel to support lots of SCSI devices.
++
+ config CHR_DEV_ST
+ tristate "SCSI tape support"
+ depends on SCSI
+@@ -1148,16 +1156,6 @@ config SCSI_QLOGIC_1280
+ To compile this driver as a module, choose M here: the
+ module will be called qla1280.
+
+-config SCSI_QLOGIC_1280_PIO
+- bool "Use PIO instead of MMIO" if !X86_VISWS
+- depends on SCSI_QLOGIC_1280
+- default y if X86_VISWS
+- help
+- This instructs the driver to use programmed I/O ports (PIO) instead
+- of PCI shared memory (MMIO). This can possibly solve some problems
+- in case your mainboard has memory consistency issues. If unsure,
+- say N.
+-
+ config SCSI_QLOGICPTI
+ tristate "PTI Qlogic, ISP Driver"
+ depends on SBUS && SCSI
+@@ -1435,7 +1433,7 @@ config A3000_SCSI
+
+ config A4000T_SCSI
+ bool "A4000T SCSI support (EXPERIMENTAL)"
+- depends on AMIGA && SCSI && EXPERIMENTAL
++ depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN
+ help
+ Support for the NCR53C710 SCSI controller on the Amiga 4000T.
+
+@@ -1503,7 +1501,7 @@ config FASTLANE_SCSI
+
+ config A4091_SCSI
+ bool "A4091 SCSI support (EXPERIMENTAL)"
+- depends on ZORRO && SCSI && EXPERIMENTAL
++ depends on ZORRO && SCSI && EXPERIMENTAL && BROKEN
+ help
+ Support for the NCR53C710 chip on the Amiga 4091 Z3 SCSI2 controller
+ (1993). Very obscure -- the 4091 was part of an Amiga 4000 upgrade
+@@ -1511,7 +1509,7 @@ config A4091_SCSI
+
+ config WARPENGINE_SCSI
+ bool "WarpEngine SCSI support (EXPERIMENTAL)"
+- depends on ZORRO && SCSI && EXPERIMENTAL
++ depends on ZORRO && SCSI && EXPERIMENTAL && BROKEN
+ help
+ Support for MacroSystem Development's WarpEngine Amiga SCSI-2
+ controller. Info at
+@@ -1519,7 +1517,7 @@ config WARPENGINE_SCSI
+
+ config BLZ603EPLUS_SCSI
+ bool "Blizzard PowerUP 603e+ SCSI (EXPERIMENTAL)"
+- depends on ZORRO && SCSI && EXPERIMENTAL
++ depends on ZORRO && SCSI && EXPERIMENTAL && BROKEN
+ help
+ If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+
+ accelerator, say Y. Otherwise, say N.
+@@ -1535,7 +1533,7 @@ config OKTAGON_SCSI
+
+ config ATARI_SCSI
+ tristate "Atari native SCSI support"
+- depends on ATARI && SCSI
++ depends on ATARI && SCSI && BROKEN
+ ---help---
+ If you have an Atari with built-in NCR5380 SCSI controller (TT,
+ Falcon, ...) say Y to get it supported. Of course also, if you have
+@@ -1604,7 +1602,7 @@ config MVME147_SCSI
+
+ config MVME16x_SCSI
+ bool "NCR53C710 SCSI driver for MVME16x"
+- depends on MVME16x && SCSI
++ depends on MVME16x && SCSI && BROKEN
+ help
+ The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
+ SCSI controller chip. Almost everyone using one of these boards
+@@ -1612,7 +1610,7 @@ config MVME16x_SCSI
+
+ config BVME6000_SCSI
+ bool "NCR53C710 SCSI driver for BVME6000"
+- depends on BVME6000 && SCSI
++ depends on BVME6000 && SCSI && BROKEN
+ help
+ The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
+ SCSI controller chip. Almost everyone using one of these boards
+--- linux-2.6.0-test6/drivers/scsi/megaraid.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/scsi/megaraid.c 2003-10-05 00:33:24.000000000 -0700
+@@ -586,7 +586,7 @@ mega_find_card(Scsi_Host_Template *host_
+
+ /* Set the Mode of addressing to 64 bit if we can */
+ if((adapter->flag & BOARD_64BIT)&&(sizeof(dma_addr_t) == 8)) {
+- pci_set_dma_mask(pdev, 0xffffffffffffffff);
++ pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ adapter->has_64bit_addr = 1;
+ }
+ else {
+--- linux-2.6.0-test6/drivers/scsi/ncr53c8xx.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/scsi/ncr53c8xx.c 2003-10-05 00:33:24.000000000 -0700
+@@ -7757,7 +7757,7 @@ static void ncr_init_ccb(ncb_p np, ccb_p
+ cp->start.schedule.l_cmd = cpu_to_scr(SCR_JUMP);
+ cp->start.p_phys = cpu_to_scr(CCB_PHYS(cp, phys));
+
+- bcopy(&cp->start, &cp->restart, sizeof(cp->restart));
++ memcpy(&cp->restart, &cp->start, sizeof(cp->restart));
+
+ cp->start.schedule.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle));
+ cp->restart.schedule.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort));
+--- linux-2.6.0-test6/drivers/scsi/nsp32.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/scsi/nsp32.c 2003-10-05 00:33:24.000000000 -0700
+@@ -3435,15 +3435,6 @@ static inline int nsp32_prom_get(nsp32_h
+ * Power Management
+ */
+ #ifdef CONFIG_PM
+-/* Save Device Context */
+-static int nsp32_save_state(struct pci_dev *pdev, u32 state)
+-{
+- struct Scsi_Host *host = pci_get_drvdata(pdev);
+-
+- nsp32_msg(KERN_INFO, "pci-save_state: stub, pdev=0x%p, state=%ld, slot=%s, host=0x%p", pdev, state, pci_name(pdev), host);
+-
+- return 0;
+-}
+
+ /* Device suspended */
+ static int nsp32_suspend(struct pci_dev *pdev, u32 state)
+@@ -3573,7 +3564,6 @@ static struct pci_driver nsp32_driver =
+ .probe = nsp32_probe,
+ .remove = __devexit_p(nsp32_remove),
+ #ifdef CONFIG_PM
+- .save_state = nsp32_save_state,
+ .suspend = nsp32_suspend,
+ .resume = nsp32_resume,
+ .enable_wake = nsp32_enable_wake,
+--- linux-2.6.0-test6/drivers/scsi/qla1280.c 2003-09-27 18:57:45.000000000 -0700
++++ 25/drivers/scsi/qla1280.c 2003-10-05 00:33:24.000000000 -0700
+@@ -16,10 +16,15 @@
+ * General Public License for more details.
+ *
+ ******************************************************************************/
+-#define QLA1280_VERSION "3.23.36"
++#define QLA1280_VERSION "3.23.37"
+ /*****************************************************************************
+ Revision History:
+- Rev 3.23.36 September 19, 2003, Christoph Hellwig
++ Rev 3.23.37 October 1, 2003, Jes Sorensen
++ - Make MMIO depend on CONFIG_X86_VISWS instead of yet another
++ random CONFIG option
++ - Clean up locking in probe path
++ Rev 3.23.36 October 1, 2003, Christoph Hellwig
++ - queuecommand only ever receives new commands - clear flags
+ - Reintegrate lost fixes from Linux 2.5
+ Rev 3.23.35 August 14, 2003, Jes Sorensen
+ - Build against 2.6
+@@ -315,14 +320,14 @@
+
+ #if LINUX_VERSION_CODE >= 0x020545
+ #include <scsi/scsi_host.h>
++#include "scsi.h"
+ #else
+ #include <linux/blk.h>
++#include "scsi.h"
+ #include "hosts.h"
+ #include "sd.h"
+ #endif
+
+-#include "scsi.h"
+-
+ #if LINUX_VERSION_CODE < 0x020407
+ #error "Kernels older than 2.4.7 are no longer supported"
+ #endif
+@@ -339,7 +344,10 @@
+ #define DEBUG_PRINT_NVRAM 0
+ #define DEBUG_QLA1280 0
+
+-#ifdef CONFIG_SCSI_QLOGIC_1280_PIO
++/*
++ * The SGI VISWS is broken and doesn't support MMIO ;-(
++ */
++#ifdef CONFIG_X86_VISWS
+ #define MEMORY_MAPPED_IO 0
+ #else
+ #define MEMORY_MAPPED_IO 1
+@@ -414,6 +422,11 @@ scsi_adjust_queue_depth(Scsi_Device *dev
+ #else
+ #define HOST_LOCK ha->host->host_lock
+ #endif
++#if LINUX_VERSION_CODE < 0x020600
++#define DEV_SIMPLE_TAGS(device) device->tagged_queue
++#else
++#define DEV_SIMPLE_TAGS(device) device->simple_tags
++#endif
+ #if defined(__ia64__) && !defined(ia64_platform_is)
+ #define ia64_platform_is(foo) (!strcmp(x, platform_name))
+ #endif
+@@ -647,11 +660,11 @@ static int ql_debug_level = 1;
+ #define PROC_BUF &qla1280_buffer[len]
+
+ #if LINUX_VERSION_CODE < 0x020600
+-static int qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
+- int hostno, int inout)
++static int qla1280_proc_info(char *buffer, char **start, off_t offset,
++ int length, int hostno, int inout)
+ #else
+-static int qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+- off_t offset, int length, int inout)
++static int qla1280_proc_info(struct Scsi_Host *host, char *buffer,
++ char **start, off_t offset, int length, int inout)
+ #endif
+ {
+ struct scsi_qla_host *ha;
+@@ -955,8 +968,8 @@ qla1280_do_device_init(struct pci_dev *p
+ host->io_port, host->io_port + 0xff);
+ goto error_free_irq;
+ }
+-
+ #endif
++
+ /* load the F/W, read paramaters, and init the H/W */
+ if (qla1280_initialize_adapter(ha)) {
+ printk(KERN_INFO "qla1x160: Failed to initialize adapter\n");
+@@ -1598,6 +1611,7 @@ qla1280_intr_handler(int irq, void *dev_
+ return IRQ_RETVAL(handled);
+ }
+
++
+ static int
+ qla12160_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
+ {
+@@ -1666,9 +1680,7 @@ qla1280_slave_configure(Scsi_Device *dev
+ int target = device->id;
+ int status = 0;
+ struct nvram *nv;
+-#if LINUX_VERSION_CODE < 0x020500
+ unsigned long flags;
+-#endif
+
+ ha = (struct scsi_qla_host *)device->host->hostdata;
+ nv = &ha->nvram;
+@@ -1706,17 +1718,13 @@ qla1280_slave_configure(Scsi_Device *dev
+ nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0;
+ }
+
+-#if LINUX_VERSION_CODE < 0x020500
+ spin_lock_irqsave(HOST_LOCK, flags);
+-#endif
+ if (nv->bus[bus].target[target].parameter.f.enable_sync) {
+ status = qla12160_set_target_parameters(ha, bus, target);
+ }
+
+ qla12160_get_target_parameters(ha, device);
+-#if LINUX_VERSION_CODE < 0x020500
+ spin_unlock_irqrestore(HOST_LOCK, flags);
+-#endif
+ return status;
+ }
+
+@@ -1995,7 +2003,7 @@ qla1280_mem_alloc(struct scsi_qla_host *
+ if (ha->request_ring)
+ pci_free_consistent(ha->pdev,
+ ((REQUEST_ENTRY_CNT + 1) *
+- (sizeof(request_t))),
++ (sizeof(request_t))),
+ ha->request_ring, ha->request_dma);
+ finish:
+ LEAVE("qla1280_mem_alloc");
+@@ -2088,6 +2096,9 @@ qla1280_initialize_adapter(struct scsi_q
+ struct device_reg *reg;
+ int status;
+ int bus;
++#if LINUX_VERSION_CODE > 0x020500
++ unsigned long flags;
++#endif
+
+ ENTER("qla1280_initialize_adapter");
+
+@@ -2131,6 +2142,15 @@ qla1280_initialize_adapter(struct scsi_q
+ "NVRAM\n");
+ }
+
++#if LINUX_VERSION_CODE >= 0x020500
++ /*
++ * It's necessary to grab the spin here as qla1280_mailbox_command
++ * needs to be able to drop the lock unconditionally to wait
++ * for completion.
++ * In 2.4 ->detect is called with the io_request_lock held.
++ */
++ spin_lock_irqsave(HOST_LOCK, flags);
++#endif
+ /* If firmware needs to be loaded */
+ if (qla1280_isp_firmware(ha)) {
+ if (!(status = qla1280_chip_diag (ha))) {
+@@ -2183,6 +2203,9 @@ qla1280_initialize_adapter(struct scsi_q
+ status = 1;
+
+ out:
++#if LINUX_VERSION_CODE >= 0x020500
++ spin_unlock_irqrestore(HOST_LOCK, flags);
++#endif
+ if (status)
+ dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");
+
+@@ -3208,18 +3231,14 @@ qla1280_mailbox_command(struct scsi_qla_
+ timer.function = qla1280_mailbox_timeout;
+ add_timer(&timer);
+
+-#if LINUX_VERSION_CODE < 0x020500
+ spin_unlock_irq(HOST_LOCK);
+-#endif
+ WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT);
+ data = qla1280_debounce_register(®->istatus);
+
+ wait_for_completion(&wait);
+ del_timer_sync(&timer);
+
+-#if LINUX_VERSION_CODE < 0x020500
+ spin_lock_irq(HOST_LOCK);
+-#endif
+
+ ha->mailbox_wait = NULL;
+
+@@ -3636,7 +3655,7 @@ qla1280_64bit_start_scsi(struct scsi_qla
+ (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+ /* Enable simple tag queuing if device supports it. */
+- if (cmd->device->simple_tags)
++ if (DEV_SIMPLE_TAGS(cmd->device))
+ pkt->control_flags |= cpu_to_le16(BIT_3);
+
+ /* Load SCSI command packet. */
+@@ -3936,7 +3955,7 @@ qla1280_32bit_start_scsi(struct scsi_qla
+ (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+ /* Enable simple tag queuing if device supports it. */
+- if (cmd->device->simple_tags)
++ if (DEV_SIMPLE_TAGS(cmd->device))
+ pkt->control_flags |= cpu_to_le16(BIT_3);
+
+ /* Load SCSI command packet. */
+@@ -4823,6 +4842,7 @@ qla1280_debounce_register(volatile u16 *
+ return ret;
+ }
+
++
+ /************************************************************************
+ * qla1280_check_for_dead_scsi_bus *
+ * *
+@@ -4891,7 +4911,7 @@ qla12160_get_target_parameters(struct sc
+ } else
+ printk(" Async");
+
+- if (device->simple_tags)
++ if (DEV_SIMPLE_TAGS(device))
+ printk(", Tagged queuing: depth %d", device->queue_depth);
+ printk("\n");
+ }
+@@ -5105,6 +5125,7 @@ qla1280_get_token(char *str)
+ return ret;
+ }
+
++
+ static Scsi_Host_Template driver_template = {
+ .proc_info = qla1280_proc_info,
+ .name = "Qlogic ISP 1280/12160",
+@@ -5132,6 +5153,7 @@ static Scsi_Host_Template driver_templat
+
+ #include "scsi_module.c"
+
++
+ /*
+ * Overrides for Emacs so that we almost follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+--- linux-2.6.0-test6/drivers/scsi/qlogicfc.c 2003-08-22 19:23:41.000000000 -0700
++++ 25/drivers/scsi/qlogicfc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -718,8 +718,8 @@ int isp2x00_detect(Scsi_Host_Template *
+ continue;
+
+ /* Try to configure DMA attributes. */
+- if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
+- pci_set_dma_mask(pdev, (u64) 0xffffffff))
++ if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) &&
++ pci_set_dma_mask(pdev, 0xffffffffULL))
+ continue;
+
+ host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
+--- linux-2.6.0-test6/drivers/scsi/sd.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sd.c 2003-10-05 00:36:26.000000000 -0700
+@@ -62,6 +62,7 @@
+ */
+ #define SD_MAJORS 16
+ #define SD_DISKS (SD_MAJORS << 4)
++#define TOTAL_SD_DISKS CONFIG_MAX_SD_DISKS
+
+ /*
+ * Time out in seconds for disks and Magneto-opticals (which are slower).
+@@ -87,7 +88,7 @@ struct scsi_disk {
+ unsigned RCD : 1; /* state of disk RCD bit, unused */
+ };
+
+-static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG];
++static unsigned long sd_index_bits[TOTAL_SD_DISKS / BITS_PER_LONG];
+ static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED;
+
+ static int sd_revalidate_disk(struct gendisk *disk);
+@@ -122,6 +123,9 @@ static int sd_major(int major_idx)
+ return SCSI_DISK1_MAJOR + major_idx - 1;
+ case 8 ... 15:
+ return SCSI_DISK8_MAJOR + major_idx - 8;
++#define MAX_IDX (TOTAL_SD_DISKS >> 4)
++ case 16 ... MAX_IDX:
++ return SCSI_DISK15_MAJOR;
+ default:
+ BUG();
+ return 0; /* shut up gcc */
+@@ -348,9 +352,9 @@ queue:
+ * In the latter case @inode and @filp carry an abridged amount
+ * of information as noted above.
+ **/
+-static int sd_open(struct inode *inode, struct file *filp)
++static int sd_open(struct block_device *bdev, struct file *filp)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
++ struct gendisk *disk = bdev->bd_disk;
+ struct scsi_disk *sdkp = scsi_disk(disk);
+ struct scsi_device *sdev = sdkp->device;
+ int retval;
+@@ -370,7 +374,7 @@ static int sd_open(struct inode *inode,
+ goto error_out;
+
+ if (sdev->removable || sdkp->write_prot)
+- check_disk_change(inode->i_bdev);
++ check_disk_change(bdev);
+
+ /*
+ * If the drive is empty, just let the open fail.
+@@ -421,9 +425,8 @@ error_out:
+ * Note: may block (uninterruptible) if error recovery is underway
+ * on this disk.
+ **/
+-static int sd_release(struct inode *inode, struct file *filp)
++static int sd_release(struct gendisk *disk)
+ {
+- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct scsi_disk *sdkp = scsi_disk(disk);
+ struct scsi_device *sdev = sdkp->device;
+
+@@ -486,10 +489,9 @@ static int sd_hdio_getgeo(struct block_d
+ * Note: most ioctls are forward onto the block subsystem or further
+ * down in the scsi subsytem.
+ **/
+-static int sd_ioctl(struct inode * inode, struct file * filp,
++static int sd_ioctl(struct block_device *bdev, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+ {
+- struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ struct scsi_device *sdp = scsi_disk(disk)->device;
+ int error;
+@@ -1275,8 +1277,8 @@ static int sd_probe(struct device *dev)
+ goto out_free;
+
+ spin_lock(&sd_index_lock);
+- index = find_first_zero_bit(sd_index_bits, SD_DISKS);
+- if (index == SD_DISKS) {
++ index = find_first_zero_bit(sd_index_bits, TOTAL_SD_DISKS);
++ if (index == TOTAL_SD_DISKS) {
+ spin_unlock(&sd_index_lock);
+ error = -EBUSY;
+ goto out_put;
+@@ -1291,15 +1293,24 @@ static int sd_probe(struct device *dev)
+ sdkp->openers = 0;
+
+ gd->major = sd_major(index >> 4);
+- gd->first_minor = (index & 15) << 4;
++ if (index > SD_DISKS)
++ gd->first_minor = ((index - SD_DISKS) & 15) << 4;
++ else
++ gd->first_minor = (index & 15) << 4;
+ gd->minors = 16;
+ gd->fops = &sd_fops;
+
+- if (index >= 26) {
++ if (index < 26) {
++ sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
++ } else if (index < (26*27)) {
+ sprintf(gd->disk_name, "sd%c%c",
+ 'a' + index/26-1,'a' + index % 26);
+ } else {
+- sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
++ const unsigned int m1 = (index/ 26 - 1) / 26 - 1;
++ const unsigned int m2 = (index / 26 - 1) % 26;
++ const unsigned int m3 = index % 26;
++ sprintf(gd->disk_name, "sd%c%c%c",
++ 'a' + m1, 'a' + m2, 'a' + m3);
+ }
+
+ strcpy(gd->devfs_name, sdp->devfs_name);
+--- linux-2.6.0-test6/drivers/scsi/sr.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sr.c 2003-10-05 00:34:45.000000000 -0700
+@@ -289,12 +289,12 @@ static int sr_init_command(struct scsi_c
+ return 0;
+
+ memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
+- if (rq_data_dir(rq) == WRITE)
++ if (!rq->data_len)
++ SCpnt->sc_data_direction = SCSI_DATA_NONE;
++ else if (rq_data_dir(rq) == WRITE)
+ SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+- else if (rq->data_len)
+- SCpnt->sc_data_direction = SCSI_DATA_READ;
+ else
+- SCpnt->sc_data_direction = SCSI_DATA_NONE;
++ SCpnt->sc_data_direction = SCSI_DATA_READ;
+
+ this_count = rq->data_len;
+ if (rq->timeout)
+@@ -413,22 +413,22 @@ queue:
+ return 1;
+ }
+
+-static int sr_block_open(struct inode *inode, struct file *file)
++static int sr_block_open(struct block_device *bdev, struct file *file)
+ {
+- struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
+- return cdrom_open(&cd->cdi, inode, file);
++ struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
++ return cdrom_open(&cd->cdi, bdev, file);
+ }
+
+-static int sr_block_release(struct inode *inode, struct file *file)
++static int sr_block_release(struct gendisk *disk)
+ {
+- struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
+- return cdrom_release(&cd->cdi, file);
++ struct scsi_cd *cd = scsi_cd(disk);
++ return cdrom_release(&cd->cdi);
+ }
+
+-static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+- unsigned long arg)
++static int sr_block_ioctl(struct block_device *bdev, struct file *file,
++ unsigned cmd, unsigned long arg)
+ {
+- struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
++ struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+ struct scsi_device *sdev = cd->device;
+
+ /*
+@@ -440,7 +440,7 @@ static int sr_block_ioctl(struct inode *
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ return scsi_ioctl(sdev, cmd, (void *)arg);
+ }
+- return cdrom_ioctl(&cd->cdi, inode, cmd, arg);
++ return cdrom_ioctl(&cd->cdi, bdev, cmd, arg);
+ }
+
+ static int sr_block_media_changed(struct gendisk *disk)
+--- linux-2.6.0-test6/drivers/scsi/sun3_scsi.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/drivers/scsi/sun3_scsi.c 2003-10-05 00:33:24.000000000 -0700
+@@ -308,7 +308,6 @@ int sun3scsi_detect(Scsi_Host_Template *
+ return 1;
+ }
+
+-#ifdef MODULE
+ int sun3scsi_release (struct Scsi_Host *shpnt)
+ {
+ if (shpnt->irq != SCSI_IRQ_NONE)
+@@ -318,7 +317,6 @@ int sun3scsi_release (struct Scsi_Host *
+
+ return 0;
+ }
+-#endif
+
+ #ifdef RESET_BOOT
+ /*
+--- linux-2.6.0-test6/drivers/scsi/sun3_scsi.h 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/scsi/sun3_scsi.h 2003-10-05 00:33:24.000000000 -0700
+@@ -52,11 +52,7 @@ static int sun3scsi_detect (Scsi_Host_Te
+ static const char *sun3scsi_info (struct Scsi_Host *);
+ static int sun3scsi_bus_reset(Scsi_Cmnd *);
+ static int sun3scsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+-#ifdef MODULE
+ static int sun3scsi_release (struct Scsi_Host *);
+-#else
+-#define sun3scsi_release NULL
+-#endif
+
+ #ifndef CMD_PER_LUN
+ #define CMD_PER_LUN 2
+--- linux-2.6.0-test6/drivers/scsi/sun3_scsi_vme.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/drivers/scsi/sun3_scsi_vme.c 2003-10-05 00:33:24.000000000 -0700
+@@ -140,7 +140,7 @@ static struct Scsi_Host *default_instanc
+
+ static int sun3scsi_detect(Scsi_Host_Template * tpnt)
+ {
+- unsigned long ioaddr, irq;
++ unsigned long ioaddr, irq = 0;
+ static int called = 0;
+ struct Scsi_Host *instance;
+ int i;
+@@ -277,17 +277,15 @@ static int sun3scsi_detect(Scsi_Host_Tem
+ return 1;
+ }
+
+-#ifdef MODULE
+ int sun3scsi_release (struct Scsi_Host *shpnt)
+ {
+ if (shpnt->irq != SCSI_IRQ_NONE)
+ free_irq (shpnt->irq, NULL);
+
+- iounmap(sun3_scsi_regp);
++ iounmap((void *)sun3_scsi_regp);
+
+ return 0;
+ }
+-#endif
+
+ #ifdef RESET_BOOT
+ /*
+--- linux-2.6.0-test6/drivers/scsi/sym53c8xx_2/sym_glue.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sym53c8xx_2/sym_glue.c 2003-10-05 00:34:19.000000000 -0700
+@@ -2159,8 +2159,7 @@ sym53c8xx_pci_init(struct pci_dev *pdev,
+
+ /* If the chip can do Memory Write Invalidate, enable it */
+ if (chip->features & FE_WRIE) {
+- if (pci_set_mwi(pdev))
+- return -1;
++ pci_set_mwi(pdev);
+ }
+
+ /*
+--- linux-2.6.0-test6/drivers/scsi/sym53c8xx_2/sym_glue.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sym53c8xx_2/sym_glue.h 2003-10-05 00:33:24.000000000 -0700
+@@ -70,10 +70,6 @@
+ #include <scsi/scsi_host.h>
+ #include "../scsi.h" /* XXX: DID_* */
+
+-#ifndef bcopy
+-#define bcopy(s, d, n) memcpy((d), (s), (n))
+-#endif
+-
+ #ifndef bzero
+ #define bzero(d, n) memset((d), 0, (n))
+ #endif
+--- linux-2.6.0-test6/drivers/scsi/sym53c8xx_2/sym_hipd.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sym53c8xx_2/sym_hipd.c 2003-10-05 00:34:20.000000000 -0700
+@@ -838,7 +838,8 @@ static int sym_prepare_setting(hcb_p np,
+
+ period = parisc_setup_hcb(np, period);
+
+- if (period <= 250) np->minsync = 10;
++ if (period == 250) np->minsync = 9;
++ else if (period <= 250) np->minsync = 10;
+ else if (period <= 303) np->minsync = 11;
+ else if (period <= 500) np->minsync = 12;
+ else np->minsync = (period + 40 - 1) / 40;
+@@ -5889,9 +5890,9 @@ int sym_hcb_attach(hcb_p np, struct sym_
+ /*
+ * Copy scripts to controller instance.
+ */
+- bcopy(fw->a_base, np->scripta0, np->scripta_sz);
+- bcopy(fw->b_base, np->scriptb0, np->scriptb_sz);
+- bcopy(fw->z_base, np->scriptz0, np->scriptz_sz);
++ memcpy(np->scripta0, fw->a_base, np->scripta_sz);
++ memcpy(np->scriptb0, fw->b_base, np->scriptb_sz);
++ memcpy(np->scriptz0, fw->z_base, np->scriptz_sz);
+
+ /*
+ * Setup variable parts in scripts and compute
+--- linux-2.6.0-test6/drivers/scsi/sym53c8xx_2/sym_misc.c 2003-06-14 12:18:32.000000000 -0700
++++ 25/drivers/scsi/sym53c8xx_2/sym_misc.c 2003-10-05 00:33:24.000000000 -0700
+@@ -225,7 +225,7 @@ void sym_announce_transfer_rate(hcb_p np
+ */
+ void sym_update_trans_settings(hcb_p np, tcb_p tp)
+ {
+- bcopy(&tp->tinfo.user, &tp->tinfo.goal, sizeof(tp->tinfo.goal));
++ memcpy(&tp->tinfo.goal, &tp->tinfo.user, sizeof(tp->tinfo.goal));
+
+ if (tp->inq_version >= 4) {
+ switch(tp->inq_byte56 & INQ56_CLOCKING) {
+--- linux-2.6.0-test6/drivers/scsi/sym53c8xx_comm.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/scsi/sym53c8xx_comm.h 2003-10-05 00:33:24.000000000 -0700
+@@ -88,10 +88,6 @@
+ #define u_int unsigned int
+ #define u_long unsigned long
+
+-#ifndef bcopy
+-#define bcopy(s, d, n) memcpy((d), (s), (n))
+-#endif
+-
+ #ifndef bcmp
+ #define bcmp(s, d, n) memcmp((d), (s), (n))
+ #endif
+--- linux-2.6.0-test6/drivers/serial/8250.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/serial/8250.c 2003-10-05 00:36:10.000000000 -0700
+@@ -469,8 +469,14 @@ static void autoconfig_16550a(struct uar
+ */
+ serial_outp(up, UART_LCR, UART_LCR_DLAB);
+ if (serial_in(up, UART_EFR) == 0) {
+- DEBUG_AUTOCONF("EFRv1 ");
+- up->port.type = PORT_16650;
++ serial_outp(up, UART_EFR, 0xA8);
++ if (serial_in(up, UART_EFR) != 0) {
++ DEBUG_AUTOCONF("EFRv1 ");
++ up->port.type = PORT_16650;
++ } else {
++ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
++ }
++ serial_outp(up, UART_EFR, 0);
+ return;
+ }
+
+@@ -490,7 +496,9 @@ static void autoconfig_16550a(struct uar
+ * Attempt to switch to bank 2, read the value of the LOOP bit
+ * from EXCR1. Switch back to bank 0, change it in MCR. Then
+ * switch back to bank 2, read it from EXCR1 again and check
+- * it's changed. If so, set baud_base in EXCR2 to 921600.
++ * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
++ * On PowerPC we don't want to change baud_base, as we have
++ * a number of different divisors. -- Tom Rini
+ */
+ serial_outp(up, UART_LCR, 0);
+ status1 = serial_in(up, UART_MCR);
+@@ -506,12 +514,14 @@ static void autoconfig_16550a(struct uar
+ serial_outp(up, UART_MCR, status1);
+
+ if ((status2 ^ status1) & UART_MCR_LOOP) {
++#ifndef CONFIG_PPC
+ serial_outp(up, UART_LCR, 0xE0);
+ status1 = serial_in(up, 0x04); /* EXCR1 */
+ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
+ serial_outp(up, 0x04, status1);
+ serial_outp(up, UART_LCR, 0);
++#endif
+
+ up->port.type = PORT_NS16550A;
+ up->port.uartclk = 921600*16;
+@@ -825,7 +835,7 @@ receive_chars(struct uart_8250_port *up,
+ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+ tty->flip.work.func((void *)tty);
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+- return; // if TTY_DONT_FLIP is set
++ return; /* if TTY_DONT_FLIP is set */
+ }
+ ch = serial_inp(up, UART_RX);
+ *tty->flip.char_buf_ptr = ch;
+@@ -1186,12 +1196,21 @@ static void serial8250_break_ctl(struct
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+
++#ifdef CONFIG_KGDB
++static int kgdb_irq = -1;
++#endif
++
+ static int serial8250_startup(struct uart_port *port)
+ {
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+ unsigned long flags;
+ int retval;
+
++#ifdef CONFIG_KGDB
++ if (up->port.irq == kgdb_irq)
++ return -EBUSY;
++#endif
++
+ up->capabilities = uart_config[up->port.type].flags;
+
+ if (up->port.type == PORT_16C950) {
+@@ -1857,6 +1876,10 @@ static void __init serial8250_register_p
+ for (i = 0; i < UART_NR; i++) {
+ struct uart_8250_port *up = &serial8250_ports[i];
+
++#ifdef CONFIG_KGDB
++ if (up->port.irq == kgdb_irq)
++ up->port.kgdb = 1;
++#endif
+ up->port.line = i;
+ up->port.ops = &serial8250_pops;
+ init_timer(&up->timer);
+@@ -2101,7 +2124,8 @@ void serial8250_get_irq_map(unsigned int
+
+ /**
+ * serial8250_suspend_port - suspend one serial port
+- * @line: serial line number
++ * @line: serial line number
++ * @level: the level of port suspension, as per uart_suspend_port
+ *
+ * Suspend one serial port.
+ */
+@@ -2112,7 +2136,8 @@ void serial8250_suspend_port(int line)
+
+ /**
+ * serial8250_resume_port - resume one serial port
+- * @line: serial line number
++ * @line: serial line number
++ * @level: the level of port resumption, as per uart_resume_port
+ *
+ * Resume one serial port.
+ */
+@@ -2121,6 +2146,31 @@ void serial8250_resume_port(int line)
+ uart_resume_port(&serial8250_reg, &serial8250_ports[line].port);
+ }
+
++#ifdef CONFIG_KGDB
++/*
++ * Find all the ports using the given irq and shut them down.
++ * Result should be that the irq will be released.
++ */
++void shutdown_for_kgdb(struct async_struct * info)
++{
++ int irq = info->state->irq;
++ struct uart_8250_port *up;
++ int ttyS;
++
++ kgdb_irq = irq; /* save for later init */
++ for (ttyS = 0; ttyS < UART_NR; ttyS++){
++ up = &serial8250_ports[ttyS];
++ if (up->port.irq == irq && (irq_lists + irq)->head) {
++#ifdef CONFIG_DEBUG_SPINLOCK /* ugly business... */
++ if(up->port.lock.magic != SPINLOCK_MAGIC)
++ spin_lock_init(&up->port.lock);
++#endif
++ serial8250_shutdown(&up->port);
++ }
++ }
++}
++#endif /* CONFIG_KGDB */
++
+ static int __init serial8250_init(void)
+ {
+ int ret, i;
+--- linux-2.6.0-test6/drivers/serial/serial_core.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/serial/serial_core.c 2003-10-05 00:36:10.000000000 -0700
+@@ -263,9 +263,9 @@ static void uart_shutdown(struct uart_st
+
+ /**
+ * uart_update_timeout - update per-port FIFO timeout.
+- * @port: uart_port structure describing the port.
++ * @port: uart_port structure describing the port
+ * @cflag: termios cflag value
+- * @quot: uart clock divisor quotient
++ * @baud: speed of the port
+ *
+ * Set the port FIFO timeout value. The @cflag value should
+ * reflect the actual hardware settings.
+@@ -1973,6 +1973,11 @@ uart_configure_port(struct uart_driver *
+ {
+ unsigned int flags;
+
++#ifdef CONFIG_KGDB
++ if (port->kgdb)
++ return;
++#endif
++
+ /*
+ * If there isn't a port here, don't do anything further.
+ */
+--- linux-2.6.0-test6/drivers/telephony/ixj.h 2003-06-22 12:04:44.000000000 -0700
++++ 25/drivers/telephony/ixj.h 2003-10-05 00:33:24.000000000 -0700
+@@ -42,6 +42,7 @@ static char ixj_h_rcsid[] = "$Id: ixj.h,
+
+ #define IXJ_VERSION 3031
+
++#include <linux/version.h>
+ #include <linux/types.h>
+
+ #include <linux/ixjuser.h>
+--- linux-2.6.0-test6/drivers/telephony/phonedev.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/telephony/phonedev.c 2003-10-05 00:33:24.000000000 -0700
+@@ -14,7 +14,6 @@
+ * phone_register_device now works with unit!=PHONE_UNIT_ANY
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/drivers/usb/core/inode.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/core/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -38,6 +38,7 @@
+ #include <linux/namei.h>
+ #include <linux/usbdevice_fs.h>
+ #include <linux/smp_lock.h>
++#include <linux/parser.h>
+ #include <asm/byteorder.h>
+
+ static struct super_operations usbfs_ops;
+@@ -62,86 +63,94 @@ static umode_t devmode = S_IWUSR | S_IRU
+ static umode_t busmode = S_IXUGO | S_IRUGO;
+ static umode_t listmode = S_IRUGO;
+
++enum {
++ Opt_devuid, Opt_devgid, Opt_devmode,
++ Opt_busuid, Opt_busgid, Opt_busmode,
++ Opt_listuid, Opt_listgid, Opt_listmode,
++ Opt_err,
++};
++
++static match_table_t tokens = {
++ {Opt_devuid, "devuid=%u"},
++ {Opt_devgid, "devgid=%u"},
++ {Opt_devmode, "devmode=%o"},
++ {Opt_busuid, "busuid=%u"},
++ {Opt_busgid, "busgid=%u"},
++ {Opt_busmode, "busmode=%o"},
++ {Opt_listuid, "listuid=%u"},
++ {Opt_listgid, "listgid=%u"},
++ {Opt_listmode, "listmode=%o"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(struct super_block *s, char *data)
+ {
+- char *curopt = NULL, *value;
++ char *p;
++ int option;
+
+- while ((curopt = strsep(&data, ",")) != NULL) {
+- if (!*curopt)
++ while ((p = strsep(&data, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(curopt, '=')) != NULL)
+- *value++ = 0;
+- if (!strcmp(curopt, "devuid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- devuid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "devgid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- devgid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "devmode")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "busuid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- busuid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "busgid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- busgid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "busmode")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "listuid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- listuid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- }
+- if (!strcmp(curopt, "listgid")) {
+- if (!value || !value[0])
+- return -EINVAL;
+- listgid = simple_strtoul(value, &value, 0);
+- if (*value)
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_devuid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ devuid = option;
++ break;
++ case Opt_devgid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ devgid = option;
++ break;
++ case Opt_devmode:
++ if (match_octal(&args[0], &option))
+ return -EINVAL;
+- }
+- if (!strcmp(curopt, "listmode")) {
+- if (!value || !value[0])
++ devmode = option & S_IRWXUGO;
++ break;
++ case Opt_busuid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ busuid = option;
++ break;
++ case Opt_busgid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ busgid = option;
++ break;
++ case Opt_busmode:
++ if (match_octal(&args[0], &option))
+ return -EINVAL;
+- listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+- if (*value)
++ busmode = option & S_IRWXUGO;
++ break;
++ case Opt_listuid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ listuid = option;
++ break;
++ case Opt_listgid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ listgid = option;
++ break;
++ case Opt_listmode:
++ if (match_octal(&args[0], &option))
+ return -EINVAL;
++ listmode = option & S_IRWXUGO;
++ break;
++ default:
++ err("usbfs: unrecognised mount option \"%s\" "
++ "or missing value\n", p);
++ return -EINVAL;
+ }
+ }
+
+ return 0;
+ }
+
+-
+-/* --------------------------------------------------------------------- */
+-
+ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t dev)
+ {
+ struct inode *inode = new_inode(sb);
+--- linux-2.6.0-test6/drivers/usb/host/uhci-debug.c 2003-07-02 14:53:16.000000000 -0700
++++ 25/drivers/usb/host/uhci-debug.c 2003-10-05 00:33:24.000000000 -0700
+@@ -99,82 +99,6 @@ static int uhci_show_td(struct uhci_td *
+ return out - buf;
+ }
+
+-static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+-{
+- char *out = buf;
+-
+- /* Try to make sure there's enough memory */
+- if (len < 80)
+- return 0;
+-
+- out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s\n",
+- port,
+- status,
+- (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+- (status & USBPORTSC_PR) ? "PortReset " : "",
+- (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+- (status & USBPORTSC_RD) ? "ResumeDetect " : "",
+- (status & USBPORTSC_PEC) ? "EnableChange " : "",
+- (status & USBPORTSC_PE) ? "PortEnabled " : "",
+- (status & USBPORTSC_CSC) ? "ConnectChange " : "",
+- (status & USBPORTSC_CCS) ? "PortConnected " : "");
+-
+- return out - buf;
+-}
+-
+-static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+-{
+- char *out = buf;
+- unsigned int io_addr = uhci->io_addr;
+- unsigned short usbcmd, usbstat, usbint, usbfrnum;
+- unsigned int flbaseadd;
+- unsigned char sof;
+- unsigned short portsc1, portsc2;
+-
+- /* Try to make sure there's enough memory */
+- if (len < 80 * 6)
+- return 0;
+-
+- usbcmd = inw(io_addr + 0);
+- usbstat = inw(io_addr + 2);
+- usbint = inw(io_addr + 4);
+- usbfrnum = inw(io_addr + 6);
+- flbaseadd = inl(io_addr + 8);
+- sof = inb(io_addr + 12);
+- portsc1 = inw(io_addr + 16);
+- portsc2 = inw(io_addr + 18);
+-
+- out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n",
+- usbcmd,
+- (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
+- (usbcmd & USBCMD_CF) ? "CF " : "",
+- (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
+- (usbcmd & USBCMD_FGR) ? "FGR " : "",
+- (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
+- (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
+- (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+- (usbcmd & USBCMD_RS) ? "RS " : "");
+-
+- out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n",
+- usbstat,
+- (usbstat & USBSTS_HCH) ? "HCHalted " : "",
+- (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
+- (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
+- (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
+- (usbstat & USBSTS_ERROR) ? "USBError " : "",
+- (usbstat & USBSTS_USBINT) ? "USBINT " : "");
+-
+- out += sprintf(out, " usbint = %04x\n", usbint);
+- out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
+- 0xfff & (4*(unsigned int)usbfrnum));
+- out += sprintf(out, " flbaseadd = %08x\n", flbaseadd);
+- out += sprintf(out, " sof = %02x\n", sof);
+- out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+- out += uhci_show_sc(2, portsc2, out, len - (out - buf));
+-
+- return out - buf;
+-}
+-
+ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+ {
+ char *out = buf;
+@@ -274,6 +198,13 @@ out:
+ return out - buf;
+ }
+
++#define show_frame_num() \
++ if (!shown) { \
++ shown = 1; \
++ out += sprintf(out, "- Frame %d\n", i); \
++ }
++
++#ifdef CONFIG_PROC_FS
+ static const char *qh_names[] = {
+ "skel_int128_qh", "skel_int64_qh",
+ "skel_int32_qh", "skel_int16_qh",
+@@ -283,18 +214,88 @@ static const char *qh_names[] = {
+ "skel_bulk_qh", "skel_term_qh"
+ };
+
+-#define show_frame_num() \
+- if (!shown) { \
+- shown = 1; \
+- out += sprintf(out, "- Frame %d\n", i); \
+- }
+-
+ #define show_qh_name() \
+ if (!shown) { \
+ shown = 1; \
+ out += sprintf(out, "- %s\n", qh_names[i]); \
+ }
+
++static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
++{
++ char *out = buf;
++
++ /* Try to make sure there's enough memory */
++ if (len < 80)
++ return 0;
++
++ out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s\n",
++ port,
++ status,
++ (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
++ (status & USBPORTSC_PR) ? "PortReset " : "",
++ (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
++ (status & USBPORTSC_RD) ? "ResumeDetect " : "",
++ (status & USBPORTSC_PEC) ? "EnableChange " : "",
++ (status & USBPORTSC_PE) ? "PortEnabled " : "",
++ (status & USBPORTSC_CSC) ? "ConnectChange " : "",
++ (status & USBPORTSC_CCS) ? "PortConnected " : "");
++
++ return out - buf;
++}
++
++static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
++{
++ char *out = buf;
++ unsigned int io_addr = uhci->io_addr;
++ unsigned short usbcmd, usbstat, usbint, usbfrnum;
++ unsigned int flbaseadd;
++ unsigned char sof;
++ unsigned short portsc1, portsc2;
++
++ /* Try to make sure there's enough memory */
++ if (len < 80 * 6)
++ return 0;
++
++ usbcmd = inw(io_addr + 0);
++ usbstat = inw(io_addr + 2);
++ usbint = inw(io_addr + 4);
++ usbfrnum = inw(io_addr + 6);
++ flbaseadd = inl(io_addr + 8);
++ sof = inb(io_addr + 12);
++ portsc1 = inw(io_addr + 16);
++ portsc2 = inw(io_addr + 18);
++
++ out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n",
++ usbcmd,
++ (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
++ (usbcmd & USBCMD_CF) ? "CF " : "",
++ (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
++ (usbcmd & USBCMD_FGR) ? "FGR " : "",
++ (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
++ (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
++ (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
++ (usbcmd & USBCMD_RS) ? "RS " : "");
++
++ out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n",
++ usbstat,
++ (usbstat & USBSTS_HCH) ? "HCHalted " : "",
++ (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
++ (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
++ (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
++ (usbstat & USBSTS_ERROR) ? "USBError " : "",
++ (usbstat & USBSTS_USBINT) ? "USBINT " : "");
++
++ out += sprintf(out, " usbint = %04x\n", usbint);
++ out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
++ 0xfff & (4*(unsigned int)usbfrnum));
++ out += sprintf(out, " flbaseadd = %08x\n", flbaseadd);
++ out += sprintf(out, " sof = %02x\n", sof);
++ out += uhci_show_sc(1, portsc1, out, len - (out - buf));
++ out += uhci_show_sc(2, portsc2, out, len - (out - buf));
++
++ return out - buf;
++}
++
+ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
+ {
+ struct list_head *tmp;
+@@ -512,7 +513,6 @@ static int uhci_sprint_schedule(struct u
+ return out - buf;
+ }
+
+-#ifdef CONFIG_PROC_FS
+ #define MAX_OUTPUT (64 * 1024)
+
+ static struct proc_dir_entry *uhci_proc_root = NULL;
+--- linux-2.6.0-test6/drivers/usb/host/uhci-hcd.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/usb/host/uhci-hcd.c 2003-10-05 00:33:24.000000000 -0700
+@@ -2185,8 +2185,8 @@ static int uhci_reset(struct usb_hcd *hc
+ /* Maybe kick BIOS off this hardware. Then reset, so we won't get
+ * interrupts from any previous setup.
+ */
+- pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
+ reset_hc(uhci);
++ pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
+ return 0;
+ }
+
+--- linux-2.6.0-test6/drivers/usb/input/Kconfig 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/usb/input/Kconfig 2003-10-05 00:33:24.000000000 -0700
+@@ -186,8 +186,5 @@ config USB_XPAD
+ For information about how to connect the X-Box pad to USB, see
+ Documentation/input/xpad.txt.
+
+- This driver is also available as a module ( = code which can be
+- inserted in and removed from the running kernel whenever you want).
+- The module will be called xpad. If you want to compile it as a
+- module, say M here and read <file:Documentation/modules.txt>.
+-
++ To compile this driver as a module, choose M here: the
++ module will be called xpad.
+--- linux-2.6.0-test6/drivers/usb/misc/brlvger.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/misc/brlvger.c 2003-10-05 00:33:24.000000000 -0700
+@@ -591,14 +591,14 @@ brlvger_write(struct file *file, const c
+ int firstpart = 6 - off;
+
+ #ifdef WRITE_DEBUG
+- dbg3("off: %d, rs: %d, count: %d, firstpart: %d",
++ dbg3("off: %lld, rs: %d, count: %d, firstpart: %d",
+ off, rs, count, firstpart);
+ #endif
+
+ firstpart = (firstpart < count) ? firstpart : count;
+
+ #ifdef WRITE_DEBUG
+- dbg3("off: %d", off);
++ dbg3("off: %lld", off);
+ dbg3("firstpart: %d", firstpart);
+ #endif
+
+@@ -618,7 +618,7 @@ brlvger_write(struct file *file, const c
+ off +=2;
+
+ #ifdef WRITE_DEBUG
+- dbg3("off: %d, rs: %d, count: %d, firstpart: %d, "
++ dbg3("off: %lld, rs: %d, count: %d, firstpart: %d, "
+ "written: %d", off, rs, count, firstpart, written);
+ #endif
+ }
+--- linux-2.6.0-test6/drivers/usb/misc/speedtch.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/usb/misc/speedtch.c 2003-10-05 00:33:24.000000000 -0700
+@@ -189,8 +189,7 @@ struct udsl_vcc_data {
+ struct atm_vcc *vcc;
+
+ /* raw cell reassembly */
+- struct sk_buff *skb;
+- unsigned int max_pdu;
++ struct sk_buff *sarb;
+ };
+
+ /* send */
+@@ -314,12 +313,10 @@ static void udsl_extract_cells (struct u
+ {
+ struct udsl_vcc_data *cached_vcc = NULL;
+ struct atm_vcc *vcc;
+- struct sk_buff *skb;
++ struct sk_buff *sarb;
+ struct udsl_vcc_data *vcc_data;
+ int cached_vci = 0;
+ unsigned int i;
+- unsigned int length;
+- unsigned int pdu_length;
+ int pti;
+ int vci;
+ short cached_vpi = 0;
+@@ -344,74 +341,73 @@ static void udsl_extract_cells (struct u
+ }
+
+ vcc = vcc_data->vcc;
++ sarb = vcc_data->sarb;
+
+- if (!vcc_data->skb && !(vcc_data->skb = dev_alloc_skb (vcc_data->max_pdu))) {
+- dbg ("udsl_extract_cells: no memory for skb (vcc: 0x%p)!", vcc);
+- if (pti)
+- atomic_inc (&vcc->stats->rx_err);
+- continue;
+- }
+-
+- skb = vcc_data->skb;
+-
+- if (skb->len + ATM_CELL_PAYLOAD > vcc_data->max_pdu) {
+- dbg ("udsl_extract_cells: buffer overrun (max_pdu: %u, skb->len %u, vcc: 0x%p)", vcc_data->max_pdu, skb->len, vcc);
++ if (sarb->tail + ATM_CELL_PAYLOAD > sarb->end) {
++ dbg ("udsl_extract_cells: buffer overrun (sarb->len %u, vcc: 0x%p)!", sarb->len, vcc);
+ /* discard cells already received */
+- skb_trim (skb, 0);
+- DEBUG_ON (vcc_data->max_pdu < ATM_CELL_PAYLOAD);
++ skb_trim (sarb, 0);
+ }
+
+- memcpy (skb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
+- __skb_put (skb, ATM_CELL_PAYLOAD);
++ memcpy (sarb->tail, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
++ __skb_put (sarb, ATM_CELL_PAYLOAD);
+
+ if (pti) {
++ struct sk_buff *skb;
++ unsigned int length;
++ unsigned int pdu_length;
++
+ length = (source [ATM_CELL_SIZE - 6] << 8) + source [ATM_CELL_SIZE - 5];
+
+ /* guard against overflow */
+ if (length > ATM_MAX_AAL5_PDU) {
+- dbg ("udsl_extract_cells: bogus length %u (vcc: 0x%p)", length, vcc);
+- goto drop;
++ dbg ("udsl_extract_cells: bogus length %u (vcc: 0x%p)!", length, vcc);
++ atomic_inc (&vcc->stats->rx_err);
++ goto out;
+ }
+
+ pdu_length = UDSL_NUM_CELLS (length) * ATM_CELL_PAYLOAD;
+
+- if (skb->len < pdu_length) {
+- dbg ("udsl_extract_cells: bogus pdu_length %u (skb->len: %u, vcc: 0x%p)", pdu_length, skb->len, vcc);
+- goto drop;
++ if (sarb->len < pdu_length) {
++ dbg ("udsl_extract_cells: bogus pdu_length %u (sarb->len: %u, vcc: 0x%p)!", pdu_length, sarb->len, vcc);
++ atomic_inc (&vcc->stats->rx_err);
++ goto out;
+ }
+
+- if (crc32_be (~0, skb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
+- dbg ("udsl_extract_cells: packet failed crc check (vcc: 0x%p)", vcc);
+- goto drop;
++ if (crc32_be (~0, sarb->tail - pdu_length, pdu_length) != 0xc704dd7b) {
++ dbg ("udsl_extract_cells: packet failed crc check (vcc: 0x%p)!", vcc);
++ atomic_inc (&vcc->stats->rx_err);
++ goto out;
+ }
+
+- if (!atm_charge (vcc, skb->truesize)) {
+- dbg ("udsl_extract_cells: failed atm_charge (skb->truesize: %u)", skb->truesize);
+- goto drop_no_stats; /* atm_charge increments rx_drop */
+- }
++ vdbg ("udsl_extract_cells: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", length, pdu_length, vcc);
+
+- /* now that we are sure to send the skb, it is ok to change skb->data */
+- if (skb->len > pdu_length)
+- skb_pull (skb, skb->len - pdu_length); /* discard initial junk */
++ if (!(skb = dev_alloc_skb (length))) {
++ dbg ("udsl_extract_cells: no memory for skb (length: %u)!", length);
++ atomic_inc (&vcc->stats->rx_drop);
++ goto out;
++ }
+
+- skb_trim (skb, length); /* drop zero padding and trailer */
++ vdbg ("udsl_extract_cells: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", skb, skb->truesize);
+
+- atomic_inc (&vcc->stats->rx);
++ if (!atm_charge (vcc, skb->truesize)) {
++ dbg ("udsl_extract_cells: failed atm_charge (skb->truesize: %u)!", skb->truesize);
++ dev_kfree_skb (skb);
++ goto out; /* atm_charge increments rx_drop */
++ }
+
+- PACKETDEBUG (skb->data, skb->len);
++ memcpy (skb->data, sarb->tail - pdu_length, length);
++ __skb_put (skb, length);
+
+ vdbg ("udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u", skb, skb->len, skb->truesize);
+
+- vcc->push (vcc, skb);
+-
+- vcc_data->skb = NULL;
++ PACKETDEBUG (skb->data, skb->len);
+
+- continue;
++ vcc->push (vcc, skb);
+
+-drop:
+- atomic_inc (&vcc->stats->rx_err);
+-drop_no_stats:
+- skb_trim (skb, 0);
++ atomic_inc (&vcc->stats->rx);
++out:
++ skb_trim (sarb, 0);
+ }
+ }
+ }
+@@ -871,6 +867,7 @@ static int udsl_atm_open (struct atm_vcc
+ {
+ struct udsl_instance_data *instance = vcc->dev->dev_data;
+ struct udsl_vcc_data *new;
++ unsigned int max_pdu;
+
+ dbg ("udsl_atm_open: vpi %hd, vci %d", vpi, vci);
+
+@@ -883,8 +880,10 @@ static int udsl_atm_open (struct atm_vcc
+ return -EINVAL;
+
+ /* only support AAL5 */
+- if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU))
++ if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) {
++ dbg ("udsl_atm_open: unsupported ATM type %d!", vcc->qos.aal);
+ return -EINVAL;
++ }
+
+ if (!instance->firmware_loaded) {
+ dbg ("udsl_atm_open: firmware not loaded!");
+@@ -894,11 +893,13 @@ static int udsl_atm_open (struct atm_vcc
+ down (&instance->serialize); /* vs self, udsl_atm_close */
+
+ if (udsl_find_vcc (instance, vpi, vci)) {
++ dbg ("udsl_atm_open: %hd/%d already in use!", vpi, vci);
+ up (&instance->serialize);
+ return -EADDRINUSE;
+ }
+
+ if (!(new = kmalloc (sizeof (struct udsl_vcc_data), GFP_KERNEL))) {
++ dbg ("udsl_atm_open: no memory for vcc_data!");
+ up (&instance->serialize);
+ return -ENOMEM;
+ }
+@@ -907,7 +908,15 @@ static int udsl_atm_open (struct atm_vcc
+ new->vcc = vcc;
+ new->vpi = vpi;
+ new->vci = vci;
+- new->max_pdu = max (1, UDSL_NUM_CELLS (vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD;
++
++ /* udsl_extract_cells requires at least one cell */
++ max_pdu = max (1, UDSL_NUM_CELLS (vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD;
++ if (!(new->sarb = alloc_skb (max_pdu, GFP_KERNEL))) {
++ dbg ("udsl_atm_open: no memory for SAR buffer!");
++ kfree (new);
++ up (&instance->serialize);
++ return -ENOMEM;
++ }
+
+ vcc->dev_data = new;
+ vcc->vpi = vpi;
+@@ -925,7 +934,7 @@ static int udsl_atm_open (struct atm_vcc
+
+ tasklet_schedule (&instance->receive_tasklet);
+
+- dbg ("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, new->max_pdu);
++ dbg ("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu);
+
+ return 0;
+ }
+@@ -952,9 +961,8 @@ static void udsl_atm_close (struct atm_v
+ list_del (&vcc_data->list);
+ tasklet_enable (&instance->receive_tasklet);
+
+- if (vcc_data->skb)
+- dev_kfree_skb (vcc_data->skb);
+- vcc_data->skb = NULL;
++ kfree_skb (vcc_data->sarb);
++ vcc_data->sarb = NULL;
+
+ kfree (vcc_data);
+ vcc->dev_data = NULL;
+@@ -1216,7 +1224,7 @@ static void udsl_usb_disconnect (struct
+
+ for (i = 0; i < num_rcv_urbs; i++)
+ if ((result = usb_unlink_urb (instance->receivers [i].urb)) < 0)
+- dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d", i, result);
++ dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d!", i, result);
+
+ /* wait for completion handlers to finish */
+ do {
+@@ -1252,7 +1260,7 @@ static void udsl_usb_disconnect (struct
+
+ for (i = 0; i < num_snd_urbs; i++)
+ if ((result = usb_unlink_urb (instance->senders [i].urb)) < 0)
+- dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d", i, result);
++ dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d!", i, result);
+
+ /* wait for completion handlers to finish */
+ do {
+@@ -1298,11 +1306,9 @@ static void udsl_usb_disconnect (struct
+
+ static int __init udsl_usb_init (void)
+ {
+- struct sk_buff *skb; /* dummy for sizeof */
+-
+ dbg ("udsl_usb_init: driver version " DRIVER_VERSION);
+
+- if (sizeof (struct udsl_control) > sizeof (skb->cb)) {
++ if (sizeof (struct udsl_control) > sizeof (((struct sk_buff *)0)->cb)) {
+ printk (KERN_ERR __FILE__ ": unusable with this kernel!\n");
+ return -EIO;
+ }
+--- linux-2.6.0-test6/drivers/usb/serial/keyspan.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/serial/keyspan.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,6 +28,9 @@
+
+ Change History
+
++ 2003sep04 LPM (Keyspan) add support for new single port product USA19HS.
++ Improve setup message handling for all devices.
++
+ Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <keyspan@jsl.com>)
+ Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4)
+ Linux source tree. The Linux tree lacked support for the 49WLC and
+@@ -172,6 +175,7 @@ struct keyspan_port_private {
+ int baud;
+ int old_baud;
+ unsigned int cflag;
++ unsigned int old_cflag;
+ enum {flow_none, flow_cts, flow_xon} flow_control;
+ int rts_state; /* Handshaking pins (outputs) */
+ int dtr_state;
+@@ -187,11 +191,12 @@ struct keyspan_port_private {
+
+
+ /* Include Keyspan message headers. All current Keyspan Adapters
+- make use of one of three message formats which are referred
+- to as USA-26, USA-28 and USA-49 by Keyspan and within this driver. */
++ make use of one of four message formats which are referred
++ to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
+ #include "keyspan_usa26msg.h"
+ #include "keyspan_usa28msg.h"
+ #include "keyspan_usa49msg.h"
++#include "keyspan_usa90msg.h"
+
+
+ /* Functions used by new usb-serial code. */
+@@ -346,8 +351,8 @@ static int keyspan_ioctl(struct usb_seri
+ return -ENOIOCTLCMD;
+ }
+
+- /* Write function is generic for the three protocols used
+- with only a minor change for usa49 required */
++ /* Write function is similar for the four protocols used
++ with only a minor change for usa90 (usa19hs) required */
+ static int keyspan_write(struct usb_serial_port *port, int from_user,
+ const unsigned char *buf, int count)
+ {
+@@ -356,18 +361,26 @@ static int keyspan_write(struct usb_seri
+ int flip;
+ int left, todo;
+ struct urb *this_urb;
+- int err;
++ int err, maxDataLen, dataOffset;
+
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
+
++ if (d_details->msg_format == msg_usa90) {
++ maxDataLen = 64;
++ dataOffset = 0;
++ } else {
++ maxDataLen = 63;
++ dataOffset = 1;
++ }
++
+ dbg("%s - for port %d (%d chars), flip=%d",
+ __FUNCTION__, port->number, count, p_priv->out_flip);
+
+ for (left = count; left > 0; left -= todo) {
+ todo = left;
+- if (todo > 63)
+- todo = 63;
++ if (todo > maxDataLen)
++ todo = maxDataLen;
+
+ flip = p_priv->out_flip;
+
+@@ -390,20 +403,20 @@ static int keyspan_write(struct usb_seri
+ break;
+ }
+
+- /* First byte in buffer is "last flag" - unused so
++ /* First byte in buffer is "last flag" (except for usa19hx) - unused so
+ for now so set to zero */
+ ((char *)this_urb->transfer_buffer)[0] = 0;
+
+ if (from_user) {
+- if (copy_from_user(this_urb->transfer_buffer + 1, buf, todo))
++ if (copy_from_user(this_urb->transfer_buffer + dataOffset, buf, todo))
+ return -EFAULT;
+ } else {
+- memcpy (this_urb->transfer_buffer + 1, buf, todo);
++ memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
+ }
+ buf += todo;
+
+ /* send the data out the bulk port */
+- this_urb->transfer_buffer_length = todo + 1;
++ this_urb->transfer_buffer_length = todo + dataOffset;
+
+ this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ this_urb->dev = port->serial->dev;
+@@ -443,9 +456,12 @@ static void usa26_indat_callback(struct
+ if (urb->actual_length) {
+ /* 0x80 bit is error flag */
+ if ((data[0] & 0x80) == 0) {
+- /* no error on any byte */
++ /* no errors on individual bytes, only possible overrun err*/
++ if (data[0] & RXERROR_OVERRUN)
++ err = TTY_OVERRUN;
++ else err = 0;
+ for (i = 1; i < urb->actual_length ; ++i) {
+- tty_insert_flip_char(tty, data[i], 0);
++ tty_insert_flip_char(tty, data[i], err);
+ }
+ } else {
+ /* some bytes had errors, every byte has status */
+@@ -474,7 +490,7 @@ static void usa26_indat_callback(struct
+ return;
+ }
+
+- /* Outdat handling is common for usa26, usa28 and usa49 messages */
++ /* Outdat handling is common for all devices */
+ static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs)
+ {
+ struct usb_serial_port *port;
+@@ -577,7 +593,7 @@ static void usa26_glocont_callback(struc
+ }
+
+
+-static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
++static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
+ {
+ int i, err;
+ struct usb_serial_port *port;
+@@ -861,29 +877,172 @@ static void usa49_outcont_callback(struc
+ dbg ("%s", __FUNCTION__);
+ }
+
++static void usa90_indat_callback(struct urb *urb, struct pt_regs *regs)
++{
++ int i, err;
++ int endpoint;
++ struct usb_serial_port *port;
++ struct keyspan_port_private *p_priv;
++ struct tty_struct *tty;
++ unsigned char *data = urb->transfer_buffer;
++
++ dbg ("%s", __FUNCTION__);
++
++ endpoint = usb_pipeendpoint(urb->pipe);
++
++
++ if (urb->status) {
++ dbg("%s - nonzero status: %x on endpoint %d.",
++ __FUNCTION__, urb->status, endpoint);
++ return;
++ }
++
++ port = (struct usb_serial_port *) urb->context;
++ p_priv = usb_get_serial_port_data(port);
++
++ tty = port->tty;
++ if (urb->actual_length) {
++
++ /* if current mode is DMA, looks like usa28 format
++ otherwise looks like usa26 data format */
++
++ if (p_priv->baud > 57600) {
++ for (i = 0; i < urb->actual_length ; ++i)
++ tty_insert_flip_char(tty, data[i], 0);
++ }
++ else {
++
++ /* 0x80 bit is error flag */
++ if ((data[0] & 0x80) == 0) {
++ /* no errors on individual bytes, only possible overrun err*/
++ if (data[0] & RXERROR_OVERRUN)
++ err = TTY_OVERRUN;
++ else err = 0;
++ for (i = 1; i < urb->actual_length ; ++i)
++ tty_insert_flip_char(tty, data[i], err);
++
++ }
++ else {
++ /* some bytes had errors, every byte has status */
++ dbg("%s - RX error!!!!", __FUNCTION__);
++ for (i = 0; i + 1 < urb->actual_length; i += 2) {
++ int stat = data[i], flag = 0;
++ if (stat & RXERROR_OVERRUN)
++ flag |= TTY_OVERRUN;
++ if (stat & RXERROR_FRAMING)
++ flag |= TTY_FRAME;
++ if (stat & RXERROR_PARITY)
++ flag |= TTY_PARITY;
++ /* XXX should handle break (0x10) */
++ tty_insert_flip_char(tty, data[i+1], flag);
++ }
++ }
++ }
++ tty_flip_buffer_push(tty);
++ }
++
++ /* Resubmit urb so we continue receiving */
++ urb->dev = port->serial->dev;
++ if (port->open_count)
++ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
++ dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ }
++ return;
++}
++
++
++static void usa90_instat_callback(struct urb *urb, struct pt_regs *regs)
++{
++ unsigned char *data = urb->transfer_buffer;
++ struct keyspan_usa90_portStatusMessage *msg;
++ struct usb_serial *serial;
++ struct usb_serial_port *port;
++ struct keyspan_port_private *p_priv;
++ int old_dcd_state, err;
++
++ serial = (struct usb_serial *) urb->context;
++
++ if (urb->status) {
++ dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
++ return;
++ }
++ if (urb->actual_length < 14) {
++ dbg("%s - %d byte report??", __FUNCTION__, urb->actual_length);
++ goto exit;
++ }
++
++ msg = (struct keyspan_usa90_portStatusMessage *)data;
++
++ /* Now do something useful with the data */
++
++ port = serial->port[0];
++ p_priv = usb_get_serial_port_data(port);
++
++ /* Update handshaking pin state information */
++ old_dcd_state = p_priv->dcd_state;
++ p_priv->cts_state = ((msg->cts) ? 1 : 0);
++ p_priv->dsr_state = ((msg->dsr) ? 1 : 0);
++ p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
++ p_priv->ri_state = ((msg->ri) ? 1 : 0);
++
++ if (port->tty && !C_CLOCAL(port->tty)
++ && old_dcd_state != p_priv->dcd_state) {
++ if (old_dcd_state)
++ tty_hangup(port->tty);
++ /* else */
++ /* wake_up_interruptible(&p_priv->open_wait); */
++ }
++
++ /* Resubmit urb so we continue receiving */
++ urb->dev = serial->dev;
++ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
++ dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
++ }
++exit:
++ ;
++}
++
++static void usa90_outcont_callback(struct urb *urb, struct pt_regs *regs)
++{
++ struct usb_serial_port *port;
++ struct keyspan_port_private *p_priv;
++
++ port = (struct usb_serial_port *) urb->context;
++ p_priv = usb_get_serial_port_data(port);
+
++ if (p_priv->resend_cont) {
++ dbg ("%s - sending setup", __FUNCTION__);
++ keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
++ }
++}
+
+ static int keyspan_write_room (struct usb_serial_port *port)
+ {
+ struct keyspan_port_private *p_priv;
+ const struct keyspan_device_details *d_details;
+ int flip;
++ int data_len;
+ struct urb *this_urb;
+
+ dbg("%s", __FUNCTION__);
+ p_priv = usb_get_serial_port_data(port);
+ d_details = p_priv->device_details;
+
++ if (d_details->msg_format == msg_usa90)
++ data_len = 64;
++ else
++ data_len = 63;
++
+ flip = p_priv->out_flip;
+
+ /* Check both endpoints to see if any are available. */
+ if ((this_urb = p_priv->out_urbs[flip]) != 0) {
+ if (this_urb->status != -EINPROGRESS)
+- return (63);
++ return (data_len);
+ flip = (flip + 1) & d_details->outdat_endp_flip;
+ if ((this_urb = p_priv->out_urbs[flip]) != 0)
+ if (this_urb->status != -EINPROGRESS)
+- return (63);
++ return (data_len);
+ }
+ return (0);
+ }
+@@ -902,17 +1061,24 @@ static int keyspan_open (struct usb_seri
+ struct usb_serial *serial = port->serial;
+ const struct keyspan_device_details *d_details;
+ int i, err;
++ int baud_rate, device_port;
+ struct urb *urb;
++ unsigned int cflag;
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+- d_details = s_priv->device_details;
++ d_details = p_priv->device_details;
+
+ dbg("%s - port%d.", __FUNCTION__, port->number);
+
+ /* Set some sane defaults */
+ p_priv->rts_state = 1;
+ p_priv->dtr_state = 1;
++ p_priv->baud = 9600;
++
++ /* force baud and lcr to be set on open */
++ p_priv->old_baud = 0;
++ p_priv->old_cflag = 0;
+
+ p_priv->out_flip = 0;
+ p_priv->in_flip = 0;
+@@ -922,7 +1088,10 @@ static int keyspan_open (struct usb_seri
+ if ((urb = p_priv->in_urbs[i]) == NULL)
+ continue;
+ urb->dev = serial->dev;
+- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0);
++
++ /* make sure endpoint data toggle is synchronized with the device */
++
++ usb_clear_halt(urb->dev, urb->pipe);
+
+ if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ dbg("%s - submit urb %d failed (%d)", __FUNCTION__, i, err);
+@@ -937,12 +1106,29 @@ static int keyspan_open (struct usb_seri
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ }
+
+- // if the device is a USA49x, determine whether it is an W or WLC model
+- // and set the baud clock accordingly
++ /* get the terminal config for the setup message now so we don't
++ * need to send 2 of them */
++
++ cflag = port->tty->termios->c_cflag;
++ device_port = port->number - port->serial->minor;
++
++ /* Baud rate calculation takes baud rate as an integer
++ so other rates can be generated if desired. */
++ baud_rate = tty_get_baud_rate(port->tty);
++ /* If no match or invalid, leave as default */
++ if (baud_rate >= 0
++ && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
++ NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
++ p_priv->baud = baud_rate;
++ }
++
++ /* set CTS/RTS handshake etc. */
++ p_priv->cflag = cflag;
++ p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
+
+ keyspan_send_setup(port, 1);
+ //mdelay(100);
+- keyspan_set_termios(port, NULL);
++ //keyspan_set_termios(port, NULL);
+
+ return (0);
+ }
+@@ -977,7 +1163,7 @@ static void keyspan_close(struct usb_ser
+ keyspan_send_setup(port, 2);
+ /* pilot-xfer seems to work best with this delay */
+ mdelay(100);
+- keyspan_set_termios(port, NULL);
++ // keyspan_set_termios(port, NULL);
+ }
+
+ /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
+@@ -1172,6 +1358,14 @@ static struct callbacks {
+ .outdat_callback = usa2x_outdat_callback,
+ .inack_callback = usa49_inack_callback,
+ .outcont_callback = usa49_outcont_callback,
++ }, {
++ /* msg_usa90 callbacks */
++ .instat_callback = usa90_instat_callback,
++ .glocont_callback = usa28_glocont_callback,
++ .indat_callback = usa90_indat_callback,
++ .outdat_callback = usa2x_outdat_callback,
++ .inack_callback = usa28_inack_callback,
++ .outcont_callback = usa90_outcont_callback,
+ }
+ };
+
+@@ -1295,6 +1489,41 @@ static int keyspan_usa19_calc_baud(u32 b
+ return (KEYSPAN_BAUD_RATE_OK);
+ }
+
++/* usa19hs function doesn't require prescaler */
++static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
++ u8 *rate_low, u8 *prescaler, int portnum)
++{
++ u32 b16, /* baud rate times 16 (actual rate used internally) */
++ div; /* divisor */
++
++ dbg ("%s - %d.", __FUNCTION__, baud_rate);
++
++ /* prevent divide by zero... */
++ if( (b16 = (baud_rate * 16L)) == 0)
++ return (KEYSPAN_INVALID_BAUD_RATE);
++
++
++
++ /* calculate the divisor */
++ if( (div = (baudclk / b16)) == 0)
++ return (KEYSPAN_INVALID_BAUD_RATE);
++
++ if(div > 0xffff)
++ return (KEYSPAN_INVALID_BAUD_RATE);
++
++ /* return the counter values if non-null */
++ if (rate_low)
++ *rate_low = (u8) (div & 0xff);
++
++ if (rate_hi)
++ *rate_hi = (u8) ((div >> 8) & 0xff);
++
++ if (rate_low && rate_hi)
++ dbg ("%s - %d %02x %02x.", __FUNCTION__, baud_rate, *rate_hi, *rate_low);
++
++ return (KEYSPAN_BAUD_RATE_OK);
++}
++
+ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
+ u8 *rate_low, u8 *prescaler, int portnum)
+ {
+@@ -1447,6 +1676,7 @@ static int keyspan_usa26_send_setup(stru
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+ /* dbg ("%s - already writing", __FUNCTION__); */
++ mdelay(5);
+ return(-1);
+ }
+
+@@ -1597,6 +1827,7 @@ static int keyspan_usa28_send_setup(stru
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+ dbg ("%s already writing", __FUNCTION__);
++ mdelay(5);
+ return(-1);
+ }
+
+@@ -1729,6 +1960,7 @@ static int keyspan_usa49_send_setup(stru
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+ /* dbg ("%s - already writing", __FUNCTION__); */
++ mdelay(5);
+ return(-1);
+ }
+
+@@ -1857,6 +2089,144 @@ static int keyspan_usa49_send_setup(stru
+ return (0);
+ }
+
++static int keyspan_usa90_send_setup(struct usb_serial *serial,
++ struct usb_serial_port *port,
++ int reset_port)
++{
++ struct keyspan_usa90_portControlMessage msg;
++ struct keyspan_serial_private *s_priv;
++ struct keyspan_port_private *p_priv;
++ const struct keyspan_device_details *d_details;
++ struct urb *this_urb;
++ int err;
++ u8 prescaler;
++
++ dbg ("%s", __FUNCTION__);
++
++ s_priv = usb_get_serial_data(serial);
++ p_priv = usb_get_serial_port_data(port);
++ d_details = s_priv->device_details;
++
++ /* only do something if we have a bulk out endpoint */
++ if ((this_urb = p_priv->outcont_urb) == NULL) {
++ dbg("%s - oops no urb.", __FUNCTION__);
++ return -1;
++ }
++
++ /* Save reset port val for resend.
++ Don't overwrite resend for open/close condition. */
++ if ((reset_port + 1) > p_priv->resend_cont)
++ p_priv->resend_cont = reset_port + 1;
++ if (this_urb->status == -EINPROGRESS) {
++ dbg ("%s already writing", __FUNCTION__);
++ mdelay(5);
++ return(-1);
++ }
++
++ memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
++
++ /* Only set baud rate if it's changed */
++ if (p_priv->old_baud != p_priv->baud) {
++ p_priv->old_baud = p_priv->baud;
++ msg.setClocking = 0x01;
++ if (d_details->calculate_baud_rate
++ (p_priv->baud, d_details->baudclk, &msg.baudHi,
++ &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
++ dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
++ p_priv->baud);
++ p_priv->baud = 9600;
++ d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk,
++ &msg.baudHi, &msg.baudLo, &prescaler, 0);
++ }
++ msg.setRxMode = 1;
++ msg.setTxMode = 1;
++ }
++
++ /* modes must always be correctly specified */
++ if (p_priv->baud > 57600)
++ {
++ msg.rxMode = RXMODE_DMA;
++ msg.txMode = TXMODE_DMA;
++ }
++ else
++ {
++ msg.rxMode = RXMODE_BYHAND;
++ msg.txMode = TXMODE_BYHAND;
++ }
++
++ msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
++ switch (p_priv->cflag & CSIZE) {
++ case CS5:
++ msg.lcr |= USA_DATABITS_5;
++ break;
++ case CS6:
++ msg.lcr |= USA_DATABITS_6;
++ break;
++ case CS7:
++ msg.lcr |= USA_DATABITS_7;
++ break;
++ case CS8:
++ msg.lcr |= USA_DATABITS_8;
++ break;
++ }
++ if (p_priv->cflag & PARENB) {
++ /* note USA_PARITY_NONE == 0 */
++ msg.lcr |= (p_priv->cflag & PARODD)?
++ USA_PARITY_ODD: USA_PARITY_EVEN;
++ }
++ if (p_priv->old_cflag != p_priv->cflag) {
++ p_priv->old_cflag = p_priv->cflag;
++ msg.setLcr = 0x01;
++ }
++
++ if (p_priv->flow_control == flow_cts)
++ msg.txFlowControl = TXFLOW_CTS;
++ msg.setTxFlowControl = 0x01;
++ msg.setRxFlowControl = 0x01;
++
++ msg.rxForwardingLength = 16;
++ msg.rxForwardingTimeout = 16;
++ msg.txAckSetting = 0;
++ msg.xonChar = 17;
++ msg.xoffChar = 19;
++
++ /* Opening port */
++ if (reset_port == 1) {
++ msg.portEnabled = 1;
++ msg.rxFlush = 1;
++ msg.txBreak = (p_priv->break_on);
++ }
++ /* Closing port */
++ else if (reset_port == 2) {
++ msg.portEnabled = 0;
++ }
++ /* Sending intermediate configs */
++ else {
++ if (port->open_count)
++ msg.portEnabled = 1;
++ msg.txBreak = (p_priv->break_on);
++ }
++
++ /* Do handshaking outputs */
++ msg.setRts = 0x01;
++ msg.rts = p_priv->rts_state;
++
++ msg.setDtr = 0x01;
++ msg.dtr = p_priv->dtr_state;
++
++ p_priv->resend_cont = 0;
++ memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
++
++ /* send the data out the device on control endpoint */
++ this_urb->transfer_buffer_length = sizeof(msg);
++
++ this_urb->dev = serial->dev;
++ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
++ dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
++ }
++ return (0);
++}
++
+ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
+ {
+ struct usb_serial *serial = port->serial;
+@@ -1878,9 +2248,13 @@ static void keyspan_send_setup(struct us
+ case msg_usa49:
+ keyspan_usa49_send_setup(serial, port, reset_port);
+ break;
++ case msg_usa90:
++ keyspan_usa90_send_setup(serial, port, reset_port);
++ break;
+ }
+ }
+
++
+ /* Gets called by the "real" driver (ie once firmware is loaded
+ and renumeration has taken place. */
+ static int keyspan_startup (struct usb_serial *serial)
+--- linux-2.6.0-test6/drivers/usb/serial/keyspan.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/usb/serial/keyspan.h 2003-10-05 00:33:24.000000000 -0700
+@@ -82,6 +82,10 @@ static int keyspan_usa28_calc_baud (u32
+ u8 *rate_hi, u8 *rate_low,
+ u8 *prescaler, int portnum);
+
++static int keyspan_usa19hs_calc_baud (u32 baud_rate, u32 baudclk,
++ u8 *rate_hi, u8 *rate_low,
++ u8 *prescaler, int portnum);
++
+ static int keyspan_usa28_send_setup (struct usb_serial *serial,
+ struct usb_serial_port *port,
+ int reset_port);
+@@ -92,6 +96,9 @@ static int keyspan_usa49_send_setup (st
+ struct usb_serial_port *port,
+ int reset_port);
+
++static int keyspan_usa90_send_setup (struct usb_serial *serial,
++ struct usb_serial_port *port,
++ int reset_port);
+
+ /* Struct used for firmware - increased size of data section
+ to allow Keyspan's 'C' firmware struct to be used unmodified */
+@@ -183,6 +190,7 @@ struct ezusb_hex_record {
+ #define KEYSPAN_USA18X_BAUDCLK (12000000L) /* a guess */
+ #define KEYSPAN_USA19_BAUDCLK (12000000L)
+ #define KEYSPAN_USA19W_BAUDCLK (24000000L)
++#define KEYSPAN_USA19HS_BAUDCLK (14769231L)
+ #define KEYSPAN_USA28_BAUDCLK (1843200L)
+ #define KEYSPAN_USA28X_BAUDCLK (12000000L)
+ #define KEYSPAN_USA49W_BAUDCLK (48000000L)
+@@ -215,6 +223,7 @@ struct ezusb_hex_record {
+ #define keyspan_usa18x_product_id 0x0112
+ #define keyspan_usa19_product_id 0x0107
+ #define keyspan_usa19qi_product_id 0x010c
++#define keyspan_usa19hs_product_id 0x0121
+ #define keyspan_mpr_product_id 0x011c
+ #define keyspan_usa19qw_product_id 0x0119
+ #define keyspan_usa19w_product_id 0x0108
+@@ -230,7 +239,7 @@ struct keyspan_device_details {
+ /* product ID value */
+ int product_id;
+
+- enum {msg_usa26, msg_usa28, msg_usa49} msg_format;
++ enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
+
+ /* Number of physical ports */
+ int num_ports;
+@@ -349,6 +358,22 @@ static const struct keyspan_device_detai
+ .baudclk = KEYSPAN_USA19W_BAUDCLK,
+ };
+
++static const struct keyspan_device_details usa19hs_device_details = {
++ product_id: keyspan_usa19hs_product_id,
++ msg_format: msg_usa90,
++ num_ports: 1,
++ indat_endp_flip: 0,
++ outdat_endp_flip: 0,
++ indat_endpoints: {0x81},
++ outdat_endpoints: {0x01},
++ inack_endpoints: {-1},
++ outcont_endpoints: {0x02},
++ instat_endpoint: 0x82,
++ glocont_endpoint: -1,
++ calculate_baud_rate: keyspan_usa19hs_calc_baud,
++ baudclk: KEYSPAN_USA19HS_BAUDCLK,
++};
++
+ static const struct keyspan_device_details usa28_device_details = {
+ .product_id = keyspan_usa28_product_id,
+ .msg_format = msg_usa28,
+@@ -437,6 +462,7 @@ static const struct keyspan_device_detai
+ &usa19qi_device_details,
+ &usa19qw_device_details,
+ &usa19w_device_details,
++ &usa19hs_device_details,
+ &usa28_device_details,
+ &usa28x_device_details,
+ &usa28xa_device_details,
+@@ -464,6 +490,7 @@ static struct usb_device_id keyspan_ids_
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
++ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19hs_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
+@@ -544,8 +571,8 @@ static struct usb_serial_device_type key
+ .short_name = "keyspan_1",
+ .id_table = keyspan_1port_ids,
+ .num_interrupt_in = NUM_DONT_CARE,
+- .num_bulk_in = 3,
+- .num_bulk_out = 4,
++ .num_bulk_in = NUM_DONT_CARE,
++ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+ .open = keyspan_open,
+ .close = keyspan_close,
+--- linux-2.6.0-test6/drivers/usb/serial/keyspan_usa26msg.h 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/serial/keyspan_usa26msg.h 2003-10-05 00:33:24.000000000 -0700
+@@ -4,7 +4,7 @@
+ Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved
+ This file is available under a BSD-style copyright
+
+- Keyspan USB Async Firmware to run on Anchor EZ-USB
++ Keyspan USB Async Message Formats for the USA28X
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+@@ -19,11 +19,7 @@
+
+ This file is available under a BSD-style copyright
+
+- 2. Redistributions in binary form must reproduce the above copyright
+- notice, this list of conditions and the following disclaimer in the
+- documentation and/or other materials provided with the distribution.
+-
+- 3. The name of InnoSys Incorporated may not be used to endorse or promote
++ 2. The name of InnoSys Incorporated may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+--- linux-2.6.0-test6/drivers/usb/serial/keyspan_usa28msg.h 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/serial/keyspan_usa28msg.h 2003-10-05 00:33:24.000000000 -0700
+@@ -4,7 +4,7 @@
+ Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved
+ This file is available under a BSD-style copyright
+
+- Keyspan USB Async Firmware to run on Anchor EZ-USB
++ Keyspan USB Async Message Formats for the USA26X
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+@@ -19,11 +19,7 @@
+
+ This file is available under a BSD-style copyright
+
+- 2. Redistributions in binary form must reproduce the above copyright
+- notice, this list of conditions and the following disclaimer in the
+- documentation and/or other materials provided with the distribution.
+-
+- 3. The name of InnoSys Incorporated may not be used to endorse or promote
++ 2. The name of InnoSys Incorporated may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+--- linux-2.6.0-test6/drivers/usb/serial/keyspan_usa49msg.h 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/usb/serial/keyspan_usa49msg.h 2003-10-05 00:33:24.000000000 -0700
+@@ -4,7 +4,7 @@
+ Copyright (C) 1998-2000 InnoSys Incorporated. All Rights Reserved
+ This file is available under a BSD-style copyright
+
+- Keyspan USB Async Firmware to run on Anchor EZ-USB
++ Keyspan USB Async Message Formats for the USA49W
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+@@ -19,11 +19,7 @@
+
+ This file is available under a BSD-style copyright
+
+- 2. Redistributions in binary form must reproduce the above copyright
+- notice, this list of conditions and the following disclaimer in the
+- documentation and/or other materials provided with the distribution.
+-
+- 3. The name of InnoSys Incorporated may not be used to endorse or promote
++ 2. The name of InnoSys Incorporated may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/usb/serial/keyspan_usa90msg.h 2003-10-05 00:33:24.000000000 -0700
+@@ -0,0 +1,198 @@
++/*
++ usa90msg.h
++
++ Copyright (c) 1998-2003 InnoSys Incorporated. All Rights Reserved
++ This file is available under a BSD-style copyright
++
++ Keyspan USB Async Message Formats for the USA19HS
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions are
++ met:
++
++ 1. Redistributions of source code must retain this licence text
++ without modification, this list of conditions, and the following
++ disclaimer. The following copyright notice must appear immediately at
++ the beginning of all source files:
++
++ Copyright (c) 1998-2003 InnoSys Incorporated. All Rights Reserved
++
++ This file is available under a BSD-style copyright
++
++ 2. The name of InnoSys Incorprated may not be used to endorse or promote
++ products derived from this software without specific prior written
++ permission.
++
++ THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR
++ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
++ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ SUCH DAMAGE.
++
++ Revisions:
++
++ 2003feb14 add setTxMode/txMode and cancelRxXoff to portControl
++ 2003mar21 change name of PARITY_0/1 to add MARK/SPACE
++*/
++
++#ifndef __USA90MSG__
++#define __USA90MSG__
++
++struct keyspan_usa90_portControlMessage
++{
++ /*
++ there are three types of "commands" sent in the control message:
++
++ 1. configuration changes which must be requested by setting
++ the corresponding "set" flag (and should only be requested
++ when necessary, to reduce overhead on the device):
++ */
++
++ u8 setClocking, // host requests baud rate be set
++ baudLo, // host does baud divisor calculation
++ baudHi, // host does baud divisor calculation
++
++ setLcr, // host requests lcr be set
++ lcr, // use PARITY, STOPBITS, DATABITS below
++
++ setRxMode, // set receive mode
++ rxMode, // RXMODE_DMA or RXMODE_BYHAND
++
++ setTxMode, // set transmit mode
++ txMode, // TXMODE_DMA or TXMODE_BYHAND
++
++ setTxFlowControl, // host requests tx flow control be set
++ txFlowControl , // use TX_FLOW... bits below
++ setRxFlowControl, // host requests rx flow control be set
++ rxFlowControl, // use RX_FLOW... bits below
++ sendXoff, // host requests XOFF transmitted immediately
++ sendXon, // host requests XON char transmitted
++ xonChar, // specified in current character format
++ xoffChar, // specified in current character format
++
++ sendChar, // host requests char transmitted immediately
++ txChar, // character to send
++
++ setRts, // host requests RTS output be set
++ rts, // 1=on, 0=off
++ setDtr, // host requests DTR output be set
++ dtr; // 1=on, 0=off
++
++
++ /*
++ 2. configuration data which is simply used as is
++ and must be specified correctly in every host message.
++ */
++
++ u8 rxForwardingLength, // forward when this number of chars available
++ rxForwardingTimeout, // (1-31 in ms)
++ txAckSetting; // 0=don't ack, 1=normal, 2-255 TBD...
++ /*
++ 3. Firmware states which cause actions if they change
++ and must be specified correctly in every host message.
++ */
++
++ u8 portEnabled, // 0=disabled, 1=enabled
++ txFlush, // 0=normal, 1=toss outbound data
++ txBreak, // 0=break off, 1=break on
++ loopbackMode; // 0=no loopback, 1=loopback enabled
++
++ /*
++ 4. commands which are flags only; these are processed in order
++ (so that, e.g., if rxFlush and rxForward flags are set, the
++ port will have no data to forward); any non-zero value
++ is respected
++ */
++
++ u8 rxFlush, // toss inbound data
++ rxForward, // forward all inbound data, NOW (as if fwdLen==1)
++ cancelRxXoff, // cancel any receive XOFF state (_txXoff)
++ returnStatus; // return current status NOW
++};
++
++// defines for bits in lcr
++#define USA_DATABITS_5 0x00
++#define USA_DATABITS_6 0x01
++#define USA_DATABITS_7 0x02
++#define USA_DATABITS_8 0x03
++#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes
++#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte
++#define STOPBITS_678_2 0x04 // 2 stop bits for 6-8 bit byte
++#define USA_PARITY_NONE 0x00
++#define USA_PARITY_ODD 0x08
++#define USA_PARITY_EVEN 0x18
++#define PARITY_MARK_1 0x28 // force parity MARK
++#define PARITY_SPACE_0 0x38 // force parity SPACE
++
++#define TXFLOW_CTS 0x04
++#define TXFLOW_DSR 0x08
++#define TXFLOW_XOFF 0x01
++#define TXFLOW_XOFF_ANY 0x02
++#define TXFLOW_XOFF_BITS (TXFLOW_XOFF | TXFLOW_XOFF_ANY)
++
++#define RXFLOW_XOFF 0x10
++#define RXFLOW_RTS 0x20
++#define RXFLOW_DTR 0x40
++#define RXFLOW_DSR_SENSITIVITY 0x80
++
++#define RXMODE_BYHAND 0x00
++#define RXMODE_DMA 0x02
++
++#define TXMODE_BYHAND 0x00
++#define TXMODE_DMA 0x02
++
++
++// all things called "StatusMessage" are sent on the status endpoint
++
++struct keyspan_usa90_portStatusMessage
++{
++ u8 msr, // reports the actual MSR register
++ cts, // reports CTS pin
++ dcd, // reports DCD pin
++ dsr, // reports DSR pin
++ ri, // reports RI pin
++ _txXoff, // port is in XOFF state (we received XOFF)
++ rxBreak, // reports break state
++ rxOverrun, // count of overrun errors (since last reported)
++ rxParity, // count of parity errors (since last reported)
++ rxFrame, // count of frame errors (since last reported)
++ portState, // PORTSTATE_xxx bits (useful for debugging)
++ messageAck, // message acknowledgement
++ charAck, // character acknowledgement
++ controlResponse; // (value = returnStatus) a control message has been processed
++};
++
++// bits in RX data message when STAT byte is included
++
++#define RXERROR_OVERRUN 0x02
++#define RXERROR_PARITY 0x04
++#define RXERROR_FRAMING 0x08
++#define RXERROR_BREAK 0x10
++
++#define PORTSTATE_ENABLED 0x80
++#define PORTSTATE_TXFLUSH 0x01
++#define PORTSTATE_TXBREAK 0x02
++#define PORTSTATE_LOOPBACK 0x04
++
++// MSR bits
++
++#define MSR_dCTS 0x01 // CTS has changed since last report
++#define MSR_dDSR 0x02
++#define MSR_dRI 0x04
++#define MSR_dDCD 0x08
++
++#define MSR_CTS 0x10 // current state of CTS
++#define MSR_DSR 0x20
++#define MSR_RI 0x40
++#define MSR_DCD 0x80
++
++// ie: the maximum length of an endpoint buffer
++#define MAX_DATA_LEN 64
++
++#endif
+--- linux-2.6.0-test6/drivers/usb/storage/freecom.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/drivers/usb/storage/freecom.c 2003-10-05 00:33:24.000000000 -0700
+@@ -101,7 +101,8 @@ struct freecom_status {
+ #define FCM_PACKET_IDE_READ 0xC0
+
+ /* All packets (except for status) are 64 bytes long. */
+-#define FCM_PACKET_LENGTH 64
++#define FCM_PACKET_LENGTH 64
++#define FCM_STATUS_PACKET_LENGTH 4
+
+ static int
+ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
+@@ -216,7 +217,7 @@ int freecom_transport(Scsi_Cmnd *srb, st
+ /* There are times we can optimize out this status read, but it
+ * doesn't hurt us to always do it now. */
+ result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
+- FCM_PACKET_LENGTH, &partial);
++ FCM_STATUS_PACKET_LENGTH, &partial);
+ US_DEBUGP("foo Status result %d %u\n", result, partial);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+@@ -256,10 +257,10 @@ int freecom_transport(Scsi_Cmnd *srb, st
+
+ /* get the data */
+ result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
+- FCM_PACKET_LENGTH, &partial);
++ FCM_STATUS_PACKET_LENGTH, &partial);
+
+ US_DEBUGP("bar Status result %d %u\n", result, partial);
+- if (result > USB_STOR_XFER_SHORT)
++ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUG(pdump ((void *) fst, partial));
+@@ -302,6 +303,9 @@ int freecom_transport(Scsi_Cmnd *srb, st
+
+ switch (us->srb->sc_data_direction) {
+ case SCSI_DATA_READ:
++ /* catch bogus "read 0 length" case */
++ if (!length)
++ break;
+ /* Make sure that the status indicates that the device
+ * wants data as well. */
+ if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
+@@ -331,6 +335,9 @@ int freecom_transport(Scsi_Cmnd *srb, st
+ break;
+
+ case SCSI_DATA_WRITE:
++ /* catch bogus "write 0 length" case */
++ if (!length)
++ break;
+ /* Make sure the status indicates that the device wants to
+ * send us data. */
+ /* !!IMPLEMENT!! */
+@@ -362,6 +369,7 @@ int freecom_transport(Scsi_Cmnd *srb, st
+ break;
+
+ default:
++ /* should never hit here -- filtered in usb.c */
+ US_DEBUGP ("freecom unimplemented direction: %d\n",
+ us->srb->sc_data_direction);
+ // Return fail, SCSI seems to handle this better.
+--- linux-2.6.0-test6/drivers/usb/storage/unusual_devs.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/usb/storage/unusual_devs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -394,6 +394,12 @@ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0
+ "Dimage F300",
+ US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+
++/* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
++UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001,
++ "Minolta",
++ "DIMAGE E223",
++ US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
++
+ UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100,
+ "Hagiwara",
+ "FlashGate SmartMedia",
+@@ -542,7 +548,7 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0x
+ * - They don't like the INQUIRY command. So we must handle this command
+ * of the SCSI layer ourselves.
+ */
+-UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
++UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x5009,
+ "Casio",
+ "QV DigitalCamera",
+ US_SC_8070, US_PR_CB, NULL,
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/drivers/video/asiliantfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -0,0 +1,619 @@
++/*
++ * drivers/video/asiliantfb.c
++ * frame buffer driver for Asiliant 69000 chip
++ * Copyright (C) 2001-2003 Saito.K & Jeanne
++ *
++ * from driver/video/chipsfb.c and,
++ *
++ * drivers/video/asiliantfb.c -- frame buffer device for
++ * Asiliant 69030 chip (formerly Intel, formerly Chips & Technologies)
++ * Author: apc@agelectronics.co.uk
++ * Copyright (C) 2000 AG Electronics
++ * Note: the data sheets don't seem to be available from Asiliant.
++ * They are available by searching developer.intel.com, but are not otherwise
++ * linked to.
++ *
++ * This driver should be portable with minimal effort to the 69000 display
++ * chip, and to the twin-display mode of the 69030.
++ * Contains code from Thomas Hhenleitner <th@visuelle-maschinen.de> (thanks)
++ *
++ * Derived from the CT65550 driver chipsfb.c:
++ * Copyright (C) 1998 Paul Mackerras
++ * ...which was derived from the Powermac "chips" driver:
++ * Copyright (C) 1997 Fabio Riccardi.
++ * And from the frame buffer device for Open Firmware-initialized devices:
++ * Copyright (C) 1997 Geert Uytterhoeven.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/pci.h>
++#include <asm/io.h>
++
++static struct fb_info asiliantfb_info;
++
++/* Built in clock of the 69030 */
++const unsigned Fref = 14318180;
++
++static u32 pseudo_palette[17];
++
++#define mmio_base (p->screen_base + 0x400000)
++
++#define mm_write_ind(num, val, ap, dp) do { \
++ writeb((num), mmio_base + (ap)); writeb((val), mmio_base + (dp)); \
++} while (0)
++
++static void mm_write_xr(struct fb_info *p, u8 reg, u8 data)
++{
++ mm_write_ind(reg, data, 0x7ac, 0x7ad);
++}
++#define write_xr(num, val) mm_write_xr(p, num, val)
++
++static void mm_write_fr(struct fb_info *p, u8 reg, u8 data)
++{
++ mm_write_ind(reg, data, 0x7a0, 0x7a1);
++}
++#define write_fr(num, val) mm_write_fr(p, num, val)
++
++static void mm_write_cr(struct fb_info *p, u8 reg, u8 data)
++{
++ mm_write_ind(reg, data, 0x7a8, 0x7a9);
++}
++#define write_cr(num, val) mm_write_cr(p, num, val)
++
++static void mm_write_gr(struct fb_info *p, u8 reg, u8 data)
++{
++ mm_write_ind(reg, data, 0x79c, 0x79d);
++}
++#define write_gr(num, val) mm_write_gr(p, num, val)
++
++static void mm_write_sr(struct fb_info *p, u8 reg, u8 data)
++{
++ mm_write_ind(reg, data, 0x788, 0x789);
++}
++#define write_sr(num, val) mm_write_sr(p, num, val)
++
++static void mm_write_ar(struct fb_info *p, u8 reg, u8 data)
++{
++ readb(mmio_base + 0x7b4);
++ mm_write_ind(reg, data, 0x780, 0x780);
++}
++#define write_ar(num, val) mm_write_ar(p, num, val)
++
++/*
++ * Exported functions
++ */
++int asiliantfb_init(void);
++
++static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
++static int asiliantfb_check_var(struct fb_var_screeninfo *var,
++ struct fb_info *info);
++static int asiliantfb_set_par(struct fb_info *info);
++static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++ u_int transp, struct fb_info *info);
++
++static struct fb_ops asiliantfb_ops = {
++ .owner = THIS_MODULE,
++ .fb_check_var = asiliantfb_check_var,
++ .fb_set_par = asiliantfb_set_par,
++ .fb_setcolreg = asiliantfb_setcolreg,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_cursor = soft_cursor,
++};
++
++/* Calculate the ratios for the dot clocks without using a single long long
++ * value */
++static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)
++{
++ unsigned pixclock = *ppixclock;
++ unsigned Ftarget = 1000000 * (1000000 / pixclock);
++ unsigned n;
++ unsigned best_error = 0xffffffff;
++ unsigned best_m = 0xffffffff,
++ best_n = 0xffffffff;
++ unsigned ratio;
++ unsigned remainder;
++ unsigned char divisor = 0;
++
++ /* Calculate the frequency required. This is hard enough. */
++ ratio = 1000000 / pixclock;
++ remainder = 1000000 % pixclock;
++ Ftarget = 1000000 * ratio + (1000000 * remainder) / pixclock;
++
++ while (Ftarget < 100000000) {
++ divisor += 0x10;
++ Ftarget <<= 1;
++ }
++
++ ratio = Ftarget / Fref;
++ remainder = Ftarget % Fref;
++
++ /* This expresses the constraint that 150kHz <= Fref/n <= 5Mhz,
++ * together with 3 <= n <= 257. */
++ for (n = 3; n <= 257; n++) {
++ unsigned m = n * ratio + (n * remainder) / Fref;
++
++ /* 3 <= m <= 257 */
++ if (m >= 3 && m <= 257) {
++ unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ?
++ ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
++ if (new_error < best_error) {
++ best_n = n;
++ best_m = m;
++ best_error = new_error;
++ }
++ }
++ /* But if VLD = 4, then 4m <= 1028 */
++ else if (m <= 1028) {
++ /* remember there are still only 8-bits of precision in m, so
++ * avoid over-optimistic error calculations */
++ unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ?
++ ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
++ if (new_error < best_error) {
++ best_n = n;
++ best_m = m;
++ best_error = new_error;
++ }
++ }
++ }
++ if (best_m > 257)
++ best_m >>= 2; /* divide m by 4, and leave VCO loop divide at 4 */
++ else
++ divisor |= 4; /* or set VCO loop divide to 1 */
++ *dclk2_m = best_m - 2;
++ *dclk2_n = best_n - 2;
++ *dclk2_div = divisor;
++ *ppixclock = pixclock;
++ return;
++}
++
++static void asiliant_set_timing(struct fb_info *p)
++{
++ unsigned hd = p->var.xres / 8;
++ unsigned hs = (p->var.xres + p->var.right_margin) / 8;
++ unsigned he = (p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
++ unsigned ht = (p->var.left_margin + p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
++ unsigned vd = p->var.yres;
++ unsigned vs = p->var.yres + p->var.lower_margin;
++ unsigned ve = p->var.yres + p->var.lower_margin + p->var.vsync_len;
++ unsigned vt = p->var.upper_margin + p->var.yres + p->var.lower_margin + p->var.vsync_len;
++ unsigned wd = (p->var.xres_virtual * ((p->var.bits_per_pixel+7)/8)) / 8;
++
++ if ((p->var.xres == 640) && (p->var.yres == 480) && (p->var.pixclock == 39722)) {
++ write_fr(0x01, 0x02); /* LCD */
++ } else {
++ write_fr(0x01, 0x01); /* CRT */
++ }
++
++ write_cr(0x11, (ve - 1) & 0x0f);
++ write_cr(0x00, (ht - 5) & 0xff);
++ write_cr(0x01, hd - 1);
++ write_cr(0x02, hd);
++ write_cr(0x03, ((ht - 1) & 0x1f) | 0x80);
++ write_cr(0x04, hs);
++ write_cr(0x05, (((ht - 1) & 0x20) <<2) | (he & 0x1f));
++ write_cr(0x3c, (ht - 1) & 0xc0);
++ write_cr(0x06, (vt - 2) & 0xff);
++ write_cr(0x30, (vt - 2) >> 8);
++ write_cr(0x07, 0x00);
++ write_cr(0x08, 0x00);
++ write_cr(0x09, 0x00);
++ write_cr(0x10, (vs - 1) & 0xff);
++ write_cr(0x32, ((vs - 1) >> 8) & 0xf);
++ write_cr(0x11, ((ve - 1) & 0x0f) | 0x80);
++ write_cr(0x12, (vd - 1) & 0xff);
++ write_cr(0x31, ((vd - 1) & 0xf00) >> 8);
++ write_cr(0x13, wd & 0xff);
++ write_cr(0x41, (wd & 0xf00) >> 8);
++ write_cr(0x15, (vs - 1) & 0xff);
++ write_cr(0x33, ((vs - 1) >> 8) & 0xf);
++ write_cr(0x38, ((ht - 5) & 0x100) >> 8);
++ write_cr(0x16, (vt - 1) & 0xff);
++ write_cr(0x18, 0x00);
++
++ if (p->var.xres == 640) {
++ writeb(0xc7, mmio_base + 0x784); /* set misc output reg */
++ } else {
++ writeb(0x07, mmio_base + 0x784); /* set misc output reg */
++ }
++}
++
++static int asiliantfb_check_var(struct fb_var_screeninfo *var,
++ struct fb_info *p)
++{
++ unsigned long Ftarget, ratio, remainder;
++
++ ratio = 1000000 / var->pixclock;
++ remainder = 1000000 % var->pixclock;
++ Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
++
++ /* First check the constraint that the maximum post-VCO divisor is 32,
++ * and the maximum Fvco is 220MHz */
++ if (Ftarget > 220000000 || Ftarget < 3125000) {
++ printk(KERN_ERR "asiliantfb dotclock must be between 3.125 and 220MHz\n");
++ return -ENXIO;
++ }
++ var->xres_virtual = var->xres;
++ var->yres_virtual = var->yres;
++
++ if (var->bits_per_pixel == 24) {
++ var->red.offset = 16;
++ var->green.offset = 8;
++ var->blue.offset = 0;
++ var->red.length = var->blue.length = var->green.length = 8;
++ } else if (var->bits_per_pixel == 16) {
++ switch (var->red.offset) {
++ case 11:
++ var->green.length = 6;
++ break;
++ case 10:
++ var->green.length = 5;
++ break;
++ default:
++ return -EINVAL;
++ }
++ var->green.offset = 5;
++ var->blue.offset = 0;
++ var->red.length = var->blue.length = 5;
++ } else if (var->bits_per_pixel == 8) {
++ var->red.offset = var->green.offset = var->blue.offset = 0;
++ var->red.length = var->green.length = var->blue.length = 8;
++ }
++ return 0;
++}
++
++static int asiliantfb_set_par(struct fb_info *p)
++{
++ u8 dclk2_m; /* Holds m-2 value for register */
++ u8 dclk2_n; /* Holds n-2 value for register */
++ u8 dclk2_div; /* Holds divisor bitmask */
++
++ /* Set pixclock */
++ asiliant_calc_dclk2(&p->var.pixclock, &dclk2_m, &dclk2_n, &dclk2_div);
++
++ /* Set color depth */
++ if (p->var.bits_per_pixel == 24) {
++ write_xr(0x81, 0x16); /* 24 bit packed color mode */
++ write_xr(0x82, 0x00); /* Disable palettes */
++ write_xr(0x20, 0x20); /* 24 bit blitter mode */
++ } else if (p->var.bits_per_pixel == 16) {
++ if (p->var.red.offset == 11)
++ write_xr(0x81, 0x15); /* 16 bit color mode */
++ else
++ write_xr(0x81, 0x14); /* 15 bit color mode */
++ write_xr(0x82, 0x00); /* Disable palettes */
++ write_xr(0x20, 0x10); /* 16 bit blitter mode */
++ } else if (p->var.bits_per_pixel == 8) {
++ write_xr(0x0a, 0x02); /* Linear */
++ write_xr(0x81, 0x12); /* 8 bit color mode */
++ write_xr(0x82, 0x00); /* Graphics gamma enable */
++ write_xr(0x20, 0x00); /* 8 bit blitter mode */
++ }
++ p->fix.line_length = p->var.xres * (p->var.bits_per_pixel >> 3);
++ p->fix.visual = (p->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
++ write_xr(0xc4, dclk2_m);
++ write_xr(0xc5, dclk2_n);
++ write_xr(0xc7, dclk2_div);
++ /* Set up the CR registers */
++ asiliant_set_timing(p);
++ return 0;
++}
++
++static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
++ u_int transp, struct fb_info *p)
++{
++ if (regno > 255)
++ return 1;
++ red >>= 8;
++ green >>= 8;
++ blue >>= 8;
++
++ /* Set hardware palete */
++ writeb(regno, mmio_base + 0x790);
++ udelay(1);
++ writeb(red, mmio_base + 0x791);
++ writeb(green, mmio_base + 0x791);
++ writeb(blue, mmio_base + 0x791);
++
++ switch(p->var.bits_per_pixel) {
++ case 15:
++ if (regno < 16) {
++ ((u32 *)(p->pseudo_palette))[regno] =
++ ((red & 0xf8) << 7) |
++ ((green & 0xf8) << 2) |
++ ((blue & 0xf8) >> 3);
++ }
++ break;
++ case 16:
++ if (regno < 16) {
++ ((u32 *)(p->pseudo_palette))[regno] =
++ ((red & 0xf8) << 8) |
++ ((green & 0xfc) << 3) |
++ ((blue & 0xf8) >> 3);
++ }
++ break;
++ case 24:
++ if (regno < 24) {
++ ((u32 *)(p->pseudo_palette))[regno] =
++ (red << 16) |
++ (green << 8) |
++ (blue);
++ }
++ break;
++ }
++ return 0;
++}
++
++struct chips_init_reg {
++ unsigned char addr;
++ unsigned char data;
++};
++
++#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
++
++static struct chips_init_reg chips_init_sr[] =
++{
++ {0x00, 0x03}, /* Reset register */
++ {0x01, 0x01}, /* Clocking mode */
++ {0x02, 0x0f}, /* Plane mask */
++ {0x04, 0x0e} /* Memory mode */
++};
++
++static struct chips_init_reg chips_init_gr[] =
++{
++ {0x03, 0x00}, /* Data rotate */
++ {0x05, 0x00}, /* Graphics mode */
++ {0x06, 0x01}, /* Miscellaneous */
++ {0x08, 0x00} /* Bit mask */
++};
++
++static struct chips_init_reg chips_init_ar[] =
++{
++ {0x10, 0x01}, /* Mode control */
++ {0x11, 0x00}, /* Overscan */
++ {0x12, 0x0f}, /* Memory plane enable */
++ {0x13, 0x00} /* Horizontal pixel panning */
++};
++
++static struct chips_init_reg chips_init_cr[] =
++{
++ {0x0c, 0x00}, /* Start address high */
++ {0x0d, 0x00}, /* Start address low */
++ {0x40, 0x00}, /* Extended Start Address */
++ {0x41, 0x00}, /* Extended Start Address */
++ {0x14, 0x00}, /* Underline location */
++ {0x17, 0xe3}, /* CRT mode control */
++ {0x70, 0x00} /* Interlace control */
++};
++
++
++static struct chips_init_reg chips_init_fr[] =
++{
++ {0x01, 0x02},
++ {0x03, 0x08},
++ {0x08, 0xcc},
++ {0x0a, 0x08},
++ {0x18, 0x00},
++ {0x1e, 0x80},
++ {0x40, 0x83},
++ {0x41, 0x00},
++ {0x48, 0x13},
++ {0x4d, 0x60},
++ {0x4e, 0x0f},
++
++ {0x0b, 0x01},
++
++ {0x21, 0x51},
++ {0x22, 0x1d},
++ {0x23, 0x5f},
++ {0x20, 0x4f},
++ {0x34, 0x00},
++ {0x24, 0x51},
++ {0x25, 0x00},
++ {0x27, 0x0b},
++ {0x26, 0x00},
++ {0x37, 0x80},
++ {0x33, 0x0b},
++ {0x35, 0x11},
++ {0x36, 0x02},
++ {0x31, 0xea},
++ {0x32, 0x0c},
++ {0x30, 0xdf},
++ {0x10, 0x0c},
++ {0x11, 0xe0},
++ {0x12, 0x50},
++ {0x13, 0x00},
++ {0x16, 0x03},
++ {0x17, 0xbd},
++ {0x1a, 0x00},
++};
++
++
++static struct chips_init_reg chips_init_xr[] =
++{
++ {0xce, 0x00}, /* set default memory clock */
++ {0xcc, 200 }, /* MCLK ratio M */
++ {0xcd, 18 }, /* MCLK ratio N */
++ {0xce, 0x90}, /* MCLK divisor = 2 */
++
++ {0xc4, 209 },
++ {0xc5, 118 },
++ {0xc7, 32 },
++ {0xcf, 0x06},
++ {0x09, 0x01}, /* IO Control - CRT controller extensions */
++ {0x0a, 0x02}, /* Frame buffer mapping */
++ {0x0b, 0x01}, /* PCI burst write */
++ {0x40, 0x03}, /* Memory access control */
++ {0x80, 0x82}, /* Pixel pipeline configuration 0 */
++ {0x81, 0x12}, /* Pixel pipeline configuration 1 */
++ {0x82, 0x08}, /* Pixel pipeline configuration 2 */
++
++ {0xd0, 0x0f},
++ {0xd1, 0x01},
++};
++
++static void __init chips_hw_init(struct fb_info *p)
++{
++ int i;
++
++ for (i = 0; i < N_ELTS(chips_init_xr); ++i)
++ write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
++ write_xr(0x81, 0x12);
++ write_xr(0x82, 0x08);
++ write_xr(0x20, 0x00);
++ for (i = 0; i < N_ELTS(chips_init_sr); ++i)
++ write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
++ for (i = 0; i < N_ELTS(chips_init_gr); ++i)
++ write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
++ for (i = 0; i < N_ELTS(chips_init_ar); ++i)
++ write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
++ /* Enable video output in attribute index register */
++ writeb(0x20, mmio_base + 0x780);
++ for (i = 0; i < N_ELTS(chips_init_cr); ++i)
++ write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
++ for (i = 0; i < N_ELTS(chips_init_fr); ++i)
++ write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
++}
++
++static struct fb_fix_screeninfo asiliantfb_fix __initdata = {
++ .id = "Asiliant 69000",
++ .type = FB_TYPE_PACKED_PIXELS,
++ .visual = FB_VISUAL_PSEUDOCOLOR,
++ .accel = FB_ACCEL_NONE,
++ .line_length = 640,
++ .smem_len = 0x200000, /* 2MB */
++};
++
++static struct fb_var_screeninfo asiliantfb_var __initdata = {
++ .xres = 640,
++ .yres = 480,
++ .xres_virtual = 640,
++ .yres_virtual = 480,
++ .bits_per_pixel = 8,
++ .red = { .length = 8 },
++ .green = { .length = 8 },
++ .blue = { .length = 8 },
++ .height = -1,
++ .width = -1,
++ .vmode = FB_VMODE_NONINTERLACED,
++ .pixclock = 39722,
++ .left_margin = 48,
++ .right_margin = 16,
++ .upper_margin = 33,
++ .lower_margin = 10,
++ .hsync_len = 96,
++ .vsync_len = 2,
++};
++
++static void __init init_asiliant(struct fb_info *p, unsigned long addr)
++{
++ p->fix = asiliantfb_fix;
++ p->fix.smem_start = addr;
++ p->var = asiliantfb_var;
++ p->fbops = &asiliantfb_ops;
++ p->pseudo_palette = pseudo_palette;
++ p->flags = FBINFO_FLAG_DEFAULT;
++
++ fb_alloc_cmap(&p->cmap, 256, 0);
++
++ if (register_framebuffer(p) < 0) {
++ printk(KERN_ERR "C&T 69000 framebuffer failed to register\n");
++ return;
++ }
++
++ printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n",
++ p->node, p->fix.smem_len / 1024);
++
++ writeb(0xff, mmio_base + 0x78c);
++ chips_hw_init(p);
++}
++
++static int __devinit
++asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
++{
++ struct fb_info *p = &asiliantfb_info;
++ unsigned long addr, size;
++
++ if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
++ return -ENODEV;
++ addr = pci_resource_start(dp, 0);
++ size = pci_resource_len(dp, 0);
++ if (addr == 0)
++ return -ENODEV;
++ if (p->screen_base != 0)
++ return -EBUSY;
++ if (!request_mem_region(addr, size, "asiliantfb"))
++ return -EBUSY;
++
++ p->screen_base = ioremap(addr, 0x800000);
++ if (p->screen_base == NULL) {
++ release_mem_region(addr, size);
++ return -ENOMEM;
++ }
++
++ pci_write_config_dword(dp, 4, 0x02800083);
++ writeb(3, addr + 0x400784);
++
++ init_asiliant(p, addr);
++
++ /* Clear the entire framebuffer */
++ memset(p->screen_base, 0, 0x200000);
++
++ pci_set_drvdata(dp, p);
++ return 0;
++}
++
++static void __devexit asiliantfb_remove(struct pci_dev *dp)
++{
++ struct fb_info *p = pci_get_drvdata(dp);
++
++ if (p != &asiliantfb_info || p->screen_base == NULL)
++ return;
++ unregister_framebuffer(p);
++ iounmap(p->screen_base);
++ p->screen_base = NULL;
++ release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0));
++}
++
++static struct pci_device_id asiliantfb_pci_tbl[] __devinitdata = {
++ { PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID },
++ { 0 }
++};
++
++MODULE_DEVICE_TABLE(pci, asiliantfb_pci_tbl);
++
++static struct pci_driver asiliantfb_driver = {
++ .name = "asiliantfb",
++ .id_table = asiliantfb_pci_tbl,
++ .probe = asiliantfb_pci_init,
++ .remove = __devexit_p(asiliantfb_remove),
++};
++
++int __init asiliantfb_init(void)
++{
++ return pci_module_init(&asiliantfb_driver);
++}
++
++static void __exit asiliantfb_exit(void)
++{
++ pci_unregister_driver(&asiliantfb_driver);
++}
++
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/video/aty/aty128fb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/aty/aty128fb.c 2003-10-05 00:34:46.000000000 -0700
+@@ -2041,9 +2041,9 @@ aty128fb_setcolreg(u_int regno, u_int re
+ #define ATY_MIRROR_CRT_ON 0x00000002
+
+ /* out param: u32* backlight value: 0 to 15 */
+-#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, sizeof(__u32*))
++#define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32*)
+ /* in param: u32* backlight value: 0 to 15 */
+-#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, sizeof(__u32*))
++#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32*)
+
+ static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, struct fb_info *info)
+--- linux-2.6.0-test6/drivers/video/aty/Makefile 2003-06-14 12:18:06.000000000 -0700
++++ 25/drivers/video/aty/Makefile 2003-10-05 00:34:22.000000000 -0700
+@@ -4,4 +4,3 @@ obj-$(CONFIG_FB_ATY128) += aty128fb.o
+ atyfb-y := atyfb_base.o mach64_accel.o
+ atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o
+ atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o
+-atyfb-objs := $(atyfb-y)
+--- linux-2.6.0-test6/drivers/video/chipsfb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/chipsfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -85,7 +85,7 @@ static struct pmu_sleep_notifier chips_s
+ /*
+ * Exported functions
+ */
+-int chips_init(void);
++int chipsfb_init(void);
+
+ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
+ static int chipsfb_check_var(struct fb_var_screeninfo *var,
+@@ -460,7 +460,7 @@ static struct pci_driver chipsfb_driver
+ .remove = __devexit_p(chipsfb_remove),
+ };
+
+-int __init chips_init(void)
++int __init chipsfb_init(void)
+ {
+ return pci_module_init(&chipsfb_driver);
+ }
+--- linux-2.6.0-test6/drivers/video/console/fbcon.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/video/console/fbcon.c 2003-10-05 00:34:22.000000000 -0700
+@@ -195,8 +195,7 @@ static void fb_flashcursor(void *private
+ {
+ struct fb_info *info = (struct fb_info *) private;
+
+- /* Test to see if the cursor is erased but still on */
+- if (!info || (info->cursor.rop == ROP_COPY))
++ if (!info)
+ return;
+ info->cursor.enable ^= 1;
+ info->fbops->fb_cursor(info, &info->cursor);
+@@ -226,8 +225,7 @@ static void cursor_timer_handler(unsigne
+ struct fb_info *info = (struct fb_info *) dev_addr;
+
+ schedule_work(&info->queue);
+- cursor_timer.expires = jiffies + HZ / 5;
+- add_timer(&cursor_timer);
++ mod_timer(&cursor_timer, jiffies + HZ/5);
+ }
+
+ int __init fb_console_setup(char *this_opt)
+@@ -308,97 +306,6 @@ int set_con2fb_map(int unit, int newidx)
+ }
+
+ /*
+- * drawing helpers
+- */
+-static void putcs_unaligned(struct vc_data *vc, struct fb_info *info,
+- struct fb_image *image, int count,
+- const unsigned short *s)
+-{
+- unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+- unsigned int width = (vc->vc_font.width + 7) >> 3;
+- unsigned int cellsize = vc->vc_font.height * width;
+- unsigned int maxcnt = info->pixmap.size/cellsize;
+- unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
+- unsigned int shift_high = 8, size, pitch, cnt, k;
+- unsigned int buf_align = info->pixmap.buf_align - 1;
+- unsigned int scan_align = info->pixmap.scan_align - 1;
+- unsigned int idx = vc->vc_font.width >> 3;
+- u8 mask, *src, *dst, *dst0;
+-
+- while (count) {
+- if (count > maxcnt)
+- cnt = k = maxcnt;
+- else
+- cnt = k = count;
+-
+- image->width = vc->vc_font.width * cnt;
+- pitch = ((image->width + 7) >> 3) + scan_align;
+- pitch &= ~scan_align;
+- size = pitch * vc->vc_font.height + buf_align;
+- size &= ~buf_align;
+- dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+- image->data = dst0;
+- while (k--) {
+- src = vc->vc_font.data + (scr_readw(s++) & charmask)*
+- cellsize;
+- dst = dst0;
+- mask = (u8) (0xfff << shift_high);
+- move_buf_unaligned(info, dst, src, pitch, image->height,
+- mask, shift_high, shift_low, mod, idx);
+- shift_low += mod;
+- dst0 += (shift_low >= 8) ? width : width - 1;
+- shift_low &= 7;
+- shift_high = 8 - shift_low;
+- }
+- info->fbops->fb_imageblit(info, image);
+- image->dx += cnt * vc->vc_font.width;
+- count -= cnt;
+- atomic_dec(&info->pixmap.count);
+- smp_mb__after_atomic_dec();
+- }
+-}
+-
+-static void putcs_aligned(struct vc_data *vc, struct fb_info *info,
+- struct fb_image *image, int count,
+- const unsigned short *s)
+-{
+- unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+- unsigned int width = vc->vc_font.width >> 3;
+- unsigned int cellsize = vc->vc_font.height * width;
+- unsigned int maxcnt = info->pixmap.size/cellsize;
+- unsigned int scan_align = info->pixmap.scan_align - 1;
+- unsigned int buf_align = info->pixmap.buf_align - 1;
+- unsigned int pitch, cnt, size, k;
+- u8 *src, *dst, *dst0;
+-
+- while (count) {
+- if (count > maxcnt)
+- cnt = k = maxcnt;
+- else
+- cnt = k = count;
+-
+- pitch = width * cnt + scan_align;
+- pitch &= ~scan_align;
+- size = pitch * vc->vc_font.height + buf_align;
+- size &= ~buf_align;
+- image->width = vc->vc_font.width * cnt;
+- dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size);
+- image->data = dst0;
+- while (k--) {
+- src = vc->vc_font.data + (scr_readw(s++)&charmask)*cellsize;
+- dst = dst0;
+- move_buf_aligned(info, dst, src, pitch, width, image->height);
+- dst0 += width;
+- }
+- info->fbops->fb_imageblit(info, image);
+- image->dx += cnt * vc->vc_font.width;
+- count -= cnt;
+- atomic_dec(&info->pixmap.count);
+- smp_mb__after_atomic_dec();
+- }
+-}
+-
+-/*
+ * Accelerated handlers.
+ */
+ void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+@@ -432,48 +339,21 @@ void accel_clear(struct vc_data *vc, str
+ info->fbops->fb_fillrect(info, ®ion);
+ }
+
+-static void accel_putc(struct vc_data *vc, struct fb_info *info,
+- int c, int ypos, int xpos)
++void accel_putcs(struct vc_data *vc, struct fb_info *info,
++ const unsigned short *s, int count, int yy, int xx)
+ {
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ unsigned int width = (vc->vc_font.width + 7) >> 3;
++ unsigned int cellsize = vc->vc_font.height * width;
++ unsigned int maxcnt = info->pixmap.size/cellsize;
+ unsigned int scan_align = info->pixmap.scan_align - 1;
+ unsigned int buf_align = info->pixmap.buf_align - 1;
++ unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
++ unsigned int shift_high = 8, pitch, cnt, size, k;
+ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+- unsigned int size, pitch;
+- struct fb_image image;
+- u8 *src, *dst;
+-
+- image.dx = xpos * vc->vc_font.width;
+- image.dy = ypos * vc->vc_font.height;
+- image.width = vc->vc_font.width;
+- image.height = vc->vc_font.height;
+- image.fg_color = attr_fgcol(fgshift, c);
+- image.bg_color = attr_bgcol(bgshift, c);
+- image.depth = 1;
+-
+- pitch = width + scan_align;
+- pitch &= ~scan_align;
+- size = pitch * vc->vc_font.height;
+- size += buf_align;
+- size &= ~buf_align;
+- dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+- image.data = dst;
+- src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
+-
+- move_buf_aligned(info, dst, src, pitch, width, image.height);
+-
+- info->fbops->fb_imageblit(info, &image);
+- atomic_dec(&info->pixmap.count);
+- smp_mb__after_atomic_dec();
+-}
+-
+-void accel_putcs(struct vc_data *vc, struct fb_info *info,
+- const unsigned short *s, int count, int yy, int xx)
+-{
+- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+- int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
++ unsigned int idx = vc->vc_font.width >> 3;
++ u8 *src, *dst, *dst0, mask;
+ struct fb_image image;
+ u16 c = scr_readw(s);
+
+@@ -484,10 +364,44 @@ void accel_putcs(struct vc_data *vc, str
+ image.height = vc->vc_font.height;
+ image.depth = 1;
+
+- if (!(vc->vc_font.width & 7))
+- putcs_aligned(vc, info, &image, count, s);
+- else
+- putcs_unaligned(vc, info, &image, count, s);
++ while (count) {
++ if (count > maxcnt)
++ cnt = k = maxcnt;
++ else
++ cnt = k = count;
++
++ image.width = vc->vc_font.width * cnt;
++ pitch = ((image.width + 7) >> 3) + scan_align;
++ pitch &= ~scan_align;
++ size = pitch * vc->vc_font.height + buf_align;
++ size &= ~buf_align;
++ dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
++ image.data = dst0;
++ while (k--) {
++ src = vc->vc_font.data + (scr_readw(s++) & charmask)*cellsize;
++ dst = dst0;
++
++ if (mod) {
++ mask = (u8) (0xfff << shift_high);
++ move_buf_unaligned(info, &info->pixmap, dst, src, pitch,
++ image.height, mask, shift_high,
++ shift_low, mod, idx);
++ shift_low += mod;
++ dst0 += (shift_low >= 8) ? width : width - 1;
++ shift_low &= 7;
++ shift_high = 8 - shift_low;
++ } else {
++ move_buf_aligned(info, &info->pixmap, dst, src, pitch, idx,
++ image.height);
++ dst0 += width;
++ }
++ }
++ info->fbops->fb_imageblit(info, &image);
++ image.dx += cnt * vc->vc_font.width;
++ count -= cnt;
++ atomic_dec(&info->pixmap.count);
++ smp_mb__after_atomic_dec();
++ }
+ }
+
+ void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
+@@ -676,7 +590,7 @@ static const char *fbcon_startup(void)
+ if (!info->queue.func) {
+ INIT_WORK(&info->queue, fb_flashcursor, info);
+
+- cursor_timer.expires = jiffies + HZ / 50;
++ cursor_timer.expires = jiffies + HZ / 5;
+ cursor_timer.data = (unsigned long ) info;
+ add_timer(&cursor_timer);
+ }
+@@ -728,15 +642,13 @@ static __inline__ void updatescrollmode(
+ static void fbcon_set_display(struct vc_data *vc, int init, int logo)
+ {
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
++ int nr_rows, nr_cols, old_rows, old_cols, i, charcnt = 256;
+ struct display *p = &fb_display[vc->vc_num];
+- int nr_rows, nr_cols;
+- int old_rows, old_cols;
+ unsigned short *save = NULL, *r, *q;
+- int i, charcnt = 256;
+ struct font_desc *font;
+
+ if (vc->vc_num != fg_console || (info->flags & FBINFO_FLAG_MODULE) ||
+- info->fix.type == FB_TYPE_TEXT)
++ (info->fix.type == FB_TYPE_TEXT))
+ logo = 0;
+
+ info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */
+@@ -960,11 +872,19 @@ static void fbcon_clear(struct vc_data *
+ accel_clear(vc, info, real_y(p, sy), sx, height, width);
+ }
+
+-
+ static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+ {
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
++ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
++ unsigned int scan_align = info->pixmap.scan_align - 1;
++ unsigned int buf_align = info->pixmap.buf_align - 1;
++ unsigned int width = (vc->vc_font.width + 7) >> 3;
++ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
++ int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+ struct display *p = &fb_display[vc->vc_num];
++ unsigned int size, pitch;
++ struct fb_image image;
++ u8 *src, *dst;
+
+ if (!info->fbops->fb_blank && console_blanked)
+ return;
+@@ -972,7 +892,31 @@ static void fbcon_putc(struct vc_data *v
+ if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
+ return;
+
+- accel_putc(vc, info, c, real_y(p, ypos), xpos);
++ image.dx = xpos * vc->vc_font.width;
++ image.dy = real_y(p, ypos) * vc->vc_font.height;
++ image.width = vc->vc_font.width;
++ image.height = vc->vc_font.height;
++ image.fg_color = attr_fgcol(fgshift, c);
++ image.bg_color = attr_bgcol(bgshift, c);
++ image.depth = 1;
++
++ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
++
++ pitch = width + scan_align;
++ pitch &= ~scan_align;
++ size = pitch * vc->vc_font.height;
++ size += buf_align;
++ size &= ~buf_align;
++
++ dst = fb_get_buffer_offset(info, &info->pixmap, size);
++ image.data = dst;
++
++ move_buf_aligned(info, &info->pixmap, dst, src, pitch, width,
++ image.height);
++
++ info->fbops->fb_imageblit(info, &image);
++ atomic_dec(&info->pixmap.count);
++ smp_mb__after_atomic_dec();
+ }
+
+ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
+@@ -994,12 +938,16 @@ static void fbcon_cursor(struct vc_data
+ {
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
++ unsigned int scan_align = info->sprite.scan_align - 1;
++ unsigned int buf_align = info->sprite.buf_align - 1;
+ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+ int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+ struct display *p = &fb_display[vc->vc_num];
+- int w = (vc->vc_font.width + 7) >> 3, c;
+- int y = real_y(p, vc->vc_y);
++ int y = real_y(p, vc->vc_y), d_pitch, dsize;
++ int s_pitch = (vc->vc_font.width + 7) >> 3;
++ int size = s_pitch * vc->vc_font.height, c;
+ struct fb_cursor cursor;
++ u8 *src, *dst;
+
+ if (mode & CM_SOFTBACK) {
+ mode &= ~CM_SOFTBACK;
+@@ -1012,28 +960,24 @@ static void fbcon_cursor(struct vc_data
+ } else if (softback_lines)
+ fbcon_set_origin(vc);
+
+- c = scr_readw((u16 *) vc->vc_pos);
++ del_timer(&cursor_timer);
++ if (info->cursor.enable) {
++ info->cursor.enable = 0;
++ info->fbops->fb_cursor(info, &info->cursor);
++ }
+
+- cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+- cursor.set = FB_CUR_SETCUR;
+- cursor.image.depth = 1;
+-
+- switch (mode) {
+- case CM_ERASE:
+- if (info->cursor.rop == ROP_XOR) {
+- info->cursor.enable = 0;
+- info->cursor.rop = ROP_COPY;
+- info->fbops->fb_cursor(info, &cursor);
+- }
+- break;
+- case CM_MOVE:
+- case CM_DRAW:
++ if (mode != CM_ERASE) {
++ memset(&cursor, 0, sizeof(struct fb_cursor));
+ info->cursor.enable = 1;
+-
++
++ c = scr_readw((u16 *) vc->vc_pos);
++
++ src = vc->vc_font.data + ((c & charmask) * size);
+ if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||
+ info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {
+ cursor.image.fg_color = attr_fgcol(fgshift, c);
+ cursor.image.bg_color = attr_bgcol(bgshift, c);
++ cursor.image.depth = 1;
+ cursor.set |= FB_CUR_SETCMAP;
+ }
+
+@@ -1056,18 +1000,29 @@ static void fbcon_cursor(struct vc_data
+ cursor.set |= FB_CUR_SETHOT;
+ }
+
++ src = vc->vc_font.data + ((c & charmask) * size);
++
++ d_pitch = (s_pitch + scan_align) & ~scan_align;
++ dsize = d_pitch * vc->vc_font.height + buf_align;
++ dsize &= ~buf_align;
++ dst = fb_get_buffer_offset(info, &info->sprite, dsize);
++ move_buf_aligned(info, &info->sprite, dst, src, d_pitch, s_pitch, vc->vc_font.height);
++ info->cursor.image.data = dst;
++ cursor.set |= FB_CUR_SETSHAPE;
++
+ if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)) {
+- char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
+- int cur_height, size, i = 0;
++ char *mask = kmalloc(dsize, GFP_ATOMIC);
++ int cur_height, i, j, k;
+
+ if (!mask) return;
+-
++
++ memset(mask, 0, dsize);
++
+ if (info->cursor.mask)
+ kfree(info->cursor.mask);
+ info->cursor.mask = mask;
+
+ p->cursor_shape = vc->vc_cursor_type & 0x0f;
+- cursor.set |= FB_CUR_SETSHAPE;
+
+ switch (vc->vc_cursor_type & 0x0f) {
+ case CUR_NONE:
+@@ -1090,17 +1045,19 @@ static void fbcon_cursor(struct vc_data
+ cur_height = vc->vc_font.height;
+ break;
+ }
+- size = (vc->vc_font.height - cur_height) * w;
+- while (size--)
+- mask[i++] = 0;
+- size = cur_height * w;
+- while (size--)
+- mask[i++] = 0xff;
++ i = (vc->vc_font.height - cur_height) * d_pitch;
++ for (j = 0; j < cur_height; j++) {
++ for (k = 0; k < s_pitch; k++)
++ mask[i++] = 0xff;
++ i += (d_pitch - s_pitch);
++ }
+ }
+ info->cursor.rop = ROP_XOR;
+ info->fbops->fb_cursor(info, &cursor);
++ atomic_dec(&info->sprite.count);
++ smp_mb__after_atomic_dec();
++ mod_timer(&cursor_timer, jiffies + HZ/5);
+ vbl_cursor_cnt = CURSOR_DRAW_DELAY;
+- break;
+ }
+ }
+
+@@ -1826,8 +1783,10 @@ static int fbcon_do_set_font(struct vc_d
+ vc->vc_font.height = h;
+ if (vc->vc_hi_font_mask && cnt == 256) {
+ vc->vc_hi_font_mask = 0;
+- if (vc->vc_can_do_color)
++ if (vc->vc_can_do_color) {
+ vc->vc_complement_mask >>= 1;
++ vc->vc_s_complement_mask >>= 1;
++ }
+
+ /* ++Edmund: reorder the attribute bits */
+ if (vc->vc_can_do_color) {
+@@ -1847,8 +1806,10 @@ static int fbcon_do_set_font(struct vc_d
+ }
+ } else if (!vc->vc_hi_font_mask && cnt == 512) {
+ vc->vc_hi_font_mask = 0x100;
+- if (vc->vc_can_do_color)
++ if (vc->vc_can_do_color) {
+ vc->vc_complement_mask <<= 1;
++ vc->vc_s_complement_mask <<= 1;
++ }
+
+ /* ++Edmund: reorder the attribute bits */
+ {
+--- linux-2.6.0-test6/drivers/video/console/Makefile 2003-06-14 12:18:09.000000000 -0700
++++ 25/drivers/video/console/Makefile 2003-10-05 00:34:22.000000000 -0700
+@@ -3,18 +3,16 @@
+ # Rewritten to use lists instead of if-statements.
+
+ # Font handling
+-font-objs := fonts.o
++font-y := fonts.o
+
+-font-objs-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o
+-font-objs-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o
+-font-objs-$(CONFIG_FONT_8x8) += font_8x8.o
+-font-objs-$(CONFIG_FONT_8x16) += font_8x16.o
+-font-objs-$(CONFIG_FONT_6x11) += font_6x11.o
+-font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
+-font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
+-font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
+-
+-font-objs += $(font-objs-y)
++font-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o
++font-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o
++font-$(CONFIG_FONT_8x8) += font_8x8.o
++font-$(CONFIG_FONT_8x16) += font_8x16.o
++font-$(CONFIG_FONT_6x11) += font_6x11.o
++font-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
++font-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
++font-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
+
+ # Each configuration option enables a list of files.
+
+@@ -31,8 +29,11 @@ obj-$(CONFIG_FB_STI) += sti
+ # Files generated that shall be removed upon make clean
+ clean-files := promcon_tbl.c
+
+-$(obj)/promcon_tbl.c: $(src)/prom.uni
+- $(objtree)/scripts/conmakehash $< | \
++quiet_cmd_promtbl = GEN $@
++ cmd_promtbl = scripts/conmakehash $< | \
+ sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
+ -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@
+
++$(obj)/promcon_tbl.c: $(src)/prom.uni
++ $(call cmd,promtbl)
++
+--- linux-2.6.0-test6/drivers/video/console/sticore.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/console/sticore.c 2003-10-05 00:33:24.000000000 -0700
+@@ -988,7 +988,7 @@ static int __devinit sticore_pci_init(st
+
+ if (!sti) {
+ printk(KERN_WARNING "Unable to handle STI device '%s'\n",
+- pd->dev.name);
++ pci_name(pd));
+ return -ENODEV;
+ }
+ #endif /* CONFIG_PCI */
+--- linux-2.6.0-test6/drivers/video/controlfb.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/video/controlfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -136,8 +136,8 @@ static int controlfb_check_var (struct f
+ /*
+ * inititialization
+ */
+-int control_init(void);
+-void control_setup(char *);
++int controlfb_init(void);
++void controlfb_setup(char *);
+
+ /******************** Prototypes for internal functions **********************/
+
+@@ -553,7 +553,7 @@ static void control_set_hardware(struct
+ /*
+ * Called from fbmem.c for probing & initializing
+ */
+-int __init control_init(void)
++int __init controlfb_init(void)
+ {
+ struct device_node *dp;
+
+@@ -1057,7 +1057,7 @@ static void control_cleanup(void)
+ /*
+ * Parse user speficied options (`video=controlfb:')
+ */
+-void __init control_setup(char *options)
++void __init controlfb_setup(char *options)
+ {
+ char *this_opt;
+
+--- linux-2.6.0-test6/drivers/video/epson1355fb.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/drivers/video/epson1355fb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,541 +1,714 @@
+ /*
+- * linux/drivers/video/epson1355fb.c
+- * -- Support for the Epson SED1355 LCD/CRT controller
++ * linux/drivers/video/epson1355fb.c -- Epson S1D13505 frame buffer for 2.5.
+ *
+- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
++ * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
++ * (previously known as SED1355)
+ *
+- * based on linux/drivers/video/skeletonfb.c, which was
++ * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html
++ *
++ *
++ * Copyright (C) Hewlett-Packard Company. All rights reserved.
++ *
++ * Written by Christopher Hoover <ch@hpl.hp.com>
++ *
++ * Adapted from:
++ *
++ * linux/drivers/video/skeletonfb.c
++ * Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
++ * linux/drivers/video/epson1355fb.c (2.4 driver)
++ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
++ *
+ * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file COPYING in the main directory of this archive
+- * for more details.
+- */
+-/* TODO (roughly in order of priority):
+- * 16 bpp support
+- * crt support
+- * hw cursor support
+- * SwivelView
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ *
++ * Noteworthy Issues
++ * -----------------
++ *
++ * This driver is complicated by the fact that this is a 16-bit chip
++ * and, on at least one platform (ceiva), we can only do 16-bit reads
++ * and writes to the framebuffer. We hide this from user space
++ * except in the case of mmap().
++ *
++ *
++ * To Do
++ * -----
++ *
++ * - Test 8-bit pseudocolor mode
++ * - Allow setting bpp, virtual resolution
++ * - Implement horizontal panning
++ * - (maybe) Implement hardware cursor
+ */
+
+-#include <asm/io.h>
+-#include <linux/config.h>
+-#include <linux/delay.h>
+-#include <linux/errno.h>
+-#include <linux/fb.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/mm.h>
+ #include <linux/module.h>
+-#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
+ #include <linux/string.h>
++#include <linux/mm.h>
+ #include <linux/tty.h>
+-#include <video/fbcon-cfb8.h>
+-#include <video/fbcon-mfb.h>
+-#include <video/fbcon.h>
+-
+-/* Register defines. The docs don't seem to provide nice mnemonic names
+- * so I made them up myself ... */
+-
+-#define E1355_PANEL 0x02
+-#define E1355_DISPLAY 0x0D
+-#define E1355_MISC 0x1B
+-#define E1355_GPIO 0x20
+-#define E1355_LUT_INDEX 0x24
+-#define E1355_LUT_DATA 0x26
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/fb.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <asm/types.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <video/epson1355.h>
++
++static struct fb_info info;
++
++static struct epson1355fb_par {
++ unsigned long reg_addr;
++} par;
++
++static u32 pseudo_palette[16];
++
++/* ------------------------------------------------------------------------- */
+
+ #ifdef CONFIG_SUPERH
+-#define E1355_REG_BASE CONFIG_E1355_REG_BASE
+-#define E1355_FB_BASE CONFIG_E1355_FB_BASE
+
+-static inline u8 e1355_read_reg(int index)
++static inline u8 epson1355_read_reg(int index)
+ {
+- return ctrl_inb(E1355_REG_BASE + index);
++ return ctrl_inb(par.reg_addr + index);
+ }
+
+-static inline void e1355_write_reg(u8 data, int index)
++static inline void epson1355_write_reg(u8 data, int index)
+ {
+- ctrl_outb(data, E1355_REG_BASE + index);
++ ctrl_outb(data, par.reg_addr + index);
+ }
+
+-static inline u16 e1355_read_reg16(int index)
++#elif defined(CONFIG_ARM)
++
++# ifdef CONFIG_ARCH_CEIVA
++# include <asm/arch/hardware.h>
++# define EPSON1355FB_BASE_PHYS (CEIVA_PHYS_SED1355)
++# endif
++
++static inline u8 epson1355_read_reg(int index)
+ {
+- return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
++ return __raw_readb(par.reg_addr + index);
+ }
+
+-static inline void e1355_write_reg16(u16 data, int index)
++static inline void epson1355_write_reg(u8 data, int index)
+ {
+- e1355_write_reg((data&0xff), index);
+- e1355_write_reg(((data>>8)&0xff), index + 1);
++ __raw_writeb(data, par.reg_addr + index);
+ }
++
+ #else
+-#error unknown architecture
++# error "no architecture-specific epson1355_{read,write}_reg"
+ #endif
+
+-struct e1355fb_info {
+- struct fb_info_gen gen;
+-};
+-
+-static int current_par_valid = 0;
+-static struct display disp;
++#ifndef EPSON1355FB_BASE_PHYS
++# error "EPSON1355FB_BASE_PHYS is not defined"
++#endif
+
+-static struct fb_var_screeninfo default_var;
++#define EPSON1355FB_REGS_OFS (0)
++#define EPSON1355FB_REGS_PHYS (EPSON1355FB_BASE_PHYS + EPSON1355FB_REGS_OFS)
++#define EPSON1355FB_REGS_LEN (64)
+
+-int e1355fb_init(void);
+-int e1355fb_setup(char*);
+-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
+- struct fb_info_gen *info);
+-/* ------------------- chipset specific functions -------------------------- */
++#define EPSON1355FB_FB_OFS (0x00200000)
++#define EPSON1355FB_FB_PHYS (EPSON1355FB_BASE_PHYS + EPSON1355FB_FB_OFS)
++#define EPSON1355FB_FB_LEN (2 * 1024 * 1024)
+
++/* ------------------------------------------------------------------------- */
+
+-static void disable_hw_cursor(void)
++static inline u16 epson1355_read_reg16(int index)
+ {
+- u8 curs;
++ u8 lo = epson1355_read_reg(index);
++ u8 hi = epson1355_read_reg(index + 1);
+
+- curs = e1355_read_reg(0x27);
+- curs &= ~0xc0;
+- e1355_write_reg(curs, 0x27);
++ return (hi << 8) | lo;
+ }
+
+-static void e1355_detect(void)
++static inline void epson1355_write_reg16(u16 data, int index)
+ {
+- u8 rev;
++ u8 lo = data & 0xff;
++ u8 hi = (data >> 8) & 0xff;
+
+- e1355_write_reg(0x00, E1355_MISC);
++ epson1355_write_reg(lo, index);
++ epson1355_write_reg(hi, index + 1);
++}
+
+- rev = e1355_read_reg(0x00);
++static inline u32 epson1355_read_reg20(int index)
++{
++ u8 b0 = epson1355_read_reg(index);
++ u8 b1 = epson1355_read_reg(index + 1);
++ u8 b2 = epson1355_read_reg(index + 2);
+
+- if ((rev & 0xfc) != 0x0c) {
+- printk(KERN_WARNING "Epson 1355 not detected\n");
+- }
++ return (b2 & 0x0f) << 16 | (b1 << 8) | b0;
++}
+
+- /* XXX */
+- disable_hw_cursor();
++static inline void epson1355_write_reg20(u32 data, int index)
++{
++ u8 b0 = data & 0xff;
++ u8 b1 = (data >> 8) & 0xff;
++ u8 b2 = (data >> 16) & 0x0f;
+
+- e1355_encode_var(&default_var, NULL, NULL);
++ epson1355_write_reg(b0, index);
++ epson1355_write_reg(b1, index + 1);
++ epson1355_write_reg(b2, index + 2);
+ }
+
+-struct e1355_par {
+- u32 xres;
+- u32 yres;
++/* ------------------------------------------------------------------------- */
+
+- int bpp;
+- int mem_bpp;
++static void set_lut(u8 index, u8 r, u8 g, u8 b)
++{
++ epson1355_write_reg(index, REG_LUT_ADDR);
++ epson1355_write_reg(r, REG_LUT_DATA);
++ epson1355_write_reg(g, REG_LUT_DATA);
++ epson1355_write_reg(b, REG_LUT_DATA);
++}
+
+- u32 panel_xres;
+- u32 panel_yres;
+-
+- int panel_width;
+- int panel_ymul;
+-};
+
+-static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
+- const void *raw_par,
+- struct fb_info_gen *info)
+-{
+- const struct e1355_par *par = raw_par;
+-
+- memset(fix, 0, sizeof *fix);
+-
+- fix->type= FB_TYPE_PACKED_PIXELS;
++/**
++ * epson1355fb_setcolreg - sets a color register.
++ * @regno: Which register in the CLUT we are programming
++ * @red: The red value which can be up to 16 bits wide
++ * @green: The green value which can be up to 16 bits wide
++ * @blue: The blue value which can be up to 16 bits wide.
++ * @transp: If supported the alpha value which can be up to 16 bits wide.
++ * @info: frame buffer info structure
++ *
++ * Returns negative errno on error, or zero on success.
++ */
++static int epson1355fb_setcolreg(unsigned regno, unsigned r, unsigned g,
++ unsigned b, unsigned transp,
++ struct fb_info *info)
++{
++ if (info->var.grayscale)
++ r = g = b = (19595 * r + 38470 * g + 7471 * b) >> 16;
++
++ switch (info->fix.visual) {
++ case FB_VISUAL_TRUECOLOR:
++ if (regno >= 16)
++ return -EINVAL;
+
+- if (!par)
+- BUG();
++ ((u32 *) info->pseudo_palette)[regno] =
++ (r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;
+
+- if (par->bpp == 1) {
+- fix->visual = FB_VISUAL_MONO10;
+- } else if (par->bpp <= 8) {
+- fix->visual = FB_VISUAL_PSEUDOCOLOR;
+- } else {
+- fix->visual = FB_VISUAL_TRUECOLOR;
+- }
++ break;
++ case FB_VISUAL_PSEUDOCOLOR:
++ if (regno >= 256)
++ return -EINVAL;
+
+- return 0;
+-}
++ set_lut(regno, r >> 8, g >> 8, b >> 8);
+
+-static int e1355_set_bpp(struct e1355_par *par, int bpp)
+-{
+- int code;
+- u8 disp;
+- u16 bytes_per_line;
+-
+- switch(bpp) {
+- case 1:
+- code = 0; break;
+- case 2:
+- code = 1; break;
+- case 4:
+- code = 2; break;
+- case 8:
+- code = 3; break;
+- case 16:
+- code = 5; break;
++ break;
+ default:
+- return -EINVAL; break;
++ return -ENOSYS;
+ }
+-
+- disp = e1355_read_reg(E1355_DISPLAY);
+- disp &= ~0x1c;
+- disp |= code << 2;
+- e1355_write_reg(disp, E1355_DISPLAY);
+-
+- bytes_per_line = (par->xres * bpp) >> 3;
+-
+- e1355_write_reg16(bytes_per_line, 0x16);
+-
+- par->bpp = bpp;
+-
+ return 0;
+ }
+-
+-static int e1355_decode_var(const struct fb_var_screeninfo *var,
+- void *raw_par,
+- struct fb_info_gen *info)
++
++/* ------------------------------------------------------------------------- */
++
++/**
++ * epson1355fb_pan_display - Pans the display.
++ * @var: frame buffer variable screen structure
++ * @info: frame buffer structure that represents a single frame buffer
++ *
++ * Pan (or wrap, depending on the `vmode' field) the display using the
++ * `xoffset' and `yoffset' fields of the `var' structure.
++ * If the values don't fit, return -EINVAL.
++ *
++ * Returns negative errno on error, or zero on success.
++ */
++static int epson1355fb_pan_display(struct fb_var_screeninfo *var,
++ struct fb_info *info)
+ {
+- struct e1355_par *par = raw_par;
+- int ret;
++ u32 start;
+
+- if (!par)
+- BUG();
++ if (var->xoffset != 0) /* not yet ... */
++ return -EINVAL;
+
+- /*
+- * Don't allow setting any of these yet: xres and yres don't
+- * make sense for LCD panels; xres_virtual and yres_virtual
+- * should be supported fine by our hardware though.
+- */
+- if (var->xres != par->xres ||
+- var->yres != par->yres ||
+- var->xres != var->xres_virtual ||
+- var->yres != var->yres_virtual ||
+- var->xoffset != 0 ||
+- var->yoffset != 0)
++ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ return -EINVAL;
+
+- if(var->bits_per_pixel != par->bpp) {
+- ret = e1355_set_bpp(par, var->bits_per_pixel);
++ start = (info->fix.line_length >> 1) * var->yoffset;
+
+- if (ret)
+- goto out_err;
+- }
+-
+- return 0;
++ epson1355_write_reg20(start, REG_SCRN1_DISP_START_ADDR0);
+
+- out_err:
+- return ret;
++ return 0;
+ }
+
+-static void dump_panel_data(void)
++/* ------------------------------------------------------------------------- */
++
++static void lcd_enable(int enable)
+ {
+- u8 panel = e1355_read_reg(E1355_PANEL);
+- int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
++ u8 mode = epson1355_read_reg(REG_DISPLAY_MODE);
+
+- printk("%s %s %s panel, width %d bits\n",
+- panel & 2 ? "dual" : "single",
+- panel & 4 ? "color" : "mono",
+- panel & 1 ? "TFT" : "passive",
+- width[panel&1][(panel>>4)&3]);
++ if (enable)
++ mode |= 1;
++ else
++ mode &= ~1;
+
+- printk("resolution %d x %d\n",
+- (e1355_read_reg(0x04) + 1) * 8,
+- ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
++ epson1355_write_reg(mode, REG_DISPLAY_MODE);
+ }
+
+-static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
++#if defined(CONFIG_ARCH_CEIVA)
++static void backlight_enable(int enable)
+ {
+- switch(bpp) {
+- case 1:
+- case 2:
+- case 4:
+- case 8:
+- var->bits_per_pixel = bpp;
+- var->red.offset = var->green.offset = var->blue.offset = 0;
+- var->red.length = var->green.length = var->blue.length = bpp;
++ /* ### this should be protected by a spinlock ... */
++ u8 pddr = clps_readb(PDDR);
++ if (enable)
++ pddr |= (1 << 5);
++ else
++ pddr &= ~(1 << 5);
++ clps_writeb(pddr, PDDR);
++}
++#else
++static void backlight_enable(int enable)
++{
++}
++#endif
++
++
++/**
++ * epson1355fb_blank - blanks the display.
++ * @blank_mode: the blank mode we want.
++ * @info: frame buffer structure that represents a single frame buffer
++ *
++ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
++ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
++ * video mode which doesn't support it. Implements VESA suspend
++ * and powerdown modes on hardware that supports disabling hsync/vsync:
++ * blank_mode == 2: suspend vsync
++ * blank_mode == 3: suspend hsync
++ * blank_mode == 4: powerdown
++ *
++ * Returns negative errno on error, or zero on success.
++ *
++ */
++static int epson1355fb_blank(int blank_mode, struct fb_info *info)
++{
++ switch (blank_mode) {
++ case VESA_NO_BLANKING:
++ lcd_enable(1);
++ backlight_enable(1);
+ break;
+- case 16:
+- var->bits_per_pixel = 16;
+- var->red.offset = 11;
+- var->red.length = 5;
+- var->green.offset = 5;
+- var->green.length = 6;
+- var->blue.offset = 0;
+- var->blue.length = 5;
++ case VESA_VSYNC_SUSPEND:
++ case VESA_HSYNC_SUSPEND:
++ backlight_enable(0);
+ break;
++ case VESA_POWERDOWN:
++ backlight_enable(0);
++ lcd_enable(0);
++ break;
++ default:
++ return -EINVAL;
+ }
+-
+ return 0;
+ }
+
+-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
+- struct fb_info_gen *info)
++/* ------------------------------------------------------------------------- */
++
++/*
++ * We can't use the cfb generic routines, as we have to limit
++ * ourselves to 16-bit or 8-bit loads and stores to this 16-bit
++ * chip.
++ */
++
++static inline void epson1355fb_fb_writel(unsigned long v, unsigned long *a)
+ {
+- u8 panel, display;
+- u32 xres, xres_virtual, yres;
+- static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+- static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
+- int bpp, hw_bpp;
+- int is_color, is_dual, is_tft;
+- int lcd_enabled, crt_enabled;
++ u16 *p = (u16 *) a;
++ u16 l = v & 0xffff;
++ u16 h = v >> 16;
+
+- panel = e1355_read_reg(E1355_PANEL);
+- display = e1355_read_reg(E1355_DISPLAY);
++ fb_writew(l, p);
++ fb_writew(h, p + 1);
++}
+
+- is_color = (panel & 0x04) != 0;
+- is_dual = (panel & 0x02) != 0;
+- is_tft = (panel & 0x01) != 0;
++static inline unsigned long epson1355fb_fb_readl(const unsigned long *a)
++{
++ const u16 *p = (u16 *) a;
++ u16 l = fb_readw(p);
++ u16 h = fb_readw(p + 1);
+
+- bpp = bpp_tab[(display>>2)&7];
+- e1355_bpp_to_var(bpp, var);
++ return (h << 16) | l;
++}
+
+- crt_enabled = (display & 0x02) != 0;
+- lcd_enabled = (display & 0x02) != 0;
++#define FB_READL epson1355fb_fb_readl
++#define FB_WRITEL epson1355fb_fb_writel
+
+- hw_bpp = width[is_tft][(panel>>4)&3];
++/* ------------------------------------------------------------------------- */
+
+- xres = e1355_read_reg(0x04) + 1;
+- yres = e1355_read_reg16(0x08) + 1;
+-
+- xres *= 8;
+- /* talk about weird hardware .. */
+- yres *= (is_dual && !crt_enabled) ? 2 : 1;
+-
+- xres_virtual = e1355_read_reg16(0x16);
+- /* it's in 2-byte words initially */
+- xres_virtual *= 16;
+- xres_virtual /= var->bits_per_pixel;
++static inline unsigned long copy_from_user16(void *to, const void *from,
++ unsigned long n)
++{
++ u16 *dst = (u16 *) to;
++ u16 *src = (u16 *) from;
+
+- var->xres = xres;
+- var->yres = yres;
+- var->xres_virtual = xres_virtual;
+- var->yres_virtual = yres;
++ if (!access_ok(VERIFY_READ, from, n))
++ return n;
+
+- var->xoffset = var->yoffset = 0;
++ while (n > 1) {
++ u16 v;
++ if (__get_user(v, src))
++ return n;
+
+- var->grayscale = !is_color;
+-
+- return 0;
+-}
++ fb_writew(v, dst);
+
+-#define is_dual(panel) (((panel)&3)==2)
++ src++, dst++;
++ n -= 2;
++ }
+
+-static void get_panel_data(struct e1355_par *par)
+-{
+- u8 panel;
+- int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
++ if (n) {
++ u8 v;
+
+- panel = e1355_read_reg(E1355_PANEL);
++ if (__get_user(v, ((u8 *) src)))
++ return n;
+
+- par->panel_width = width[panel&1][(panel>>4)&3];
+- par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
+- par->panel_ymul = is_dual(panel) ? 2 : 1;
+- par->panel_yres = ((e1355_read_reg16(0x08) + 1)
+- * par->panel_ymul);
++ fb_writeb(v, dst);
++ }
++ return 0;
+ }
+
+-static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
++static inline unsigned long copy_to_user16(void *to, const void *from,
++ unsigned long n)
+ {
+- struct e1355_par *par = raw_par;
++ u16 *dst = (u16 *) to;
++ u16 *src = (u16 *) from;
+
+- get_panel_data(par);
+-}
++ if (!access_ok(VERIFY_WRITE, to, n))
++ return n;
+
+-static void e1355_set_par(const void *par, struct fb_info_gen *info)
+-{
+-}
++ while (n > 1) {
++ u16 v = fb_readw(src);
+
+-static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+- unsigned *blue, unsigned *transp,
+- struct fb_info *info)
+-{
+- u8 r, g, b;
++ if (__put_user(v, dst))
++ return n;
+
+- e1355_write_reg(regno, E1355_LUT_INDEX);
+- r = e1355_read_reg(E1355_LUT_DATA);
+- g = e1355_read_reg(E1355_LUT_DATA);
+- b = e1355_read_reg(E1355_LUT_DATA);
++ src++, dst++;
++ n -= 2;
++ }
+
+- *red = r << 8;
+- *green = g << 8;
+- *blue = b << 8;
++ if (n) {
++ u8 v = fb_readb(src);
+
++ if (__put_user(v, ((u8 *) dst)))
++ return n;
++ }
+ return 0;
+ }
+
+-static int e1355fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+- unsigned blue, unsigned transp,
+- struct fb_info *info)
+-{
+- u8 r = (red >> 8) & 0xf0;
+- u8 g = (green>>8) & 0xf0;
+- u8 b = (blue>> 8) & 0xf0;
+-
+- e1355_write_reg(regno, E1355_LUT_INDEX);
+- e1355_write_reg(r, E1355_LUT_DATA);
+- e1355_write_reg(g, E1355_LUT_DATA);
+- e1355_write_reg(b, E1355_LUT_DATA);
+-
+- return 0;
+-}
+
+-static int e1355_pan_display(const struct fb_var_screeninfo *var,
+- struct fb_info_gen *info)
++static ssize_t
++epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+ {
+- BUG();
+-
+- return -EINVAL;
++ unsigned long p = *ppos;
++
++ /* from fbmem.c except for our own copy_*_user */
++ if (p >= info.fix.smem_len)
++ return 0;
++ if (count >= info.fix.smem_len)
++ count = info.fix.smem_len;
++ if (count + p > info.fix.smem_len)
++ count = info.fix.smem_len - p;
++
++ if (count) {
++ char *base_addr;
++
++ base_addr = info.screen_base;
++ count -= copy_to_user16(buf, base_addr + p, count);
++ if (!count)
++ return -EFAULT;
++ *ppos += count;
++ }
++ return count;
+ }
+
+-/*
+- * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
+- * I'm not sure they aren't dangerous to the hardware, so be warned.
+- */
+-#undef AERO_HACKS
++static ssize_t
++epson1355fb_write(struct file *file, const char *buf,
++ size_t count, loff_t * ppos)
++{
++ unsigned long p = *ppos;
++ int err;
++
++ /* from fbmem.c except for our own copy_*_user */
++ if (p > info.fix.smem_len)
++ return -ENOSPC;
++ if (count >= info.fix.smem_len)
++ count = info.fix.smem_len;
++ err = 0;
++ if (count + p > info.fix.smem_len) {
++ count = info.fix.smem_len - p;
++ err = -ENOSPC;
++ }
+
+-static int e1355_blank(int blank_mode, struct fb_info_gen *info)
+-{
+- u8 disp;
++ if (count) {
++ char *base_addr;
+
+- switch (blank_mode) {
+- case VESA_NO_BLANKING:
+- disp = e1355_read_reg(E1355_DISPLAY);
+- disp |= 1;
+- e1355_write_reg(disp, E1355_DISPLAY);
+-
+-#ifdef AERO_HACKS
+- e1355_write_reg(0x6, 0x20);
+-#endif
+- break;
++ base_addr = info.screen_base;
++ count -= copy_from_user16(base_addr + p, buf, count);
++ *ppos += count;
++ err = -EFAULT;
++ }
++ if (count)
++ return count;
++ return err;
++}
++
++/* ------------------------------------------------------------------------- */
++
++static struct fb_ops epson1355fb_fbops = {
++ .owner = THIS_MODULE,
++ .fb_setcolreg = epson1355fb_setcolreg,
++ .fb_pan_display = epson1355fb_pan_display,
++ .fb_blank = epson1355fb_blank,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_read = epson1355fb_read,
++ .fb_write = epson1355fb_write,
++ .fb_cursor = soft_cursor,
++};
+
+- case VESA_VSYNC_SUSPEND:
+- case VESA_HSYNC_SUSPEND:
+- case VESA_POWERDOWN:
+- disp = e1355_read_reg(E1355_DISPLAY);
+- disp &= ~1;
+- e1355_write_reg(disp, E1355_DISPLAY);
++/* ------------------------------------------------------------------------- */
+
+-#ifdef AERO_HACKS
+- e1355_write_reg(0x0, 0x20);
+-#endif
+- break;
++static __init unsigned int get_fb_size(struct fb_info *info)
++{
++ unsigned int size = 2 * 1024 * 1024;
++ char *p = info->screen_base;
+
+- default:
+- return -EINVAL;
+- }
++ /* the 512k framebuffer is aliased at start + 0x80000 * n */
++ fb_writeb(1, p);
++ fb_writeb(0, p + 0x80000);
++ if (!fb_readb(p))
++ size = 512 * 1024;
+
+- return 0;
++ fb_writeb(0, p);
++
++ return size;
+ }
+
+-static struct display_switch e1355_dispsw;
++static int epson1355_width_tab[2][4] __initdata =
++ { {4, 8, 16, -1}, {9, 12, 16, -1} };
++static int epson1355_bpp_tab[8] __initdata = { 1, 2, 4, 8, 15, 16 };
+
+-static void e1355_set_disp(const void *unused, struct display *disp,
+- struct fb_info_gen *info)
++static void __init fetch_hw_state(struct fb_info *info)
+ {
+- struct display_switch *d;
++ struct fb_var_screeninfo *var = &info->var;
++ struct fb_fix_screeninfo *fix = &info->fix;
++ u8 panel, display;
++ u16 offset;
++ u32 xres, yres;
++ u32 xres_virtual, yres_virtual;
++ int bpp, lcd_bpp;
++ int is_color, is_dual, is_tft;
++ int lcd_enabled, crt_enabled;
++
++ fix->type = FB_TYPE_PACKED_PIXELS;
+
+- disp->dispsw = &e1355_dispsw;
+-
+- switch(disp->var.bits_per_pixel) {
+-#ifdef FBCON_HAS_MFB
+- case 1:
+- d = &fbcon_mfb; break;
+-#endif
+-#ifdef FBCON_HAS_CFB8
++ display = epson1355_read_reg(REG_DISPLAY_MODE);
++ bpp = epson1355_bpp_tab[(display >> 2) & 7];
++
++ switch (bpp) {
+ case 8:
+- d = &fbcon_cfb8; break;
+-#endif
++ fix->visual = FB_VISUAL_PSEUDOCOLOR;
++ var->bits_per_pixel = 8;
++ var->red.offset = var->green.offset = var->blue.offset = 0;
++ var->red.length = var->green.length = var->blue.length = 8;
++ break;
++ case 16:
++ /* 5-6-5 RGB */
++ fix->visual = FB_VISUAL_TRUECOLOR;
++ var->bits_per_pixel = 16;
++ var->red.offset = 11;
++ var->red.length = 5;
++ var->green.offset = 5;
++ var->green.length = 6;
++ var->blue.offset = 0;
++ var->blue.length = 5;
++ break;
+ default:
+- BUG(); break;
++ BUG();
+ }
+
+- memcpy(&e1355_dispsw, d, sizeof *d);
++ if (fix->visual == FB_VISUAL_TRUECOLOR) {
++ info->pseudo_palette = &pseudo_palette;
++ fb_alloc_cmap(&(info->cmap), 16, 0);
++ } else
++ fb_alloc_cmap(&(info->cmap), 1 << bpp, 0);
++
++ panel = epson1355_read_reg(REG_PANEL_TYPE);
++ is_color = (panel & 0x04) != 0;
++ is_dual = (panel & 0x02) != 0;
++ is_tft = (panel & 0x01) != 0;
++ crt_enabled = (display & 0x02) != 0;
++ lcd_enabled = (display & 0x01) != 0;
++ lcd_bpp = epson1355_width_tab[is_tft][(panel >> 4) & 3];
++
++ xres = (epson1355_read_reg(REG_HORZ_DISP_WIDTH) + 1) * 8;
++ yres = (epson1355_read_reg16(REG_VERT_DISP_HEIGHT0) + 1) *
++ ((is_dual && !crt_enabled) ? 2 : 1);
++ offset = epson1355_read_reg16(REG_MEM_ADDR_OFFSET0) & 0x7ff;
++ xres_virtual = offset * 16 / bpp;
++ yres_virtual = fix->smem_len / (offset * 2);
++
++ var->xres = xres;
++ var->yres = yres;
++ var->xres_virtual = xres_virtual;
++ var->yres_virtual = yres_virtual;
++ var->xoffset = var->yoffset = 0;
+
+- /* reading is terribly slow for us */
+-#if 0 /* XXX: need to work out why this doesn't work */
+- e1355_dispsw.bmove = fbcon_redraw_bmove;
++ fix->line_length = offset * 2;
++
++ fix->xpanstep = 0; /* no pan yet */
++ fix->ypanstep = 1;
++ fix->ywrapstep = 0;
++ fix->accel = FB_ACCEL_NONE;
++
++ var->grayscale = !is_color;
++
++#ifdef DEBUG
++ printk(KERN_INFO
++ "epson1355fb: xres=%d, yres=%d, "
++ "is_color=%d, is_dual=%d, is_tft=%d\n",
++ xres, yres, is_color, is_dual, is_tft);
++ printk(KERN_INFO
++ "epson1355fb: bpp=%d, lcd_bpp=%d, "
++ "crt_enabled=%d, lcd_enabled=%d\n",
++ bpp, lcd_bpp, crt_enabled, lcd_enabled);
+ #endif
+ }
+
+-/* ------------ Interfaces to hardware functions ------------ */
+
++static void clearfb16(struct fb_info *info)
++{
++ u16 *dst = (u16 *) info->screen_base;
++ unsigned long n = info->fix.smem_len;
+
+-struct fbgen_hwswitch e1355_switch = {
+- .detect = e1355_detect,
+- .encode_fix = e1355_encode_fix,
+- .decode_var = e1355_decode_var,
+- .encode_var = e1355_encode_var,
+- .get_par = e1355_get_par,
+- .set_par = e1355_set_par,
+- .getcolreg = e1355_getcolreg,
+- .pan_display = e1355_pan_display,
+- .blank = e1355_blank,
+- .set_disp = e1355_set_disp,
+-};
++ while (n > 1) {
++ fb_writew(0, dst);
++ dst++, n -= 2;
++ }
+
++ if (n)
++ fb_writeb(0, dst);
++}
+
+-/* ------------ Hardware Independent Functions ------------ */
++static void epson1355fb_deinit(void);
+
++int __init epson1355fb_init(void)
++{
++ u8 revision;
++ int rc = 0;
+
+-static struct fb_ops e1355fb_ops = {
+- .owner = THIS_MODULE,
+- .fb_get_fix = fbgen_get_fix,
+- .fb_get_var = fbgen_get_var,
+- .fb_set_var = fbgen_set_var,
+- .fb_get_cmap = fbgen_get_cmap,
+- .fb_set_cmap = gen_set_cmap,
+- .fb_setcolreg = e1355fb_setcolreg,
+- .fb_pan_display =fbgen_pan_display,
+- .fb_blank = fbgen_blank,
+-};
++ if (!request_mem_region
++ (EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN,
++ "S1D13505 registers")) {
++ printk(KERN_ERR "epson1355fb: unable to reserve "
++ "registers at 0x%0x\n", EPSON1355FB_REGS_PHYS);
++ rc = -EBUSY;
++ goto bail;
++ }
+
+-static struct e1355fb_info fb_info;
++ if (!request_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN,
++ "S1D13505 framebuffer")) {
++ printk(KERN_ERR "epson1355fb: unable to reserve "
++ "framebuffer at 0x%0x\n", EPSON1355FB_FB_PHYS);
++ rc = -EBUSY;
++ goto bail;
++ }
++
++ par.reg_addr = (unsigned long)
++ ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
++ if (!par.reg_addr) {
++ printk(KERN_ERR "epson1355fb: unable to map registers\n");
++ rc = -ENOMEM;
++ goto bail;
++ }
++
++ info.screen_base =
++ ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
++ if (!info.screen_base) {
++ printk(KERN_ERR
++ "epson1355fb: unable to map framebuffer\n");
++ rc = -ENOMEM;
++ goto bail;
++ }
++
++ revision = epson1355_read_reg(REG_REVISION_CODE);
++ if ((revision >> 2) != 3) {
++ printk(KERN_INFO "epson1355fb: epson1355 not found\n");
++ rc = -ENODEV;
++ goto bail;
++ }
++
++ info.fix.mmio_start = EPSON1355FB_REGS_PHYS;
++ info.fix.mmio_len = EPSON1355FB_REGS_LEN;
++ info.fix.smem_start = EPSON1355FB_FB_PHYS;
++ info.fix.smem_len = get_fb_size(&info);
++
++ printk(KERN_INFO
++ "epson1355fb: regs mapped at 0x%lx, fb %d KiB mapped at 0x%p\n",
++ par.reg_addr, info.fix.smem_len / 1024, info.screen_base);
++
++ strcpy(info.fix.id, "S1D13505");
++ info.par = ∥
++ info.node = NODEV;
++ info.fbops = &epson1355fb_fbops;
++ info.flags = FBINFO_FLAG_DEFAULT;
++
++ /* we expect the boot loader to have initialized the chip
++ with appropriate parameters from which we can determinte
++ the flavor of lcd panel attached */
++ fetch_hw_state(&info);
++
++ /* turn this puppy on ... */
++ clearfb16(&info);
++ backlight_enable(1);
++ lcd_enable(1);
++
++ if (register_framebuffer(&info) < 0) {
++ rc = -EINVAL;
++ goto bail;
++ }
++
++ printk(KERN_INFO "fb%d: %s frame buffer device\n",
++ minor(info.node), info.fix.id);
+
+-int __init e1355fb_setup(char *str)
+-{
+ return 0;
++
++ bail:
++ epson1355fb_deinit();
++ return rc;
+ }
+
+-int __init e1355fb_init(void)
++static void epson1355fb_deinit(void)
+ {
+- fb_info.gen.fbhw = &e1355_switch;
+- fb_info.gen.fbhw->detect();
+- strcpy(fb_info.gen.info.modename, "SED1355");
+- fb_info.gen.info.changevar = NULL;
+- fb_info.gen.info.fbops = &e1355fb_ops;
+- fb_info.gen.info.screen_base = (void *)E1355_FB_BASE;
+- fb_info.gen.currcon = -1;
+- fb_info.gen.info.disp = &disp;
+- fb_info.gen.parsize = sizeof(struct e1355_par);
+- fb_info.gen.info.switch_con = &fbgen_switch;
+- fb_info.gen.info.updatevar = &fbgen_update_var;
+- fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+- /* This should give a reasonable default video mode */
+- fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+- fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+- fbgen_set_disp(-1, &fb_info.gen);
+- if (disp.var.bits_per_pixel > 1)
+- do_install_cmap(0, &fb_info.gen);
+- if (register_framebuffer(&fb_info.gen.info) < 0)
+- return -EINVAL;
+- printk(KERN_INFO "fb%d: %s frame buffer device\n", fb_info.gen.info.node,
+- fb_info.gen.info.modename);
++ fb_dealloc_cmap(&info.cmap);
+
+- return 0;
++ if (info.screen_base)
++ iounmap(info.screen_base);
++ if (par.reg_addr)
++ iounmap((void *) par.reg_addr);
++
++ release_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
++ release_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
+ }
+
++static void __exit epson1355fb_cleanup(void)
++{
++ backlight_enable(0);
++ lcd_enable(0);
+
+- /*
+- * Cleanup
+- */
+-
+-void e1355fb_cleanup(struct fb_info *info)
+-{
+- /*
+- * If your driver supports multiple boards, you should unregister and
+- * clean up all instances.
+- */
+-
+- unregister_framebuffer(info);
+- /* ... */
++ unregister_framebuffer(&info);
++ epson1355fb_deinit();
+ }
+
++/* ------------------------------------------------------------------------- */
++
++#ifdef MODULE
++module_init(epson1355fb_init);
++#endif
++module_exit(epson1355fb_cleanup);
++
++MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>");
++MODULE_DESCRIPTION("Framebuffer driver for Epson S1D13505");
+ MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/drivers/video/fbmem.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/video/fbmem.c 2003-10-05 00:34:22.000000000 -0700
+@@ -25,7 +25,6 @@
+ #include <linux/mman.h>
+ #include <linux/tty.h>
+ #include <linux/init.h>
+-#include <linux/linux_logo.h>
+ #include <linux/proc_fs.h>
+ #ifdef CONFIG_KMOD
+ #include <linux/kmod.h>
+@@ -102,13 +101,13 @@ extern int hgafb_setup(char*);
+ extern int matroxfb_init(void);
+ extern int matroxfb_setup(char*);
+ extern int hpfb_init(void);
+-extern int control_init(void);
+-extern int control_setup(char*);
+-extern int platinum_init(void);
+-extern int platinum_setup(char*);
++extern int controlfb_init(void);
++extern int controlfb_setup(char*);
++extern int platinumfb_init(void);
++extern int platinumfb_setup(char*);
+ extern int valkyriefb_init(void);
+ extern int valkyriefb_setup(char*);
+-extern int chips_init(void);
++extern int chipsfb_init(void);
+ extern int g364fb_init(void);
+ extern int sa1100fb_init(void);
+ extern int fm2fb_init(void);
+@@ -135,14 +134,14 @@ extern int tx3912fb_init(void);
+ extern int tx3912fb_setup(char*);
+ extern int radeonfb_init(void);
+ extern int radeonfb_setup(char*);
+-extern int e1355fb_init(void);
+-extern int e1355fb_setup(char*);
++extern int epson1355fb_init(void);
+ extern int pvr2fb_init(void);
+ extern int pvr2fb_setup(char*);
+ extern int sstfb_init(void);
+ extern int sstfb_setup(char*);
+ extern int i810fb_init(void);
+ extern int i810fb_setup(char*);
++extern int asiliantfb_init(void);
+ extern int ffb_init(void);
+ extern int ffb_setup(char*);
+ extern int cg6_init(void);
+@@ -221,16 +220,16 @@ static struct {
+ { "radeonfb", radeonfb_init, radeonfb_setup },
+ #endif
+ #ifdef CONFIG_FB_CONTROL
+- { "controlfb", control_init, control_setup },
++ { "controlfb", controlfb_init, controlfb_setup },
+ #endif
+ #ifdef CONFIG_FB_PLATINUM
+- { "platinumfb", platinum_init, platinum_setup },
++ { "platinumfb", platinumfb_init, platinumfb_setup },
+ #endif
+ #ifdef CONFIG_FB_VALKYRIE
+ { "valkyriefb", valkyriefb_init, valkyriefb_setup },
+ #endif
+ #ifdef CONFIG_FB_CT65550
+- { "chipsfb", chips_init, NULL },
++ { "chipsfb", chipsfb_init, NULL },
+ #endif
+ #ifdef CONFIG_FB_IMSTT
+ { "imsttfb", imsttfb_init, imsttfb_setup },
+@@ -342,8 +341,8 @@ static struct {
+ #ifdef CONFIG_FB_TX3912
+ { "tx3912fb", tx3912fb_init, tx3912fb_setup },
+ #endif
+-#ifdef CONFIG_FB_E1355
+- { "e1355fb", e1355fb_init, e1355fb_setup },
++#ifdef CONFIG_FB_EPSON1355
++ { "s1d1355fb", epson1355fb_init, NULL },
+ #endif
+ #ifdef CONFIG_FB_PVR2
+ { "pvr2fb", pvr2fb_init, pvr2fb_setup },
+@@ -360,6 +359,10 @@ static struct {
+ #ifdef CONFIG_FB_VOODOO1
+ { "sstfb", sstfb_init, sstfb_setup },
+ #endif
++#ifdef CONFIG_FB_ASILIANT
++ { "asiliantfb", asiliantfb_init, NULL },
++#endif
++
+ /*
+ * Generic drivers that don't use resource management (yet)
+ */
+@@ -409,20 +412,20 @@ void sys_outbuf(u8 *src, u8 *dst, unsign
+ memcpy(dst, src, size);
+ }
+
+-void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
+- u32 s_pitch, u32 height)
++void move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf, u8 *dst, u8 *src,
++ u32 d_pitch, u32 s_pitch, u32 height)
+ {
+ int i;
+
+ for (i = height; i--; ) {
+- info->pixmap.outbuf(src, dst, s_pitch);
++ buf->outbuf(src, dst, s_pitch);
+ src += s_pitch;
+ dst += d_pitch;
+ }
+ }
+
+-void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
+- u32 height, u32 mask, u32 shift_high, u32 shift_low,
++void move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf, u8 *dst, u8 *src,
++ u32 d_pitch, u32 height, u32 mask, u32 shift_high, u32 shift_low,
+ u32 mod, u32 idx)
+ {
+ int i, j;
+@@ -430,21 +433,21 @@ void move_buf_unaligned(struct fb_info *
+
+ for (i = height; i--; ) {
+ for (j = 0; j < idx; j++) {
+- tmp = info->pixmap.inbuf(dst+j);
++ tmp = buf->inbuf(dst+j);
+ tmp &= mask;
+ tmp |= *src >> shift_low;
+- info->pixmap.outbuf(&tmp, dst+j, 1);
++ buf->outbuf(&tmp, dst+j, 1);
+ tmp = *src << shift_high;
+- info->pixmap.outbuf(&tmp, dst+j+1, 1);
++ buf->outbuf(&tmp, dst+j+1, 1);
+ src++;
+ }
+- tmp = info->pixmap.inbuf(dst+idx);
++ tmp = buf->inbuf(dst+idx);
+ tmp &= mask;
+ tmp |= *src >> shift_low;
+- info->pixmap.outbuf(&tmp, dst+idx, 1);
++ buf->outbuf(&tmp, dst+idx, 1);
+ if (shift_high < mod) {
+ tmp = *src << shift_high;
+- info->pixmap.outbuf(&tmp, dst+idx+1, 1);
++ buf->outbuf(&tmp, dst+idx+1, 1);
+ }
+ src++;
+ dst += d_pitch;
+@@ -455,26 +458,29 @@ void move_buf_unaligned(struct fb_info *
+ * we need to lock this section since fb_cursor
+ * may use fb_imageblit()
+ */
+-u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
++char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
+ {
+- u32 align = info->pixmap.buf_align - 1;
++ u32 align = buf->buf_align - 1;
+ u32 offset, count = 1000;
++ char *addr = buf->addr;
+
+- spin_lock(&info->pixmap.lock);
+- offset = info->pixmap.offset + align;
+- offset &= ~align;
+- if (offset + size > info->pixmap.size) {
+- while (atomic_read(&info->pixmap.count) && count--);
+- if (info->fbops->fb_sync &&
+- info->pixmap.flags & FB_PIXMAP_SYNC)
+- info->fbops->fb_sync(info);
+- offset = 0;
++ spin_lock(&buf->lock);
++ if (!(buf->flags & FB_PIXMAP_IO)) {
++ offset = buf->offset + align;
++ offset &= ~align;
++ if (offset + size > buf->size) {
++ while (atomic_read(&buf->count) && count--);
++ if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
++ info->fbops->fb_sync(info);
++ offset = 0;
++ }
++ buf->offset = offset + size;
++ addr += offset;
+ }
+- info->pixmap.offset = offset + size;
+- atomic_inc(&info->pixmap.count);
++ atomic_inc(&buf->count);
+ smp_mb__after_atomic_inc();
+- spin_unlock(&info->pixmap.lock);
+- return offset;
++ spin_unlock(&buf->lock);
++ return addr;
+ }
+
+ #ifdef CONFIG_LOGO
+@@ -656,7 +662,7 @@ int fb_prepare_logo(struct fb_info *info
+ }
+
+ /* Return if no suitable logo was found */
+- fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
++ fb_logo.logo = find_logo(info->var.bits_per_pixel);
+
+ if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
+ fb_logo.logo = NULL;
+@@ -726,8 +732,6 @@ int fb_show_logo(struct fb_info *info)
+ x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
+ image.dx = x;
+ info->fbops->fb_imageblit(info, &image);
+- //atomic_dec(&info->pixmap.count);
+- //smp_mb__after_atomic_dec();
+ }
+
+ if (palette != NULL)
+@@ -1238,6 +1242,22 @@ register_framebuffer(struct fb_info *fb_
+ fb_info->pixmap.inbuf = sys_inbuf;
+ spin_lock_init(&fb_info->pixmap.lock);
+
++ if (fb_info->sprite.addr == NULL) {
++ fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
++ if (fb_info->sprite.addr) {
++ fb_info->sprite.size = FBPIXMAPSIZE;
++ fb_info->sprite.buf_align = 1;
++ fb_info->sprite.scan_align = 1;
++ fb_info->sprite.flags = FB_PIXMAP_IO;
++ }
++ }
++ fb_info->sprite.offset = 0;
++ if (fb_info->sprite.outbuf == NULL)
++ fb_info->sprite.outbuf = sys_outbuf;
++ if (fb_info->sprite.inbuf == NULL)
++ fb_info->sprite.inbuf = sys_inbuf;
++ spin_lock_init(&fb_info->sprite.lock);
++
+ registered_fb[i] = fb_info;
+
+ devfs_mk_cdev(MKDEV(FB_MAJOR, i),
+@@ -1371,6 +1391,33 @@ int __init video_setup(char *options)
+
+ __setup("video=", video_setup);
+
++static int fbdev_dummy(void)
++{
++ return 0;
++}
++
++#define FBDEV_EMPTY (void *)fbdev_dummy
++
++const struct fb_ops dummy_fbdev = {
++ .fb_open = FBDEV_EMPTY,
++ .fb_release = FBDEV_EMPTY,
++ .fb_read = FBDEV_EMPTY,
++ .fb_write = FBDEV_EMPTY,
++ .fb_check_var = FBDEV_EMPTY,
++ .fb_set_par = FBDEV_EMPTY,
++ .fb_setcolreg = FBDEV_EMPTY,
++ .fb_blank = FBDEV_EMPTY,
++ .fb_pan_display = FBDEV_EMPTY,
++ .fb_fillrect = FBDEV_EMPTY,
++ .fb_copyarea = FBDEV_EMPTY,
++ .fb_imageblit = FBDEV_EMPTY,
++ .fb_cursor = FBDEV_EMPTY,
++ .fb_rotate = FBDEV_EMPTY,
++ .fb_sync = FBDEV_EMPTY,
++ .fb_ioctl = FBDEV_EMPTY,
++ .fb_mmap = FBDEV_EMPTY,
++};
++
+ /*
+ * Visible symbols for modules
+ */
+--- linux-2.6.0-test6/drivers/video/g364fb.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/drivers/video/g364fb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -127,20 +127,55 @@ static struct fb_ops g364fb_ops = {
+
+ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+ {
++
++ /* Turn the cursor off before we start changing it. */
++ *(unsigned int *) CTLA_REG |= CURS_TOGGLE;
++
++ if (cursor->set & FB_CUR_SETHOT)
++ info->cursor.hot = cursor->hot;
+
+- switch (cursor->enable) {
+- case CM_ERASE:
+- *(unsigned int *) CTLA_REG |= CURS_TOGGLE;
+- break;
++ if (cursor->set & FB_CUR_SETPOS) {
++ unsigned int tmp;
+
+- case CM_MOVE:
+- case CM_DRAW:
+- *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
+- *(unsigned int *) CURS_POS_REG =
+- ((x * fontwidth(p)) << 12) | ((y * fontheight(p)) -
+- info->var.yoffset);
+- break;
++ info->cursor.image.dx = cursor->image.dx;
++ info->cursor.image.dy = cursor->image.dy;
++
++ tmp = cursor->image.dy - info->var.yoffset;
++ tmp |= (cursor->image.dx - info->var.xoffset) << 12;
++
++ *(unsigned int *) CURS_POS_REG = tmp;
++ }
++
++ if (cursor->set & FB_CUR_SETSIZE) {
++ info->cursor.image.height = cursor->image.height;
++ info->cursor.image.width = cursor->image.width;
++
++ /* set the whole cursor to transparent */
++ for (i = 0; i < 512; i++)
++ *(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
+ }
++
++ if (cursor->set & FB_CUR_SETCMAP) {
++ volatile unsigned int *curs_pal_ptr =
++ (volatile unsigned int *) CURS_PAL_REG;
++
++ /* setup cursor */
++ curs_pal_ptr[0] |= 0x00ffffff;
++ curs_pal_ptr[2] |= 0x00ffffff;
++ curs_pal_ptr[4] |= 0x00ffffff;
++ }
++
++ if (cursor->set & FB_CUR_SETSHAPE) {
++ /*
++ * switch the last two lines to cursor palette 3
++ * we assume here, that FONTSIZE_X is 8
++ */
++ *(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
++ *(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
++ }
++
++ if (info->cursor.enable)
++ *(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
+ return 0;
+ }
+
+@@ -196,10 +231,6 @@ static int g364fb_setcolreg(u_int regno,
+ */
+ int __init g364fb_init(void)
+ {
+- volatile unsigned int *pal_ptr =
+- (volatile unsigned int *) CLR_PAL_REG;
+- volatile unsigned int *curs_pal_ptr =
+- (volatile unsigned int *) CURS_PAL_REG;
+ int mem, i, j;
+
+ /* TBD: G364 detection */
+@@ -212,23 +243,6 @@ int __init g364fb_init(void)
+ (*((volatile unsigned int *) VDISPLAY_REG) & 0x00ffffff) / 2;
+ *(volatile unsigned int *) CTLA_REG |= ENABLE_VTG;
+
+- /* setup cursor */
+- curs_pal_ptr[0] |= 0x00ffffff;
+- curs_pal_ptr[2] |= 0x00ffffff;
+- curs_pal_ptr[4] |= 0x00ffffff;
+-
+- /*
+- * first set the whole cursor to transparent
+- */
+- for (i = 0; i < 512; i++)
+- *(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
+-
+- /*
+- * switch the last two lines to cursor palette 3
+- * we assume here, that FONTSIZE_X is 8
+- */
+- *(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
+- *(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
+ fb_var.xres_virtual = fbvar.xres;
+ fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
+ fb_fix.smem_start = 0x40000000; /* physical address */
+--- linux-2.6.0-test6/drivers/video/i810/Makefile 2003-06-14 12:18:06.000000000 -0700
++++ 25/drivers/video/i810/Makefile 2003-10-05 00:34:22.000000000 -0700
+@@ -1,16 +1,9 @@
+ #
+ # Makefile for the Intel 810/815 framebuffer driver
+ #
+-# Note! Dependencies are done automagically by 'make dep', which also
+-# removes any old dependencies. DON'T put your own dependencies here
+-# unless it's something special (ie not a .c file).
+-#
+-# Note 2! The CFLAGS definitions are now in the main makefile...
+-
+
+ obj-$(CONFIG_FB_I810) += i810fb.o
+
+-
+ i810fb-objs := i810_main.o i810_accel.o
+
+ ifdef CONFIG_FB_I810_GTF
+--- linux-2.6.0-test6/drivers/video/imsttfb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/imsttfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1495,6 +1495,8 @@ imsttfb_probe(struct pci_dev *pdev, cons
+ default:
+ printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
+ "contact maintainer.\n", pdev->device);
++ release_mem_region(addr, size);
++ kfree(info);
+ return -ENODEV;
+ }
+
+--- linux-2.6.0-test6/drivers/video/Kconfig 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/video/Kconfig 2003-10-05 00:34:22.000000000 -0700
+@@ -188,19 +188,19 @@ config FB_AMIGA_AGA
+ otherwise say N.
+
+ config FB_CYBER
+- tristate "Amiga CyberVision support"
+- depends on FB && ZORRO
++ tristate "Amiga CyberVision 64 support"
++ depends on FB && ZORRO && BROKEN
+ help
+ This enables support for the Cybervision 64 graphics card from
+ Phase5. Please note that its use is not all that intuitive (i.e. if
+ you have any questions, be sure to ask!). Say N unless you have a
+ Cybervision 64 or plan to get one before you next recompile the
+ kernel. Please note that this driver DOES NOT support the
+- Cybervision 64 3D card, as they use incompatible video chips.
++ Cybervision 64/3D card, as they use incompatible video chips.
+
+ config FB_VIRGE
+- bool "Amiga CyberVision3D support "
+- depends on FB && ZORRO
++ bool "Amiga CyberVision 64/3D support "
++ depends on FB && ZORRO && BROKEN
+ help
+ This enables support for the Cybervision 64/3D graphics card from
+ Phase5. Please note that its use is not all that intuitive (i.e. if
+@@ -210,8 +210,8 @@ config FB_VIRGE
+ Cybervision 64 card, as they use incompatible video chips.
+
+ config FB_RETINAZ3
+- tristate "Amiga RetinaZ3 support"
+- depends on FB && ZORRO
++ tristate "Amiga Retina Z3 support"
++ depends on FB && ZORRO && BROKEN
+ help
+ This enables support for the Retina Z3 graphics card. Say N unless
+ you have a Retina Z3 or plan to get one before you next recompile
+@@ -226,7 +226,7 @@ config FB_FM2
+
+ config FB_ATARI
+ bool "Atari native chipset support"
+- depends on FB && ATARI
++ depends on FB && ATARI && BROKEN
+ help
+ This is the frame buffer device driver for the builtin graphics
+ chipset found in Ataris.
+@@ -266,6 +266,10 @@ config FB_CT65550
+ This is the frame buffer device driver for the Chips & Technologies
+ 65550 graphics chip in PowerBooks.
+
++config FB_ASILIANT
++ bool "Chips 69000 display support"
++ depends on FB && PCI
++
+ config FB_IMSTT
+ bool "IMS Twin Turbo display support"
+ depends on FB && PCI
+@@ -367,7 +371,7 @@ config BUS_I2C
+
+ config FB_SUN3
+ bool "Sun3 framebuffer support"
+- depends on FB && (SUN3 || SUN3X)
++ depends on FB && (SUN3 || SUN3X) && BROKEN
+
+ config FB_BW2
+ bool "BWtwo support"
+@@ -414,35 +418,15 @@ config FB_PVR2_DEBUG
+ messages. Most people will want to say N here. If unsure, you will
+ also want to say N.
+
+-config FB_E1355
++config FB_EPSON1355
+ bool "Epson 1355 framebuffer support"
+- depends on FB && SUPERH
++ depends on FB && (SUPERH || ARCH_CEIVA)
+ help
+ Build in support for the SED1355 Epson Research Embedded RAMDAC
+ LCD/CRT Controller (since redesignated as the S1D13505) as a
+ framebuffer. Product specs at
+ <http://www.erd.epson.com/vdc/html/products.htm>.
+
+-config E1355_REG_BASE
+- hex "Register Base Address"
+- depends on FB_E1355
+- default "a8000000"
+- help
+- Epson SED1355/S1D13505 LCD/CRT controller register base address.
+- See the manuals at
+- <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
+- discussion.
+-
+-config E1355_FB_BASE
+- hex "Framebuffer Base Address"
+- depends on FB_E1355
+- default "a8200000"
+- help
+- Epson SED1355/S1D13505 LCD/CRT controller memory base address. See
+- the manuals at
+- <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
+- discussion.
+-
+ config FB_RIVA
+ tristate "nVidia Riva support"
+ depends on FB && PCI
+@@ -703,26 +687,40 @@ config FB_ATY_XL_INIT
+ Say Y here to support booting a Rage XL without BIOS support.
+
+ config FB_SIS
+- tristate "SIS acceleration"
++ tristate "SiS acceleration"
+ depends on FB && PCI
+ help
+- This is the frame buffer device driver for the SiS 630 and 640 Super
+- Socket 7 UMA cards. Specs available at <http://www.sis.com.tw/>.
++ This is the frame buffer device driver for the SiS 300, 315 and Xabre
++ series VGA controller.
++
++ Specs available at <http://www.sis.com.tw/>.
++
++ See <http://www.winischhofer.net/linuxsisvga.shtml> for
++ documentation and updates.
++
++ The driver is also available as a module ( = code which can be
++ inserted and removed from the running kernel whenever you want). The
++ module will be called sisfb. If you want to compile it as a
++ module, say M here and read Documentation/modules.txt.
+
+ config FB_SIS_300
+- bool "SIS 630/540/730 support"
++ bool "SIS 300 series support"
+ depends on FB_SIS
+ help
+- This is the frame buffer device driver for the SiS 630 and related
+- Super Socket 7 UMA cards. Specs available at
+- <http://www.sis.com.tw/>.
++ This is the frame buffer device driver for the SiS 300 series VGA
++ controllers. This includes the 300, 540, 630, 730.
++ Documentation and updates available at
++ http://www.winischhofer.net/linuxsisvga.shtml
+
+ config FB_SIS_315
+- bool "SIS 315H/315 support"
++ bool "SIS 315/Xabre support"
+ depends on FB_SIS
+ help
+- This is the frame buffer device driver for the SiS 315 graphics
+- card. Specs available at <http://www.sis.com.tw/>.
++ This is the frame buffer device driver for the SiS 315 and Xabre
++ series VGA controllers. This includes the 315, 315H, 315PRO, 650,
++ 651, M650, 652, M652, 740, 330 (Xabre), 660, M660, 760, M760.
++ Documentation and updates available at
++ http://www.winischhofer.net/linuxsisvga.shtml
+
+ config FB_NEOMAGIC
+ tristate "NeoMagic display support"
+--- linux-2.6.0-test6/drivers/video/logo/logo.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/drivers/video/logo/logo.c 2003-10-05 00:34:22.000000000 -0700
+@@ -32,8 +32,7 @@ extern const struct linux_logo logo_supe
+ extern const struct linux_logo logo_superh_vga16;
+ extern const struct linux_logo logo_superh_clut224;
+
+-
+-const struct linux_logo *fb_find_logo(int depth)
++const struct linux_logo *find_logo(int depth)
+ {
+ const struct linux_logo *logo = 0;
+
+--- linux-2.6.0-test6/drivers/video/Makefile 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/video/Makefile 2003-10-05 00:34:22.000000000 -0700
+@@ -22,7 +22,7 @@ obj-$(CONFIG_FB_Q40) += q40
+ obj-$(CONFIG_FB_ATARI) += atafb.o
+ obj-$(CONFIG_FB_68328) += 68328fb.o
+ obj-$(CONFIG_FB_RADEON) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+-obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
++obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
+ obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+ obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+ obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+@@ -68,9 +68,10 @@ obj-$(CONFIG_FB_HGA) += hga
+ obj-$(CONFIG_FB_SA1100) += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+ obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+-obj-$(CONFIG_FB_E1355) += epson1355fb.o
+-obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
++obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
++obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbcillrect.o cfbcopyarea.o cfbimgblt.o
+ obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
++obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+
+ obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+ obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+--- linux-2.6.0-test6/drivers/video/neofb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/neofb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -81,9 +81,10 @@ extern int tosh_smm(SMMRegisters *regs);
+ #include <asm/mtrr.h>
+ #endif
+
++#include <video/vga.h>
+ #include <video/neomagic.h>
+
+-#define NEOFB_VERSION "0.4.1"
++#define NEOFB_VERSION "0.4.2"
+
+ /* --------------------------------------------------------------------- */
+
+@@ -152,6 +153,16 @@ static biosMode bios32[] = {
+ };
+ #endif
+
++static inline u32 read_le32(int regindex, const struct neofb_par *par)
++{
++ return readl(par->neo2200 + par->cursorOff + regindex);
++}
++
++static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
++{
++ writel(val, par->neo2200 + par->cursorOff + regindex);
++}
++
+ static int neoFindMode(int xres, int yres, int depth)
+ {
+ int xres_s;
+@@ -363,44 +374,61 @@ static int vgaHWInit(const struct fb_var
+ par->Attribute[18] = 0x0F;
+ par->Attribute[19] = 0x00;
+ par->Attribute[20] = 0x00;
+-
+ return 0;
+ }
+
+-static void vgaHWLock(void)
++static void vgaHWLock(struct vgastate *state)
+ {
+ /* Protect CRTC[0-7] */
+- VGAwCR(0x11, VGArCR(0x11) | 0x80);
++ vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
+ }
+
+ static void vgaHWUnlock(void)
+ {
+ /* Unprotect CRTC[0-7] */
+- VGAwCR(0x11, VGArCR(0x11) & ~0x80);
++ vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
+ }
+
+-static void neoLock(void)
++static void neoLock(struct vgastate *state)
+ {
+- VGAwGR(0x09, 0x00);
+- vgaHWLock();
++ vga_wgfx(state->vgabase, 0x09, 0x00);
++ vgaHWLock(state);
+ }
+
+ static void neoUnlock(void)
+ {
+ vgaHWUnlock();
+- VGAwGR(0x09, 0x26);
++ vga_wgfx(NULL, 0x09, 0x26);
+ }
+
+ /*
+- * vgaHWSeqReset
+- * perform a sequencer reset.
++ * VGA Palette management
+ */
+-void vgaHWSeqReset(int start)
++static int paletteEnabled = 0;
++
++inline void VGAenablePalette(void)
+ {
+- if (start)
+- VGAwSEQ(0x00, 0x01); /* Synchronous Reset */
++ vga_r(NULL, VGA_IS1_RC);
++ vga_w(NULL, VGA_ATT_W, 0x00);
++ paletteEnabled = 1;
++}
++
++inline void VGAdisablePalette(void)
++{
++ vga_r(NULL, VGA_IS1_RC);
++ vga_w(NULL, VGA_ATT_W, 0x20);
++ paletteEnabled = 0;
++}
++
++inline void VGAwATTR(u8 index, u8 value)
++{
++ if (paletteEnabled)
++ index &= ~0x20;
+ else
+- VGAwSEQ(0x00, 0x03); /* End Reset */
++ index |= 0x20;
++
++ vga_r(NULL, VGA_IS1_RC);
++ vga_wattr(NULL, index, value);
+ }
+
+ void vgaHWProtect(int on)
+@@ -411,21 +439,18 @@ void vgaHWProtect(int on)
+ /*
+ * Turn off screen and disable sequencer.
+ */
+- tmp = VGArSEQ(0x01);
+-
+- vgaHWSeqReset(1); /* start synchronous reset */
+- VGAwSEQ(0x01, tmp | 0x20); /* disable the display */
++ tmp = vga_rseq(NULL, 0x01);
++ vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */
++ vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */
+
+ VGAenablePalette();
+ } else {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+-
+- tmp = VGArSEQ(0x01);
+-
+- VGAwSEQ(0x01, tmp & ~0x20); /* reenable display */
+- vgaHWSeqReset(0); /* clear synchronousreset */
++ tmp = vga_rseq(NULL, 0x01);
++ vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */
++ vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */
+
+ VGAdisablePalette();
+ }
+@@ -436,19 +461,19 @@ static void vgaHWRestore(const struct fb
+ {
+ int i;
+
+- VGAwMISC(par->MiscOutReg);
++ vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
+
+ for (i = 1; i < 5; i++)
+- VGAwSEQ(i, par->Sequencer[i]);
++ vga_wseq(NULL, i, par->Sequencer[i]);
+
+ /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
+- VGAwCR(17, par->CRTC[17] & ~0x80);
++ vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
+
+ for (i = 0; i < 25; i++)
+- VGAwCR(i, par->CRTC[i]);
++ vga_wcrt(NULL, i, par->CRTC[i]);
+
+ for (i = 0; i < 9; i++)
+- VGAwGR(i, par->Graphics[i]);
++ vga_wgfx(NULL, i, par->Graphics[i]);
+
+ VGAenablePalette();
+
+@@ -535,6 +560,36 @@ static inline void neo2200_accel_init(st
+ /* --------------------------------------------------------------------- */
+
+ static int
++neofb_open(struct fb_info *info, int user)
++{
++ struct neofb_par *par = (struct neofb_par *) info->par;
++ int cnt = atomic_read(&par->ref_count);
++
++ if (cnt) {
++ memset(&par->state, 0, sizeof(struct vgastate));
++ par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
++ save_vga(&par->state);
++ }
++ atomic_inc(&par->ref_count);
++ return 0;
++}
++
++static int
++neofb_release(struct fb_info *info, int user)
++{
++ struct neofb_par *par = (struct neofb_par *) info->par;
++ int cnt = atomic_read(&par->ref_count);
++
++ if (!cnt)
++ return -EINVAL;
++ if (cnt == 1) {
++ restore_vga(&par->state);
++ }
++ atomic_dec(&par->ref_count);
++ return 0;
++}
++
++static int
+ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
+ struct neofb_par *par = (struct neofb_par *) info->par;
+@@ -981,13 +1036,13 @@ static int neofb_set_par(struct fb_info
+ }
+
+ /* alread unlocked above */
+- /* BOGUS VGAwGR (0x09, 0x26); */
++ /* BOGUS vga_wgfx(NULL, 0x09, 0x26); */
+
+ /* don't know what this is, but it's 0 from bootup anyway */
+- VGAwGR(0x15, 0x00);
++ vga_wgfx(NULL, 0x15, 0x00);
+
+ /* was set to 0x01 by my bios in text and vesa modes */
+- VGAwGR(0x0A, par->GeneralLockReg);
++ vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
+
+ /*
+ * The color mode needs to be set before calling vgaHWRestore
+@@ -996,7 +1051,7 @@ static int neofb_set_par(struct fb_info
+ * NOTE: Make sure we don't change bits make sure we don't change
+ * any reserved bits.
+ */
+- temp = VGArGR(0x90);
++ temp = vga_rgfx(NULL, 0x90);
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ temp &= 0xF0; /* Save bits 7:4 */
+@@ -1015,7 +1070,7 @@ static int neofb_set_par(struct fb_info
+ break;
+ }
+
+- VGAwGR(0x90, temp);
++ vga_wgfx(NULL, 0x90, temp);
+
+ /*
+ * In some rare cases a lockup might occur if we don't delay
+@@ -1027,9 +1082,9 @@ static int neofb_set_par(struct fb_info
+ * Disable horizontal and vertical graphics and text expansions so
+ * that vgaHWRestore works properly.
+ */
+- temp = VGArGR(0x25);
++ temp = vga_rgfx(NULL, 0x25);
+ temp &= 0x39;
+- VGAwGR(0x25, temp);
++ vga_wgfx(NULL, 0x25, temp);
+
+ /*
+ * Sleep for 200ms to make sure that the two operations above have
+@@ -1041,19 +1096,18 @@ static int neofb_set_par(struct fb_info
+ * This function handles restoring the generic VGA registers. */
+ vgaHWRestore(info, par);
+
+-
+- VGAwGR(0x0E, par->ExtCRTDispAddr);
+- VGAwGR(0x0F, par->ExtCRTOffset);
+- temp = VGArGR(0x10);
++ vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
++ vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
++ temp = vga_rgfx(NULL, 0x10);
+ temp &= 0x0F; /* Save bits 3:0 */
+ temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */
+- VGAwGR(0x10, temp);
++ vga_wgfx(NULL, 0x10, temp);
+
+- VGAwGR(0x11, par->SysIfaceCntl2);
+- VGAwGR(0x15, 0 /*par->SingleAddrPage */ );
+- VGAwGR(0x16, 0 /*par->DualAddrPage */ );
++ vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
++ vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );
++ vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );
+
+- temp = VGArGR(0x20);
++ temp = vga_rgfx(NULL, 0x20);
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ temp &= 0xFC; /* Save bits 7:2 */
+@@ -1074,79 +1128,78 @@ static int neofb_set_par(struct fb_info
+ temp |= (par->PanelDispCntlReg1 & ~0x98);
+ break;
+ }
+- VGAwGR(0x20, temp);
++ vga_wgfx(NULL, 0x20, temp);
+
+- temp = VGArGR(0x25);
++ temp = vga_rgfx(NULL, 0x25);
+ temp &= 0x38; /* Save bits 5:3 */
+ temp |= (par->PanelDispCntlReg2 & ~0x38);
+- VGAwGR(0x25, temp);
++ vga_wgfx(NULL, 0x25, temp);
+
+ if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
+- temp = VGArGR(0x30);
++ temp = vga_rgfx(NULL, 0x30);
+ temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
+ temp |= (par->PanelDispCntlReg3 & ~0xEF);
+- VGAwGR(0x30, temp);
++ vga_wgfx(NULL, 0x30, temp);
+ }
+
+- VGAwGR(0x28, par->PanelVertCenterReg1);
+- VGAwGR(0x29, par->PanelVertCenterReg2);
+- VGAwGR(0x2a, par->PanelVertCenterReg3);
++ vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
++ vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
++ vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
+
+ if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
+- VGAwGR(0x32, par->PanelVertCenterReg4);
+- VGAwGR(0x33, par->PanelHorizCenterReg1);
+- VGAwGR(0x34, par->PanelHorizCenterReg2);
+- VGAwGR(0x35, par->PanelHorizCenterReg3);
++ vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
++ vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
++ vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
++ vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
+ }
+
+ if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
+- VGAwGR(0x36, par->PanelHorizCenterReg4);
++ vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
+
+ if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
+- VGAwGR(0x36, par->PanelHorizCenterReg4);
+- VGAwGR(0x37, par->PanelVertCenterReg5);
+- VGAwGR(0x38, par->PanelHorizCenterReg5);
++ vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
++ vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
++ vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
+
+ clock_hi = 1;
+ }
+
+ /* Program VCLK3 if needed. */
+- if (par->ProgramVCLK && ((VGArGR(0x9B) != par->VCLK3NumeratorLow)
+- || (VGArGR(0x9F) != par->VCLK3Denominator)
+- || (clock_hi && ((VGArGR(0x8F) & ~0x0f)
+- != (par->
+- VCLK3NumeratorHigh &
++ if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
++ || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
++ || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
++ != (par->VCLK3NumeratorHigh &
+ ~0x0F))))) {
+- VGAwGR(0x9B, par->VCLK3NumeratorLow);
++ vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
+ if (clock_hi) {
+- temp = VGArGR(0x8F);
++ temp = vga_rgfx(NULL, 0x8F);
+ temp &= 0x0F; /* Save bits 3:0 */
+ temp |= (par->VCLK3NumeratorHigh & ~0x0F);
+- VGAwGR(0x8F, temp);
++ vga_wgfx(NULL, 0x8F, temp);
+ }
+- VGAwGR(0x9F, par->VCLK3Denominator);
++ vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
+ }
+
+ if (par->biosMode)
+- VGAwCR(0x23, par->biosMode);
++ vga_wcrt(NULL, 0x23, par->biosMode);
+
+- VGAwGR(0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
++ vga_wgfx(NULL, 0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
+
+ /* Program vertical extension register */
+ if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
+ info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
+- VGAwCR(0x70, par->VerticalExt);
++ vga_wcrt(NULL, 0x70, par->VerticalExt);
+ }
+
+ vgaHWProtect(0); /* Turn on screen */
+
+ /* Calling this also locks offset registers required in update_start */
+- neoLock();
++ neoLock(&par->state);
+
+ info->fix.line_length =
+ info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
+@@ -1167,6 +1220,8 @@ static int neofb_set_par(struct fb_info
+ static void neofb_update_start(struct fb_info *info,
+ struct fb_var_screeninfo *var)
+ {
++ struct neofb_par *par = (struct neofb_par *) info->par;
++ struct vgastate *state = &par->state;
+ int oldExtCRTDispAddr;
+ int Base;
+
+@@ -1180,18 +1235,18 @@ static void neofb_update_start(struct fb
+ /*
+ * These are the generic starting address registers.
+ */
+- VGAwCR(0x0C, (Base & 0x00FF00) >> 8);
+- VGAwCR(0x0D, (Base & 0x00FF));
++ vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
++ vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
+
+ /*
+ * Make sure we don't clobber some other bits that might already
+ * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
+ * be needed.
+ */
+- oldExtCRTDispAddr = VGArGR(0x0E);
+- VGAwGR(0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
++ oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
++ vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
+
+- neoLock();
++ neoLock(state);
+ }
+
+ /*
+@@ -1353,7 +1408,7 @@ neo2200_fillrect(struct fb_info *info, c
+ }
+
+ par->neo2200->dstStart =
+- dst * ((info->var.bits_per_pixel + 7) / 8);
++ dst * ((info->var.bits_per_pixel + 7) >> 3);
+ par->neo2200->xyExt =
+ (rect->height << 16) | (rect->width & 0xffff);
+ }
+@@ -1361,24 +1416,20 @@ neo2200_fillrect(struct fb_info *info, c
+ static void
+ neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+ {
+- struct neofb_par *par = (struct neofb_par *) info->par;
+ u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
++ struct neofb_par *par = (struct neofb_par *) info->par;
+ u_long src, dst, bltCntl;
+
+ bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
+
+- if (sy < dy) {
++ if ((dy > sy) || ((dy == sy) && (dx > sx))) {
++ /* Start with the lower right corner */
+ sy += (area->height - 1);
+ dy += (area->height - 1);
+-
+- bltCntl |= NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
+- }
+-
+- if (area->sx < area->dx) {
+ sx += (area->width - 1);
+ dx += (area->width - 1);
+
+- bltCntl |= NEO_BC0_X_DEC;
++ bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
+ }
+
+ src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
+@@ -1496,8 +1547,60 @@ neofb_sync(struct fb_info *info)
+ return 0;
+ }
+
++static int
++neofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
++{
++ struct neofb_par *par = (struct neofb_par *) info->par;
++
++ /* Disable cursor */
++ write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);
++
++ if (cursor->set & FB_CUR_SETPOS) {
++ u32 x = cursor->image.dx;
++ u32 y = cursor->image.dy;
++
++ info->cursor.image.dx = x;
++ info->cursor.image.dy = y;
++ write_le32(NEOREG_CURSX, x, par);
++ write_le32(NEOREG_CURSY, y, par);
++ }
++
++ if (cursor->set & FB_CUR_SETSIZE) {
++ }
++
++ if (cursor->set & FB_CUR_SETCMAP) {
++ if (cursor->image.depth == 1) {
++ u32 fg = cursor->image.fg_color;
++ u32 bg = cursor->image.bg_color;
++
++ info->cursor.image.fg_color = fg;
++ info->cursor.image.bg_color = bg;
++
++ fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
++ bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
++ write_le32(NEOREG_CURSFGCOLOR, fg, par);
++ write_le32(NEOREG_CURSBGCOLOR, bg, par);
++ }
++ }
++
++ if (cursor->set & FB_CUR_SETSHAPE) {
++ unsigned long dest = (unsigned long) par->cursorPad;
++ int i, j;
++
++ //memset_io(par->cursorPad, 0xff, 1);
++ //write_le32(NEOREG_CURSMEMPOS, ((0x000f & (dest >> 10)) << 8) |
++ // ((0x0ff0 & (dest >> 10)) >> 4), par);
++ }
++
++ if (info->cursor.enable)
++ write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);
++ return 0;
++}
++
+ static struct fb_ops neofb_ops = {
+ .owner = THIS_MODULE,
++ .fb_open = neofb_open,
++ .fb_release = neofb_release,
+ .fb_check_var = neofb_check_var,
+ .fb_set_par = neofb_set_par,
+ .fb_setcolreg = neofb_setcolreg,
+@@ -1507,7 +1610,7 @@ static struct fb_ops neofb_ops = {
+ .fb_fillrect = neofb_fillrect,
+ .fb_copyarea = neofb_copyarea,
+ .fb_imageblit = neofb_imageblit,
+- .fb_cursor = soft_cursor,
++ .fb_cursor = neofb_cursor,
+ };
+
+ /* --------------------------------------------------------------------- */
+@@ -1650,6 +1753,7 @@ static int __devinit neo_map_video(struc
+ struct pci_dev *dev, int video_len)
+ {
+ struct neofb_par *par = (struct neofb_par *) info->par;
++ unsigned long addr;
+
+ DBG("neo_map_video");
+
+@@ -1681,6 +1785,10 @@ static int __devinit neo_map_video(struc
+
+ /* Clear framebuffer, it's all white in memory after boot */
+ memset(info->screen_base, 0, info->fix.smem_len);
++
++ /* Allocate Cursor drawing pad. */
++ addr = info->fix.smem_start + info->fix.smem_len;
++ par->cursorPad = (u8 *) ioremap(addr, info->sprite.size);
+ return 0;
+ }
+
+@@ -1725,16 +1833,16 @@ static int __devinit neo_init_hw(struct
+ printk(KERN_DEBUG "--- Neo extended register dump ---\n");
+ for (w = 0; w < 0x85; w++)
+ printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
+- (void *) VGArCR(w));
++ (void *) vga_rcrt(NULL, w);
+ for (w = 0; w < 0xC7; w++)
+ printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
+- (void *) VGArGR(w));
++ (void *) vga_rgfx(NULL, w));
+ #endif
+
+ /* Determine the panel type */
+- VGAwGR(0x09, 0x26);
+- type = VGArGR(0x21);
+- display = VGArGR(0x20);
++ vga_wgfx(NULL, 0x09, 0x26);
++ type = vga_rgfx(NULL, 0x21);
++ display = vga_rgfx(NULL, 0x20);
+ if (!par->internal_display && !par->external_display) {
+ par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
+ par->external_display = display & 1;
+@@ -1744,8 +1852,8 @@ static int __devinit neo_init_hw(struct
+ }
+
+ /* Determine panel width -- used in NeoValidMode. */
+- w = VGArGR(0x20);
+- VGAwGR(0x09, 0x00);
++ w = vga_rgfx(NULL, 0x20);
++ vga_wgfx(NULL, 0x09, 0x00);
+ switch ((w & 0x18) >> 3) {
+ case 0x00:
+ par->NeoPanelWidth = 640;
+@@ -1870,10 +1978,20 @@ static int __devinit neo_init_hw(struct
+ par->neo2200 = (Neo2200 *) par->mmio_vbase;
+ break;
+ }
+-
++ info->sprite.size = CursorMem;
++ info->sprite.addr = kmalloc(CursorMem, GFP_KERNEL);
++ info->sprite.scan_align = 1;
++ info->sprite.buf_align = 1;
++ info->sprite.flags = FB_PIXMAP_IO;
+ par->maxClock = maxClock;
+-
+- return videoRam * 1024;
++ par->cursorOff = CursorOff;
++ /*
++ * We decrease the size of the framebuffer by a page
++ * instead of the size of the cursor pad to avoid
++ * userland being able to page fault the cursor
++ * region and start drawing in it.
++ */
++ return ((videoRam * 1024) - PAGE_SIZE);
+ }
+
+
+--- linux-2.6.0-test6/drivers/video/platinumfb.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/video/platinumfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -104,9 +104,6 @@ static int platinum_var_to_par(const str
+ * Interface used by the world
+ */
+
+-int platinum_init(void);
+-int platinum_setup(char*);
+-
+ static struct fb_ops platinumfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = platinumfb_check_var,
+@@ -492,7 +489,7 @@ static int platinum_par_to_var(struct fb
+ /*
+ * Parse user speficied options (`video=platinumfb:')
+ */
+-int __init platinum_setup(char *options)
++int __init platinumfb_setup(char *options)
+ {
+ char *this_opt;
+
+@@ -672,7 +669,7 @@ static struct of_platform_driver platinu
+ .remove = platinumfb_remove,
+ };
+
+-int __init platinum_init(void)
++int __init platinumfb_init(void)
+ {
+ of_register_driver(&platinum_driver);
+
+--- linux-2.6.0-test6/drivers/video/pm3fb.c 2003-06-14 12:18:02.000000000 -0700
++++ 25/drivers/video/pm3fb.c 2003-10-05 00:33:24.000000000 -0700
+@@ -54,7 +54,6 @@
+
+ #include <linux/config.h>
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+--- linux-2.6.0-test6/drivers/video/pvr2fb.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/drivers/video/pvr2fb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -166,6 +166,11 @@ static u_long videomemory = 0xa5000000,
+ static int cable_type = -1;
+ static int video_output = -1;
+
++#ifdef CONFIG_MTRR
++static int enable_mtrr = 1;
++static int mtrr_handle;
++#endif
++
+ static int nopan = 0;
+ static int nowrap = 1;
+
+@@ -385,6 +390,7 @@ static int pvr2fb_set_par(struct fb_info
+
+ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+ {
++ struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
+ u_short vtotal, hsync_total;
+ u_long line_length;
+
+@@ -413,7 +419,7 @@ static int pvr2fb_check_var(struct fb_va
+
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->xoffset || var->yoffset < 0 ||
+- var->yoffset >= var->yres_virtual) {
++ var->yoffset >= var->yres_virtual)
+ var->xoffset = var->yoffset = 0;
+ } else {
+ if (var->xoffset > var->xres_virtual - var->xres ||
+@@ -421,9 +427,8 @@ static int pvr2fb_check_var(struct fb_va
+ var->xoffset < 0 || var->yoffset < 0)
+ var->xoffset = var->yoffset = 0;
+ }
+- } else {
++ } else
+ var->xoffset = var->yoffset = 0;
+- }
+
+ /*
+ * XXX: Need to be more creative with this (i.e. allow doublecan for
+@@ -456,7 +461,6 @@ static int pvr2fb_check_var(struct fb_va
+ DPRINTK("invalid hsync total for NTSC\n");
+ return -EINVAL;
+ }
+- }
+ }
+ /* Check memory sizes */
+ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+@@ -599,10 +603,10 @@ static int pvr2_init_cable(void)
+
+ int __init pvr2fb_init(void)
+ {
++ struct fb_var_screeninfo var;
+ u_long modememused;
+- int err = -EINVAL;
+
+- if (!mach_is_dreamcast())
++ if (!MACH_DREAMCAST)
+ return -ENXIO;
+
+ fb_info = kmalloc(sizeof(struct fb_info) + sizeof(struct pvr2fb_par) +
+@@ -650,8 +654,8 @@ int __init pvr2fb_init(void)
+
+ if (!fb_info->screen_base) {
+ printk("Failed to remap MMIO space\n");
+- err = -ENXIO;
+- goto out_err;
++ kfree(fb_info);
++ return -ENXIO;
+ }
+
+ memset_io((unsigned long)fb_info->screen_base, 0, pvr2_fix.smem_len);
+@@ -665,6 +669,8 @@ int __init pvr2fb_init(void)
+ fb_info->pseudo_palette = (void *)(fb_info->par + 1);
+ fb_info->flags = FBINFO_FLAG_DEFAULT;
+
++ memset(&var, 0, sizeof(var));
++
+ if (video_output == VO_VGA)
+ defmode = DEFMODE_VGA;
+
+@@ -677,41 +683,46 @@ int __init pvr2fb_init(void)
+
+ if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0,
+ "pvr2 VBL handler", fb_info)) {
+- err = -EBUSY;
+- goto out_err;
++ DPRINTK("couldn't register VBL int\n");
++ kfree(fb_info);
++ return -EBUSY;
+ }
+
+- if (register_framebuffer(fb_info) < 0)
+- goto reg_failed;
++#ifdef CONFIG_MTRR
++ if (enable_mtrr) {
++ mtrr_handle = mtrr_add(videomemory, videomemorysize, MTRR_TYPE_WRCOMB, 1);
++ printk("pvr2fb: MTRR turned on\n");
++ }
++#endif
+
+- modememused = get_line_length(fb_info->var.xres_virtual,
+- fb_info->var.bits_per_pixel);
+- modememused *= fb_info->var.yres_virtual;
++ if (register_framebuffer(fb_info) < 0) {
++ kfree(fb_info);
++ return -EINVAL;
++ }
+
++ modememused = get_line_length(var.xres_virtual, var.bits_per_pixel);
++ modememused *= var.yres_virtual;
+ printk("fb%d: %s frame buffer device, using %ldk/%ldk of video memory\n",
+ fb_info->node, fb_info->fix.id, modememused>>10,
+ videomemorysize>>10);
+ printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
+- fb_info->node, fb_info->var.xres, fb_info->var.yres,
+- fb_info->var.bits_per_pixel,
+- get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
++ fb_info->node, var.xres, var.yres, var.bits_per_pixel,
++ get_line_length(var.xres, var.bits_per_pixel),
+ (char *)pvr2_get_param(cables, NULL, cable_type, 3),
+ (char *)pvr2_get_param(outputs, NULL, video_output, 3));
+
+ return 0;
+-
+-reg_failed:
+- free_irq(HW_EVENT_VSYNC, 0);
+-out_err:
+- kfree(fb_info);
+-
+- return err;
+ }
+
+ static void __exit pvr2fb_exit(void)
+ {
++#ifdef CONFIG_MTRR
++ if (enable_mtrr) {
++ mtrr_del(mtrr_handle, videomemory, videomemorysize);
++ printk("pvr2fb: MTRR turned off\n");
++ }
++#endif
+ unregister_framebuffer(fb_info);
+- free_irq(HW_EVENT_VSYNC, 0);
+ kfree(fb_info);
+ }
+
+@@ -767,6 +778,10 @@ int __init pvr2fb_setup(char *options)
+ nopan = 1;
+ } else if (!strncmp(this_opt, "nowrap", 6)) {
+ nowrap = 1;
++#ifdef CONFIG_MTRR
++ } else if (!strncmp(this_opt, "nomtrr", 6)) {
++ enable_mtrr = 0;
++#endif
+ } else {
+ mode_option = this_opt;
+ }
+--- linux-2.6.0-test6/drivers/video/radeonfb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/radeonfb.c 2003-10-05 00:34:47.000000000 -0700
+@@ -1099,7 +1099,7 @@ static int radeon_get_dfpinfo_BIOS(struc
+ printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n",
+ rinfo->panel_xres, rinfo->panel_yres);
+
+- for(i=0; i<20; i++) {
++ for(i=0; i<21; i++) {
+ tmp0 = rinfo->bios_seg + readw(tmp+64+i*2);
+ if (tmp0 == 0)
+ break;
+@@ -2090,7 +2090,7 @@ static int radeonfb_set_par (struct fb_i
+
+ }
+ /* Update fix */
+- info->fix.line_length = rinfo->pitch*64;
++ info->fix.line_length = mode->xres_virtual*(mode->bits_per_pixel/8);
+ info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+ #ifdef CONFIG_BOOTX_TEXT
+--- linux-2.6.0-test6/drivers/video/riva/fbdev.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/drivers/video/riva/fbdev.c 2003-10-05 00:34:22.000000000 -0700
+@@ -143,7 +143,17 @@ enum riva_chips {
+ CH_GEFORCE4_TI_4200,
+ CH_QUADRO4_900XGL,
+ CH_QUADRO4_750XGL,
+- CH_QUADRO4_700XGL
++ CH_QUADRO4_700XGL,
++ CH_GEFORCE4_TI_4800,
++ CH_GEFORCE4_TI_4280,
++ CH_GEFORCE4_TI_4800SE,
++ CH_GEFORCE4_4200_GO,
++ CH_GEFORCE_FX_5800_U,
++ CH_GEFORCE_FX_5800,
++ CH_GEFORCE_FX_5600_U,
++ CH_GEFORCE_FX_5600,
++ CH_GEFORCE_FX_5200_U,
++ CH_GEFORCE_FX_5200
+ };
+
+ /* directly indexed by riva_chips enum, above */
+@@ -190,7 +200,17 @@ static struct riva_chip_info {
+ { "GeForce4 Ti 4200", NV_ARCH_20 },
+ { "Quadro4-900-XGL", NV_ARCH_20 },
+ { "Quadro4-750-XGL", NV_ARCH_20 },
+- { "Quadro4-700-XGL", NV_ARCH_20 }
++ { "Quadro4-700-XGL", NV_ARCH_20 },
++ { "GeForce4 Ti 4800", NV_ARCH_20 },
++ { "GeForce4 Ti 4280", NV_ARCH_20},
++ { "GeForce4 Ti 4800 SE", NV_ARCH_20},
++ { "GeForce4 4200 GO", NV_ARCH_20},
++ { "GeForce FX 5800 ULTRA", NV_ARCH_20},
++ { "GeForce FX 5800", NV_ARCH_20},
++ { "GeForce FX 5600 ULTRA", NV_ARCH_20},
++ { "GeForce FX 5600", NV_ARCH_20},
++ { "GeForce FX 5200 ULTRA", NV_ARCH_20},
++ { "GeForce FX 5200", NV_ARCH_20}
+ };
+
+ static struct pci_device_id rivafb_pci_tbl[] = {
+@@ -274,6 +294,26 @@ static struct pci_device_id rivafb_pci_t
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_750XGL },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_700XGL },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4800 },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4280,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4280 },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_SE,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4800SE },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_4200_GO },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_U,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5800_U },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5800 },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_U,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5600_U },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5600 },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_U,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5200_U },
++ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_FX_5200 },
+ { 0, } /* terminate list */
+ };
+ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
+@@ -1469,8 +1509,6 @@ static void rivafb_imageblit(struct fb_i
+ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+ {
+ struct riva_par *par = (struct riva_par *) info->par;
+- u8 data[MAX_CURS * MAX_CURS/8];
+- u8 mask[MAX_CURS * MAX_CURS/8];
+ u16 fg, bg;
+ int i;
+
+@@ -1492,7 +1530,6 @@ static int rivafb_cursor(struct fb_info
+ if (cursor->set & FB_CUR_SETSIZE) {
+ info->cursor.image.height = cursor->image.height;
+ info->cursor.image.width = cursor->image.width;
+- memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+ }
+
+ if (cursor->set & FB_CUR_SETCMAP) {
+@@ -1503,29 +1540,22 @@ static int rivafb_cursor(struct fb_info
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
+ u32 bg_idx = info->cursor.image.bg_color;
+ u32 fg_idx = info->cursor.image.fg_color;
+- u32 s_pitch = (info->cursor.image.width+7) >> 3;
+- u32 d_pitch = MAX_CURS/8;
+- u8 *dat = (u8 *) cursor->image.data;
++ u8 *dat = (u8 *) info->cursor.image.data;
+ u8 *msk = (u8 *) info->cursor.mask;
+ u8 src[64];
+
+ switch (info->cursor.rop) {
+ case ROP_XOR:
+- for (i = 0; i < s_pitch * info->cursor.image.height; i++)
++ for (i = 0; i < info->sprite.size; i++)
+ src[i] = dat[i] ^ msk[i];
+ break;
+ case ROP_COPY:
+ default:
+- for (i = 0; i < s_pitch * info->cursor.image.height; i++)
+-
++ for (i = 0; i < info->sprite.size; i++)
+ src[i] = dat[i] & msk[i];
+ break;
+ }
+
+- move_buf_aligned(info, data, src, d_pitch, s_pitch, info->cursor.image.height);
+-
+- move_buf_aligned(info, mask, msk, d_pitch, s_pitch, info->cursor.image.height);
+-
+ bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+ ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+ ((info->cmap.blue[bg_idx] & 0xf8) >> 3);
+@@ -1536,7 +1566,7 @@ static int rivafb_cursor(struct fb_info
+
+ par->riva.LockUnlock(&par->riva, 0);
+
+- rivafb_load_cursor_image(par, data, mask, bg, fg,
++ rivafb_load_cursor_image(par, dat, msk, bg, fg,
+ info->cursor.image.width,
+ info->cursor.image.height);
+ }
+@@ -1572,7 +1602,7 @@ static struct fb_ops riva_fb_ops = {
+ .fb_fillrect = rivafb_fillrect,
+ .fb_copyarea = rivafb_copyarea,
+ .fb_imageblit = rivafb_imageblit,
+- .fb_cursor = rivafb_cursor,
++ .fb_cursor = soft_cursor,
+ .fb_sync = rivafb_sync,
+ };
+
+@@ -1603,6 +1633,15 @@ static int __devinit riva_set_fbinfo(str
+ info->pixmap.buf_align = 4;
+ info->pixmap.scan_align = 4;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
++/*
++ info->sprite.addr = (char *) par->riva.CURSOR;
++ info->sprite.size = MAX_CURS * MAX_CURS * 2;
++ info->sprite.buf_align = info->sprite.size;
++ info->sprite.scan_align = MAX_CURS >> 3;
++ info->sprite.access_align = 2;
++ info->sprite.flags = FB_PIXMAP_IO;
++ memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
++*/
+ return 0;
+ }
+
+--- linux-2.6.0-test6/drivers/video/riva/nv_type.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/video/riva/nv_type.h 2003-10-05 00:34:22.000000000 -0700
+@@ -50,8 +50,16 @@
+ #define NV_CHIP_QUADRO4_900XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL)
+ #define NV_CHIP_QUADRO4_750XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL)
+ #define NV_CHIP_QUADRO4_700XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL)
+-#define NV_CHIP_0x0280 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280)
+-#define NV_CHIP_0x0281 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281)
++#define NV_CHIP_GEFORCE4_TI_4800 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800)
++#define NV_CHIP_GEFORCE4_TI_4280 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4280)
++#define NV_CHIP_GEFORCE4_TI_4800SE ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_SE)
++#define NV_CHIP_GEFORCE4_4200_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO)
++#define NV_CHIP_GEFORCE_FX_5800_U ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_U)
++#define NV_CHIP_GEFORCE_FX_5800 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800)
++#define NV_CHIP_GEFORCE_FX_5600_U ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_U)
++#define NV_CHIP_GEFORCE_FX_5600 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600)
++#define NV_CHIP_GEFORCE_FX_5200_U ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_U)
++#define NV_CHIP_GEFORCE_FX_5200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200)
+ #define NV_CHIP_0x0288 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288)
+ #define NV_CHIP_0x0289 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289)
+
+--- linux-2.6.0-test6/drivers/video/sis/300vtbl.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/drivers/video/sis/300vtbl.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,7 +1,37 @@
+-
+-
+-/* Register settings for SiS 300 series */
+-
++/* $XFree86$ */
++/*
++ * Register settings for SiS 300 series
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
+
+ typedef struct _SiS300_StStruct
+ {
+@@ -39,470 +69,109 @@ static const SiS300_StStruct SiS300_SMo
+ {0xff, 0, 0, 0, 0, 0, 0, 0}
+ };
+
+-typedef struct _SiS300_StandTableStruct
+-{
+- UCHAR CRT_COLS;
+- UCHAR ROWS;
+- UCHAR CHAR_HEIGHT;
+- USHORT CRT_LEN;
+- UCHAR SR[4];
+- UCHAR MISC;
+- UCHAR CRTC[0x19];
+- UCHAR ATTR[0x14];
+- UCHAR GRC[9];
+-} SiS300_StandTableStruct;
+-
+-static const SiS300_StandTableStruct SiS300_StandTable[] =
+-{
+- {0x28,0x18,0x08,0x0800, /* 0x00 */
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x28,0x18,0x08,0x0800, /* 0x01 */
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x08,0x1000, /* 0x02 */
+- {0x01,0x03,0x00,0x02},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x08,0x1000, /* 0x03 */
+- {0x01,0x03,0x00,0x02},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x28,0x18,0x08,0x4000, /* 0x04 */
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+- 0xff},
+- {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x03,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+- 0xff} },
+- {0x28,0x18,0x08,0x4000, /* 0x05 */
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+- 0xff},
+- {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x03,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+- 0xff} },
+- {0x50,0x18,0x08,0x4000, /* 0x06 */
+- {0x01,0x01,0x00,0x06},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
+- 0xff},
+- {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+- 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+- 0x01,0x00,0x01,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
+- 0xff} },
+- {0x50,0x18,0x0e,0x1000, /* 0x07 */
+- {0x00,0x03,0x00,0x03},
+- 0xa6,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+- 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+- 0x0e,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+- 0xff} },
+-/* MDA_DAC*/
+- {0x00,0x00,0x00,0x0000, /* 0x08 */
+- {0x00,0x00,0x00,0x15},
+- 0x15,
+- {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
+- 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
+- 0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15},
+- {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x3f} },
+-/* CGA_DAC*/
+- {0x00,0x10,0x04,0x0114, /* 0x09 */
+- {0x11,0x09,0x15,0x00},
+- 0x10,
+- {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
+- 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
+- 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
+- 0x04},
+- {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
+- 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
+- 0x3e,0x2b,0x3b,0x2f},
+- {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+- 0x3f} },
+-/* EGA_DAC*/
+- {0x00,0x10,0x04,0x0114, /* 0x0a */
+- {0x11,0x05,0x15,0x20},
+- 0x30,
+- {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
+- 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
+- 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
+- 0x06},
+- {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
+- 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
+- 0x1e,0x0b,0x1b,0x0f},
+- {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+- 0x3f} },
+-/* VGA_DAC*/
+- {0x00,0x10,0x04,0x0114, /* 0x0b */
+- {0x11,0x09,0x15,0x2a},
+- 0x3a,
+- {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
+- 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
+- 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
+- 0x1f},
+- {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
+- 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
+- 0x1c,0x0e,0x11,0x15},
+- {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
+- 0x04} },
+- {0x08,0x0c,0x10,0x0a08, /* 0x0c */
+- {0x0c,0x0e,0x10,0x0b},
+- 0x0c,
+- {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
+- 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
+- 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
+- 0x06},
+- {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
+- 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
+- 0x00,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00} },
+- {0x28,0x18,0x08,0x2000, /* 0x0d */
+- {0x09,0x0f,0x00,0x06},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff} },
+- {0x50,0x18,0x08,0x4000, /* 0x0e */
+- {0x01,0x0f,0x00,0x06},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff} },
+- {0x00,0x00,0x00,0x0000, /* 0x0f */ /* TW: Standtable for VGA modes */
+- {0x01,0x0f,0x00,0x0e},
+- 0x23,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+- 0x01,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+- 0xff} },
+- {0x4a,0x36,0x00,0x00c0, /* 0x10 */
+- {0x00,0x00,0x00,0x00},
+- 0x00,
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x3a,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x1a,0x00,0x57,0x39,0x00,0xc0,
+- 0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00} },
+- {0x50,0x18,0x0e,0x8000, /* 0x11 */
+- {0x01,0x0f,0x00,0x06},
+- 0xa2,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+- 0xff},
+- {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+- 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+- 0x0b,0x00,0x05,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+- 0xff} },
+- {0x50,0x18,0x0e,0x8000, /* 0x12 */
+- {0x01,0x0f,0x00,0x06},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff} },
+- {0x28,0x18,0x0e,0x0800, /* 0x13 */
+- {0x09,0x03,0x00,0x02},
+- 0xa3,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x28,0x18,0x0e,0x0800, /* 0x14 */
+- {0x09,0x03,0x00,0x02},
+- 0xa3,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x0e,0x1000, /* 0x15 */
+- {0x01,0x03,0x00,0x02},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x0e,0x1000, /* 0x16 */
+- {0x01,0x03,0x00,0x02},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x28,0x18,0x10,0x0800, /* 0x17 */
+- {0x08,0x03,0x00,0x02},
+- 0x67,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x0c,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x10,0x1000, /* 0x18 */
+- {0x00,0x03,0x00,0x02},
+- 0x67,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x0c,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff} },
+- {0x50,0x18,0x10,0x1000, /* 0x19 */
+- {0x00,0x03,0x00,0x02},
+- 0x66,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+- 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+- 0x0e,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+- 0xff} },
+- {0x50,0x1d,0x10,0xa000, /* 0x1a */
+- {0x01,0x0f,0x00,0x06},
+- 0xe3,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xc3,
+- 0xff},
+- {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+- 0xff} },
+- {0x50,0x1d,0x10,0xa000, /* 0x1b */
+- {0x01,0x0f,0x00,0x06},
+- 0xe3,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff} },
+- {0x28,0x18,0x08,0x2000, /* 0x1c */
+- {0x01,0x0f,0x00,0x0e},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,
+- 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+- 0x41,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+- 0xff} }
+-};
+-
+ typedef struct _SiS300_ExtStruct
+ {
+- UCHAR Ext_ModeID;
++ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+- USHORT Ext_Point;
+ USHORT Ext_VESAID;
+- UCHAR Ext_VESAMEMSize;
+- UCHAR Ext_RESINFO;
+- UCHAR VB_ExtTVFlickerIndex;
+- UCHAR VB_ExtTVEdgeIndex;
+- UCHAR VB_ExtTVYFilterIndex;
+- UCHAR REFindex;
++ UCHAR Ext_RESINFO;
++ UCHAR VB_ExtTVFlickerIndex;
++ UCHAR VB_ExtTVEdgeIndex;
++ UCHAR VB_ExtTVYFilterIndex;
++ UCHAR REFindex;
+ } SiS300_ExtStruct;
+
+ static const SiS300_ExtStruct SiS300_EModeIDTable[] =
+ {
+- {0x6a,0x2212,0x47,0x3563,0x0102,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600x? */
+- {0x2e,0x0a1b,0x36,0x3539,0x0101,0x08,0x06,0x00,0x00,0x00,0x08},
+- {0x2f,0x021b,0x35,0x3532,0x0100,0x08,0x05,0x00,0x00,0x00,0x10}, /* 640x400x8 */
+- {0x30,0x2a1b,0x47,0x3563,0x0103,0x08,0x07,0x00,0x00,0x00,0x00},
+- {0x31,0x0a1b,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x8 */
+- {0x32,0x2a1b,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x8 */
+- {0x33,0x0a1d,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x16 */
+- {0x34,0x2a1d,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x16 */
+- {0x35,0x0a1f,0xad,0x3630,0x0000,0x08,0x0c,0x00,0x00,0x00,0x11}, /* 720x480x32 */
+- {0x36,0x2a1f,0xae,0x3637,0x0000,0x08,0x0d,0x00,0x00,0x00,0x12}, /* 720x576x32 */
+- {0x37,0x0212,0x58,0x358d,0x0104,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x? */
+- {0x38,0x0a1b,0x58,0x358d,0x0105,0x08,0x08,0x00,0x00,0x00,0x13}, /* 1024x768x8 */
+- {0x3a,0x0e3b,0x69,0x35be,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
+- {0x3c,0x063b,0x7a,0x35d4,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e},
+- {0x3d,0x067d,0x7a,0x35d4,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e},
+- {0x40,0x921c,0x00,0x3516,0x010d,0x08,0x00,0x00,0x00,0x00,0x23},
+- {0x41,0x921d,0x00,0x3516,0x010e,0x08,0x00,0x00,0x00,0x00,0x23},
+- {0x43,0x0a1c,0x36,0x3539,0x0110,0x08,0x06,0x00,0x00,0x00,0x08},
+- {0x44,0x0a1d,0x36,0x3539,0x0111,0x08,0x06,0x00,0x00,0x00,0x08},
+- {0x46,0x2a1c,0x47,0x3563,0x0113,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */
+- {0x47,0x2a1d,0x47,0x3563,0x0114,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */
+- {0x49,0x0a3c,0x58,0x358d,0x0116,0x08,0x08,0x00,0x00,0x00,0x13},
+- {0x4a,0x0a3d,0x58,0x358d,0x0117,0x08,0x08,0x00,0x00,0x00,0x13},
+- {0x4c,0x0e7c,0x69,0x35be,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a},
+- {0x4d,0x0e7d,0x69,0x35be,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a},
+- {0x50,0x921b,0x01,0x351d,0x0132,0x08,0x01,0x00,0x00,0x00,0x24},
+- {0x51,0xb21b,0x13,0x3524,0x0133,0x08,0x03,0x00,0x00,0x00,0x25}, /* 400x300 */
+- {0x52,0x921b,0x24,0x352b,0x0134,0x08,0x04,0x00,0x00,0x00,0x26},
+- {0x56,0x921d,0x01,0x351d,0x0135,0x08,0x01,0x00,0x00,0x00,0x24},
+- {0x57,0xb21d,0x13,0x3524,0x0136,0x08,0x03,0x00,0x00,0x00,0x25}, /* 400x300 */
+- {0x58,0x921d,0x24,0x352b,0x0137,0x08,0x04,0x00,0x00,0x00,0x26},
+- {0x59,0x921b,0x00,0x3516,0x0138,0x08,0x00,0x00,0x00,0x00,0x23},
+- {0x5c,0x921f,0x24,0x352b,0x0000,0x08,0x04,0x00,0x00,0x00,0x26}, /* TW: inserted 512x384x32 */
+- {0x5d,0x021d,0x35,0x3532,0x0139,0x08,0x05,0x00,0x00,0x00,0x10}, /* 640x400x16 */
+- {0x5e,0x021f,0x35,0x3532,0x0000,0x08,0x05,0x00,0x00,0x00,0x10}, /* TW: inserted 640x400x32 */
+- {0x62,0x0a3f,0x36,0x3539,0x013a,0x08,0x06,0x00,0x00,0x00,0x08},
+- {0x63,0x2a3f,0x47,0x3563,0x013b,0x08,0x07,0x00,0x00,0x00,0x00}, /* 800x600 */
+- {0x64,0x0a7f,0x58,0x358d,0x013c,0x08,0x08,0x00,0x00,0x00,0x13},
+- {0x65,0x0eff,0x69,0x35be,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a},
+- {0x66,0x06ff,0x7a,0x35d4,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e},
+- {0x68,0x067b,0x8b,0x35ef,0x013f,0x08,0x0b,0x00,0x00,0x00,0x27},
+- {0x69,0x06fd,0x8b,0x35ef,0x0140,0x08,0x0b,0x00,0x00,0x00,0x27},
+- {0x6b,0x07ff,0x8b,0x35ef,0x0000,0x10,0x0b,0x00,0x00,0x00,0x27},
+- {0x6c,0x067b,0x9c,0x35f6,0x0000,0x08,0x11,0x00,0x00,0x00,0x28}, /* TW: 2048x1536x8 - not in BIOS! */
+- {0x6d,0x06fd,0x9c,0x35f6,0x0000,0x10,0x11,0x00,0x00,0x00,0x28}, /* TW: 2048x1536x16 - not in BIOS! */
+- {0x6e,0x0a3b,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x8 */
+- {0x6f,0x0a7d,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x16 */
+- /* TW: 16:9 modes copied from 310/325 series - not in ANY BIOS */
+- {0x70,0x2a1b,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x8 */
+- {0x71,0x0a1b,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x8 */
+- {0x74,0x0a1d,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x16 */
+- {0x75,0x0e3d,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x16 */
+- {0x76,0x2a1f,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x32 */
+- {0x77,0x0a3f,0x51,0x3b63,0x0000,0x08,0x13,0x00,0x00,0x00,0x30}, /* 1024x576x32 */
+- {0x78,0x0eff,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x32 */
+- {0x79,0x0e3b,0x62,0x3b74,0x0000,0x08,0x14,0x00,0x00,0x00,0x33}, /* 1280x720x8 */
+- {0x7a,0x2a1d,0x40,0x3b52,0x0000,0x08,0x12,0x00,0x00,0x07,0x2d}, /* 800x480x16 */
+- /* TW: End of new 16:9 modes */
+- {0x7b,0x0aff,0x6f,0x35b2,0x0000,0x08,0x0e,0x00,0x00,0x00,0x29}, /* 1280x960x32 */
+- {0x20,0x0a1b,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b}, /* 1024x600 */
+- {0x21,0x0a3d,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b},
+- {0x22,0x0a7f,0x54,0x0000,0x0000,0x08,0x0f,0x00,0x00,0x00,0x2b},
+- {0x23,0x0a1b,0xc5,0x0000,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c}, /* 1152x768 */
+- {0x24,0x0a3d,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c},
+- {0x25,0x0a7f,0xc5,0x431d,0x0000,0x08,0x10,0x00,0x00,0x00,0x2c},
+- {0x29,0x0e1b,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36}, /* TW: NEW 1152x864 - not in BIOS */
+- {0x2a,0x0e3d,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36},
+- {0x2b,0x0e7f,0xc5,0x0000,0x0000,0x08,0x15,0x00,0x00,0x00,0x36},
+- {0x39,0x2a1b,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38}, /* TW: NEW 848x480 - not in BIOS */
+- {0x3b,0x2a3d,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38},
+- {0x3e,0x2a7f,0xd6,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x38},
+- {0x3f,0x2a1b,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a}, /* TW: NEW 856x480 - not in BIOS */
+- {0x42,0x2a3d,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a},
+- {0x45,0x2a7f,0xd7,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x3a},
+- {0x48,0x223b,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c}, /* TW: NEW 1360x768 - not in BIOS */
+- {0x4b,0x227d,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c},
+- {0x4e,0x22ff,0xe8,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x3c},
+- {0xff,0x0000,0x00,0x0000,0xffff,0x00,0x00,0x00,0x00,0x00,0x00}
++ {0x6a,0x2212,0x0407,0x0102,SIS_RI_800x600, 0x00,0x00,0x00,0x00}, /* 800x600x? */
++ {0x2e,0x0a1b,0x0306,0x0101,SIS_RI_640x480, 0x00,0x00,0x00,0x08},
++ {0x2f,0x021b,0x0305,0x0100,SIS_RI_640x400, 0x00,0x00,0x00,0x10}, /* 640x400x8 */
++ {0x30,0x2a1b,0x0407,0x0103,SIS_RI_800x600, 0x00,0x00,0x00,0x00},
++ {0x31,0x0a1b,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x11}, /* 720x480x8 */
++ {0x32,0x2a1b,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x12}, /* 720x576x8 */
++ {0x33,0x0a1d,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x11}, /* 720x480x16 */
++ {0x34,0x2a1d,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x12}, /* 720x576x16 */
++ {0x35,0x0a1f,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x00,0x11}, /* 720x480x32 */
++ {0x36,0x2a1f,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x00,0x12}, /* 720x576x32 */
++ {0x37,0x0212,0x0508,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x13}, /* 1024x768x? */
++ {0x38,0x0a1b,0x0508,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x13}, /* 1024x768x8 */
++ {0x3a,0x0e3b,0x0609,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
++ {0x3c,0x063b,0x070a,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e},
++ {0x3d,0x067d,0x070a,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e},
++ {0x40,0x921c,0x0000,0x010d,SIS_RI_320x200, 0x00,0x00,0x00,0x23}, /* 320x200x15 */
++ {0x41,0x921d,0x0000,0x010e,SIS_RI_320x200, 0x00,0x00,0x00,0x23}, /* 320x200x16 */
++ {0x43,0x0a1c,0x0306,0x0110,SIS_RI_640x480, 0x00,0x00,0x00,0x08},
++ {0x44,0x0a1d,0x0306,0x0111,SIS_RI_640x480, 0x00,0x00,0x00,0x08},
++ {0x46,0x2a1c,0x0407,0x0113,SIS_RI_800x600, 0x00,0x00,0x00,0x00}, /* 800x600x15 */
++ {0x47,0x2a1d,0x0407,0x0114,SIS_RI_800x600, 0x00,0x00,0x00,0x00}, /* 800x600x16 */
++ {0x49,0x0a3c,0x0508,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x13},
++ {0x4a,0x0a3d,0x0508,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x13},
++ {0x4c,0x0e7c,0x0609,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a},
++ {0x4d,0x0e7d,0x0609,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a},
++ {0x50,0x921b,0x0001,0x0132,SIS_RI_320x240, 0x00,0x00,0x00,0x24}, /* 320x240x8 */
++ {0x51,0xb21b,0x0103,0x0133,SIS_RI_400x300, 0x00,0x00,0x00,0x25}, /* 400x300x8 */
++ {0x52,0x921b,0x0204,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x26}, /* 512x384x8 */
++ {0x56,0x921d,0x0001,0x0135,SIS_RI_320x240, 0x00,0x00,0x00,0x24}, /* 320x240x16 */
++ {0x57,0xb21d,0x0103,0x0136,SIS_RI_400x300, 0x00,0x00,0x00,0x25}, /* 400x300x16 */
++ {0x58,0x921d,0x0204,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x26}, /* 512x384x16 */
++ {0x59,0x921b,0x0000,0x0138,SIS_RI_320x200, 0x00,0x00,0x00,0x23}, /* 320x200x8 */
++ {0x5c,0x921f,0x0204,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x26}, /* 512x384x32 */
++ {0x5d,0x021d,0x0305,0x0139,SIS_RI_640x400, 0x00,0x00,0x00,0x10}, /* 640x400x16 */
++ {0x5e,0x021f,0x0305,0x0000,SIS_RI_640x400, 0x00,0x00,0x00,0x10}, /* 640x400x32 */
++ {0x62,0x0a3f,0x0306,0x013a,SIS_RI_640x480, 0x00,0x00,0x00,0x08},
++ {0x63,0x2a3f,0x0407,0x013b,SIS_RI_800x600, 0x00,0x00,0x00,0x00}, /* 800x600x32 */
++ {0x64,0x0a7f,0x0508,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x13},
++ {0x65,0x0eff,0x0609,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a},
++ {0x66,0x06ff,0x070a,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e},
++ {0x68,0x067b,0x080b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x27},
++ {0x69,0x06fd,0x080b,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x27},
++ {0x6b,0x07ff,0x080b,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x27},
++ {0x6c,0x067b,0x090c,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x28}, /* 2048x1536x8 - not in BIOS! */
++ {0x6d,0x06fd,0x090c,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x28}, /* 2048x1536x16 - not in BIOS! */
++ {0x70,0x2a1b,0x0400,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x2d}, /* 800x480x8 */
++ {0x71,0x0a1b,0x0501,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x30}, /* 1024x576x8 */
++ {0x74,0x0a1d,0x0501,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x30}, /* 1024x576x16 */
++ {0x75,0x0e3d,0x0602,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x33}, /* 1280x720x16 */
++ {0x76,0x2a1f,0x0400,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x2d}, /* 800x480x32 */
++ {0x77,0x0a3f,0x0501,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x30}, /* 1024x576x32 */
++ {0x78,0x0eff,0x0602,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x33}, /* 1280x720x32 */
++ {0x79,0x0e3b,0x0602,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x33}, /* 1280x720x8 */
++ {0x7a,0x2a1d,0x0400,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x2d}, /* 800x480x16 */
++ {0x7c,0x0a3b,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x29}, /* 1280x960x8 */
++ {0x7d,0x0a7d,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x29}, /* 1280x960x16 */
++ {0x7e,0x0aff,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x29}, /* 1280x960x32 */
++ {0x20,0x0a1b,0x0504,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x2b}, /* 1024x600 */
++ {0x21,0x0a3d,0x0504,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x2b},
++ {0x22,0x0a7f,0x0504,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x2b},
++ {0x23,0x0a1b,0x0c05,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x2c}, /* 1152x768 */
++ {0x24,0x0a3d,0x0c05,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x2c},
++ {0x25,0x0a7f,0x0c05,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x2c},
++ {0x29,0x0e1b,0x0c05,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x36}, /* 1152x864 */
++ {0x2a,0x0e3d,0x0c05,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x36},
++ {0x2b,0x0e7f,0x0c05,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x36},
++ {0x39,0x2a1b,0x0d06,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x38}, /* 848x480 */
++ {0x3b,0x2a3d,0x0d06,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x38},
++ {0x3e,0x2a7f,0x0d06,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x38},
++ {0x3f,0x2a1b,0x0d07,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x3a}, /* 856x480 */
++ {0x42,0x2a3d,0x0d07,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x3a},
++ {0x45,0x2a7f,0x0d07,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x3a},
++ {0x48,0x223b,0x0e08,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x3c}, /* 1360x768 */
++ {0x4b,0x227d,0x0e08,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x3c},
++ {0x4e,0x22ff,0x0e08,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x3c},
++ {0x4f,0x921f,0x0000,0x0000,SIS_RI_320x200, 0x00,0x00,0x00,0x23}, /* 320x200x32 */
++ {0x53,0x921f,0x0001,0x0000,SIS_RI_320x240, 0x00,0x00,0x00,0x24}, /* 320x240x32 */
++ {0x54,0xb21f,0x0103,0x0000,SIS_RI_400x300, 0x00,0x00,0x00,0x25}, /* 400x300x32 */
++ {0x55,0x2e3b,0x0609,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x3d}, /* 1280x768 */
++ {0x5a,0x2e7d,0x0609,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x3d},
++ {0x5b,0x2eff,0x0609,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x3d},
++ {0x5f,0x2a1b,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x3e}, /* 768x576x8 */
++ {0x60,0x2a1d,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x3e}, /* 768x576x16 */
++ {0x61,0x2a1f,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x3e}, /* 768x576x32 */
++ {0x67,0x2e3b,0x0e08,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x3f}, /* 1360x1024x8 (BARCO) */
++ {0x6f,0x2e7d,0x0e08,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x3f}, /* 1360x1024x16 (BARCO) */
++ {0x72,0x2eff,0x0e08,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x3f}, /* 1360x1024x32 (BARCO) */
++ {0xff,0x0000,0x0000,0xffff,0x00, 0x00,0x00,0x00,0x00}
+ };
+
+ typedef struct _SiS300_Ext2Struct
+@@ -514,76 +183,77 @@ typedef struct _SiS300_Ext2Struct
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+- USHORT ROM_OFFSET;
+ } SiS300_Ext2Struct;
+
+ static const SiS300_Ext2Struct SiS300_RefIndex[] =
+ { /* TW: Don't ever insert anything here, table is indexed */
+- {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3563}, /* 00 */
+- {0x0467,0x0e,0x44,0x05,0x6a, 800, 600,0x3568}, /* 01 */
+- {0x0067,0x0f,0x07,0x48,0x6a, 800, 600,0x356d}, /* 02 - CRT1CRTC was 0x4f */
+- {0x0067,0x10,0x06,0x8b,0x6a, 800, 600,0x3572}, /* 03 */
+- {0x0147,0x11,0x08,0x00,0x6a, 800, 600,0x3577}, /* 04 */
+- {0x0147,0x12,0x0c,0x00,0x6a, 800, 600,0x357c}, /* 05 */
+- {0x0047,0x11,0x4e,0x00,0x6a, 800, 600,0x3581}, /* 06 - CRT1CRTC was 0x51 */
+- {0x0047,0x11,0x13,0x00,0x6a, 800, 600,0x3586}, /* 07 */
+- {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3539}, /* 08 */
+- {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x353e}, /* 09 */
+- {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3543}, /* 0a */
+- {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3548}, /* 0b */
+- {0xc047,0x09,0x05,0x00,0x2e, 640, 480,0x354d}, /* 0c */
+- {0xc047,0x0a,0x08,0x00,0x2e, 640, 480,0x3552}, /* 0d */
+- {0xc047,0x0b,0x0a,0x00,0x2e, 640, 480,0x3557}, /* 0e */
+- {0xc047,0x0c,0x10,0x00,0x2e, 640, 480,0x355c}, /* 0f */
+- {0x487f,0x04,0x00,0x00,0x2f, 640, 400,0x3532}, /* 10 */
+- {0xc00f,0x31,0x01,0x06,0x31, 720, 480,0x3630}, /* 11 */
+- {0x000f,0x32,0x03,0x06,0x32, 720, 576,0x3637}, /* 12 */
+- {0x0187,0x15,0x05,0x00,0x37,1024, 768,0x358d}, /* 13 */
+- {0xc877,0x16,0x09,0x06,0x37,1024, 768,0x3592}, /* 14 */
+- {0xc067,0x17,0x0b,0x49,0x37,1024, 768,0x3597}, /* 15 - CRT1CRTC was 0x97 */
+- {0x0267,0x18,0x0d,0x00,0x37,1024, 768,0x359c}, /* 16 */
+- {0x0047,0x19,0x11,0x8c,0x37,1024, 768,0x35a1}, /* 17 - CRT1CRTC was 0x59 */
+- {0x0047,0x1a,0x52,0x00,0x37,1024, 768,0x35a6}, /* 18 */
+- {0x0007,0x1b,0x16,0x00,0x37,1024, 768,0x35ab}, /* 19 - CRT1CRTC was 0x5b */
+- {0x0387,0x1c,0x4d,0x00,0x3a,1280,1024,0x35be}, /* 1a - CRT1CRTC was 0x5c */
+- {0x0077,0x1d,0x14,0x07,0x3a,1280,1024,0x35c3}, /* 1b */
+- {0x0047,0x1e,0x17,0x00,0x3a,1280,1024,0x35c8}, /* 1c */
+- {0x0007,0x1f,0x98,0x00,0x3a,1280,1024,0x35cd}, /* 1d */
+- {0x0007,0x20,0x59,0x00,0x3c,1600,1200,0x35d4}, /* 1e - CRT1CRTC was 0x60 */
+- {0x0007,0x21,0x5a,0x00,0x3c,1600,1200,0x35d9}, /* 1f */
+- {0x0007,0x22,0x1b,0x00,0x3c,1600,1200,0x35de}, /* 20 */
+- {0x0007,0x23,0x1d,0x00,0x3c,1600,1200,0x35e3}, /* 21 - CRT1CRTC was 0x63 */
+- {0x0007,0x24,0x1e,0x00,0x3c,1600,1200,0x35e8}, /* 22 */
+- {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3516}, /* 23 */
+- {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x351d}, /* 24 */
+- {0x0077,0x02,0x04,0x05,0x51, 400, 300,0x3524}, /* 25 */
+- {0xc877,0x03,0x09,0x06,0x52, 512, 384,0x352b}, /* 26 */ /* was c077 */
+- {0x8207,0x25,0x1f,0x00,0x68,1920,1440,0x35ef}, /* 27 */
+- {0x0007,0x26,0x20,0x00,0x6c,2048,1536,0x35f6}, /* 28 */
+- {0x0067,0x27,0x14,0x08,0x6e,1280, 960,0x35b7}, /* 29 - TW: 1280x960-60 */
+- {0x0027,0x45,0x3c,0x08,0x6e,1280, 960,0x35b7}, /* 2a - TW: 1280x960-85 */
+- {0xc077,0x33,0x09,0x06,0x20,1024, 600,0x0000}, /* 2b */
+- {0xc077,0x34,0x0b,0x06,0x23,1152, 768,0x0000}, /* 2c */ /* VCLK 0x09 */
+- {0x0057,0x35,0x27,0x08,0x70, 800, 480,0x3b52}, /* 2d - TW: 16:9 modes */
+- {0x0047,0x36,0x37,0x08,0x70, 800, 480,0x3b57}, /* 2e */
+- {0x0047,0x37,0x08,0x08,0x70, 800, 480,0x3b5c}, /* 2f */
+- {0x0057,0x38,0x09,0x09,0x71,1024, 576,0x3b63}, /* 30 */
+- {0x0047,0x39,0x38,0x09,0x71,1024, 576,0x3b68}, /* 31 */
+- {0x0047,0x3a,0x11,0x09,0x71,1024, 576,0x3b6d}, /* 32 */
+- {0x0057,0x3b,0x39,0x0a,0x75,1280, 720,0x3b74}, /* 33 */
+- {0x0047,0x3c,0x3a,0x0a,0x75,1280, 720,0x3b79}, /* 34 */
+- {0x0007,0x3d,0x3b,0x0a,0x75,1280, 720,0x3b7e}, /* 35 - TW: END of 16:9 modes */
+- {0x0047,0x3e,0x34,0x06,0x29,1152, 864,0x0000}, /* 36 TW: 1152x864-75Hz - Non-BIOS, new */
+- {0x0047,0x44,0x3a,0x06,0x29,1152, 864,0x0000}, /* 37 TW: 1152x864-85Hz - Non-BIOS, new */
+- {0x00c7,0x3f,0x28,0x00,0x39, 848, 480,0x0000}, /* 38 TW: 848x480-38Hzi - Non-BIOS, new */
+- {0xc047,0x40,0x3d,0x00,0x39, 848, 480,0x0000}, /* 39 TW: 848x480-60Hz - Non-BIOS, new */
+- {0x00c7,0x41,0x28,0x00,0x3f, 856, 480,0x0000}, /* 3a TW: 856x480-38Hzi - Non-BIOS, new */
+- {0xc047,0x42,0x28,0x00,0x3f, 856, 480,0x0000}, /* 3b TW: 856x480-60Hz - Non-BIOS, new */
+- {0x0047,0x43,0x3e,0x00,0x48,1360, 768,0x0000}, /* 3c TW: 1360x768-60Hz - Non-BIOS, new */
+- {0xffff,0,0,0,0,0,0,0}
++ {0x085f,0x0d,0x03,0x05,0x6a, 800, 600}, /* 00 */
++ {0x0467,0x0e,0x44,0x05,0x6a, 800, 600}, /* 01 */
++ {0x0067,0x0f,0x07,0x48,0x6a, 800, 600}, /* 02 - CRT1CRTC was 0x4f */
++ {0x0067,0x10,0x06,0x8b,0x6a, 800, 600}, /* 03 */
++ {0x0147,0x11,0x08,0x00,0x6a, 800, 600}, /* 04 */
++ {0x0147,0x12,0x0c,0x00,0x6a, 800, 600}, /* 05 */
++ {0x0047,0x11,0x4e,0x00,0x6a, 800, 600}, /* 06 - CRT1CRTC was 0x51 */
++ {0x0047,0x11,0x13,0x00,0x6a, 800, 600}, /* 07 */
++ {0xc85f,0x05,0x00,0x04,0x2e, 640, 480}, /* 08 */
++ {0xc067,0x06,0x02,0x04,0x2e, 640, 480}, /* 09 */
++ {0xc067,0x07,0x02,0x47,0x2e, 640, 480}, /* 0a */
++ {0xc067,0x08,0x03,0x8a,0x2e, 640, 480}, /* 0b */
++ {0xc047,0x09,0x05,0x00,0x2e, 640, 480}, /* 0c */
++ {0xc047,0x0a,0x08,0x00,0x2e, 640, 480}, /* 0d */
++ {0xc047,0x0b,0x0a,0x00,0x2e, 640, 480}, /* 0e */
++ {0xc047,0x0c,0x10,0x00,0x2e, 640, 480}, /* 0f */
++ {0x487f,0x04,0x00,0x00,0x2f, 640, 400}, /* 10 */
++ {0xc00f,0x31,0x01,0x06,0x31, 720, 480}, /* 11 */
++ {0x000f,0x32,0x03,0x06,0x32, 720, 576}, /* 12 */
++ {0x0187,0x15,0x05,0x00,0x37,1024, 768}, /* 13 */
++ {0xc877,0x16,0x09,0x06,0x37,1024, 768}, /* 14 */
++ {0xc067,0x17,0x0b,0x49,0x37,1024, 768}, /* 15 - CRT1CRTC was 0x97 */
++ {0x0267,0x18,0x0d,0x00,0x37,1024, 768}, /* 16 */
++ {0x0047,0x19,0x11,0x8c,0x37,1024, 768}, /* 17 - CRT1CRTC was 0x59 */
++ {0x0047,0x1a,0x52,0x00,0x37,1024, 768}, /* 18 */
++ {0x0007,0x1b,0x16,0x00,0x37,1024, 768}, /* 19 - CRT1CRTC was 0x5b */
++ {0x0387,0x1c,0x4d,0x00,0x3a,1280,1024}, /* 1a - CRT1CRTC was 0x5c */
++ {0x0077,0x1d,0x14,0x07,0x3a,1280,1024}, /* 1b */
++ {0x0047,0x1e,0x17,0x00,0x3a,1280,1024}, /* 1c */
++ {0x0007,0x1f,0x98,0x00,0x3a,1280,1024}, /* 1d */
++ {0x0007,0x20,0x59,0x00,0x3c,1600,1200}, /* 1e - CRT1CRTC was 0x60 */
++ {0x0007,0x21,0x5a,0x00,0x3c,1600,1200}, /* 1f */
++ {0x0007,0x22,0x1b,0x00,0x3c,1600,1200}, /* 20 */
++ {0x0007,0x23,0x1d,0x00,0x3c,1600,1200}, /* 21 - CRT1CRTC was 0x63 */
++ {0x0007,0x24,0x1e,0x00,0x3c,1600,1200}, /* 22 */
++ {0x407f,0x00,0x00,0x00,0x40, 320, 200}, /* 23 */
++ {0xc07f,0x01,0x00,0x04,0x50, 320, 240}, /* 24 */
++ {0x0077,0x02,0x04,0x05,0x51, 400, 300}, /* 25 */
++ {0xc877,0x03,0x09,0x06,0x52, 512, 384}, /* 26 */ /* was c077 */
++ {0x8207,0x25,0x1f,0x00,0x68,1920,1440}, /* 27 */
++ {0x0007,0x26,0x20,0x00,0x6c,2048,1536}, /* 28 */
++ {0x0067,0x27,0x14,0x08,0x6e,1280, 960}, /* 29 - TW: 1280x960-60 */
++ {0x0027,0x45,0x3c,0x08,0x6e,1280, 960}, /* 2a - TW: 1280x960-85 */
++ {0xc077,0x33,0x09,0x06,0x20,1024, 600}, /* 2b */
++ {0xc077,0x34,0x0b,0x06,0x23,1152, 768}, /* 2c */ /* VCLK 0x09 */
++ {0x0057,0x35,0x27,0x08,0x70, 800, 480}, /* 2d */
++ {0x0047,0x36,0x37,0x08,0x70, 800, 480}, /* 2e */
++ {0x0047,0x37,0x08,0x08,0x70, 800, 480}, /* 2f */
++ {0x0057,0x38,0x09,0x09,0x71,1024, 576}, /* 30 */
++ {0x0047,0x39,0x38,0x09,0x71,1024, 576}, /* 31 */
++ {0x0047,0x3a,0x11,0x09,0x71,1024, 576}, /* 32 */
++ {0x0057,0x3b,0x39,0x0a,0x75,1280, 720}, /* 33 */
++ {0x0047,0x3c,0x3a,0x0a,0x75,1280, 720}, /* 34 */
++ {0x0007,0x3d,0x3b,0x0a,0x75,1280, 720}, /* 35 */
++ {0x0047,0x3e,0x34,0x06,0x29,1152, 864}, /* 36 1152x864-75Hz */
++ {0x0047,0x44,0x3a,0x06,0x29,1152, 864}, /* 37 1152x864-85Hz */
++ {0x00c7,0x3f,0x28,0x00,0x39, 848, 480}, /* 38 848x480-38Hzi */
++ {0xc067,0x40,0x3d,0x0b,0x39, 848, 480}, /* 39 848x480-60Hz */
++ {0x00c7,0x41,0x28,0x00,0x3f, 856, 480}, /* 3a 856x480-38Hzi */
++ {0xc047,0x42,0x28,0x00,0x3f, 856, 480}, /* 3b 856x480-60Hz */
++ {0x0067,0x43,0x3e,0x0c,0x48,1360, 768}, /* 3c 1360x768-60Hz */
++ {0x0077,0x46,0x3f,0x08,0x55,1280, 768}, /* 3d 1280x768-60Hz */
++ {0x000f,0x47,0x03,0x06,0x5f, 768, 576}, /* 3e 768x576 */
++ {0x0027,0x48,0x13,0x08,0x67,1360,1024}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
++ {0xffff, 0, 0, 0, 0, 0, 0}
+ };
+
+-/*add for 300 oem util*/
+ typedef struct _SiS_VBModeIDTableStruct
+ {
+ UCHAR ModeID;
+@@ -649,9 +319,8 @@ static const SiS_VBModeIDTableStruct Si
+ {0x6e,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+ {0x6f,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+ {0x7b,0x00,0x00,0x01,0x00,0x00,0x0b,0x0d},
+- {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00} /* TW: added! */
++ {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+ };
+-/*end*/
+
+ typedef struct _SiS300_CRT1TableStruct
+ {
+@@ -660,15 +329,32 @@ typedef struct _SiS300_CRT1TableStruct
+
+ static const SiS300_CRT1TableStruct SiS300_CRT1Table[] =
+ {
+- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 */
+- 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
++#if 1
++ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x00 - 320x200 */
++ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
++ 0x00}},
++#endif
++#if 0
++ {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f, /* 0x00 - corrected 320x200-72 - does not work */
++ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04,
+ 0x00}},
+- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+- 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
++#endif
++ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* 0x01 */
++ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00, /* HRE [4],[15] is invalid - but correcting it does not work */
+ 0x00}},
+- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
++#if 0
++ {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e, /* 0x01 - corrected 320x240-60 - does not work */
++ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04,
++ 0x00}},
++#endif
++ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 */
++ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
++ 0x01}},
++#if 0
++ {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0, /* 0x02 - corrected 400x300-60 */
+ 0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
+ 0x01}},
++#endif
+ {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
+ 0x01}},
+@@ -683,7 +369,7 @@ static const SiS300_CRT1TableStruct SiS
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* 0x05 - corrected 640x480-60 */
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00}},
+- #if 0
++#if 0
+ {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e, /* 0x06 */
+ 0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
+ 0x00}},
+@@ -841,15 +527,10 @@ static const SiS300_CRT1TableStruct SiS
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1, /* 0x33 - 1024x600 */
+ 0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
+ 0x01}},
+-#if 0
+- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5, /* 0x34 - 1152x768 */
+- 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+- 0x01}},
+-#endif
+- {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5, /* 0x34 - 1152x768 - TW: corrected */
++ {{0xa3,0x8f,0x8f,0x97,0x96,0x97,0x24,0xf5, /* 0x34 - 1152x768 - corrected */
+ 0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
+ 0x01}},
+- {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x35 - NEW 16:9 modes, not in BIOS ------ */
++ {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba, /* 0x35 */
+ 0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
+ 0x01}}, /* 0x35 */
+ {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
+@@ -864,7 +545,7 @@ static const SiS300_CRT1TableStruct SiS
+ {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
+ 0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
+ 0x01}}, /* 0x39 */
+- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* TW: 95 was 15 - illegal HBE! */
++ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1, /* 95 was 15 - illegal HBE! */
+ 0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
+ 0x01}}, /* 0x3a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
+@@ -875,36 +556,40 @@ static const SiS300_CRT1TableStruct SiS
+ 0x01}}, /* 0x3c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
+ 0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
+- 0x01}}, /* 0x3d */ /* TW: End of 16:9 modes --------------- */
+- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* TW: New, 1152x864-75 (not in any BIOS) */
++ 0x01}}, /* 0x3d */
++ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
+ 0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
+ 0x01}}, /* 0x3e */
+- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 848x480-38i, not in BIOS */
++ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x3f */
+-#if 0
+- {{0x81,0x69,0x69,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 848x480-60, not in BIOS - incorrect for Philips panel */
+- 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+- 0x00}}, /* 0x40 */
+-#endif
+- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* TW: New, 848x480-60, not in BIOS */
++ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
+ 0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
+ 0x00}}, /* 0x40 */
+- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* TW: New, 856x480-38i, not in BIOS */
++ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
+ 0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
+ 0x00}}, /* 0x41 */
+- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* TW: New, 856x480-60, not in BIOS */
++ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
+ 0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
+ 0x00}}, /* 0x42 */
+- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* TW: New, 1360x768-60, not in BIOS */
++ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
+ 0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
+ 0x01}}, /* 0x43 */
+- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* TW: New, 1152x864-84 (not in any BIOS) */
++ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84 */
+ 0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
+- 0x01}}, /* 0x44 */
+- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* TW: New, 1280x960-85 (not in any BIOS) */
++ 0x01}}, /* 0x44 */
++ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
+ 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+- 0x01}} /* 0x45 */
++ 0x01}}, /* 0x45 */
++ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5, /* 1280x768-60 */
++ 0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
++ 0x01}}, /* 0x46 */
++ {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
++ 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
++ 0x01}}, /* 0x47 */
++ {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52, /* 1360x1024 (Barco iQ Pro R300) */
++ 0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
++ 0x00}} /* 0x48 */
+ };
+
+ typedef struct _SiS300_MCLKDataStruct
+@@ -913,8 +598,8 @@ typedef struct _SiS300_MCLKDataStruct
+ USHORT CLOCK;
+ } SiS300_MCLKDataStruct;
+
+-static const SiS300_MCLKDataStruct SiS300_MCLKData_630[] = /* 630 */
+-{ /* TW: at 0x54 in BIOS */
++static const SiS300_MCLKDataStruct SiS300_MCLKData_630[] =
++{
+ { 0x5a,0x64,0x80, 66},
+ { 0xb3,0x45,0x80, 83},
+ { 0x37,0x61,0x80,100},
+@@ -925,8 +610,8 @@ static const SiS300_MCLKDataStruct SiS3
+ { 0x37,0x61,0x80,100}
+ };
+
+-static const SiS300_MCLKDataStruct SiS300_MCLKData_300[] = /* 300 */
+-{ /* TW: at 0x54 in BIOS */
++static const SiS300_MCLKDataStruct SiS300_MCLKData_300[] =
++{
+ { 0x68,0x43,0x80,125},
+ { 0x68,0x43,0x80,125},
+ { 0x68,0x43,0x80,125},
+@@ -937,6 +622,7 @@ static const SiS300_MCLKDataStruct SiS3
+ { 0x37,0x61,0x80,100}
+ };
+
++#ifdef LINUXBIOS
+ typedef struct _SiS300_ECLKDataStruct
+ {
+ UCHAR SR2E,SR2F,SR30;
+@@ -954,6 +640,7 @@ static const SiS300_ECLKDataStruct SiS3
+ { 0x54,0x43,0x80,100},
+ { 0x54,0x43,0x80,100}
+ };
++#endif
+
+ typedef struct _SiS300_VCLKDataStruct
+ {
+@@ -964,71 +651,77 @@ typedef struct _SiS300_VCLKDataStruct
+ static const SiS300_VCLKDataStruct SiS300_VCLKData[] =
+ {
+ { 0x1b,0xe1, 25}, /* 0x00 */
+- { 0x4e,0xe4, 28},
++ { 0x4e,0xe4, 28}, /* 0x01 */
+ { 0x57,0xe4, 32}, /* 0x02 */
+- { 0xc3,0xc8, 36},
++ { 0xc3,0xc8, 36}, /* 0x03 */
+ { 0x42,0xc3, 40}, /* 0x04 */
+- { 0x5d,0xc4, 45},
++ { 0x5d,0xc4, 45}, /* 0x05 */
+ { 0x52,0x65, 50}, /* 0x06 */
+- { 0x53,0x65, 50},
++ { 0x53,0x65, 50}, /* 0x07 */
+ { 0x6d,0x66, 56}, /* 0x08 */
+- { 0x5a,0x64, 65},
++ { 0x5a,0x64, 65}, /* 0x09 */
+ { 0x46,0x44, 68}, /* 0x0a */
+- { 0x3e,0x43, 75},
+- { 0x6d,0x46, 76}, /* 0x0c: 800x600 | LVDS_2(CH), MITAC(CH); - 730, A901(301B): 0xb1,0x46, 76 */
+- { 0x41,0x43, 79},
++ { 0x3e,0x43, 75}, /* 0x0b */
++ { 0x6d,0x46, 76}, /* 0x0c */ /* 800x600 | LVDS_2(CH), MITAC(CH); - 730, A901(301B): 0xb1,0x46, 76 */
++ { 0x41,0x43, 79}, /* 0x0d */
+ { 0x31,0x42, 79}, /* 0x0e */
+- { 0x46,0x25, 85},
++ { 0x46,0x25, 85}, /* 0x0f */
+ { 0x78,0x29, 87}, /* 0x10 */
+- { 0x62,0x44, 95},
++ { 0x62,0x44, 95}, /* 0x11 */
+ { 0x2b,0x22,105}, /* 0x12 */
+- { 0x49,0x24,106},
++ { 0x49,0x24,106}, /* 0x13 */
+ { 0xc3,0x28,108}, /* 0x14 */
+- { 0x3c,0x23,109},
++ { 0x3c,0x23,109}, /* 0x15 */
+ { 0xf7,0x2c,132}, /* 0x16 */
+- { 0xd4,0x28,136},
++ { 0xd4,0x28,136}, /* 0x17 */
+ { 0x41,0x05,158}, /* 0x18 */
+- { 0x43,0x05,162},
++ { 0x43,0x05,162}, /* 0x19 */
+ { 0xe1,0x0f,175}, /* 0x1a */
+ { 0xfc,0x12,189}, /* 0x1b */
+ { 0xde,0x26,194}, /* 0x1c */
+- { 0x54,0x05,203},
++ { 0x54,0x05,203}, /* 0x1d */
+ { 0x3f,0x03,230}, /* 0x1e */
+- { 0x30,0x02,234},
++ { 0x30,0x02,234}, /* 0x1f */
+ { 0x24,0x01,266}, /* 0x20 */
+- { 0x52,0x2a, 54}, /* 301 TV */
+- { 0x52,0x6a, 27}, /* 301 TV */
+- { 0x62,0x24, 70}, /* 301 TV */
+- { 0x62,0x64, 70}, /* 301 TV */
+- { 0xa8,0x4c, 30}, /* 301 TV */
+- { 0x20,0x26, 33}, /* 301 TV */
+- { 0x31,0xc2, 39},
+- { 0xbf,0xc8, 35}, /* 0x28 - 856x480 */
+- { 0x60,0x36, 30}, /* 0x29 CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */
+- { 0x40,0x4a, 28},
+- { 0x9f,0x46, 44},
+- { 0x97,0x2c, 26},
+- { 0x44,0xe4, 25},
+- { 0x7e,0x32, 47},
+- { 0x8a,0x24, 31}, /* 0x2f CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - 730, A901(301B): 0x57, 0xe4, 31 */
+- { 0x97,0x2c, 26},
+- { 0xce,0x3c, 39},
+- { 0x52,0x4a, 36}, /* 0x32 CH/PAL 800x600 5/6 */
+- { 0x34,0x61, 95},
+- { 0x78,0x27,108},
+- { 0xce,0x25,189}, /* 0x35 */
+- { 0x45,0x6b, 21}, /* 0x36 */ /* TW: Added from Mitac */
+- { 0x52,0xe2, 49}, /* 0x37 - added for 16:9 modes (not in any BIOS) */
+- { 0x2b,0x61, 78}, /* 0x38 - added for 16:9 modes (not in any BIOS) */
+- { 0x70,0x44,108}, /* 0x39 - added for 16:9 modes (not in any BIOS) */
+- { 0x54,0x42,135}, /* 0x3a - added for 16:9 modes (not in any BIOS) */
+- { 0x41,0x22,157}, /* 0x3b - added for 16:9 modes (not in any BIOS) */
+- { 0x52,0x07,149}, /* 0x3c - added for 1280x960-85 (not in any BIOS)*/
+- { 0x62,0xc6, 34}, /* 0x3d - added for 848x480-60 (not in any BIOS) */
+- { 0x30,0x23, 88}, /* 0x3e - added for 1360x768-60 (not in any BIOS)*/
+- { 0x3f,0x64, 46}, /* 0x3f - added for 640x480-100 (not in any BIOS)*/
+- { 0x72,0x2a, 76}, /* 0x40 - test for SiS730 */
+- { 0x15,0x21, 79}, /* 0x41 - test for SiS730 */
++ { 0x52,0x2a, 54}, /* 0x21 */ /* 301 TV */
++ { 0x52,0x6a, 27}, /* 0x22 */ /* 301 TV */
++ { 0x62,0x24, 70}, /* 0x23 */ /* 301 TV */
++ { 0x62,0x64, 70}, /* 0x24 */ /* 301 TV */
++ { 0xa8,0x4c, 30}, /* 0x25 */ /* 301 TV */
++ { 0x20,0x26, 33}, /* 0x26 */ /* 301 TV */
++ { 0x31,0xc2, 39}, /* 0x27 */
++ { 0xbf,0xc8, 35}, /* 0x28 */ /* 856x480 */
++ { 0x60,0x36, 30}, /* 0x29 */ /* CH/UNTSC TEXT | LVDS_2(CH) - 730, A901(301B), Mitac(CH): 0xe0, 0xb6, 30 */
++ { 0x40,0x4a, 28}, /* 0x2a */
++ { 0x9f,0x46, 44}, /* 0x2b */
++ { 0x97,0x2c, 26}, /* 0x2c */
++ { 0x44,0xe4, 25}, /* 0x2d */
++ { 0x7e,0x32, 47}, /* 0x2e */
++ { 0x8a,0x24, 31}, /* 0x2f */ /* CH/PAL TEXT | LVDS_2(CH), Mitac(CH) - 730, A901(301B): 0x57, 0xe4, 31 */
++ { 0x97,0x2c, 26}, /* 0x30 */
++ { 0xce,0x3c, 39}, /* 0x31 */
++ { 0x52,0x4a, 36}, /* 0x32 */ /* CH/PAL 800x600 5/6 */
++ { 0x34,0x61, 95}, /* 0x33 */
++ { 0x78,0x27,108}, /* 0x34 */ /* Replacement for index 0x14 for 630 (?) */
++ { 0xce,0x25,189}, /* 0x35 */ /* Replacement for index 0x1b for 730 (and 540?) */
++ { 0x45,0x6b, 21}, /* 0x36 */
++ { 0x52,0xe2, 49}, /* 0x37 */ /* 16:9 modes */
++ { 0x2b,0x61, 78}, /* 0x38 */ /* 16:9 modes */
++ { 0x70,0x44,108}, /* 0x39 */ /* 16:9 modes */
++ { 0x54,0x42,135}, /* 0x3a */ /* 16:9 modes */
++ { 0x41,0x22,157}, /* 0x3b */ /* 16:9 modes */
++ { 0x52,0x07,149}, /* 0x3c */ /* 1280x960-85 */
++ { 0x62,0xc6, 34}, /* 0x3d */ /* 848x480-60 */
++ { 0x30,0x23, 88}, /* 0x3e */ /* 1360x768-60 */
++#if 0
++ { 0x3f,0x64, 46}, /* 0x3f */ /* 640x480-100 */
++#endif
++ { 0x70,0x29, 81}, /* 0x3f */ /* 1280x768-60 */
++ { 0x72,0x2a, 76}, /* 0x40 */ /* test for SiS730 */
++ { 0x15,0x21, 79}, /* 0x41 */ /* test for SiS730 */
++ { 0xa1,0x42,108}, /* 0x42 */ /* 1280x960 LCD */
++ { 0x37,0x61,100}, /* 0x43 */ /* 1280x960 LCD */
++ { 0xe3,0x9a,106}, /* 0x44 */ /* 1360x1024 - special for Barco iQ R300 */
+ { 0xff,0x00, 0}
+ };
+
+@@ -1089,66 +782,10 @@ static const SiS300_VCLKDataStruct SiS3
+ static const UCHAR SiS300_ScreenOffset[] =
+ {
+ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,
+- 0x64,0x78,0x80,0x2d,0x35,0x48,0x35, /* 0x35 for 848 and 856 */
+- 0x55,0xff /* 0x55 for 1360 */
++ 0x64,0x78,0x80,0x2d,0x35,0x48,0x35,
++ 0x55,0x30,0xff
+ };
+
+-typedef struct _SiS300_StResInfoStruct
+-{
+- USHORT HTotal;
+- USHORT VTotal;
+-} SiS300_StResInfoStruct;
+-
+-static const SiS300_StResInfoStruct SiS300_StResInfo[] =
+-{
+- { 640,400},
+- { 640,350},
+- { 720,400},
+- { 720,350},
+- { 640,480}
+-};
+-
+-typedef struct _SiS300_ModeResInfoStruct
+-{
+- USHORT HTotal;
+- USHORT VTotal;
+- UCHAR XChar;
+- UCHAR YChar;
+-} SiS300_ModeResInfoStruct;
+-
+-static const SiS300_ModeResInfoStruct SiS300_ModeResInfo[] =
+-{
+- { 320, 200, 8, 8}, /* 0x00 */
+- { 320, 240, 8, 8}, /* 0x01 */
+- { 320, 400, 8, 8}, /* 0x02 */
+- { 400, 300, 8, 8}, /* 0x03 */
+- { 512, 384, 8, 8}, /* 0x04 */
+- { 640, 400, 8,16}, /* 0x05 */
+- { 640, 480, 8,16}, /* 0x06 */
+- { 800, 600, 8,16}, /* 0x07 */
+- { 1024, 768, 8,16}, /* 0x08 */
+- { 1280,1024, 8,16}, /* 0x09 */
+- { 1600,1200, 8,16}, /* 0x0a */
+- { 1920,1440, 8,16}, /* 0x0b */
+- { 720, 480, 8,16}, /* 0x0c */
+- { 720, 576, 8,16}, /* 0x0d */
+- { 1280, 960, 8,16}, /* 0x0e */
+- { 1024, 600, 8,16}, /* 0x0f */
+- { 1152, 768, 8,16}, /* 0x10 */
+- { 2048,1536, 8,16}, /* 0x11 - TW: Not in BIOS! */
+- { 800, 480, 8,16}, /* 0x12 - TW: New, not in any BIOS */
+- { 1024, 576, 8,16}, /* 0x13 - TW: New, not in any BIOS */
+- { 1280, 720, 8,16}, /* 0x14 - TW: New, not in any BIOS */
+- { 1152, 864, 8,16}, /* 0x15 - TW: New, not in any BIOS */
+- { 848, 480, 8,16}, /* 0x16 - TW: New, not in any BIOS */
+- { 856, 480, 8,16}, /* 0x17 - TW: New, not in any BIOS */
+- { 1360, 768, 8,16} /* 0x18 - TW: New, not in any BIOS */
+-};
+-
+-static const UCHAR SiS300_OutputSelect = 0x40;
+-
+-static const UCHAR SiS300_SoftSetting = 0x30;
+-
+ #ifndef LINUX_XF86
+ static UCHAR SiS300_SR07 = 0x10;
+ #endif
+@@ -1183,7 +820,7 @@ static UCHAR SiS300_CRT2Data_4_10 = 0x80
+ static const USHORT SiS300_RGBSenseData = 0xd1;
+ static const USHORT SiS300_VideoSenseData = 0xb3;
+ static const USHORT SiS300_YCSenseData = 0xb9;
+-static const USHORT SiS300_RGBSenseData2 = 0x0190; /*301b*/
++static const USHORT SiS300_RGBSenseData2 = 0x0190;
+ static const USHORT SiS300_VideoSenseData2 = 0x0174;
+ static const USHORT SiS300_YCSenseData2 = 0x016b;
+
+@@ -1192,15 +829,6 @@ static const UCHAR SiS300_CR40[5][4];
+ static UCHAR SiS300_CR49[2];
+ #endif
+
+-static const UCHAR SiS300_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */
+-static const UCHAR SiS300_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */
+-static const UCHAR SiS300_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* palmn */
+-static const UCHAR SiS300_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
+-static const UCHAR SiS300_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6}; /* 301b */
+-static const UCHAR SiS300_PALPhase2[] = {0x2a,0x09,0x86,0xe9}; /* 301b */
+-static const UCHAR SiS300_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/
+-static const UCHAR SiS300_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/
+-
+ typedef struct _SiS300_PanelDelayTblStruct
+ {
+ UCHAR timer[2];
+@@ -1208,7 +836,7 @@ typedef struct _SiS300_PanelDelayTblStru
+
+ static const SiS300_PanelDelayTblStruct SiS300_PanelDelayTbl[] =
+ {
+- {{0x05,0xaa}}, /* TW: From 2.04.5a */
++ {{0x05,0xaa}},
+ {{0x05,0x14}},
+ {{0x05,0x36}},
+ {{0x05,0x14}},
+@@ -1355,309 +983,6 @@ static const SiS300_LCDDataStruct SiS30
+ { 1, 1,1688,1066,1688,1066}
+ };
+
+-static const SiS300_LCDDataStruct SiS300_LCD1280x960Data[] =
+-{
+- { 9, 2, 800, 500,1800,1000},
+- { 9, 2, 800, 500,1800,1000},
+- { 4, 1, 900, 500,1800,1000},
+- { 4, 1, 900, 500,1800,1000},
+- { 9, 2, 800, 500,1800,1000},
+- { 30, 11,1056, 625,1800,1000},
+- { 5, 3,1350, 800,1800,1000},
+- { 1, 1,1576,1050,1576,1050},
+- { 1, 1,1800,1000,1800,1000}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_ExtLCD1400x1050Data[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_ExtLCD1600x1200Data[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_StLCD1400x1050Data[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_StLCD1600x1200Data[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_NoScaleData1400x1050[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS300_LCDDataStruct SiS300_NoScaleData1600x1200[] = /* TW: New */
+-{
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0},
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-
+-typedef struct _SiS300_TVDataStruct
+-{
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT TVHDE;
+- USHORT TVVDE;
+- USHORT RVBHRS;
+- UCHAR FlickerMode;
+- USHORT HALFRVBHRS;
+- UCHAR RY1COE;
+- UCHAR RY2COE;
+- UCHAR RY3COE;
+- UCHAR RY4COE;
+-} SiS300_TVDataStruct;
+-
+-static const SiS300_TVDataStruct SiS300_StPALData[] =
+-{
+- { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
+- { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22}
+-};
+-
+-static const SiS300_TVDataStruct SiS300_ExtPALData[] =
+-{
+- { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
+- { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
+- { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18},
+- { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a},
+- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a},
+- { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16},
+- { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20},
+- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20}
+-
+-};
+-
+-static const SiS300_TVDataStruct SiS300_StNTSCData[] =
+-{
+- { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
+- { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18}
+-};
+-
+-static const SiS300_TVDataStruct SiS300_ExtNTSCData[] =
+-{
+- { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
+- { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
+- { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
+- { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
+- { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16},
+- { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00},
+- { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08},
+- { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xf1,0x04,0x1f,0x18}
+-};
+-
+-#if 0
+-static const SiS300_TVDataStruct SiS300_St1HiTVData[]=
+-{
+-
+-};
+-#endif
+-
+-static const SiS300_TVDataStruct SiS300_St2HiTVData[]=
+-{
+- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 1, 1, 0x3e8,0x233,0x311,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
+- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
+-};
+-
+-static const SiS300_TVDataStruct SiS300_ExtHiTVData[]=
+-{
+- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x348,0x1e3,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00},
+- { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},
+- { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00},
+- { 4, 1, 0x41a,0x233,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},
+- { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}
+-};
+-
+-static const UCHAR SiS300_NTSCTiming[] =
+-{
+- 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+- 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+- 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17, /* (in 2.06.50) */
+-/* 0x0c,0x50,0x00,0x99,0x00,0xec,0x4a,0x17, (in 2.04.5a) */
+- 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02, /* (in 2.06.50) */
+-/* 0x88,0x00,0x4b,0x00,0x00,0xe2,0x00,0x02, (in 2.04.5a) */
+- 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+- 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
+-};
+-
+-static const UCHAR SiS300_PALTiming[] =
+-{
+- 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
+- 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+- 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17, /* (in 2.06.50) */
+-/* 0x70,0x50,0x00,0x97,0x00,0xd7,0x5d,0x17, (in 2.04.5a) */
+- 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02, /* (in 2.06.50) */
+-/* 0x88,0x00,0x45,0x00,0x00,0xe8,0x00,0x02, (in 2.04.5a) */
+- 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+- 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
+-};
+-
+-static const UCHAR SiS300_HiTVExtTiming[] = /* TW: New */
+-{
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+- 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+- 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+- 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+-};
+-
+-static const UCHAR SiS300_HiTVSt1Timing[] = /* TW: New */
+-{
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
+- 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10,
+- 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86,
+- 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
+-};
+-
+-static const UCHAR SiS300_HiTVSt2Timing[] = /* TW: New */
+-{
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+- 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+- 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+- 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+-};
+-
+-static const UCHAR SiS300_HiTVTextTiming[] = /* TW: New */
+-{
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
+- 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
+- 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
+- 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
+-};
+-
+-static const UCHAR SiS300_HiTVGroup3Data[] = /* TW: New */
+-{
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+- 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9,
+- 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+-
+-static const UCHAR SiS300_HiTVGroup3Simu[] = /* TW: New */
+-{
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+- 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4,
+- 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+-
+-static const UCHAR SiS300_HiTVGroup3Text[] = /* TW: New */
+-{
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+- 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca,
+- 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+-
+ typedef struct _SiS300_LVDSDataStruct
+ {
+ USHORT VGAHT;
+@@ -1666,366 +991,14 @@ typedef struct _SiS300_LVDSDataStruct
+ USHORT LCDVT;
+ } SiS300_LVDSDataStruct;
+
+-static const SiS300_LVDSDataStruct SiS300_LVDS320x480Data_1[] =
+-{
+- {848, 433,400, 525},
+- {848, 389,400, 525},
+- {848, 433,400, 525},
+- {848, 389,400, 525},
+- {848, 518,400, 525},
+- {1056,628,400, 525},
+- {400, 525,400, 525},
+- {800, 449,1000, 644},
+- {800, 525,1000, 635}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS800x600Data_1[] =
+-{
+- {848, 433,1060, 629},
+- {848, 389,1060, 629},
+- {848, 433,1060, 629},
+- {848, 389,1060, 629},
+- {848, 518,1060, 629},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {800, 449,1000, 644},
+- {800, 525,1000, 635}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS800x600Data_2[] =
+-{
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {800, 449,1000, 644},
+- {800, 525,1000, 635}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_1[] =
+-{
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 518,1344, 806},
+- {1050, 638,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1024x768Data_2[] =
+-{
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_1[]=
+-{
+- {1048, 442,1688,1066},
+- {1048, 392,1688,1066},
+- {1048, 442,1688,1066},
+- {1048, 392,1688,1066},
+- {1048, 522,1688,1066},
+- {1208, 642,1688,1066},
+- {1432, 810,1688,1066},
+- {1688,1066,1688,1066}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x1024Data_2[]=
+-{
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_1[] =
+-{
+- {928, 416, 1688, 1066},
+- {928, 366, 1688, 1066},
+- {928, 416, 1688, 1066},
+- {928, 366, 1688, 1066},
+- {928, 496, 1688, 1066},
+- {1088, 616, 1688, 1066},
+- {1312, 784, 1688, 1066},
+- {1568, 1040, 1688, 1066},
+- {1688, 1066, 1688, 1066}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1400x1050Data_2[] =
+-{
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1600x1200Data_1[]=
+-{
+- {1088, 450, 2048,1250},
+- {1088, 400, 2048,1250},
+- {1088, 450, 2048,1250},
+- {1088, 400, 2048,1250},
+- {1088, 530, 2048,1250},
+- {1248, 650, 2048,1250},
+- {1472, 818, 2048,1250},
+- {1728,1066, 2048,1250},
+- {1848,1066, 2048,1250},
+- {2048,1250, 2048,1250}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1600x1200Data_2[]=
+-{
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x768Data_1[]=
+-{
+- { 768, 438, 1408, 806},
+- { 768, 388, 1408, 806},
+- { 768, 438, 1408, 806},
+- { 768, 388, 1408, 806},
+- { 768, 518, 1408, 806},
+- { 928, 638, 1408, 806},
+- {1152, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x768Data_2[]=
+-{
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1024x600Data_1[] =
+-{
+- {840, 604,1344, 800},
+- {840, 560,1344, 800},
+- {840, 604,1344, 800},
+- {840, 560,1344, 800},
+- {840, 689,1344, 800},
+- {1050, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {800, 449,1280, 789},
+- {800, 525,1280, 785}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1024x600Data_2[] =
+-{
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {1344, 800,1344, 800},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1152x768Data_1[] =
+-{
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 518,1344, 806},
+- {1050, 638,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1152x768Data_2[] =
+-{
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-/* TW: pass 1:1 data */
+-static const SiS300_LVDSDataStruct SiS300_LVDSXXXxXXXData_1[]=
+-{
+- { 800, 449, 800, 449},
+- { 800, 449, 800, 449},
+- { 900, 449, 900, 449},
+- { 900, 449, 900, 449},
+- { 800, 525, 800, 525}, /* 640x480 */
+- {1056, 628, 1056, 628}, /* 800x600 */
+- {1344, 806, 1344, 806}, /* 1024x768 */
+- {1344,1066, 1344,1066}, /* 1280x1024 */ /* INSERTED ! */
+- {1688, 806, 1688, 806}, /* 1280x768 ! */
+- /* No other panels ! */
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS640x480Data_1[] =
+-{
+- {800, 449, 800, 449},
+- {800, 449, 800, 449},
+- {800, 449, 800, 449},
+- {800, 449, 800, 449},
+- {800, 525, 800, 525},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_1[] = /* TW: New */
+-{
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 438,1344, 806},
+- {840, 409,1344, 806},
+- {840, 518,1344, 806},
+- {1050, 638,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LVDS1280x960Data_2[] = /* TW: New */
+-{
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_1[] = /* TW: New */
+-{ /* TW: Might be temporary (invalid) data */
+- {928, 416, 1688, 1066},
+- {928, 366, 1688, 1066},
+- {1008, 416, 1688, 1066},
+- {1008, 366, 1688, 1066},
+- {1200, 530, 1688, 1066},
+- {1088, 616, 1688, 1066},
+- {1312, 784, 1688, 1066},
+- {1568, 1040, 1688, 1066},
+- {1688, 1066, 1688, 1066}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LCDA1400x1050Data_2[] = /* TW: New */
+-{ /* TW: Temporary data. Not valid */
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_1[] = /* TW: New */
+-{ /* TW: Temporary data. Not valid */
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {800, 449,1280, 801},
+- {800, 525,1280, 813}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_LCDA1600x1200Data_2[] = /* TW: New */
+-{ /* TW: Temporary data. Not valid */
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0}
+-};
+-
+-
+-/* TW: New: */
+-static const SiS300_LVDSDataStruct SiS300_CHTVUNTSCData[] =
+-{
+- {840, 600, 840, 600},
+- {840, 600, 840, 600},
+- {840, 600, 840, 600},
+- {840, 600, 840, 600},
+- {784, 600, 784, 600},
+- {1064, 750,1064, 750}
+-};
+-
+-static const SiS300_LVDSDataStruct SiS300_CHTVONTSCData[] =
+-{
+- {840, 525, 840, 525},
+- {840, 525, 840, 525},
+- {840, 525, 840, 525},
+- {840, 525, 840, 525},
+- {784, 525, 784, 525},
+- {1040, 700,1040, 700}
+-};
+-
+ static const SiS300_LVDSDataStruct SiS300_CHTVUPALData[] =
+ {
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+- {840, 750, 840, 750},
+- {936, 836, 936, 836}
++ { 840, 750, 840, 750},
++ { 936, 836, 936, 836}
+ };
+
+ static const SiS300_LVDSDataStruct SiS300_CHTVOPALData[] =
+@@ -2034,8 +1007,8 @@ static const SiS300_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+- {840, 625, 840, 625},
+- {960, 750, 960, 750}
++ { 840, 625, 840, 625},
++ { 960, 750, 960, 750}
+ };
+
+ static const SiS300_LVDSDataStruct SiS300_CHTVSOPALData[] =
+@@ -2044,12 +1017,10 @@ static const SiS300_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+- {840, 500, 840, 500},
+- {944, 625, 944, 625}
++ { 840, 500, 840, 500},
++ { 944, 625, 944, 625}
+ };
+
+-/* TW: new end */
+-
+ typedef struct _SiS300_LVDSDesStruct
+ {
+ USHORT LCDHDES;
+@@ -2058,57 +1029,90 @@ typedef struct _SiS300_LVDSDesStruct
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType00_1[] =
+ {
++ { 1059, 626 }, /* 2.08 */
++ { 1059, 624 },
++ { 1059, 626 },
++ { 1059, 624 },
++ { 1059, 624 },
++ { 0, 627 },
++ { 0, 627 },
++ { 0, 0 },
++ { 0, 0 }
++#if 0
+ {0, 626},
+ {0, 624},
+ {0, 626},
+ {0, 624},
+ {0, 624},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ {0, 627},
++ {0, 627},
++ {0, 0},
++ {0, 0}
++#endif
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType01_1[] =
+ {
++ { 0, 0 }, /* 2.08 */
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 },
++ { 0, 0 }
++#if 0
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
++#endif
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType02_1[] =
+ {
++ { 1059, 626 }, /* 2.08 */
++ { 1059, 624 },
++ { 1059, 626 },
++ { 1059, 624 },
++ { 1059, 624 },
++ { 0, 627 },
++ { 0, 627 },
++ { 0, 0 },
++ { 0, 0 }
++#if 0
+ {0, 626},
+ {0, 624},
+ {0, 626},
+ {0, 624},
+ {0, 624},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ {0, 627},
++ {0, 627},
++ {0, 0},
++ {0, 0}
++#endif
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType03_1[] =
+ {
+- { 8, 436},
+- { 8, 440},
+- { 8, 436},
+- { 8, 440},
+- { 8, 512},
++ { 8, 436},
++ { 8, 440},
++ { 8, 436},
++ { 8, 440},
++ { 8, 512},
+ {1343, 798},
+ {1343, 794},
+ {1343, 798},
+ {1343, 794}
+ };
+
+-static const SiS300_LVDSDesStruct SiS300_PanelType04_1[] =
++static const SiS300_LVDSDesStruct SiS300_PanelType04_1[] = /* 1280x1024 */
+ {
+ {1343, 798},
+ {1343, 794},
+@@ -2116,9 +1120,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType05_1[] =
+@@ -2129,9 +1133,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType06_1[] =
+@@ -2142,9 +1146,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType07_1[] =
+@@ -2155,9 +1159,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType08_1[] =
+@@ -2167,10 +1171,10 @@ static const SiS300_LVDSDesStruct SiS30
+ {1059, 626},
+ {1059, 624},
+ {1059, 624},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ { 0, 627},
++ { 0, 627},
++ { 0, 0},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType09_1[] =
+@@ -2181,9 +1185,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0a_1[] =
+@@ -2193,23 +1197,23 @@ static const SiS300_LVDSDesStruct SiS30
+ {1059, 626},
+ {1059, 624},
+ {1059, 624},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ { 0, 627},
++ { 0, 627},
++ { 0, 0},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0b_1[] =
+ {
+- {1343, 0},
+- {1343, 0},
+- {1343, 0},
+- {1343, 0},
+- {1343, 0}, /* 640x480 - BIOS 1343, 0 */
+- {1343, 0},
+- { 0, 799},
+- { 0, 0},
+- { 0, 0}
++ {1343, 0},
++ {1343, 0},
++ {1343, 0},
++ {1343, 0},
++ {1343, 0},
++ {1343, 0},
++ { 0, 799},
++ { 0, 0},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0c_1[] =
+@@ -2220,9 +1224,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0d_1[] =
+@@ -2233,9 +1237,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0e_1[] =
+@@ -2244,11 +1248,11 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 798},
+ {1343, 794},
+- {1343, 0}, /* 640x480 */
+- {1343, 0}, /* 800x600 */
+- { 0, 805}, /* 1024x768 */
+- { 0, 794}, /* 1280x1024 */
+- { 0, 0} /* 1280x960 - not applicable */
++ {1343, 0}, /* 640x480 */
++ {1343, 0}, /* 800x600 */
++ { 0, 805}, /* 1024x768 */
++ { 0, 794}, /* 1280x1024 */
++ { 0, 0} /* 1280x960 - not applicable */
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType0f_1[] =
+@@ -2259,9 +1263,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1343, 794},
+ {1343, 0},
+ {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType00_2[] =
+@@ -2271,10 +1275,10 @@ static const SiS300_LVDSDesStruct SiS30
+ {976, 527},
+ {976, 502},
+ {976, 567},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ { 0, 627},
++ { 0, 627},
++ { 0, 0},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType01_2[] =
+@@ -2285,9 +1289,9 @@ static const SiS300_LVDSDesStruct SiS30
+ {1152, 597},
+ {1152, 662},
+ {1232, 722},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 805},
++ { 0, 794},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType02_2[] =
+@@ -2297,10 +1301,10 @@ static const SiS300_LVDSDesStruct SiS30
+ {976, 527},
+ {976, 502},
+ {976, 567},
+- { 0, 627},
+- { 0, 627},
+- { 0, 0},
+- { 0, 0}
++ { 0, 627},
++ { 0, 627},
++ { 0, 0},
++ { 0, 0}
+ };
+
+ static const SiS300_LVDSDesStruct SiS300_PanelType03_2[] =
+@@ -2472,156 +1476,57 @@ static const SiS300_LVDSDesStruct SiS30
+ { 0, 0}
+ };
+
+-static const SiS300_LVDSDesStruct SiS300_PanelTypeNS_1[]=
++/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
++static const SiS300_LVDSDesStruct SiS300_PanelType04_1a[] = /* 1280x1024 (1366x1024) */
+ {
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 806},
+- { 0, 0 }
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelTypeNS_2[] =
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1076_1[] = /* TW: New */
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1076_2[] = /* TW: New */
+-{
+- { 1152, 622 },
+- { 1152, 597 },
+- { 1152, 622 },
+- { 1152, 597 },
+- { 1152, 622 },
+- { 1232, 722 },
+- { 0, 0 },
+- { 0, 794 },
+- { 0, 0 }
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1210_1[] = /* TW: New */
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1210_2[] = /* TW: New */
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1296_1[] = /* TW: New */
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_PanelType1296_2[] = /* TW: New */
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-
+-/* TW: New */
+-static const SiS300_LVDSDesStruct SiS300_CHTVUNTSCDesData[] =
+-{
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_CHTVONTSCDesData[] =
+-{
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+-static const SiS300_LVDSDesStruct SiS300_CHTVUPALDesData[] =
+-{
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- { 0, 0},
+- { 0, 0}
++ {1330, 798}, /* 320x200 */
++ {1330, 794},
++ {1330, 798},
++ {1330, 794},
++ {1330, 0}, /* 640x480 / 320x240 */
++ {1343, 0}, /* 800x600 / 400x300 */
++ { 0, 805}, /* 1024x768 / 512x384 */
++ {1688,1066}, /* 1280x1024 */
++ { 0, 0} /* 1360x1024 */
+ };
+
+-static const SiS300_LVDSDesStruct SiS300_CHTVOPALDesData[] =
++static const SiS300_LVDSDesStruct SiS300_PanelType04_2a[] =
+ {
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- { 0, 0},
+- { 0, 0}
++ {1152, 622},
++ {1152, 597},
++ {1152, 622},
++ {1152, 597},
++ {1152, 662},
++ {1232, 722},
++ { 0, 805},
++ {1688,1066},
++ { 0, 0}
++};
++
++/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
++static const SiS300_LVDSDesStruct SiS300_PanelType04_1b[] = /* 1024x768 */
++{
++ {1330, 798}, /* 320x200 */
++ {1330, 794},
++ {1330, 798},
++ {1330, 794},
++ {1330, 0}, /* 640x480 / 320x240 */
++ {1343, 0}, /* 800x600 / 400x300 */
++ { 0, 805} /* 1024x768 / 512x384 */
++};
++
++static const SiS300_LVDSDesStruct SiS300_PanelType04_2b[] =
++{
++ {1152, 622},
++ {1152, 597},
++ {1152, 622},
++ {1152, 597},
++ {1152, 662},
++ {1232, 722},
++ { 0, 805}
+ };
+-/* TW: New end */
+
+-/* TW: New for SiS300+301LV */
++
+ typedef struct _SiS300_Part2PortTblStruct
+ {
+ UCHAR CR[12];
+@@ -2726,6 +1631,28 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01 }}
+ };
+
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] =
++{
++ {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
++ 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
++ 0x00 }},
++ {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
++ 0x00 }},
++ {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
++ 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
++ 0x00 }},
++ {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
++ 0x00 }},
++ {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e,
++ 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04,
++ 0x00 }},
++ {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
++ 0x01 }}
++};
++
+ static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1[] =
+ {
+ {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
+@@ -2751,55 +1678,31 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01}}
+ };
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] =
+-{
+- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00 }},
+- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00 }},
+- {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00 }},
+- {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00 }},
+- {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
+- 0x00 }},
+- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
+- 0x01 }},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01 }}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_1_H[] =
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] =
+ {
+- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
+- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
+- 0x00 }},
+- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
+- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
+- 0x00 }},
+- {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
+- 0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
+- 0x00 }},
+- {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
+- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
+- 0x00 }},
+- {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e,
+- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04,
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+ 0x00 }},
+- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
+- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
++ 0xE2,0x89,0xdf,0x05,0x00,0x00,0x44,
++ 0x00}},
++ {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
++ 0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
++ 0x01}},
++ {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+ 0x01 }}
+-};
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_1_H[] =
+-{
++#if 0
+ {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
+ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+ 0x00 }},
+@@ -2821,6 +1724,32 @@ static const SiS300_LVDSCRT1DataStruct
+ {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
+ 0x02,0x88,0xFf,0x25,0x10,0x00,0x01,
+ 0x01 }}
++#endif
++};
++
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1[] =
++{
++ {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00 }},
++ {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
++ 0x00 }},
++ {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00 }},
++ {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
++ 0x00 }},
++ {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e,
++ 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
++ 0x00 }},
++ {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
++ 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
++ 0x01 }},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01 }}
+ };
+
+ static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_1_H[] =
+@@ -2870,32 +1799,29 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01 }}
+ };
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] =
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] =
+ {
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
++ 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
+ 0x00 }},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
++ 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
+ 0x00 }},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
++ 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
+ 0x00 }},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e,
++ 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
+ 0x00 }},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
++ {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba,
++ 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05,
+ 0x00 }},
+- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
+- 0x01 }},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
+ 0x01 }}
+ };
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] =
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2[] =
+ {
+ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+@@ -2920,28 +1846,6 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01 }}
+ };
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT1800x600_2_H[] =
+-{
+- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
+- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
+- 0x00 }},
+- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
+- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
+- 0x00 }},
+- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
+- 0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
+- 0x00 }},
+- {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e,
+- 0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
+- 0x00 }},
+- {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba,
+- 0x1c,0x80,0xdf,0x73,0x00,0x00,0x05,
+- 0x00 }},
+- {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
+- 0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
+- 0x01 }}
+-};
+-
+ static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x768_2_H[] =
+ {
+ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+@@ -2967,6 +1871,31 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01 }}
+ };
+
++static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2[] =
++{
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00 }},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00 }},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00 }},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00 }},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
++ 0x00 }},
++ {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
++ 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
++ 0x01 }},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01 }}
++};
++
+ static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11280x1024_2_H[] =
+ {
+ {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
+@@ -2992,207 +1921,6 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x01}}
+ };
+
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_1[] =
+-{
+- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
+- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
+- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
+- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
+- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
+- 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
+- 0x00}},
+- {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
+- 0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+- 0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_1_H[] =
+-{
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
+- 0x00}},
+- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_2[] =
+-{
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11024x600_2_H[] =
+-{
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_1[] =
+-{
+- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
+- 0x00}},
+- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_1_H[] =
+-{
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
+- 0x00}},
+- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_2[] =
+-{
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS300_LVDSCRT1DataStruct SiS300_LVDSCRT11152x768_2_H[] =
+-{
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-/* TW: New */
+ static const SiS300_LVDSCRT1DataStruct SiS300_CHTVCRT1UNTSC[] =
+ {
+ {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
+@@ -3302,9 +2030,7 @@ static const SiS300_LVDSCRT1DataStruct
+ 0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
+ 0x01 }}
+ };
+-/* TW: New end */
+
+-/* TW: New */
+ typedef struct _SiS300_CHTVRegDataStruct
+ {
+ UCHAR Reg[16];
+@@ -3361,9 +2087,7 @@ static const SiS300_CHTVRegDataStruct Si
+ {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */
+ {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}} /* TW: Mode 19: 800x600 PAL 1/1 */
+ };
+-/* TW: New end */
+
+-/* TW: New */
+ static const UCHAR SiS300_CHTVVCLKUNTSC[] = {0x29,0x29,0x29,0x29,0x2a,0x2e};
+
+ static const UCHAR SiS300_CHTVVCLKONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+@@ -3375,6 +2099,5 @@ static const UCHAR SiS300_CHTVVCLKUPAL[]
+ static const UCHAR SiS300_CHTVVCLKOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x30,0x32};
+
+ static const UCHAR SiS300_CHTVVCLKSOPAL[] = {0x2f,0x2f,0x2f,0x2f,0x36,0x29};
+-/* TW: New end */
+
+
+--- linux-2.6.0-test6/drivers/video/sis/310vtbl.h 2003-06-14 12:18:23.000000000 -0700
++++ 25/drivers/video/sis/310vtbl.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,7 +1,37 @@
+-
+-
+-/* Register settings for SiS 310/325/330 series */
+-
++/* $XFree86$ */
++/*
++ * Register settings for SiS 315/330 series
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
+
+ typedef struct _SiS310_StStruct
+ {
+@@ -39,466 +69,12 @@ static const SiS310_StStruct SiS310_SMod
+ {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
+ };
+
+-typedef struct _SiS310_StandTableStruct
+-{
+- UCHAR CRT_COLS;
+- UCHAR ROWS;
+- UCHAR CHAR_HEIGHT;
+- USHORT CRT_LEN;
+- UCHAR SR[4];
+- UCHAR MISC;
+- UCHAR CRTC[0x19];
+- UCHAR ATTR[0x14];
+- UCHAR GRC[9];
+-} SiS310_StandTableStruct;
+-
+-static const SiS310_StandTableStruct SiS310_StandTable[]=
+-{
+-/* 0x00: MD_0_200 */
+- {
+- 0x28,0x18,0x08,0x0800,
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x01: MD_1_200 */
+- {
+- 0x28,0x18,0x08,0x0800,
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x02: MD_2_200 */
+- {
+- 0x50,0x18,0x08,0x1000,
+- {0x01,0x03,0x00,0x02},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x03: MD_3_200 - mode 0x03 - 0 */
+- {
+- 0x50,0x18,0x08,0x1000,
+- {0x01,0x03,0x00,0x02},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x04: MD_4 */
+- {
+- 0x28,0x18,0x08,0x4000,
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+- 0xff},
+- {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x03,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+- 0xff}
+- },
+-/* 0x05: MD_5 */
+- {
+- 0x28,0x18,0x08,0x4000,
+- {0x09,0x03,0x00,0x02},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
+- 0xff},
+- {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x03,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
+- 0xff}
+- },
+-/* 0x06: MD_6 */
+- {
+- 0x50,0x18,0x08,0x4000,
+- {0x01,0x01,0x00,0x06},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
+- 0xff},
+- {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+- 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+- 0x01,0x00,0x01,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
+- 0xff}
+- },
+-/* 0x07: MD_7 */
+- {
+- 0x50,0x18,0x0e,0x1000,
+- {0x00,0x03,0x00,0x03},
+- 0xa6,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+- 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+- 0x0e,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+- 0xff}
+- },
+-/* 0x08: MDA_DAC */
+- {
+- 0x00,0x00,0x00,0x0000,
+- {0x00,0x00,0x00,0x15},
+- 0x15,
+- {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
+- 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
+- 0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+- 0x15,0x15,0x15,0x15},
+- {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x3f}
+- },
+-/* 0x09: CGA_DAC */
+- {
+- 0x00,0x10,0x04,0x0114,
+- {0x11,0x09,0x15,0x00},
+- 0x10,
+- {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
+- 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
+- 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
+- 0x04},
+- {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
+- 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
+- 0x3e,0x2b,0x3b,0x2f},
+- {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+- 0x3f}
+- },
+-/* 0x0a: EGA_DAC */
+- {
+- 0x00,0x10,0x04,0x0114,
+- {0x11,0x05,0x15,0x20},
+- 0x30,
+- {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
+- 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
+- 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
+- 0x06},
+- {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
+- 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
+- 0x1e,0x0b,0x1b,0x0f},
+- {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
+- 0x3f}
+- },
+-/* 0x0b: VGA_DAC */
+- {
+- 0x00,0x10,0x04,0x0114,
+- {0x11,0x09,0x15,0x2a},
+- 0x3a,
+- {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
+- 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
+- 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
+- 0x1f},
+- {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
+- 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
+- 0x1c,0x0e,0x11,0x15},
+- {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
+- 0x04}
+- },
+-/* 0x0c */
+- {
+- 0x08,0x0c,0x10,0x0a08,
+- {0x0c,0x0e,0x10,0x0b},
+- 0x0c,
+- {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
+- 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
+- 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
+- 0x06},
+- {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
+- 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
+- 0x00,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00}
+- },
+-/* 0x0d: MD_D */
+- {
+- 0x28,0x18,0x08,0x2000,
+- {0x09,0x0f,0x00,0x06},
+- 0x63,
+- {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff}
+- },
+-/* 0x0e: MD_E */
+- {
+- 0x50,0x18,0x08,0x4000,
+- {0x01,0x0f,0x00,0x06},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff}
+- },
+-/* 0x0f: ExtVGATable - modes > 0x13 */
+- {
+- 0x00,0x00,0x00,0x0000,
+- {0x01,0x0f,0x00,0x0e},
+- 0x23,
+- {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+- 0x01,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+- 0xff}
+- },
+-/* 0x10: ROM_SAVEPTR */
+- {
+- 0x9f,0x3b,0x00,0x00c0,
+- {0x00,0x00,0x00,0x00},
+- 0x00,
+- {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
+- 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
+- 0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00,0x00,0x00,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x00}
+- },
+-/* 0x11: MD_F */
+- {
+- 0x50,0x18,0x0e,0x8000,
+- {0x01,0x0f,0x00,0x06},
+- 0xa2,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+- 0xff},
+- {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
+- 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
+- 0x0b,0x00,0x05,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
+- 0xff}
+- },
+-/* 0x12: MD_10 */
+- {
+- 0x50,0x18,0x0e,0x8000,
+- {0x01,0x0f,0x00,0x06},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff}
+- },
+-/* 0x13: MD_0_350 */
+- {
+- 0x28,0x18,0x0e,0x0800,
+- {0x09,0x03,0x00,0x02},
+- 0xa3,
+- {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x14: MD_1_350 */
+- {
+- 0x28,0x18,0x0e,0x0800,
+- {0x09,0x03,0x00,0x02},
+- 0xa3,
+- {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x15: MD_2_350 */
+- {
+- 0x50,0x18,0x0e,0x1000,
+- {0x01,0x03,0x00,0x02},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x16: MD_3_350 - mode 0x03 - 1 */
+- {
+- 0x50,0x18,0x0e,0x1000,
+- {0x01,0x03,0x00,0x02},
+- 0xa3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
+- 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x08,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x17: MD_0_1_400 */
+- {
+- 0x28,0x18,0x10,0x0800,
+- {0x08,0x03,0x00,0x02},
+- 0x67,
+- {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x0c,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x18: MD_2_3_400 - mode 0x03 - 2 */
+- {
+- 0x50,0x18,0x10,0x1000,
+- {0x00,0x03,0x00,0x02},
+- 0x67,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x0c,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
+- 0xff}
+- },
+-/* 0x19: MD_7_400 */
+- {
+- 0x50,0x18,0x10,0x1000,
+- {0x00,0x03,0x00,0x02},
+- 0x66,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+- 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+- 0x0e,0x00,0x0f,0x08},
+- {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
+- 0xff}
+- },
+-/* 0x1a: MD_11 */
+- {
+- 0x50,0x1d,0x10,0xa000,
+- {0x01,0x0f,0x00,0x06},
+- 0xe3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3,
+- 0xff},
+- {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
+- 0xff}
+- },
+-/* 0x1b: ExtEGATable - Modes <= 0x02 */
+- {
+- 0x50,0x1d,0x10,0xa000,
+- {0x01,0x0f,0x00,0x06},
+- 0xe3,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+- 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
+- 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
+- 0x01,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
+- 0xff}
+- },
+-/* 0x1c: MD_13 */
+- {
+- 0x28,0x18,0x08,0x2000,
+- {0x01,0x0f,0x00,0x0e},
+- 0x63,
+- {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+- 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
+- 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
+- 0xff},
+- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+- 0x41,0x00,0x0f,0x00},
+- {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+- 0xff}
+- }
+-};
+-
+ typedef struct _SiS310_ExtStruct
+ {
+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+- USHORT Ext_Point; /* TW: Address of table entry in (older) BIOS image */
+ USHORT Ext_VESAID;
+- UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+@@ -506,93 +82,93 @@ typedef struct _SiS310_ExtStruct
+ UCHAR REFindex;
+ } SiS310_ExtStruct;
+
+-/* TW: Checked with 650/LVDS and 650/301LVx 1.10.6s */
+ static const SiS310_ExtStruct SiS310_EModeIDTable[]=
+ {
+- {0x6a,0x2212,0x0407,0x3a81,0x0102,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x? */
+- {0x2e,0x0a1b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x8 */
+-/* {0x2e,0x021b,0x0306,0x3a57,0x0101,0x08,0x06,0x00,0x00,0x05,0x08}, */ /* 640x480x8 - 650/LVDS BIOS (no CRt2Mode) */
+- {0x2f,0x0a1b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, /* 640x400x8 */
+-/* {0x2f,0x021b,0x0305,0x3a50,0x0100,0x08,0x05,0x00,0x00,0x05,0x10}, */ /* 640x400x8 - 650/LVDS BIOS (no CRt2Mode) */
+- {0x30,0x2a1b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x8 */
+-/* {0x30,0x221b,0x0407,0x3a81,0x0103,0x08,0x07,0x00,0x00,0x07,0x00}, */ /* 800x600x8 - 650/LVDS BIOS (no CRt2Mode) */
+-/* {0x31,0x0a1b,0x030d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, */ /* 720x480x8 */
+- {0x31,0x0a1b,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x8 BIOS (301/LVDS) */
+- {0x32,0x0a1b,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x8 */
+- {0x33,0x0a1d,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x16 */
+- {0x34,0x2a1d,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x16 */
+- {0x35,0x0a1f,0x0a0d,0x3b85,0x0000,0x08,0x0d,0x00,0x00,0x06,0x11}, /* 720x480x32 */
+- {0x36,0x2a1f,0x0a0e,0x3b8c,0x0000,0x08,0x0e,0x00,0x00,0x06,0x12}, /* 720x576x32 */
+- {0x37,0x0212,0x0508,0x3aab,0x0104,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x? */
+- {0x38,0x0a1b,0x0508,0x3aab,0x0105,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x8 */
+- {0x3a,0x0e3b,0x0609,0x3adc,0x0107,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
+- {0x3c,0x0e3b,0x070a,0x3af2,0x0130,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
+- {0x3d,0x0e7d,0x070a,0x3af2,0x0131,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 - 650/301LVx - no CRT2Mode? */
+- {0x40,0x9a1c,0x0000,0x3a34,0x010d,0x08,0x00,0x00,0x00,0x04,0x25},
+- {0x41,0x9a1d,0x0000,0x3a34,0x010e,0x08,0x00,0x00,0x00,0x04,0x25},
+- {0x43,0x0a1c,0x0306,0x3a57,0x0110,0x08,0x06,0x00,0x00,0x05,0x08},
+- {0x44,0x0a1d,0x0306,0x3a57,0x0111,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x16 */
+- {0x46,0x2a1c,0x0407,0x3a81,0x0113,0x08,0x07,0x00,0x00,0x07,0x00},
+- {0x47,0x2a1d,0x0407,0x3a81,0x0114,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x16 */
+- {0x49,0x0a3c,0x0508,0x3aab,0x0116,0x08,0x08,0x00,0x00,0x00,0x13},
+- {0x4a,0x0a3d,0x0508,0x3aab,0x0117,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x16 */
+- {0x4c,0x0e7c,0x0609,0x3adc,0x0119,0x08,0x09,0x00,0x00,0x00,0x1a},
+- {0x4d,0x0e7d,0x0609,0x3adc,0x011a,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
+- {0x50,0x9a1b,0x0001,0x3a3b,0x0132,0x08,0x01,0x00,0x00,0x04,0x26}, /* 320x240 */
+- {0x51,0xba1b,0x0103,0x3a42,0x0133,0x08,0x03,0x00,0x00,0x07,0x27},
+- {0x52,0xba1b,0x0204,0x3a49,0x0134,0x08,0x04,0x00,0x00,0x00,0x28}, /* 650/301 BIOS */
+- {0x56,0x9a1d,0x0001,0x3a3b,0x0135,0x08,0x01,0x00,0x00,0x04,0x26},
+- {0x57,0xba1d,0x0103,0x3a42,0x0136,0x08,0x03,0x00,0x00,0x07,0x27},
+- {0x58,0xba1d,0x0204,0x3a49,0x0137,0x08,0x04,0x00,0x00,0x00,0x28}, /* BIOS (301+LVDS) */
+- {0x59,0x9a1b,0x0000,0x3a34,0x0138,0x08,0x00,0x00,0x00,0x04,0x25}, /* 320x200 */
+- {0x5A,0x021b,0x0014,0x3b83,0x0138,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x8 fstn add new mode*/
+- {0x5B,0x0a1d,0x0014,0x3b83,0x0135,0x08,0x01,0x00,0x00,0x04,0x3f}, /* 320x480x16 fstn add new mode*/
+- {0x5c,0xba1f,0x0204,0x3a49,0x0000,0x08,0x04,0x00,0x00,0x00,0x28}, /* TW: inserted 512x384x32 */
+- {0x5d,0x0a1d,0x0305,0x3a50,0x0139,0x08,0x05,0x00,0x00,0x07,0x10},
+- {0x5e,0x0a1f,0x0305,0x3a50,0x0000,0x08,0x05,0x00,0x00,0x07,0x10}, /* TW: Inserted 640x400x32 */
+- {0x62,0x0a3f,0x0306,0x3a57,0x013a,0x08,0x06,0x00,0x00,0x05,0x08}, /* 640x480x32 */
+- {0x63,0x2a3f,0x0407,0x3a81,0x013b,0x08,0x07,0x00,0x00,0x07,0x00}, /* 800x600x32 */
+- {0x64,0x0a7f,0x0508,0x3aab,0x013c,0x08,0x08,0x00,0x00,0x08,0x13}, /* 1024x768x32 */
+- {0x65,0x0eff,0x0609,0x3adc,0x013d,0x08,0x09,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
+- {0x66,0x0eff,0x070a,0x3af2,0x013e,0x08,0x0a,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
+- {0x68,0x067b,0x080b,0x3b17,0x013f,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
+- {0x69,0x06fd,0x080b,0x3b17,0x0140,0x08,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
+- {0x6b,0x07ff,0x080b,0x3b17,0x0141,0x10,0x0b,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
+- {0x6c,0x067b,0x090c,0x3b37,0x0000,0x08,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
+- {0x6d,0x06fd,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
+- {0x6e,0x07ff,0x090c,0x3b37,0x0000,0x10,0x0c,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
+- {0x70,0x2a1b,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x8 */
+- {0x71,0x0a1b,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
+- {0x74,0x0a1d,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
+- {0x75,0x0a3d,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
+- {0x76,0x2a1f,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x32 */
+- {0x77,0x0a1f,0x0511,0x3b63,0x0000,0x08,0x11,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
+- {0x78,0x0a3f,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
+- {0x79,0x0a3b,0x0612,0x3b74,0x0000,0x08,0x12,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
+- {0x7a,0x2a1d,0x0410,0x3b52,0x0000,0x08,0x10,0x00,0x00,0x07,0x34}, /* 800x480x16 */
+- {0x7c,0x0e3b,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x8 - TW */
+- {0x7d,0x0e7d,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x16 - TW */
+- {0x7e,0x0eff,0x060f,0x3ad0,0x0000,0x08,0x0f,0x00,0x00,0x00,0x3d}, /* 1280x960x32 - TW */
+- /* TW: 650/LVDS BIOS new modes */
+- {0x23,0x0e3b,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
+- {0x24,0x0e7d,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
+- {0x25,0x0eff,0x0614,0x36f7,0x0000,0x08,0x14,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
+- {0x26,0x0e3b,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
+- {0x27,0x0e7d,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
+- {0x28,0x0eff,0x0c15,0x36fe,0x0000,0x08,0x15,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
+- {0x29,0x0e1b,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43}, /* TW: NEW 1152x864 - not in BIOS */
+- {0x2a,0x0e3d,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+- {0x2b,0x0e7f,0x0d16,0x0000,0x0000,0x08,0x16,0x00,0x00,0x00,0x43},
+- {0x39,0x2a1b,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45}, /* TW: NEW 848x480 - not in BIOS */
+- {0x3b,0x2a3d,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45},
+- {0x3e,0x2a7f,0x0b17,0x0000,0x0000,0x08,0x17,0x00,0x00,0x00,0x45},
+- {0x3f,0x2a1b,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47}, /* TW: NEW 856x480 - not in BIOS */
+- {0x42,0x2a3d,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47},
+- {0x45,0x2a7f,0x0b13,0x0000,0x0000,0x08,0x13,0x00,0x00,0x00,0x47},
+- {0x48,0x2a1b,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49}, /* TW: NEW 1360x768 - not in BIOS */
+- {0x4b,0x2a3d,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49},
+- {0x4e,0x2a7f,0x0e18,0x0000,0x0000,0x08,0x18,0x00,0x00,0x00,0x49},
+- {0xff,0x0000,0x0000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00}
++ {0x6a,0x2212,0x0407,0x0102,SIS_RI_800x600, 0x00,0x00,0x07,0x00}, /* 800x600x? */
++ {0x2e,0x0a1b,0x0306,0x0101,SIS_RI_640x480, 0x00,0x00,0x05,0x08}, /* 640x480x8 */
++ {0x2f,0x0a1b,0x0305,0x0100,SIS_RI_640x400, 0x00,0x00,0x05,0x10}, /* 640x400x8 */
++ {0x30,0x2a1b,0x0407,0x0103,SIS_RI_800x600, 0x00,0x00,0x07,0x00}, /* 800x600x8 */
++ {0x31,0x0a1b,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x11}, /* 720x480x8 */
++ {0x32,0x0a1b,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x12}, /* 720x576x8 */
++ {0x33,0x0a1d,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x11}, /* 720x480x16 */
++ {0x34,0x2a1d,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x12}, /* 720x576x16 */
++ {0x35,0x0a1f,0x0a0d,0x0000,SIS_RI_720x480, 0x00,0x00,0x06,0x11}, /* 720x480x32 */
++ {0x36,0x2a1f,0x0a0e,0x0000,SIS_RI_720x576, 0x00,0x00,0x06,0x12}, /* 720x576x32 */
++ {0x37,0x0212,0x0508,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x13}, /* 1024x768x? */
++ {0x38,0x0a1b,0x0508,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x13}, /* 1024x768x8 */
++ {0x3a,0x0e3b,0x0609,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
++ {0x3c,0x0e3b,0x070a,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
++ {0x3d,0x0e7d,0x070a,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
++ {0x40,0x9a1c,0x0000,0x010d,SIS_RI_320x200, 0x00,0x00,0x04,0x25}, /* 320x200x15 */
++ {0x41,0x9a1d,0x0000,0x010e,SIS_RI_320x200, 0x00,0x00,0x04,0x25}, /* 320x200x16 */
++ {0x43,0x0a1c,0x0306,0x0110,SIS_RI_640x480, 0x00,0x00,0x05,0x08},
++ {0x44,0x0a1d,0x0306,0x0111,SIS_RI_640x480, 0x00,0x00,0x05,0x08}, /* 640x480x16 */
++ {0x46,0x2a1c,0x0407,0x0113,SIS_RI_800x600, 0x00,0x00,0x07,0x00},
++ {0x47,0x2a1d,0x0407,0x0114,SIS_RI_800x600, 0x00,0x00,0x07,0x00}, /* 800x600x16 */
++ {0x49,0x0a3c,0x0508,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x13},
++ {0x4a,0x0a3d,0x0508,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x13}, /* 1024x768x16 */
++ {0x4c,0x0e7c,0x0609,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a},
++ {0x4d,0x0e7d,0x0609,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
++ {0x50,0x9a1b,0x0001,0x0132,SIS_RI_320x240, 0x00,0x00,0x04,0x26}, /* 320x240x8 */
++ {0x51,0xba1b,0x0103,0x0133,SIS_RI_400x300, 0x00,0x00,0x07,0x27}, /* 400x300x8 */
++ {0x52,0xba1b,0x0204,0x0134,SIS_RI_512x384, 0x00,0x00,0x00,0x28}, /* 512x384x8 */
++ {0x56,0x9a1d,0x0001,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x26}, /* 320x240x16 */
++ {0x57,0xba1d,0x0103,0x0136,SIS_RI_400x300, 0x00,0x00,0x07,0x27}, /* 400x300x16 */
++ {0x58,0xba1d,0x0204,0x0137,SIS_RI_512x384, 0x00,0x00,0x00,0x28}, /* 512x384x16 */
++ {0x59,0x9a1b,0x0000,0x0138,SIS_RI_320x200, 0x00,0x00,0x04,0x25}, /* 320x200x8 */
++ {0x5a,0x021b,0x0014,0x0138,SIS_RI_320x240, 0x00,0x00,0x04,0x3f}, /* 320x240x8 fstn */
++ {0x5b,0x0a1d,0x0014,0x0135,SIS_RI_320x240, 0x00,0x00,0x04,0x3f}, /* 320x240x16 fstn */
++ {0x5c,0xba1f,0x0204,0x0000,SIS_RI_512x384, 0x00,0x00,0x00,0x28}, /* 512x384x32 */
++ {0x5d,0x0a1d,0x0305,0x0139,SIS_RI_640x400, 0x00,0x00,0x07,0x10},
++ {0x5e,0x0a1f,0x0305,0x0000,SIS_RI_640x400, 0x00,0x00,0x07,0x10}, /* 640x400x32 */
++ {0x62,0x0a3f,0x0306,0x013a,SIS_RI_640x480, 0x00,0x00,0x05,0x08}, /* 640x480x32 */
++ {0x63,0x2a3f,0x0407,0x013b,SIS_RI_800x600, 0x00,0x00,0x07,0x00}, /* 800x600x32 */
++ {0x64,0x0a7f,0x0508,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x13}, /* 1024x768x32 */
++ {0x65,0x0eff,0x0609,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
++ {0x66,0x0eff,0x070a,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
++ {0x68,0x067b,0x080b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
++ {0x69,0x06fd,0x080b,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
++ {0x6b,0x07ff,0x080b,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
++ {0x6c,0x067b,0x090c,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
++ {0x6d,0x06fd,0x090c,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
++ {0x6e,0x07ff,0x090c,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
++ {0x70,0x2a1b,0x0410,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x34}, /* 800x480x8 */
++ {0x71,0x0a1b,0x0511,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x37}, /* 1024x576x8 */
++ {0x74,0x0a1d,0x0511,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x37}, /* 1024x576x16 */
++ {0x75,0x0a3d,0x0612,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
++ {0x76,0x2a1f,0x0410,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x34}, /* 800x480x32 */
++ {0x77,0x0a1f,0x0511,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x37}, /* 1024x576x32 */
++ {0x78,0x0a3f,0x0612,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
++ {0x79,0x0a3b,0x0612,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
++ {0x7a,0x2a1d,0x0410,0x0000,SIS_RI_800x480, 0x00,0x00,0x07,0x34}, /* 800x480x16 */
++ {0x7c,0x0e3b,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
++ {0x7d,0x0e7d,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
++ {0x7e,0x0eff,0x060f,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
++ {0x23,0x0e3b,0x0614,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x40}, /* 1280x768x8 */
++ {0x24,0x0e7d,0x0614,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x40}, /* 1280x768x16 */
++ {0x25,0x0eff,0x0614,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x40}, /* 1280x768x32 */
++ {0x26,0x0e3b,0x0c15,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
++ {0x27,0x0e7d,0x0c15,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
++ {0x28,0x0eff,0x0c15,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
++ {0x29,0x0e1b,0x0d16,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x43}, /* 1152x864 */
++ {0x2a,0x0e3d,0x0d16,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x43},
++ {0x2b,0x0e7f,0x0d16,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x43},
++ {0x39,0x2a1b,0x0b17,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x45}, /* 848x480 */
++ {0x3b,0x2a3d,0x0b17,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x45},
++ {0x3e,0x2a7f,0x0b17,0x0000,SIS_RI_848x480, 0x00,0x00,0x00,0x45},
++ {0x3f,0x2a1b,0x0b13,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x47}, /* 856x480 */
++ {0x42,0x2a3d,0x0b13,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x47},
++ {0x45,0x2a7f,0x0b13,0x0000,SIS_RI_856x480, 0x00,0x00,0x00,0x47},
++ {0x48,0x2a1b,0x0e18,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x49}, /* 1360x768 */
++ {0x4b,0x2a3d,0x0e18,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x49},
++ {0x4e,0x2a7f,0x0e18,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x49},
++ {0x4f,0x9a1f,0x0000,0x0000,SIS_RI_320x200, 0x00,0x00,0x04,0x25}, /* 320x200x32 */
++ {0x53,0x9a1f,0x0001,0x0000,SIS_RI_320x240, 0x00,0x00,0x04,0x26}, /* 320x240x32 */
++ {0x54,0xba1f,0x0103,0x0000,SIS_RI_400x300, 0x00,0x00,0x07,0x27}, /* 400x300x32 */
++ {0x5f,0x2a1b,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x4a}, /* 768x576x8 */
++ {0x60,0x2a1d,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x4a}, /* 768x576x16 */
++ {0x61,0x2a1f,0x0f0e,0x0000,SIS_RI_768x576, 0x00,0x00,0x00,0x4a}, /* 768x576x32 */
++ {0xff,0x0000,0x0000,0x0000,0x00, 0x00,0x00,0x00,0x00}
+ };
+
+ typedef struct _SiS310_Ext2Struct
+@@ -604,89 +180,87 @@ typedef struct _SiS310_Ext2Struct
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+- USHORT ROM_OFFSET;
+ } SiS310_Ext2Struct;
+
+ static const SiS310_Ext2Struct SiS310_RefIndex[]=
+ {
+-/* {0x005f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, 0x0 - TW: Patch for Chrontel 7019 */
+- {0x085f,0x0d,0x03,0x05,0x6a, 800, 600,0x3a81}, /* 0x0 */
+- {0x0467,0x0e,0x04,0x05,0x6a, 800, 600,0x3a86}, /* 0x1 */
+- {0x0067,0x0f,0x08,0x48,0x6a, 800, 600,0x3a8b}, /* 0x2 */
+- {0x0067,0x10,0x07,0x8b,0x6a, 800, 600,0x3a90}, /* 0x3 */
+- {0x0147,0x11,0x0a,0x00,0x6a, 800, 600,0x3a95}, /* 0x4 */
+- {0x0147,0x12,0x0d,0x00,0x6a, 800, 600,0x3a9a}, /* 0x5 - 4147 TW: Test sync change */
+- {0x0047,0x13,0x13,0x00,0x6a, 800, 600,0x3a9f}, /* 0x6 - 4047 */
+- {0x0047,0x14,0x1c,0x00,0x6a, 800, 600,0x3aa4}, /* 0x7 - 4047 */
+-/* {0xc05f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, 0x8 - TW: Patch for Chrontel 7019 */
+- {0xc85f,0x05,0x00,0x04,0x2e, 640, 480,0x3a57}, /* 0x8 */
+- {0xc067,0x06,0x02,0x04,0x2e, 640, 480,0x3a5c}, /* 0x9 */
+- {0xc067,0x07,0x02,0x47,0x2e, 640, 480,0x3a61}, /* 0xa */
+- {0xc067,0x08,0x03,0x8a,0x2e, 640, 480,0x3a66}, /* 0xb */
+- {0xc047,0x09,0x05,0x00,0x2e, 640, 480,0x3a6b}, /* 0xc - 4047 */
+- {0xc047,0x0a,0x09,0x00,0x2e, 640, 480,0x3a70}, /* 0xd - 4047 */
+- {0xc047,0x0b,0x0e,0x00,0x2e, 640, 480,0x3a75}, /* 0xe - 4047 */
+- {0xc047,0x0c,0x15,0x00,0x2e, 640, 480,0x3a7a}, /* 0xf */
+- {0x407f,0x04,0x00,0x00,0x2f, 640, 400,0x3a50}, /* 0x10 */
+- {0xc00f,0x3c,0x01,0x06,0x31, 720, 480,0x3b85}, /* 0x11 */
+- {0x000f,0x3d,0x03,0x06,0x32, 720, 576,0x3b8c}, /* 0x12 */
+- {0x0187,0x15,0x06,0x00,0x37,1024, 768,0x3aab}, /* 0x13 */
+- {0xc877,0x16,0x0b,0x06,0x37,1024, 768,0x3ab0}, /* 0x14 */
+- {0xc067,0x17,0x0f,0x49,0x37,1024, 768,0x3ab5}, /* 0x15 */
+- {0x0267,0x18,0x11,0x00,0x37,1024, 768,0x3aba}, /* 0x16 */
+- {0x0047,0x19,0x16,0x8c,0x37,1024, 768,0x3abf}, /* 0x17 */
+- {0x0047,0x1a,0x1b,0x00,0x37,1024, 768,0x3ac4}, /* 0x18 - 4047 */
+- {0x0007,0x1b,0x1f,0x00,0x37,1024, 768,0x3ac9}, /* 0x19 - 4047 */
+- {0x0387,0x1c,0x11,0x00,0x3a,1280,1024,0x3adc}, /* 0x1a */
+- {0x0077,0x1d,0x19,0x07,0x3a,1280,1024,0x3ae1}, /* 0x1b */
+- {0x0047,0x1e,0x1e,0x00,0x3a,1280,1024,0x3ae6}, /* 0x1c */
+- {0x0007,0x1f,0x20,0x00,0x3a,1280,1024,0x3aeb}, /* 0x1d */
+- {0x0027,0x20,0x21,0x09,0x3c,1600,1200,0x3af2}, /* 0x1e */
+- {0x0007,0x21,0x22,0x00,0x3c,1600,1200,0x3af7}, /* 0x1f */
+- {0x0007,0x22,0x23,0x00,0x3c,1600,1200,0x3afc}, /* 0x20 */
+- {0x0007,0x23,0x25,0x00,0x3c,1600,1200,0x3b01}, /* 0x21 */
+- {0x0007,0x24,0x26,0x00,0x3c,1600,1200,0x3b06}, /* 0x22 */
+- {0x0007,0x25,0x2c,0x00,0x3c,1600,1200,0x3b0b}, /* 0x23 */
+- {0x0007,0x26,0x34,0x00,0x3c,1600,1200,0x3b10}, /* 0x24 */
+- {0x407f,0x00,0x00,0x00,0x40, 320, 200,0x3a34}, /* 0x25 */
+- {0xc07f,0x01,0x00,0x04,0x50, 320, 240,0x3a3b}, /* 0x26 */
+- {0x007f,0x02,0x04,0x05,0x51, 400, 300,0x3a42}, /* 0x27 */
+- {0xc077,0x03,0x0b,0x06,0x52, 512, 384,0x3a49}, /* 0x28 */
+- {0x8007,0x27,0x27,0x00,0x68,1920,1440,0x3b17}, /* 0x29 */
+- {0x4007,0x28,0x29,0x00,0x68,1920,1440,0x3b1c}, /* 0x2a */
+- {0x4007,0x29,0x2e,0x00,0x68,1920,1440,0x3b21}, /* 0x2b */
+- {0x4007,0x2a,0x30,0x00,0x68,1920,1440,0x3b26}, /* 0x2c */
+- {0x4007,0x2b,0x35,0x00,0x68,1920,1440,0x3b2b}, /* 0x2d */
+- {0x4005,0x2c,0x39,0x00,0x68,1920,1440,0x3b30}, /* 0x2e */
+- {0x4007,0x2d,0x2b,0x00,0x6c,2048,1536,0x3b37}, /* 0x2f */
+- {0x4007,0x2e,0x31,0x00,0x6c,2048,1536,0x3b3c}, /* 0x30 */
+- {0x4007,0x2f,0x33,0x00,0x6c,2048,1536,0x3b41}, /* 0x31 */
+- {0x4007,0x30,0x37,0x00,0x6c,2048,1536,0x3b46}, /* 0x32 */
+- {0x4005,0x31,0x38,0x00,0x6c,2048,1536,0x3b4b}, /* 0x33 */
+- {0x0057,0x32,0x40,0x08,0x70, 800, 480,0x3b52}, /* 0x34 */
+- {0x0047,0x33,0x07,0x08,0x70, 800, 480,0x3b57}, /* 0x35 */
+- {0x0047,0x34,0x0a,0x08,0x70, 800, 480,0x3b5c}, /* 0x36 */
+- {0x0057,0x35,0x0b,0x09,0x71,1024, 576,0x3b63}, /* 0x37 */
+- {0x0047,0x36,0x11,0x09,0x71,1024, 576,0x3b68}, /* 0x38 */
+- {0x0047,0x37,0x16,0x09,0x71,1024, 576,0x3b6d}, /* 0x39 */
+- {0x0057,0x38,0x19,0x0a,0x75,1280, 720,0x3b74}, /* 0x3a */
+- {0x0047,0x39,0x1e,0x0a,0x75,1280, 720,0x3b79}, /* 0x3b */
+- {0x0007,0x3a,0x20,0x0a,0x75,1280, 720,0x3b7e}, /* 0x3c */
+- {0x0067,0x3b,0x19,0x08,0x7c,1280, 960,0x3ad0}, /* 0x3d */
+- {0x0027,0x4c,0x59,0x08,0x7c,1280, 960,0x3ad0}, /* 0x3e */
+- {0xc07f,0x01,0x00,0x06,0x5a, 320, 480,0x3b83}, /* 0x3f */ /* FSTN mode */
+- {0x0077,0x42,0x12,0x08,0x23,1280, 768,0x0000}, /* 0x40 */
+- {0x0067,0x43,0x4d,0x08,0x26,1400,1050,0x0000}, /* 0x41 */
+- {0x0007,0x4b,0x5a,0x08,0x26,1400,1050,0x0000}, /* 0x42 */ /* TW: new, not in any BIOS */
+- {0x0047,0x44,0x19,0x00,0x29,1152, 864,0x0000}, /* 0x43 TW: Non-BIOS, new */
+- {0x0047,0x4a,0x1e,0x00,0x29,1152, 864,0x0000}, /* 0x44 TW: Non-BIOS, new */
+- {0x00c7,0x45,0x57,0x00,0x39, 848, 480,0x0000}, /* 0x45 TW: 848x480-38Hzi - Non-BIOS, new */
+- {0xc047,0x46,0x55,0x00,0x39, 848, 480,0x0000}, /* 0x46 TW: 848x480-60Hz - Non-BIOS, new */
+- {0x00c7,0x47,0x57,0x00,0x3f, 856, 480,0x0000}, /* 0x47 TW: 856x480-38Hzi - Non-BIOS, new */
+- {0xc047,0x48,0x57,0x00,0x3f, 856, 480,0x0000}, /* 0x48 TW: 856x480-60Hz - Non-BIOS, new */
+- {0x0047,0x49,0x58,0x00,0x48,1360, 768,0x0000}, /* 0x49 TW: 1360x768-60Hz - Non-BIOS, new */
+- {0xffff,0x00,0x00,0x00,0x00, 0, 0,0x0000}
+-};
++ {0x085f,0x0d,0x03,0x05,0x6a, 800, 600}, /* 0x0 */
++ {0x0467,0x0e,0x04,0x05,0x6a, 800, 600}, /* 0x1 */
++ {0x0067,0x0f,0x08,0x48,0x6a, 800, 600}, /* 0x2 */
++ {0x0067,0x10,0x07,0x8b,0x6a, 800, 600}, /* 0x3 */
++ {0x0147,0x11,0x0a,0x00,0x6a, 800, 600}, /* 0x4 */
++ {0x0147,0x12,0x0d,0x00,0x6a, 800, 600}, /* 0x5 - TW: Test sync change */
++ {0x0047,0x13,0x13,0x00,0x6a, 800, 600}, /* 0x6 */
++ {0x0047,0x14,0x1c,0x00,0x6a, 800, 600}, /* 0x7 */
++ {0xc85f,0x05,0x00,0x04,0x2e, 640, 480}, /* 0x8 */
++ {0xc067,0x06,0x02,0x04,0x2e, 640, 480}, /* 0x9 */
++ {0xc067,0x07,0x02,0x47,0x2e, 640, 480}, /* 0xa */
++ {0xc067,0x08,0x03,0x8a,0x2e, 640, 480}, /* 0xb */
++ {0xc047,0x09,0x05,0x00,0x2e, 640, 480}, /* 0xc */
++ {0xc047,0x0a,0x09,0x00,0x2e, 640, 480}, /* 0xd */
++ {0xc047,0x0b,0x0e,0x00,0x2e, 640, 480}, /* 0xe */
++ {0xc047,0x0c,0x15,0x00,0x2e, 640, 480}, /* 0xf */
++ {0x407f,0x04,0x00,0x00,0x2f, 640, 400}, /* 0x10 */
++ {0xc00f,0x3c,0x01,0x06,0x31, 720, 480}, /* 0x11 */
++ {0x000f,0x3d,0x03,0x06,0x32, 720, 576}, /* 0x12 */
++ {0x0187,0x15,0x06,0x00,0x37,1024, 768}, /* 0x13 */
++ {0xc877,0x16,0x0b,0x06,0x37,1024, 768}, /* 0x14 */
++ {0xc067,0x17,0x0f,0x49,0x37,1024, 768}, /* 0x15 */
++ {0x0267,0x18,0x11,0x00,0x37,1024, 768}, /* 0x16 */
++ {0x0047,0x19,0x16,0x8c,0x37,1024, 768}, /* 0x17 */
++ {0x0047,0x1a,0x1b,0x00,0x37,1024, 768}, /* 0x18 */
++ {0x0007,0x1b,0x1f,0x00,0x37,1024, 768}, /* 0x19 */
++ {0x0387,0x1c,0x11,0x00,0x3a,1280,1024}, /* 0x1a */
++ {0x0077,0x1d,0x19,0x07,0x3a,1280,1024}, /* 0x1b */
++ {0x0047,0x1e,0x1e,0x00,0x3a,1280,1024}, /* 0x1c */
++ {0x0007,0x1f,0x20,0x00,0x3a,1280,1024}, /* 0x1d */
++ {0x0867,0x20,0x21,0x09,0x3c,1600,1200}, /* 0x1e */
++ {0x0007,0x21,0x22,0x00,0x3c,1600,1200}, /* 0x1f */
++ {0x0007,0x22,0x23,0x00,0x3c,1600,1200}, /* 0x20 */
++ {0x0007,0x23,0x25,0x00,0x3c,1600,1200}, /* 0x21 */
++ {0x0007,0x24,0x26,0x00,0x3c,1600,1200}, /* 0x22 */
++ {0x0007,0x25,0x2c,0x00,0x3c,1600,1200}, /* 0x23 */
++ {0x0007,0x26,0x34,0x00,0x3c,1600,1200}, /* 0x24 */
++ {0x407f,0x00,0x00,0x00,0x40, 320, 200}, /* 0x25 */
++ {0xc07f,0x01,0x00,0x04,0x50, 320, 240}, /* 0x26 */
++ {0x007f,0x02,0x04,0x05,0x51, 400, 300}, /* 0x27 */
++ {0xc077,0x03,0x0b,0x06,0x52, 512, 384}, /* 0x28 */
++ {0x8007,0x27,0x27,0x00,0x68,1920,1440}, /* 0x29 */
++ {0x4007,0x28,0x29,0x00,0x68,1920,1440}, /* 0x2a */
++ {0x4007,0x29,0x2e,0x00,0x68,1920,1440}, /* 0x2b */
++ {0x4007,0x2a,0x30,0x00,0x68,1920,1440}, /* 0x2c */
++ {0x4007,0x2b,0x35,0x00,0x68,1920,1440}, /* 0x2d */
++ {0x4005,0x2c,0x39,0x00,0x68,1920,1440}, /* 0x2e */
++ {0x4007,0x2d,0x2b,0x00,0x6c,2048,1536}, /* 0x2f */
++ {0x4007,0x2e,0x31,0x00,0x6c,2048,1536}, /* 0x30 */
++ {0x4007,0x2f,0x33,0x00,0x6c,2048,1536}, /* 0x31 */
++ {0x4007,0x30,0x37,0x00,0x6c,2048,1536}, /* 0x32 */
++ {0x4005,0x31,0x38,0x00,0x6c,2048,1536}, /* 0x33 */
++ {0x0057,0x32,0x40,0x08,0x70, 800, 480}, /* 0x34 */
++ {0x0047,0x33,0x07,0x08,0x70, 800, 480}, /* 0x35 */
++ {0x0047,0x34,0x0a,0x08,0x70, 800, 480}, /* 0x36 */
++ {0x0057,0x35,0x0b,0x09,0x71,1024, 576}, /* 0x37 */
++ {0x0047,0x36,0x11,0x09,0x71,1024, 576}, /* 0x38 */
++ {0x0047,0x37,0x16,0x09,0x71,1024, 576}, /* 0x39 */
++ {0x0057,0x38,0x19,0x0a,0x75,1280, 720}, /* 0x3a */
++ {0x0047,0x39,0x1e,0x0a,0x75,1280, 720}, /* 0x3b */
++ {0x0007,0x3a,0x20,0x0a,0x75,1280, 720}, /* 0x3c */
++ {0x0067,0x3b,0x19,0x08,0x7c,1280, 960}, /* 0x3d */
++ {0x0027,0x4c,0x59,0x08,0x7c,1280, 960}, /* 0x3e */
++ {0xc07f,0x4e,0x00,0x06,0x5a, 320, 240}, /* 0x3f */ /* FSTN 320x240 */
++ {0x0077,0x42,0x5b,0x08,0x23,1280, 768}, /* 0x40 */ /* TW: 0x5b was 0x12 */
++ {0x0067,0x43,0x4d,0x08,0x26,1400,1050}, /* 0x41 */
++ {0x0007,0x4b,0x5a,0x08,0x26,1400,1050}, /* 0x42 TW: not in any BIOS */
++ {0x0047,0x44,0x19,0x00,0x29,1152, 864}, /* 0x43 TW: Non-BIOS, new */
++ {0x0047,0x4a,0x1e,0x00,0x29,1152, 864}, /* 0x44 TW: Non-BIOS, new */
++ {0x00c7,0x45,0x57,0x00,0x39, 848, 480}, /* 0x45 TW: 848x480-38Hzi - Non-BIOS, new */
++ {0xc067,0x46,0x55,0x0b,0x39, 848, 480}, /* 0x46 TW: 848x480-60Hz - Non-BIOS, new */
++ {0x00c7,0x47,0x57,0x00,0x3f, 856, 480}, /* 0x47 TW: 856x480-38Hzi - Non-BIOS, new */
++ {0xc047,0x48,0x57,0x00,0x3f, 856, 480}, /* 0x48 TW: 856x480-60Hz - Non-BIOS, new */
++ {0x0067,0x49,0x58,0x0c,0x48,1360, 768}, /* 0x49 TW: 1360x768-60Hz - Non-BIOS, new */
++ {0x000f,0x4d,0x03,0x06,0x5f, 768, 576}, /* 0x4a TW: 768x576 */
++ {0xffff,0x00,0x00,0x00,0x00, 0, 0}
++};
+
+ typedef struct _SiS310_CRT1TableStruct
+ {
+@@ -710,7 +284,7 @@ static const SiS310_CRT1TableStruct SiS3
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
+ 0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
+ 0x00}}, /* 0x4 */
+-#if 0
++#if 0
+ {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
+ 0x00}}, /* 0x5 */
+@@ -940,19 +514,25 @@ static const SiS310_CRT1TableStruct SiS3
+ 0x00}}, /* 0x4b */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* TW: New, 1280x960-85, not in any BIOS */
+ 0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
+- 0x01}} /* 0x4c */
++ 0x01}}, /* 0x4c */
++ {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
++ 0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
++ 0x01}}, /* 0x4d */
++ {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
++ 0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}} /* 0x4e */
+ };
+
+-
+ typedef struct _SiS310_MCLKDataStruct
+ {
+ UCHAR SR28,SR29,SR2A;
+ USHORT CLOCK;
+ } SiS310_MCLKDataStruct;
+
++#ifdef LINUXBIOS
+ static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] =
+ {
+- { 0x3b,0x22,0x01,143}, /* TW: Was { 0x5c,0x23,0x01,166}, */
++ { 0x3b,0x22,0x01,143},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+@@ -962,7 +542,7 @@ static const SiS310_MCLKDataStruct SiS31
+ { 0x5c,0x23,0x01,166}
+ };
+
+-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] = /* @ 0x54 */
++static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] =
+ {
+ { 0x5a,0x64,0x82, 66},
+ { 0xb3,0x45,0x82, 83},
+@@ -973,8 +553,22 @@ static const SiS310_MCLKDataStruct SiS31
+ { 0x37,0x22,0x82,133},
+ { 0x37,0x22,0x82,133}
+ };
++#endif
++
++static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] =
++{
++ { 0x5c,0x23,0x01,166},
++ { 0x5c,0x23,0x01,166},
++ { 0x7c,0x08,0x01,200},
++ { 0x79,0x06,0x01,250},
++ { 0x7c,0x08,0x01,200},
++ { 0x7c,0x08,0x01,200},
++ { 0x7c,0x08,0x01,200},
++ { 0x79,0x06,0x01,250}
++};
+
+-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] = /* @ 0x54 */
++#ifdef LINUXBIOS
++static const SiS310_MCLKDataStruct SiS310_MCLKData_0_660[] = /* TODO */
+ {
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166},
+@@ -985,8 +579,9 @@ static const SiS310_MCLKDataStruct SiS31
+ { 0x7c,0x08,0x01,200},
+ { 0x79,0x06,0x01,250}
+ };
++#endif
+
+-static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] = /* @ 0x155 */
++static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] =
+ {
+ { 0x29,0x21,0x82,150},
+ { 0x5c,0x23,0x82,166},
+@@ -998,6 +593,7 @@ static const SiS310_MCLKDataStruct SiS31
+ { 0x37,0x22,0x82,133}
+ };
+
++#ifdef LINUXBIOS
+ typedef struct _SiS310_ECLKDataStruct
+ {
+ UCHAR SR2E,SR2F,SR30;
+@@ -1011,6 +607,7 @@ static const SiS310_ECLKDataStruct SiS31
+ { 0x5c,0x23,0x01,166},
+ { 0x5c,0x23,0x01,166}
+ };
++#endif
+
+ typedef struct _SiS310_VCLKDataStruct
+ {
+@@ -1020,22 +617,22 @@ typedef struct _SiS310_VCLKDataStruct
+
+ static const SiS310_VCLKDataStruct SiS310_VCLKData[]=
+ {
+- { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x5647 */
+- { 0x4e,0xe4, 28}, /* 0x1 */
+- { 0x57,0xe4, 31}, /* 0x2 */
+- { 0xc3,0xc8, 36}, /* 0x3 */
+- { 0x42,0xe2, 40}, /* 0x4 */
+- { 0xfe,0xcd, 43}, /* 0x5 */
+- { 0x5d,0xc4, 44}, /* 0x6 */
+- { 0x52,0xe2, 49}, /* 0x7 */
+- { 0x53,0xe2, 50}, /* 0x8 */
+- { 0x74,0x67, 52}, /* 0x9 */
+- { 0x6d,0x66, 56}, /* 0xa */
+- { 0x5a,0x64, 65}, /* 0xb */ /* TW: was 6c c3 - WRONG */
+- { 0x46,0x44, 67}, /* 0xc */
+- { 0xb1,0x46, 68}, /* 0xd */
+- { 0xd3,0x4a, 72}, /* 0xe */
+- { 0x29,0x61, 75}, /* 0xf */
++ { 0x1b,0xe1, 25}, /* 0x00 */
++ { 0x4e,0xe4, 28}, /* 0x01 */
++ { 0x57,0xe4, 31}, /* 0x02 */
++ { 0xc3,0xc8, 36}, /* 0x03 */
++ { 0x42,0xe2, 40}, /* 0x04 */
++ { 0xfe,0xcd, 43}, /* 0x05 */
++ { 0x5d,0xc4, 44}, /* 0x06 */
++ { 0x52,0xe2, 49}, /* 0x07 */
++ { 0x53,0xe2, 50}, /* 0x08 */
++ { 0x74,0x67, 52}, /* 0x09 */
++ { 0x6d,0x66, 56}, /* 0x0a */
++ { 0x5a,0x64, 65}, /* 0x0b */ /* TW: was 6c c3 - WRONG */
++ { 0x46,0x44, 67}, /* 0x0c */
++ { 0xb1,0x46, 68}, /* 0x0d */
++ { 0xd3,0x4a, 72}, /* 0x0e */
++ { 0x29,0x61, 75}, /* 0x0f */
+ { 0x6e,0x46, 76}, /* 0x10 */
+ { 0x2b,0x61, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+@@ -1045,7 +642,7 @@ static const SiS310_VCLKDataStruct SiS31
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x41,104}, /* 0x17 */
+ { 0x3a,0x23,105}, /* 0x18 */
+- { 0x70,0x44,108}, /* 0x19 */
++ { 0x70,0x44,108}, /* 0x19 */ /* 1400x1050 LCD */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+@@ -1078,12 +675,12 @@ static const SiS310_VCLKDataStruct SiS31
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+- { 0x52,0x2a, 54}, /* 0x3a */
+- { 0x52,0x6a, 27}, /* 0x3b */
+- { 0x62,0x24, 70}, /* 0x3c */
+- { 0x62,0x64, 70}, /* 0x3d */
+- { 0xa8,0x4c, 30}, /* 0x3e */
+- { 0x20,0x26, 33}, /* 0x3f */
++ { 0x52,0x2a, 54}, /* 0x3a */ /* 301 TV */
++ { 0x52,0x6a, 27}, /* 0x3b */ /* 301 TV */
++ { 0x62,0x24, 70}, /* 0x3c */ /* 301 TV */
++ { 0x62,0x64, 70}, /* 0x3d */ /* 301 TV */
++ { 0xa8,0x4c, 30}, /* 0x3e */ /* 301 TV */
++ { 0x20,0x26, 33}, /* 0x3f */ /* 301 TV */
+ { 0x31,0xc2, 39}, /* 0x40 */
+ { 0x60,0x36, 30}, /* 0x41 */ /* Chrontel */
+ { 0x40,0x4a, 28}, /* 0x42 */ /* Chrontel */
+@@ -1096,7 +693,7 @@ static const SiS310_VCLKDataStruct SiS31
+ { 0xce,0x3c, 39}, /* 0x49 */
+ { 0x52,0x4a, 36}, /* 0x4a */ /* Chrontel */
+ { 0x34,0x61, 95}, /* 0x4b */
+- { 0x78,0x27,108}, /* 0x4c - was 102 */ /* TW: Last entry in 650/301 BIOS */
++ { 0x78,0x27,108}, /* 0x4c - was 102 */
+ { 0x66,0x43,123}, /* 0x4d */ /* Modes 0x26-0x28 (1400x1050) */
+ { 0x41,0x4e, 21}, /* 0x4e */
+ { 0xa1,0x4a, 29}, /* 0x4f */ /* Chrontel */
+@@ -1110,7 +707,8 @@ static const SiS310_VCLKDataStruct SiS31
+ { 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */
+ { 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) */
+ { 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */
+- { 0x56,0x07,156} /* 0x5a - added for 1400x1050-75 */
++ { 0x56,0x07,156}, /* 0x5a - added for 1400x1050-75 */
++ { 0x70,0x29, 81} /* 0x5b */ /* 1280x768 LCD */
+ };
+
+ typedef struct _SiS310_VBVCLKDataStruct
+@@ -1121,22 +719,22 @@ typedef struct _SiS310_VBVCLKDataStruct
+
+ static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]=
+ {
+- { 0x1b,0xe1, 25}, /* 0x0 */ /* 650/LVDS BIOS: @ 0x579c */
+- { 0x4e,0xe4, 28}, /* 0x1 */
+- { 0x57,0xe4, 31}, /* 0x2 */
+- { 0xc3,0xc8, 36}, /* 0x3 */
+- { 0x42,0x47, 40}, /* 0x4 */
+- { 0xfe,0xcd, 43}, /* 0x5 */
+- { 0x5d,0xc4, 44}, /* 0x6 */
+- { 0x52,0x47, 49}, /* 0x7 */
+- { 0x53,0x47, 50}, /* 0x8 */
+- { 0x74,0x67, 52}, /* 0x9 */
+- { 0x6d,0x66, 56}, /* 0xa */
+- { 0x35,0x62, 65}, /* 0xb */ /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62 */
+- { 0x46,0x44, 67}, /* 0xc */
+- { 0xb1,0x46, 68}, /* 0xd */
+- { 0xd3,0x4a, 72}, /* 0xe */
+- { 0x29,0x61, 75}, /* 0xf */
++ { 0x1b,0xe1, 25}, /* 0x00 */
++ { 0x4e,0xe4, 28}, /* 0x01 */
++ { 0x57,0xe4, 31}, /* 0x02 */
++ { 0xc3,0xc8, 36}, /* 0x03 */
++ { 0x42,0x47, 40}, /* 0x04 */
++ { 0xfe,0xcd, 43}, /* 0x05 */
++ { 0x5d,0xc4, 44}, /* 0x06 */
++ { 0x52,0x47, 49}, /* 0x07 */
++ { 0x53,0x47, 50}, /* 0x08 */
++ { 0x74,0x67, 52}, /* 0x09 */
++ { 0x6d,0x66, 56}, /* 0x0a */
++ { 0x35,0x62, 65}, /* 0x0b */ /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62 */
++ { 0x46,0x44, 67}, /* 0x0c */
++ { 0xb1,0x46, 68}, /* 0x0d */
++ { 0xd3,0x4a, 72}, /* 0x0e */
++ { 0x29,0x61, 75}, /* 0x0f */
+ { 0x6d,0x46, 75}, /* 0x10 */
+ { 0x41,0x43, 78}, /* 0x11 */
+ { 0x31,0x42, 79}, /* 0x12 */
+@@ -1146,7 +744,7 @@ static const SiS310_VBVCLKDataStruct SiS
+ { 0x62,0x44, 94}, /* 0x16 */
+ { 0x2b,0x22,104}, /* 0x17 */
+ { 0x49,0x24,105}, /* 0x18 */
+- { 0xf8,0x2f,108}, /* 0x19 */
++ { 0xf8,0x2f,108}, /* 0x19 */ /* 1400x1050 LCD */
+ { 0x3c,0x23,109}, /* 0x1a */
+ { 0x5e,0x43,113}, /* 0x1b */
+ { 0xbc,0x44,116}, /* 0x1c */
+@@ -1179,19 +777,19 @@ static const SiS310_VBVCLKDataStruct SiS
+ { 0xea,0x08,340}, /* 0x37 */
+ { 0xe8,0x07,376}, /* 0x38 */
+ { 0xde,0x06,389}, /* 0x39 */
+- { 0x52,0x2a, 54}, /* 0x3a */
+- { 0x52,0x6a, 27}, /* 0x3b */
+- { 0x62,0x24, 70}, /* 0x3c */
+- { 0x62,0x64, 70}, /* 0x3d */
+- { 0xa8,0x4c, 30}, /* 0x3e */
+- { 0x20,0x26, 33}, /* 0x3f */
++ { 0x52,0x2a, 54}, /* 0x3a */ /* 301 TV */
++ { 0x52,0x6a, 27}, /* 0x3b */ /* 301 TV */
++ { 0x62,0x24, 70}, /* 0x3c */ /* 301 TV */
++ { 0x62,0x64, 70}, /* 0x3d */ /* 301 TV */
++ { 0xa8,0x4c, 30}, /* 0x3e */ /* 301 TV */
++ { 0x20,0x26, 33}, /* 0x3f */ /* 301 TV */
+ { 0x31,0xc2, 39}, /* 0x40 */
+- { 0x2e,0x48, 25}, /* 0x41 */
+- { 0x24,0x46, 25}, /* 0x42 */
+- { 0x26,0x64, 28}, /* 0x43 */
+- { 0x37,0x64, 40}, /* 0x44 */
+- { 0xa1,0x42,108}, /* 0x45 */
+- { 0x37,0x61,100}, /* 0x46 */
++ { 0x2e,0x48, 25}, /* 0x41 */ /* Replacement for LCD on 315 for index 0 */
++ { 0x24,0x46, 25}, /* 0x42 */ /* Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
++ { 0x26,0x64, 28}, /* 0x43 */ /* Replacement for LCD on 315 for index 1 */
++ { 0x37,0x64, 40}, /* 0x44 */ /* Replacement for LCD on 315 for index 4 */
++ { 0xa1,0x42,108}, /* 0x45 */ /* 1280x960 LCD */
++ { 0x37,0x61,100}, /* 0x46 */ /* 1280x960 LCD */
+ { 0x78,0x27,108}, /* 0x47 */
+ { 0x97,0x2c, 26}, /* 0x48 */ /* UNUSED - Entries from here new, not in any BIOS */
+ { 0xce,0x3c, 39}, /* 0x49 */ /* UNUSED */
+@@ -1211,72 +809,17 @@ static const SiS310_VBVCLKDataStruct SiS
+ { 0xbf,0xc8, 35}, /* 0x57 */ /* 856x480-38i,60 */
+ { 0x30,0x23, 88}, /* 0x58 */ /* 1360x768-62 (is 60Hz!) TEMP, UNUSED */
+ { 0x52,0x07,149}, /* 0x59 */ /* 1280x960-85 - UNUSED */
+- { 0x56,0x07,156} /* 0x5a */ /* 1400x1050-75 - UNUSED */
++ { 0x56,0x07,156}, /* 0x5a */ /* 1400x1050-75 - UNUSED */
++ { 0x70,0x29, 81} /* 0x5b */ /* 1280x768 LCD */
+ };
+
+ static const UCHAR SiS310_ScreenOffset[] =
+ {
+ 0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,
+- 0x78,0x80,0x2d,0x35,0x57,0x48,0x55,
++ 0x78,0x80,0x2d,0x35,0x57,0x48,0x55,0x30,
+ 0xff
+-}; /* TW: Added 1400x1050, 1152x864, 848/856x480, 1360x768 */
+-
+-typedef struct _SiS310_StResInfoStruct
+-{
+- USHORT HTotal;
+- USHORT VTotal;
+-} SiS310_StResInfoStruct;
+-
+-static const SiS310_StResInfoStruct SiS310_StResInfo[]=
+-{
+- { 640,400},
+- { 640,350},
+- { 720,400},
+- { 720,350},
+- { 640,480}
+-};
+-
+-typedef struct _SiS310_ModeResInfoStruct
+-{
+- USHORT HTotal;
+- USHORT VTotal;
+- UCHAR XChar;
+- UCHAR YChar;
+-} SiS310_ModeResInfoStruct;
+-
+-static const SiS310_ModeResInfoStruct SiS310_ModeResInfo[] =
+-{
+- { 320, 200, 8, 8}, /* 0x00 */
+- { 320, 240, 8, 8}, /* 0x01 */
+- { 320, 400, 8, 8}, /* 0x02 */
+- { 400, 300, 8, 8}, /* 0x03 */
+- { 512, 384, 8, 8}, /* 0x04 */
+- { 640, 400, 8,16}, /* 0x05 */
+- { 640, 480, 8,16}, /* 0x06 */
+- { 800, 600, 8,16}, /* 0x07 */
+- { 1024, 768, 8,16}, /* 0x08 */
+- { 1280,1024, 8,16}, /* 0x09 */
+- { 1600,1200, 8,16}, /* 0x0a */
+- { 1920,1440, 8,16}, /* 0x0b */
+- { 2048,1536, 8,16}, /* 0x0c */
+- { 720, 480, 8,16}, /* 0x0d */
+- { 720, 576, 8,16}, /* 0x0e */
+- { 1280, 960, 8,16}, /* 0x0f */
+- { 800, 480, 8,16}, /* 0x10 */
+- { 1024, 576, 8,16}, /* 0x11 */
+- { 1280, 720, 8,16}, /* 0x12 */
+- { 856, 480, 8,16}, /* 0x13 - TW: New, not in any BIOS */
+- { 1280, 768, 8,16}, /* 0x14 20; TW: New */
+- { 1400,1050, 8,16}, /* 0x15 21; TW: New */
+- { 1152, 864, 8,16}, /* 0x16 - TW: New, not in any BIOS */
+- { 848, 480, 8,16}, /* 0x17 - TW: New, not in any BIOS */
+- { 1360, 768, 8,16} /* 0x18 - TW: New, not in any BIOS */
+ };
+
+-static const UCHAR SiS310_OutputSelect = 0x40;
+-
+-static const UCHAR SiS310_SoftSetting = 0x30; /* TW: RAM setting */
+-
+ static const UCHAR SiS310_SR15[8][4]={
+ {0x00,0x04,0x60,0x60},
+ {0x0f,0x0f,0x0f,0x0f},
+@@ -1322,16 +865,6 @@ static const USHORT SiS310_VideoSenseDat
+ static const USHORT SiS310_YCSenseData2 = 0x016b;
+ #endif
+
+-static const UCHAR SiS310_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* TW: Was {0x21,0xed,0x8a,0x08}; */
+-static const UCHAR SiS310_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* TW: Was {0x2a,0x05,0xd3,0x00}; */
+-static const UCHAR SiS310_PALMPhase[] = {0x21,0xE4,0x2E,0x9B}; /* TW: palm*/
+-static const UCHAR SiS310_PALNPhase[] = {0x21,0xF4,0x3E,0xBA}; /* TW: paln*/
+-static const UCHAR SiS310_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};
+-static const UCHAR SiS310_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
+-static const UCHAR SiS310_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4}; /* TW: palm 301b*/
+-static const UCHAR SiS310_PALNPhase2[] = {0x21,0xF6,0x94,0x46}; /* TW: paln 301b*/
+-static const UCHAR SiS310_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a};
+-
+ typedef struct _SiS310_LCDDataStruct
+ {
+ USHORT RVBHCMAX;
+@@ -1353,25 +886,6 @@ static const SiS310_LCDDataStruct SiS31
+ { 1, 1,1344, 806,1344, 806}
+ };
+
+-#if 0 /* Seems out-dated, all BIOSes since 03/27/2002 have the other version */
+-static const SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
+-{
+- { 12, 5, 896, 512,1344, 806},
+- { 12, 5, 896, 510,1344, 806},
+- { 32, 15,1008, 505,1344, 806},
+- { 32, 15,1008, 514,1344, 806},
+- { 12, 5, 896, 500,1344, 806},
+- { 42, 25,1024, 625,1344, 806},
+- { 1, 1,1344, 806,1344, 806},
+- { 12, 5, 896, 500,1344, 806},
+- { 42, 25,1024, 625,1344, 806},
+- { 1, 1,1344, 806,1344, 806},
+- { 12, 5, 896, 500,1344, 806},
+- { 42, 25,1024, 625,1344, 806},
+- { 1, 1,1344, 806,1344, 806}
+-};
+-#endif
+-
+ static const SiS310_LCDDataStruct SiS310_ExtLCD1024x768Data[] =
+ {
+ { 42, 25,1536, 419,1344, 806},
+@@ -1413,7 +927,7 @@ static const SiS310_LCDDataStruct SiS31
+ { 1, 1,1688,1066,1688,1066}
+ };
+
+-static const SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
++static const SiS310_LCDDataStruct SiS310_ExtLCD1280x1024Data[] =
+ {
+ { 211, 60,1024, 501,1688,1066},
+ { 211, 60,1024, 508,1688,1066},
+@@ -1450,7 +964,7 @@ static const SiS310_LCDDataStruct SiS31
+ { 1, 1,1344, 806,1344, 806}
+ };
+
+-static const SiS310_LCDDataStruct SiS310_NoScaleData1280x1024[] =
++static const SiS310_LCDDataStruct SiS310_NoScaleData1280x1024[] =
+ {
+ { 1, 1,1688,1066,1688,1066},
+ { 1, 1,1688,1066,1688,1066},
+@@ -1463,272 +977,15 @@ static const SiS310_LCDDataStruct SiS31
+ { 1, 1,1688,1066,1688,1066}
+ };
+
+-static const SiS310_LCDDataStruct SiS310_LCD1280x960Data[] =
+-{
+- { 9, 2, 800, 500,1800,1000},
+- { 9, 2, 800, 500,1800,1000},
+- { 4, 1, 900, 500,1800,1000},
+- { 4, 1, 900, 500,1800,1000},
+- { 9, 2, 800, 500,1800,1000},
+- { 30, 11,1056, 625,1800,1000},
+- { 5, 3,1350, 800,1800,1000},
+- { 1, 1,1576,1050,1576,1050},
+- { 1, 1,1800,1000,1800,1000}
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_StLCD1400x1050Data[] =
+-{ /* TW: New from 1.11.6s */
+- { 211, 100, 2100, 408, 1688, 1066 },
+- { 211, 64, 1536, 358, 1688, 1066 },
+- { 211, 100, 2100, 408, 1688, 1066 },
+- { 211, 64, 1536, 358, 1688, 1066 },
+- { 211, 48, 840, 488, 1688, 1066 },
+- { 211, 72, 1008, 609, 1688, 1066 },
+- { 211, 128, 1400, 776, 1688, 1066 },
+- { 211, 205, 1680, 1041, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 }
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_ExtLCD1400x1050Data[] =
+-{ /* TW: New from 1.11.6s */
+- { 211, 100, 2100, 408, 1688, 1066 },
+- { 211, 64, 1536, 358, 1688, 1066 },
+- { 211, 100, 2100, 408, 1688, 1066 },
+- { 211, 64, 1536, 358, 1688, 1066 },
+- { 211, 48, 840, 488, 1688, 1066 },
+- { 211, 72, 1008, 609, 1688, 1066 },
+- { 211, 128, 1400, 776, 1688, 1066 },
+- { 211, 205, 1680, 1041, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 }
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_NoScaleData1400x1050[] =
+-{ /* TW: To be checked (BIOS uses 1280x1024 data, one line too short) */
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 },
+- { 1, 1, 1688, 1066, 1688, 1066 }
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_StLCD1600x1200Data[] =
+-{ /* TODO */
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_ExtLCD1600x1200Data[] =
+-{ /* TODO */
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-static const SiS310_LCDDataStruct SiS310_NoScaleData1600x1200[] =
+-{ /* TODO */
+- { 0, 0, 0, 0, 0, 0}
+-};
+-
+-typedef struct _SiS310_TVDataStruct
+-{
+- USHORT RVBHCMAX;
+- USHORT RVBHCFACT;
+- USHORT VGAHT;
+- USHORT VGAVT;
+- USHORT TVHDE;
+- USHORT TVVDE;
+- USHORT RVBHRS;
+- UCHAR FlickerMode;
+- USHORT HALFRVBHRS;
+- UCHAR RY1COE;
+- UCHAR RY2COE;
+- UCHAR RY3COE;
+- UCHAR RY4COE;
+-} SiS310_TVDataStruct;
+-
+-static const SiS310_TVDataStruct SiS310_StPALData[]=
+-{
+- { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
+- { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22},
+- { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22}
+-};
+-
+-static const SiS310_TVDataStruct SiS310_ExtPALData[] =
+-{
+- { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
+- { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
+- { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18},
+- { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a},
+- { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, /* 640x480 */
+- { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600 */
+- { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x480/576 */
+- { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} /* 1024x768 */
+-};
+-
+-static const SiS310_TVDataStruct SiS310_StNTSCData[]=
+-{
+- { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
+- { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
+- { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18}
+-};
+-
+-static const SiS310_TVDataStruct SiS310_ExtNTSCData[]=
+-{
+- { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
+- { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
+- { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
+- { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
+- { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480 */
+- { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600 */
+- { 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480/576 */
+- { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} /* 1024x768 */
+-};
+-
+-#if 0
+-static const SiS310_TVDataStruct SiS310_St1HiTVData[]=
+-{
+-
+-};
+-#endif
+-
+-static const SiS310_TVDataStruct SiS310_St2HiTVData[]=
+-{
+- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 1, 1, 0x3e8,0x233,0x311,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
+- { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
+-};
+-
+-static const SiS310_TVDataStruct SiS310_ExtHiTVData[]=
+-{
+- { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x348,0x1e3,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00},
+- { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},
+- { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00},
+- { 4, 1, 0x41a,0x233,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},
+- { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
+- { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}
+-};
+-
+-static const UCHAR SiS310_NTSCTiming[] = {
+- 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
+- 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
+- 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
+- 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
+- 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
+- 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
+- 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
+-};
+-
+-static const UCHAR SiS310_PALTiming[] = {
+- 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
+- 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
+- 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
+- 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
+- 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
+- 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
+-};
+-
+-static const UCHAR SiS310_HiTVExtTiming[] = {
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+- 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+- 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+- 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+-};
+-
+-static const UCHAR SiS310_HiTVSt1Timing[] = {
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
+- 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10,
+- 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86,
+- 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
+-};
+-
+-static const UCHAR SiS310_HiTVSt2Timing[] = {
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
+- 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
+- 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
+- 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
+-};
+-
+-static const UCHAR SiS310_HiTVTextTiming[] = {
+- 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+- 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
+- 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
+- 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
+- 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
+- 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40,
+- 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
+- 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
+-};
+-
+-static const UCHAR SiS310_HiTVGroup3Data[] = {
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+- 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9,
+- 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+-
+-static const UCHAR SiS310_HiTVGroup3Simu[] = {
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+- 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4,
+- 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+-
+-static const UCHAR SiS310_HiTVGroup3Text[] = {
+- 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+- 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
+- 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
+- 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
+- 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
+- 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca,
+- 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
+- 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
+-};
+
+ typedef struct _SiS310_PanelDelayTblStruct
+ {
+ UCHAR timer[2];
+ } SiS310_PanelDelayTblStruct;
+
+-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
++static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+ {
+- {{0x10,0x40}}, /* TW: from 650/301LVx 1.10.6s BIOS */
++ {{0x10,0x40}},
+ {{0x10,0x40}},
+ {{0x10,0x40}},
+ {{0x10,0x40}},
+@@ -1744,24 +1001,6 @@ static const SiS310_PanelDelayTblStruct
+ {{0x10,0x40}},
+ {{0x10,0x40}},
+ {{0x10,0x40}}
+-#if 0
+- {{0x28,0xc8}}, /* TW: from 650/301LV BIOS */
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}},
+- {{0x28,0xc8}}
+-#endif
+ };
+
+ static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+@@ -1792,363 +1031,7 @@ typedef struct _SiS310_LVDSDataStruct
+ USHORT LCDVT;
+ } SiS310_LVDSDataStruct;
+
+-static const SiS310_LVDSDataStruct SiS310_LVDS320x480Data_1[]=
+-{
+- { 848, 433, 400, 525},
+- { 848, 389, 400, 525},
+- { 848, 433, 400, 525},
+- { 848, 389, 400, 525},
+- { 848, 518, 400, 525},
+- {1056, 628, 400, 525},
+- { 400, 525, 400, 525},
+- { 800, 449,1000, 644},
+- { 800, 525,1000, 635}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS800x600Data_1[]=
+-{
+- { 848, 433,1060, 629},
+- { 848, 389,1060, 629},
+- { 848, 433,1060, 629},
+- { 848, 389,1060, 629},
+- { 848, 518,1060, 629},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- { 800, 449,1000, 644},
+- { 800, 525,1000, 635}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS800x600Data_2[]=
+-{
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- { 800, 449,1000, 644},
+- { 800, 525,1000, 635}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_1[]=
+-{
+- { 840, 438,1344, 806},
+- { 840, 409,1344, 806},
+- { 840, 438,1344, 806},
+- { 840, 409,1344, 806},
+- { 840, 518,1344, 806}, /* 640x480 */
+- {1050, 638,1344, 806}, /* 800x600 */
+- {1344, 806,1344, 806}, /* 1024x768 */
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1024x768Data_2[]=
+-{
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_1[]=
+-{
+- {1048, 442,1688,1066},
+- {1048, 392,1688,1066},
+- {1048, 442,1688,1066},
+- {1048, 392,1688,1066},
+- {1048, 522,1688,1066},
+- {1208, 642,1688,1066},
+- {1432, 810,1688,1066},
+- {1688,1066,1688,1066}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x1024Data_2[]=
+-{
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066},
+- {1688,1066,1688,1066}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_1[]=
+-{
+- { 928, 416, 1688,1066},
+- { 928, 366, 1688,1066},
+- { 928, 416, 1688,1066},
+- { 928, 366, 1688,1066},
+- { 928, 496, 1688,1066},
+- {1088, 616, 1688,1066},
+- {1312, 784, 1688,1066},
+- {1568,1040, 1688,1066},
+- {1688,1066, 1688,1066}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1400x1050Data_2[]=
+-{
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+- {1688,1066, 1688,1066},
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1600x1200Data_1[]=
+-{
+- {1088, 450, 2048,1250},
+- {1088, 400, 2048,1250},
+- {1088, 450, 2048,1250},
+- {1088, 400, 2048,1250},
+- {1088, 530, 2048,1250},
+- {1248, 650, 2048,1250},
+- {1472, 818, 2048,1250},
+- {1728,1066, 2048,1250},
+- {1848,1066, 2048,1250},
+- {2048,1250, 2048,1250}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1600x1200Data_2[]=
+-{
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250},
+- {2048,1250, 2048,1250}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x768Data_1[]=
+-{
+- { 768, 438, 1408, 806},
+- { 768, 388, 1408, 806},
+- { 768, 438, 1408, 806},
+- { 768, 388, 1408, 806},
+- { 768, 518, 1408, 806},
+- { 928, 638, 1408, 806},
+- {1152, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x768Data_2[]=
+-{
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806},
+- {1408, 806, 1408, 806}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1024x600Data_1[]=
+-{
+- { 840, 604, 1344, 800},
+- { 840, 560, 1344, 800},
+- { 840, 604, 1344, 800},
+- { 840, 560, 1344, 800},
+- { 840, 689, 1344, 800},
+- {1050, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- { 800, 449, 1280, 801},
+- { 800, 525, 1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1024x600Data_2[]=
+-{
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- {1344, 800, 1344, 800},
+- { 800, 449, 1280, 801},
+- { 800, 525, 1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1152x768Data_1[]=
+-{
+- { 840, 438, 1344, 806},
+- { 840, 409, 1344, 806},
+- { 840, 438, 1344, 806},
+- { 840, 409, 1344, 806},
+- { 840, 518, 1344, 806},
+- {1050, 638, 1344, 806},
+- {1344, 806, 1344, 806},
+- { 800, 449, 1280, 801},
+- { 800, 525, 1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1152x768Data_2[]=
+-{
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- {1344, 806, 1344, 806},
+- { 800, 449, 1280, 801},
+- { 800, 525, 1280, 813}
+-};
+-
+-/* TW: Pass 1:1 data */
+-static const SiS310_LVDSDataStruct SiS310_LVDSXXXxXXXData_1[]=
+-{
+- { 800, 449, 800, 449},
+- { 800, 449, 800, 449},
+- { 900, 449, 900, 449},
+- { 900, 449, 900, 449},
+- { 800, 525, 800, 525}, /* 640x480 */
+- {1056, 628, 1056, 628}, /* 800x600 */
+- {1344, 806, 1344, 806}, /* 1024x768 */
+- {1344,1066, 1344,1066}, /* 1280x1024 */ /* INSERTED ! */
+- {1688, 806, 1688, 806}, /* 1280x768 ! */
+- /* No other panels ! */
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS640x480Data_1[]=
+-{
+- { 800, 449, 800, 449},
+- { 800, 449, 800, 449},
+- { 800, 449, 800, 449},
+- { 800, 449, 800, 449},
+- { 800, 525, 800, 525},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628},
+- {1056, 628,1056, 628}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_1[]=
+-{
+- { 840, 438,1344, 806},
+- { 840, 409,1344, 806},
+- { 840, 438,1344, 806},
+- { 840, 409,1344, 806},
+- { 840, 518,1344, 806},
+- {1050, 638,1344, 806},
+- {1344, 806,1344, 806},
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LVDS1280x960Data_2[]=
+-{
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-/* LCDA */
+-
+-static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_1[]=
+-{ /* TW: Might be temporary (invalid) data */
+- { 928, 416, 1688,1066},
+- { 928, 366, 1688,1066},
+- {1008, 416, 1688,1066},
+- {1008, 366, 1688,1066},
+- {1200, 530, 1688,1066},
+- {1088, 616, 1688,1066},
+- {1312, 784, 1688,1066},
+- {1568,1040, 1688,1066},
+- {1688,1066, 1688,1066}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LCDA1400x1050Data_2[]=
+-{ /* TW: Temporary data. Not valid */
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_1[]=
+-{ /* TW: Temporary data. Not valid */
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- {1344, 806,1344, 806},
+- { 800, 449,1280, 801},
+- { 800, 525,1280, 813}
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_LCDA1600x1200Data_2[]=
+-{ /* TW: Temporary data. Not valid */
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0},
+- {0, 0, 0, 0}
+-};
+-
+-/* Chrontel TV */
+-
+-static const SiS310_LVDSDataStruct SiS310_CHTVUNTSCData[]=
+-{
+- { 840, 600, 840, 600},
+- { 840, 600, 840, 600},
+- { 840, 600, 840, 600},
+- { 840, 600, 840, 600},
+- { 784, 600, 784, 600},
+- {1064, 750,1064, 750},
+- {1160, 945,1160, 945} /* TW: For Ch7019 1024 */
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_CHTVONTSCData[]=
+-{
+- { 840, 525, 840, 525},
+- { 840, 525, 840, 525},
+- { 840, 525, 840, 525},
+- { 840, 525, 840, 525},
+- { 784, 525, 784, 525},
+- {1040, 700,1040, 700},
+- {1160, 840,1160, 840} /* TW: For Ch7019 1024 */
+-};
+-
+-static const SiS310_LVDSDataStruct SiS310_CHTVUPALData[]=
++static const SiS310_LVDSDataStruct SiS310_CHTVUPALData[]=
+ {
+ {1008, 625,1008, 625},
+ {1008, 625,1008, 625},
+@@ -2156,7 +1039,7 @@ static const SiS310_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ { 840, 625, 840, 625},
+ { 960, 750, 960, 750},
+- {1400,1000,1400,1000} /* TW: For Ch7019 1024 */
++ {1400,1000,1400,1000}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVOPALData[]=
+@@ -2167,7 +1050,7 @@ static const SiS310_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ { 840, 625, 840, 625},
+ { 944, 625, 944, 625},
+- {1400, 875,1400, 875} /* TW: For Ch7019 1024 */
++ {1400, 875,1400, 875}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVUPALMData[]=
+@@ -2178,7 +1061,7 @@ static const SiS310_LVDSDataStruct SiS3
+ { 840, 600, 840, 600},
+ { 784, 600, 784, 600},
+ {1064, 750,1064, 750},
+- {1160, 945,1160, 945} /* TW: For Ch7019 1024 */
++ {1160, 945,1160, 945}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVOPALMData[]=
+@@ -2189,7 +1072,7 @@ static const SiS310_LVDSDataStruct SiS3
+ { 840, 525, 840, 525},
+ { 784, 525, 784, 525},
+ {1040, 700,1040, 700},
+- {1160, 840,1160, 840} /* TW: For Ch7019 1024 */
++ {1160, 840,1160, 840}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVUPALNData[]=
+@@ -2200,7 +1083,7 @@ static const SiS310_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ { 840, 625, 840, 625},
+ { 960, 750, 960, 750},
+- {1400,1000,1400,1000} /* TW: For Ch7019 1024 */
++ {1400,1000,1400,1000}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVOPALNData[]=
+@@ -2211,7 +1094,7 @@ static const SiS310_LVDSDataStruct SiS3
+ {1008, 625,1008, 625},
+ { 840, 625, 840, 625},
+ { 944, 625, 944, 625},
+- {1400, 875,1400, 875} /* TW: For Ch7019 1024 */
++ {1400, 875,1400, 875}
+ };
+
+ static const SiS310_LVDSDataStruct SiS310_CHTVSOPALData[]= /* TW: (super overscan - no effect on 7019) */
+@@ -2231,7 +1114,7 @@ typedef struct _SiS310_LVDSDesStruct
+ USHORT LCDVDES;
+ } SiS310_LVDSDesStruct;
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType00_1[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType00_1[]= /* 800x600 */
+ {
+ { 0, 0},
+ { 0, 0},
+@@ -2244,7 +1127,7 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType01_1[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType01_1[]= /* 1024x768 */
+ {
+ { 0, 0},
+ { 0, 0},
+@@ -2257,7 +1140,7 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType02_1[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType02_1[]= /* 1280x1024 */
+ {
+ { 0, 0},
+ { 0, 0},
+@@ -2382,33 +1265,31 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType0b_1[]=
+-{
+- {1343, 798},
+- {1343, 794},
+- {1343, 798},
+- {1343, 794},
+- {1343, 0},
+- {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType0c_1[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType0b_1[]= /* 640x480_2 */
+ {
+- {1343, 798},
+- {1343, 794},
+- {1343, 798},
+- {1343, 794},
+- {1343, 0},
+- {1343, 0},
+- { 0, 805},
+- { 0, 794},
+- { 0, 0}
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 8, 524},
++ { 0, 524}
++};
++
++static const SiS310_LVDSDesStruct SiS310_PanelType0c_1[]= /* 640x480_3 */
++{
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 0, 524},
++ { 8, 524},
++ { 0, 524}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType0d_1[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType0d_1[]=
+ {
+ {1343, 798},
+ {1343, 794},
+@@ -2604,7 +1485,7 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType0b_2[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType0b_2[]= /* 640x480_2 */
+ {
+ {1152, 622},
+ {1152, 597},
+@@ -2617,7 +1498,7 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelType0c_2[]=
++static const SiS310_LVDSDesStruct SiS310_PanelType0c_2[]= /* 640x480_3 */
+ {
+ {1152, 622},
+ {1152, 597},
+@@ -2669,184 +1550,6 @@ static const SiS310_LVDSDesStruct SiS31
+ { 0, 0}
+ };
+
+-static const SiS310_LVDSDesStruct SiS310_PanelTypeNS_1[]=
+-{
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 8, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 806},
+- { 0, 0 }
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelTypeNS_2[] =
+-{
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1076_1[]=
+-{ /* 1024x768 - Checked (1.10.6s) */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1076_2[]=
+-{ /* 1024x768 - Checked (1.10.6s) */
+- { 1184, 622 },
+- { 1184, 597 },
+- { 1184, 622 },
+- { 1184, 597 },
+- { 1152, 622 },
+- { 1232, 722 },
+- { 0, 0 },
+- { 0, 794 },
+- { 0, 0 }
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1210_1[]=
+-{ /* 1280x1024 - Checked (1.10.6s) */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1210_2[]=
+-{ /* 1280x1024 - Checked (1.10.6s) */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1296_1[]=
+-{ /* 1400x1050 - Checked (1.10.6s) */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1296_2[]=
+-{ /* 1400x1050 - Checked (1.10.6s) - looks heavily invalid */
+- { 808 , 740},
+- { 0 , 715},
+- { 632 , 740},
+- { 632 , 715},
+- { 1307, 780},
+- { 1387,1157},
+- { 1499, 924},
+- { 1627,1052},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1600_1[]=
+-{ /* 1600x1200 - Checked (1.10.6s) */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_PanelType1600_2[]=
+-{ /* 1600x1200 - Checked (1.10.6s) - looks heavily invalid, not copied */
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0},
+- { 0 , 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_CHTVUNTSCDesData[]=
+-{
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_CHTVONTSCDesData[]=
+-{
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_CHTVUPALDesData[]=
+-{
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+-static const SiS310_LVDSDesStruct SiS310_CHTVOPALDesData[]=
+-{
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- {256, 0},
+- { 0, 0},
+- { 0, 0},
+- { 0, 0}
+-};
+-
+ typedef struct _SiS310_Part2PortTblStruct
+ {
+ UCHAR CR[12];
+@@ -2866,16 +1569,15 @@ static const SiS310_Part2PortTblStruct S
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] =
+-{ /* TW: Temporary data, invalid */
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
++{ /* TW: BIOS data invalid, last row taken from _3 */
++ {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
++ {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
++ {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
++ {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
++ {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
++ {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
++ {{0x36,0x13,0x02,0x25,0xFF,0x03,0x45,0x09,0x07,0xF9,0x00,0x24}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] =
+@@ -2892,16 +1594,17 @@ static const SiS310_Part2PortTblStruct S
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] =
+-{ /* TW: Temporary data, invalid */
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
++{
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] =
+@@ -2912,7 +1615,8 @@ static const SiS310_Part2PortTblStruct S
+ {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}},
+ {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
+ {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}},
+- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
++ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}, /* old */
++/* 0x36,0x13,0x02,0x25,0xff,0x03,0x45,0x09,0x07,0xf9,0x00,0x24 new? */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+ };
+@@ -2944,21 +1648,23 @@ static const SiS310_Part2PortTblStruct S
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] =
+-{ /* TW: Temporary data, invalid */
+- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
+- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
+- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
+- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
+- {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
+- {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}},
+- {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}},
+- {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
++{
++ {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
++ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
++ {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
++ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
++ {{0x3A,0x1B,0x54,0x7A,0x48,0x80,0x24,0x52,0x30,0xA3,0x3A,0x02}},
++ {{0x36,0x1B,0x90,0xB6,0x84,0xA8,0x24,0x7A,0x30,0xCB,0x62,0x02}},
++ {{0x3A,0x1C,0xE4,0x0A,0xD8,0xE0,0x24,0xB2,0x30,0x03,0x9A,0x02}},
++ {{0x4A,0x24,0x64,0x8A,0x58,0x20,0x34,0xF2,0x30,0x43,0xDA,0x52}},
++ {{0x47,0x24,0x71,0x97,0x65,0x3E,0x34,0x10,0x40,0x61,0xF8,0x02}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
+ };
+
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] =
+ { /* TW: Data from 650/301LVx 1.10.6s */
++#if 0
+ {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+@@ -2968,56 +1674,56 @@ static const SiS310_Part2PortTblStruct S
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+ {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}}
+-#if 0 /* TW: Data from 650/301LV */
+- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
+- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+-#endif
++#endif /* Data from my 301LV */
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}, /* @@@@@ TEST */
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
++ {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}
+ };
+
+ /* 1 2 4 5 6 1c 1d 1f 20 21 23 25 */
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] =
+-{ /* TW: Temporary data, invalid */
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
++{
++ {{0x31,0x1B,0xC4,0xDA,0xB0,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x34,0x1B,0x9F,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x3E,0x1B,0xCF,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
++ {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] =
+ {
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
++ {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
+ };
+
+ static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] =
+-{ /* TW: Temporary data, invalid */
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
+- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
++{
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
++ {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
+ };
+
+ typedef struct _SiS310_LCDACRT1DataStruct
+@@ -3054,7 +1760,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1[]=
+-{ /* TW: Checked (1.10.6s) */
++{
+ {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
+ 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
+ 0x00}},
+@@ -3079,7 +1785,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
+ 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
+ 0x00}},
+@@ -3107,7 +1813,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
+ 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
+ 0x00}},
+@@ -3200,7 +1906,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_1_H[]=
+-{ /* TW: Checked (1.10.6s) */
++{
+ {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
+ 0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
+ 0x00}},
+@@ -3225,7 +1931,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_1_H[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
+ 0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
+ 0x00}},
+@@ -3250,7 +1956,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_1_H[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
+ 0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
+ 0x00}},
+@@ -3343,7 +2049,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+ 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
+ 0x00}},
+@@ -3368,7 +2074,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+ 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
+ 0x00}},
+@@ -3393,7 +2099,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
+ 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
+ 0x00}},
+@@ -3486,7 +2192,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11024x768_2_H[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x4f,0x27,0x27,0x93,0x39,0x01,0x24,0xbb,
+ 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
+ 0x00 }},
+@@ -3511,7 +2217,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11280x1024_2_H[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
+ 0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
+ 0x00 }},
+@@ -3536,7 +2242,7 @@ static const SiS310_LCDACRT1DataStruct
+ };
+
+ static const SiS310_LCDACRT1DataStruct SiS310_LCDACRT11400x1050_2_H[]=
+-{ /* Checked (1.10.6s) */
++{
+ {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
+ 0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
+ 0x00}},
+@@ -3605,32 +2311,7 @@ typedef struct _SiS310_LVDSCRT1DataStruc
+ UCHAR CR[15];
+ } SiS310_LVDSCRT1DataStruct;
+
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1320x480_1[] =
+-{
+- {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
+- 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
+- 0x00 }},
+- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+- 0x00 }},
+- {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00 }},
+- {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
+- 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
+- 0x00 }},
+- {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
+- 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
+- 0x00 }},
+- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+- 0x01 }},
+- {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
+- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+- 0x00 }}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] =
++static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1800x600_1[] =
+ {
+ {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
+ 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
+@@ -3924,63 +2605,7 @@ static const SiS310_LVDSCRT1DataStruct
+ 0x01}}
+ };
+
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1[] =
+-{
+- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+- 0x00}},
+- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+- 0x00}},
+- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+- 0x00}},
+- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+- 0x00}},
+- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+- 0x00}},
+- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+- 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}},
+- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+- 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+- 0x01}},
+- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT1XXXxXXX_1_H[] =
+-{
+- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+- 0x00}},
+- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+- 0x00}},
+- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+- 0x00}},
+- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+- 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+- 0x00}},
+- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+- 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+- 0x00}},
+- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+- 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+- 0x01}},
+- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] =
++static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11400x1050_1[] =
+ {
+ {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
+ 0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
+@@ -4220,332 +2845,8 @@ static const SiS310_LVDSCRT1DataStruct
+ #endif
+ };
+
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_1[] =
+-{
+- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
+- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
+- 0x00}},
+- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
+- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
+- 0x00}},
+- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
+- 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
+- 0x00}},
+- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
+- 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
+- 0x00}},
+- {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e,
+- 0xec,0x8e,0xdf,0x05,0x20,0x00,0x01,
+- 0x00}},
+- {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0,
+- 0x64,0x86,0x57,0x7d,0x20,0x00,0x05,
+- 0x01}},
+- {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5,
+- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
+- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
+- 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_1_H[] =
+-{
+- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
+- 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
+- 0x00}},
+- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
+- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
+- 0x00}},
+- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
+- 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
+- 0x00}},
+- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
+- 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
+- 0x00}},
+- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
+- 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
+- 0x00}},
+- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
+- 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
+- 0x01}},
+- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
+- 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
+- 0x01}},
+- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
+- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
+- 0x01}},
+- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
+- 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_2[] =
++static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] =
+ {
+- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
+- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+- 0x00}},
+- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
+- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+- 0x00}},
+- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
+- 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+- 0x00}},
+- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
+- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+- 0x00}},
+- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3,
+- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x02,
+- 0x01}},
+- {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1,
+- 0xb6,0x88,0x57,0x25,0x10,0x00,0x02,
+- 0x01}},
+- {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11280x768_2_H[] =
+-{
+- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
+- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+- 0x00}},
+- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
+- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+- 0x00}},
+- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
+- 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+- 0x00}},
+- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
+- 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+- 0x00}},
+- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3,
+- 0x7c,0x8e,0x03,0x02,0x10,0x00,0x01,
+- 0x01}},
+- {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1,
+- 0xb6,0x88,0x57,0x25,0x10,0x00,0x01,
+- 0x01}},
+- {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x01,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+- 0x01}},
+- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
+- 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_1[] =
+-{
+- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
+- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
+- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
+- 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
+- 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
+- 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
+- 0x00}},
+- {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
+- 0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
+- 0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_1_H[] =
+-{
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
+- 0x00}},
+- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_2[] =
+-{
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11024x600_2_H[] =
+-{
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_1[] =
+-{
+- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
+- 0x00}},
+- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
+- 0x00}},
+- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_1_H[] =
+-{
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
+- 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
+- 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
+- 0x00}},
+- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
+- 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
+- 0x00}},
+- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
+- 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_2[] =
+-{
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
+- 0x00}},
+- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
+- 0x01}},
+- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11152x768_2_H[] =
+-{
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
+- 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
+- 0x00}},
+- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
+- 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
+- 0x01}},
+- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
+- 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+- 0x01}}
+-};
+-
+-static const SiS310_LVDSCRT1DataStruct SiS310_LVDSCRT11600x1200_1[] =
+-{
+ {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
+ 0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
+ 0x00}},
+@@ -4701,7 +3002,7 @@ static const SiS310_LVDSCRT1DataStruct
+ {{0x80,0x63,0x84,0x6d,0x0f,0xec,0xf0,
+ 0x7a,0x8f,0x57,0xed,0x20,0x00,0x06,
+ 0x01 }},
+- {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5, /* TW: 1024x768 */
++ {{0x8c,0x7f,0x90,0x86,0x09,0xaf,0xf5,
+ 0x36,0x88,0xff,0xb0,0x10,0x00,0x02,
+ 0x01}}
+ };
+@@ -4726,7 +3027,7 @@ static const SiS310_LVDSCRT1DataStruct
+ {{0x7d,0x63,0x81,0x68,0x0e,0xba,0xf0,
+ 0x78,0x8a,0x57,0xbb,0x20,0x00,0x06,
+ 0x01 }},
+- {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5, /* TW: 1024x768 */
++ {{0x8c,0x7f,0x90,0x82,0x06,0x46,0xf5,
+ 0x15,0x88,0xff,0x47,0x70,0x00,0x02,
+ 0x01 }}
+ };
+@@ -4751,7 +3052,7 @@ static const SiS310_LVDSCRT1DataStruct
+ {{0x73,0x63,0x97,0x69,0x8b,0xec,0xf0,
+ 0x90,0x8c,0x57,0xed,0x20,0x00,0x05,
+ 0x01 }},
+- {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5, /* TW: 1024x768 */
++ {{0xaa,0x7f,0x8e,0x8e,0x96,0xe6,0xf5,
+ 0x50,0x88,0xff,0xe7,0x10,0x00,0x02,
+ 0x01}}
+ };
+@@ -4776,7 +3077,7 @@ static const SiS310_LVDSCRT1DataStruct
+ {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0,
+ 0x5a,0x8b,0x57,0x70,0x20,0x00,0x05,
+ 0x01 }},
+- {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5, /* TW: 1024x768 */
++ {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5,
+ 0x28,0x88,0xff,0x6a,0x10,0x00,0x02,
+ 0x01 }}
+ };
+@@ -4801,12 +3102,11 @@ static const SiS310_LVDSCRT1DataStruct
+ {{0x71,0x63,0x95,0x69,0x8c,0x6f,0xf0,
+ 0x5a,0x8b,0x57,0x70,0x20,0x00,0x05,
+ 0x01 }},
+- {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5, /* TW: 1024x768 */
++ {{0xaa,0x7f,0x8e,0x8f,0x96,0x69,0xf5,
+ 0x28,0x88,0xff,0x6a,0x10,0x00,0x02,
+ 0x01 }}
+ };
+
+-/* TW: Data for Chrontel 7019 */
+ typedef struct _SiS310_CHTVRegDataStruct
+ {
+ UCHAR Reg[16];
+--- linux-2.6.0-test6/drivers/video/sis/init301.c 2003-07-13 21:44:34.000000000 -0700
++++ 25/drivers/video/sis/init301.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,27 +1,16 @@
+ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.c,v 1.3 2002/22/04 01:16:16 dawes Exp $ */
+ /*
+- * Mode switching code (CRT2 section) for SiS 300/540/630/730/315/550/650/740/330
+- * (Universal module for Linux kernel framebuffer, XFree86 4.x)
++ * Mode switching code (CRT2 section) for SiS 300/540/630/730/315/550/650/740/330/660
++ * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ *
+ * Assembler-To-C translation
+ * Copyright 2002, 2003 by Thomas Winischhofer <thomas@winischhofer.net>
+- * Minor parts Copyright SiS, Inc.
++ * Formerly based on non-functional code-fragements by SiS, Inc.
+ *
+- * Based on BIOS
+- * 1.10.07, 1.10a for 650/CH7019
+- * 1.11.21a for 740/CH7019
+- * 1.11.05 for 650/LVDS (w/o Chrontel)
+- * 1.07.1b, 1.10.6s, 1.11.6w, 1.11.7w, 1.11.8r for 650/301(B/LV), 650/302LV
+- * 2.04.50 (I) and 2.04.5c (II) for 630/301(B)
+- * 2.02.3b, 2.03.02, 2.04.2c, 2.04.5c, 2.07a and 2.08.b3 for 630/LVDS/LVDS+CH7005
+- * 2.04.5c, 2.04.6c for 730+LVDS+CH7005
+- * 1.09b for 315/301(B)
+- * 1.16.51 for 300+301LV (ECS A907)
+- * 1.01.03 for 330 (Xabre 400)
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
+ *
+- * Known bugs:
+- * 1024x768 panel, expanding (CR37=1): Mode 640x480 does not work on SOME panels
+- * therefore, we always do the scaling ourselves for now.
++ * Otherwise, the following terms apply:
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+@@ -73,8 +62,8 @@
+ #define SiS_I2CDELAYSHORT 150
+
+ BOOLEAN
+-SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+- PSIS_HW_DEVICE_INFO HwDeviceExtension)
++SiS_SetCRT2Group(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
++ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT ModeIdIndex;
+ USHORT RefreshRateTableIndex;
+@@ -85,9 +74,9 @@ SiS_SetCRT2Group301(SiS_Private *SiS_Pr,
+ SiS_SearchModeID(SiS_Pr,ROMAddr,&ModeNo,&ModeIdIndex);
+ } else {
+ ModeIdIndex = 0;
+- }
++ }
+
+- /* TW: Used for shifting CR33 */
++ /* Used for shifting CR33 */
+ SiS_Pr->SiS_SelectCRT2Rate = 4;
+
+ SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
+@@ -110,8 +99,6 @@ SiS_SetCRT2Group301(SiS_Private *SiS_Pr,
+ return(TRUE);
+ }
+
+- if(SiS_Pr->UseCustomMode) return(FALSE);
+-
+ SiS_GetCRT2Data(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ HwDeviceExtension);
+
+@@ -153,9 +140,9 @@ SiS_SetCRT2Group301(SiS_Private *SiS_Pr,
+ SiS_SetGroup5(SiS_Pr,HwDeviceExtension, BaseAddr,ROMAddr,
+ ModeNo,ModeIdIndex);
+
+- /* TW: For 301BDH (Panel link initialization): */
++ /* For 301BDH (Panel link initialization): */
+ if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+ if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo = 0x10)))) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ SiS_ModCRT1CRTC(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+@@ -176,10 +163,10 @@ SiS_SetCRT2Group301(SiS_Private *SiS_Pr,
+ RefreshRateTableIndex,HwDeviceExtension);
+ }
+ }
+- if(SiS_Pr->SiS_IF_DEF_FSTN == 0) {
+- SiS_SetCRT2ECLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,HwDeviceExtension);
+- }
++
++ SiS_SetCRT2ECLK(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
++ RefreshRateTableIndex,HwDeviceExtension);
++
+ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+@@ -199,74 +186,64 @@ SiS_SetCRT2Group301(SiS_Private *SiS_Pr,
+ }
+
+ #ifdef SIS300
+- if ( (HwDeviceExtension->jChipType == SIS_540) ||
+- (HwDeviceExtension->jChipType == SIS_630) ||
+- (HwDeviceExtension->jChipType == SIS_730) ||
+- (HwDeviceExtension->jChipType == SIS_300) )
+- {
+- if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+- if(SiS_Pr->SiS_UseOEM) {
+- if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) {
+- if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+- SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo);
+- }
+- } else {
+- SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo);
+- }
+- }
+- }
+- }
+-#endif
+-
+-#ifdef SIS315H
+- if ( (HwDeviceExtension->jChipType == SIS_315H) ||
+- (HwDeviceExtension->jChipType == SIS_315) ||
+- (HwDeviceExtension->jChipType == SIS_315PRO)||
+- (HwDeviceExtension->jChipType == SIS_550) ||
+- (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_650) ||
+- (HwDeviceExtension->jChipType == SIS_330) )
+- {
+- if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+- SiS_FinalizeLCD(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, HwDeviceExtension);
+-#if 0 /* Instead of FinalizeLCD(), older BIOSes (A92x) used OEMLCD() */
+- SiS_OEMLCD(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+-#endif
+- if(SiS_Pr->SiS_UseOEM) {
+- SiS_OEM310Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+- }
+- SiS_CRT2AutoThreshold(SiS_Pr,BaseAddr);
+- }
+- }
+-#endif
+-
+ if(HwDeviceExtension->jChipType < SIS_315H) {
++ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
++ if(SiS_Pr->SiS_UseOEM) {
++ if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) {
++ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
++ SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
++ RefreshRateTableIndex);
++ }
++ } else {
++ SiS_OEM300Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
++ RefreshRateTableIndex);
++ }
++ }
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
++ (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
++ SetOEMLCDData2(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,
++ ModeIdIndex,RefreshRateTableIndex);
++ }
++ if(HwDeviceExtension->jChipType == SIS_730) {
++ SiS_DisplayOn(SiS_Pr);
++ }
++ }
++ }
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(HwDeviceExtension->jChipType != SIS_730) {
+ SiS_DisplayOn(SiS_Pr);
+ }
+ }
+ }
++#endif
+
+- if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(HwDeviceExtension->jChipType == SIS_730) {
+- SiS_DisplayOn(SiS_Pr);
+- }
++#ifdef SIS315H
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
++ SiS_FinalizeLCD(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex, HwDeviceExtension);
++ if(SiS_Pr->SiS_UseOEM) {
++ SiS_OEM310Setting(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
++ }
++ SiS_CRT2AutoThreshold(SiS_Pr,BaseAddr);
+ }
++ }
++#endif
++
++ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+ SiS_EnableBridge(SiS_Pr,HwDeviceExtension,BaseAddr);
+ }
+
+ SiS_DisplayOn(SiS_Pr);
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- /* TW: Disable LCD panel when using TV */
+- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x11,0x0C);
+- } else {
+- /* TW: Disable TV when using LCD */
+- SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
+- }
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ /* Disable LCD panel when using TV */
++ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x11,0x0C);
++ } else {
++ /* Disable TV when using LCD */
++ SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
++ }
+ }
+
+ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
+@@ -283,7 +260,7 @@ SiS_LowModeStuff(SiS_Private *SiS_Pr, US
+ USHORT temp,temp1,temp2;
+
+ if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
+- return(1);
++ return(1);
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x11);
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
+ temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x00);
+@@ -304,7 +281,7 @@ SiS_LowModeStuff(SiS_Private *SiS_Pr, US
+ }
+ }
+
+-/* TW: Set Part1 registers */
++/* Set Part1 registers */
+ void
+ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension,
+@@ -313,31 +290,35 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ USHORT temp=0, tempax=0, tempbx=0, tempcx=0;
+ USHORT pushbx=0, CRT1Index=0;
+ #ifdef SIS315H
+- USHORT pushcx=0, tempbl=0;
++ USHORT tempbl=0;
+ #endif
+ USHORT modeflag, resinfo=0;
+
+- if(ModeNo<=0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ if(ModeNo <= 0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ } else {
+ CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ }
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+-
+- SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo,
+- RefreshRateTableIndex,HwDeviceExtension);
+ #ifdef SIS315H
+- SiS_SetGroup1_LCDA(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
+- HwDeviceExtension,RefreshRateTableIndex);
++ SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo,
++ RefreshRateTableIndex,HwDeviceExtension);
++
++ SiS_SetGroup1_LCDA(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
++ HwDeviceExtension,RefreshRateTableIndex);
+ #endif
+ } else {
+
+ if( (HwDeviceExtension->jChipType >= SIS_315H) &&
+ (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
+- (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ (SiS_Pr->SiS_VBInfo & SetInSlaveMode) ) {
+
+ SiS_SetCRT2Sync(SiS_Pr,BaseAddr,ROMAddr,ModeNo,
+ RefreshRateTableIndex,HwDeviceExtension);
+@@ -367,13 +348,13 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ #ifdef SIS300 /* ------------- 300 series --------------*/
+
+ temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* TW: CRT2 Horizontal Total */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
+
+ temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* TW: CRT2 Horizontal Total Overflow [7:4] */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp); /* CRT2 Horizontal Total Overflow [7:4] */
+
+ temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* TW: CRT2 Horizontal Display Enable End */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
+
+ pushbx = SiS_Pr->SiS_VGAHDE + 12; /* bx BTVGA@HRS 0x0B,0x0C */
+ tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+@@ -382,108 +363,129 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ tempcx += tempbx;
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+- /* CRT1Index &= 0x3F; - Not any longer */
+- tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+- tempbx |= ((SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14] & 0xC0) << 2);
+- tempbx = (tempbx - 1) << 3;
+- tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+- tempcx &= 0x1F;
+- temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+- temp = (temp & 0x04) << (6-2);
+- tempcx = (tempcx | temp);
+- tempcx--;
+- tempcx <<= 3;
+- }
+-
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)){
+- tempbx = 1040;
+- tempcx = 1042;
+- }
+- }
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CHSyncStart + 12;
++ tempcx = SiS_Pr->CHSyncEnd + 12;
++ }
++
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
++ unsigned char cr4, cr14, cr5, cr15;
++ if(SiS_Pr->UseCustomMode) {
++ cr4 = SiS_Pr->CCRT1CRTC[4];
++ cr14 = SiS_Pr->CCRT1CRTC[14];
++ cr5 = SiS_Pr->CCRT1CRTC[5];
++ cr15 = SiS_Pr->CCRT1CRTC[15];
++ } else {
++ cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
++ cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
++ cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
++ cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
++ }
++ tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
++ tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
++ }
++
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == SIS_RI_1024x768)){
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)){
++ tempbx = 1040;
++ tempcx = 1042;
++ }
++ }
+ }
+
+ temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* TW: CRT2 Horizontal Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* CRT2 Horizontal Retrace Start */
+ #endif /* SIS300 */
+
+ } else {
+
+-#ifdef SIS315H /* ----------------- 310/325/330 series ------------- */
++#ifdef SIS315H /* ------------------- 315/330 series --------------- */
+
+ tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HT 0x08,0x09 */
+- pushcx = tempcx;
+ if(modeflag & HalfDCLK) {
+-#ifndef NEWCH701x
+- if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_IF_DEF_CH70xx == 0)) {
+-#endif
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ tempax = SiS_Pr->SiS_VGAHDE >> 1;
+ tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+ tempcx = SiS_Pr->SiS_HT - tempax;
+ }
+-#ifndef NEWCH701x
+ } else {
+ tempcx >>= 1;
+ }
+-#endif
+ }
+ tempcx--;
+
+ temp = tempcx & 0xff;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* TW: CRT2 Horizontal Total */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,temp); /* CRT2 Horizontal Total */
+
+ temp = ((tempcx & 0xff00) >> 8) << 4;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* TW: CRT2 Horizontal Total Overflow [7:4] */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp); /* CRT2 Horizontal Total Overflow [7:4] */
+
+- tempcx = pushcx; /* BTVGA2HDEE 0x0A,0x0C */
++ tempcx = SiS_Pr->SiS_VGAHT; /* BTVGA2HDEE 0x0A,0x0C */
+ tempbx = SiS_Pr->SiS_VGAHDE;
+ tempcx -= tempbx;
+ tempcx >>= 2;
+ if(modeflag & HalfDCLK) {
+- tempbx >>= 1;
+- tempcx >>= 1;
++ tempbx >>= 1;
++ tempcx >>= 1;
+ }
+ tempbx += 16;
+
+ temp = tempbx & 0xff;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* TW: CRT2 Horizontal Display Enable End */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* CRT2 Horizontal Display Enable End */
+
+ pushbx = tempbx;
+ tempcx >>= 1;
+ tempbx += tempcx;
+ tempcx += tempbx;
+
+- if(SiS_Pr->SiS_IF_DEF_LVDS==0) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CHSyncStart + 16;
++ tempcx = SiS_Pr->CHSyncEnd + 16;
++ tempax = SiS_Pr->SiS_VGAHT;
++ if(modeflag & HalfDCLK) tempax >>= 1;
++ tempax--;
++ if(tempcx > tempax) tempcx = tempax;
++ }
++
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+- tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+- tempbx |= ((SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14] & 0xC0) << 2);
+- tempbx = (tempbx - 3) << 3; /*(VGAHRS-3)*8 */
+- tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+- tempcx &= 0x1F;
+- temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+- temp = (temp & 0x04) << (5-2); /* VGAHRE D[5] */
+- tempcx = (tempcx | temp); /* (VGAHRE-3)*8 */
+- tempcx -= 3;
+- tempcx <<= 3;
+- tempcx &= 0x00FF;
+- tempcx |= (tempbx & 0xFF00);
+- tempbx += 16;
+- tempcx += 16;
+- tempax = SiS_Pr->SiS_VGAHT;
+- if(modeflag & HalfDCLK) tempax >>= 1;
+- tempax--;
+- if(tempcx > tempax) tempcx = tempax;
++ unsigned char cr4, cr14, cr5, cr15;
++ if(SiS_Pr->UseCustomMode) {
++ cr4 = SiS_Pr->CCRT1CRTC[4];
++ cr14 = SiS_Pr->CCRT1CRTC[14];
++ cr5 = SiS_Pr->CCRT1CRTC[5];
++ cr15 = SiS_Pr->CCRT1CRTC[15];
++ } else {
++ cr4 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
++ cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
++ cr5 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
++ cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
++ }
++ tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; /* (VGAHRS-3)*8 */
++ tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; /* (VGAHRE-3)*8 */
++ tempcx &= 0x00FF;
++ tempcx |= (tempbx & 0xFF00);
++ tempbx += 16;
++ tempcx += 16;
++ tempax = SiS_Pr->SiS_VGAHT;
++ if(modeflag & HalfDCLK) tempax >>= 1;
++ tempax--;
++ if(tempcx > tempax) tempcx = tempax;
+ }
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)){
+- tempbx = 1040;
+- tempcx = 1042;
+- }
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if(resinfo == SIS_RI_1024x768) {
++ tempbx = 1040;
++ tempcx = 1042;
++ }
++ }
+ }
+- /* TW: Makes no sense, but is in 650/302LV 1.10.6s */
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == 0x08)){
++#if 0
++ /* Makes no sense, but is in 650/30xLV 1.10.6s */
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == SIS_RI_1024x768)){
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) {
+ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+ tempbx = 1040;
+@@ -491,25 +493,26 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ }
+ }
+ }
++#endif
+ }
+
+ temp = tempbx & 0xff;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* TW: CRT2 Horizontal Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp); /* CRT2 Horizontal Retrace Start */
+ #endif /* SIS315H */
+
+- } /* 310/325/330 series */
++ } /* 315/330 series */
+
+- /* TW: The following is done for all bridge/chip types/series */
++ /* The following is done for all bridge/chip types/series */
+
+ tempax = tempbx & 0xFF00;
+ tempbx = pushbx;
+ tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
+ tempax |= (tempbx & 0xFF00);
+ temp = (tempax & 0xFF00) >> 8;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0C,temp); /* TW: Overflow */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0C,temp); /* Overflow */
+
+ temp = tempcx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0D,temp); /* TW: CRT2 Horizontal Retrace End */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0D,temp); /* CRT2 Horizontal Retrace End */
+
+ /* 2. Vertical setup */
+
+@@ -517,30 +520,30 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ temp = tempcx & 0x00FF;
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+- temp--;
+- }
+- }
+- } else {
+- temp--;
+- }
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
++ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
++ temp--;
++ }
++ }
++ } else {
++ temp--;
++ }
+ } else if(HwDeviceExtension->jChipType >= SIS_315H) {
+- /* TW: 650/30xLV 1.10.6s */
+- temp--;
++ /* 650/30xLV 1.10.6s */
++ temp--;
+ }
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0E,temp); /* TW: CRT2 Vertical Total */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0E,temp); /* CRT2 Vertical Total */
+
+ tempbx = SiS_Pr->SiS_VGAVDE - 1;
+ temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0F,temp); /* TW: CRT2 Vertical Display Enable End */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0F,temp); /* CRT2 Vertical Display Enable End */
+
+ temp = ((tempbx & 0xFF00) << 3) >> 8;
+ temp |= ((tempcx & 0xFF00) >> 8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x12,temp); /* TW: Overflow (and HWCursor Test Mode) */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x12,temp); /* Overflow (and HWCursor Test Mode) */
+
+- /* TW: 650/LVDS (1.10.07), 650/30xLV (1.10.6s) */
++ /* 650/LVDS (1.10.07), 650/30xLV (1.10.6s) */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ tempbx++;
+ tempax = tempbx;
+@@ -553,29 +556,44 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ tempcx += tempbx;
+ tempcx++;
+ } else {
+- /* TW: 300 series, LVDS/301B: */
++ /* 300 series, LVDS/301B: */
+ tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
+ tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+- tempbx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+- temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+- if(temp & 0x04) tempbx |= 0x0100;
+- if(temp & 0x80) tempbx |= 0x0200;
+- temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+- if(temp & 0x08) tempbx |= 0x0400;
+- temp = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+- tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CVSyncStart;
++ tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
++ }
++
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
++ unsigned char cr8, cr7, cr13, cr9;
++ if(SiS_Pr->UseCustomMode) {
++ cr8 = SiS_Pr->CCRT1CRTC[8];
++ cr7 = SiS_Pr->CCRT1CRTC[7];
++ cr13 = SiS_Pr->CCRT1CRTC[13];
++ cr9 = SiS_Pr->CCRT1CRTC[9];
++ } else {
++ cr8 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
++ cr7 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
++ cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
++ cr9 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
++ }
++ tempbx = cr8;
++ if(cr7 & 0x04) tempbx |= 0x0100;
++ if(cr7 & 0x80) tempbx |= 0x0200;
++ if(cr13 & 0x08) tempbx |= 0x0400;
++ tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
+ }
+ }
+ temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp); /* TW: CRT2 Vertical Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp); /* CRT2 Vertical Retrace Start */
+
+ temp = ((tempbx & 0xFF00) >> 8) << 4;
+ temp |= (tempcx & 0x000F);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x11,temp); /* TW: CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x11,temp); /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
+
+ /* 3. Panel compensation delay */
+
+@@ -590,18 +608,18 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ temp = 0x10;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) temp = 0x2c;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24;
+ }
+ if(SiS_Pr->SiS_VBType & VB_SIS301) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
+ }
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) temp = 0x2c;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x08;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) temp = 0x2c;
+ else temp = 0x20;
+ }
+- if((ROMAddr) && (SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
++ if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+ if(ROMAddr[0x220] & 0x80) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV-SetCRT2ToHiVisionTV))
+ temp = ROMAddr[0x221];
+@@ -636,19 +654,20 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ }
+ }
+
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp); /* TW: Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp); /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+
+ #endif /* SIS300 */
+
+ } else {
+
+-#ifdef SIS315H /* ----------- 310/325/330 series ---------------*/
++#ifdef SIS315H /* --------------- 315/330 series ---------------*/
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+ temp = 0x10;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) temp = 0x2c;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) temp = 0x24;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) temp = 0x2c;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ temp = 0x08;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+@@ -664,7 +683,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ }
+ }
+ }
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+ tempbl = 0x00;
+ if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+ if(HwDeviceExtension->jChipType < SIS_330) {
+@@ -689,8 +708,16 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
+ }
+ }
++
++ if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
++ temp = 0x08;
++ tempbl = 0;
++ if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
++ if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
++ }
++ }
+ }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* TW: Panel Link Delay Compensation */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp); /* Panel Link Delay Compensation */
+
+ tempax = 0;
+ if (modeflag & DoubleScanMode) tempax |= 0x80;
+@@ -705,14 +732,13 @@ SiS_SetGroup1(SiS_Private *SiS_Pr,USHORT
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+- /* TW: For 301BDH, we set up the Panel Link */
+- if( (SiS_Pr->SiS_VBType & VB_NoLCD) &&
+- (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) {
++ /* For 301BDH with LCD, we set up the Panel Link */
++ if( (SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) {
+
+ SiS_SetGroup1_LVDS(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
+ HwDeviceExtension,RefreshRateTableIndex);
+
+- } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+
+ SiS_SetGroup1_301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,
+ HwDeviceExtension,RefreshRateTableIndex);
+@@ -749,23 +775,27 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+ USHORT push1,push2;
+ USHORT tempax,tempbx,tempcx,temp;
+ USHORT resinfo,modeflag;
++ unsigned char p1_7, p1_8;
+
+ if(ModeNo <= 0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ resinfo = 0;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ }
+ }
+
+- /* TW: The following is only done if bridge is in slave mode: */
++ /* The following is only done if bridge is in slave mode: */
+
+ tempax = 0xFFFF;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- modeflag |= Charx8Dot;
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) modeflag |= Charx8Dot;
+
+ if(modeflag & Charx8Dot) tempcx = 0x08;
+ else tempcx = 0x09;
+@@ -777,8 +807,7 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+ tempax = (tempax / tempcx) - 5;
+ tempbx = tempax & 0x00FF;
+
+- temp = 0xFF; /* set MAX HT */
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,temp);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0xff); /* set MAX HT */
+
+ tempax = SiS_Pr->SiS_VGAHDE; /* 0x04 Horizontal Display End */
+ if(modeflag & HalfDCLK) tempax >>= 1;
+@@ -789,13 +818,13 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+
+ temp = (tempbx & 0xFF00) >> 8;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+- temp += 2;
+- }
+- }
++ if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
++ temp += 2;
++ }
++ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if(SiS_Pr->SiS_HiVision == 3) {
+- if(resinfo == 7) temp -= 2;
++ if(resinfo == SIS_RI_800x600) temp -= 2;
+ }
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x05,temp); /* 0x05 Horizontal Display Start */
+@@ -804,140 +833,133 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+ (SiS_Pr->SiS_HiVision == 3)) {
+- temp = (tempbx & 0x00FF) - 1;
+- if(!(modeflag & HalfDCLK)) {
+- temp -= 6;
+- if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- temp -= 2;
+- if(ModeNo > 0x13) temp -= 10;
+- }
+- }
++ temp = (tempbx & 0x00FF) - 1;
++ if(!(modeflag & HalfDCLK)) {
++ temp -= 6;
++ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
++ temp -= 2;
++ if(ModeNo > 0x13) temp -= 10;
++ }
++ }
+ } else {
+- tempcx = tempbx & 0x00FF;
+- tempbx = (tempbx & 0xFF00) >> 8;
+- tempcx = (tempcx + tempbx) >> 1;
+- temp = (tempcx & 0x00FF) + 2;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV){
+- temp--;
+- if(!(modeflag & HalfDCLK)){
+- if((modeflag & Charx8Dot)){
+- temp += 4;
+- if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
+- }
+- }
+- }
+- } else {
+- if(!(modeflag & HalfDCLK)) {
+- temp -= 4;
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) {
+- if(SiS_Pr->SiS_VGAHDE >= 800) {
+- temp -= 7;
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */
+- if(SiS_Pr->SiS_ModeType == ModeEGA) {
+- if(SiS_Pr->SiS_VGAVDE == 1024) {
+- temp += 15;
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+- temp += 7;
+- }
+- }
+- }
+- if(SiS_Pr->SiS_VGAHDE >= 1280) {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) {
+- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
+- }
+- }
+- }
+- }
+- }
+- }
++ tempcx = tempbx & 0x00FF;
++ tempbx = (tempbx & 0xFF00) >> 8;
++ tempcx = (tempcx + tempbx) >> 1;
++ temp = (tempcx & 0x00FF) + 2;
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ temp--;
++ if(!(modeflag & HalfDCLK)) {
++ if((modeflag & Charx8Dot)) {
++ temp += 4;
++ if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
++ }
++ }
++ }
++ } else {
++ if(!(modeflag & HalfDCLK)) {
++ temp -= 4;
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) {
++ if(SiS_Pr->SiS_VGAHDE >= 800) {
++ temp -= 7;
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */
++ if(SiS_Pr->SiS_ModeType == ModeEGA) {
++ if(SiS_Pr->SiS_VGAVDE == 1024) {
++ temp += 15;
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
++ temp += 7;
++ }
++ }
++ }
++ if(SiS_Pr->SiS_VGAHDE >= 1280) {
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
++ }
++ }
++ }
++ }
++ }
+ }
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,temp); /* 0x07 Horizontal Retrace Start */
+
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x00); /* 0x08 Horizontal Retrace End */
++ p1_7 = temp;
++ p1_8 = 0x00;
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- if(ModeNo <= 0x01) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2a);
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x61);
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x41);
+- }
+- } else if(SiS_Pr->SiS_ModeType == ModeText) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x54);
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x55);
+- }
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x00);
+- } else if(ModeNo <= 0x13) {
+- if(modeflag & HalfDCLK) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x30);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03);
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2f);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x02);
+- }
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x5b);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03);
+- }
+- } else if( ((HwDeviceExtension->jChipType >= SIS_315H) && (ModeNo == 0x50)) ||
+- ((HwDeviceExtension->jChipType < SIS_315H) && (resinfo == 0 || resinfo == 1)) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x30);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03);
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0x2f);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,0x03);
+- }
+- }
+-
++ if(ModeNo <= 0x01) {
++ p1_7 = 0x2a;
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) p1_8 = 0x61;
++ else p1_8 = 0x41;
++ } else if(SiS_Pr->SiS_ModeType == ModeText) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) p1_7 = 0x54;
++ else p1_7 = 0x55;
++ p1_8 = 0x00;
++ } else if(ModeNo <= 0x13) {
++ if(modeflag & HalfDCLK) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ p1_7 = 0x30;
++ p1_8 = 0x03;
++ } else {
++ p1_7 = 0x2f;
++ p1_8 = 0x02;
++ }
++ } else {
++ p1_7 = 0x5b;
++ p1_8 = 0x03;
++ }
++ } else if( ((HwDeviceExtension->jChipType >= SIS_315H) &&
++ ((ModeNo == 0x50) || (ModeNo = 0x56) || (ModeNo = 0x53))) ||
++ ((HwDeviceExtension->jChipType < SIS_315H) &&
++ (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ p1_7 = 0x30,
++ p1_8 = 0x03;
++ } else {
++ p1_7 = 0x2f;
++ p1_8 = 0x03;
++ }
++ }
+ }
+ }
++
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if(SiS_Pr->SiS_HiVision & 0x03) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0xb2);
++ p1_7 = 0xb2;
+ if(SiS_Pr->SiS_HiVision & 0x02) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,0xab);
++ p1_7 = 0xab;
+ }
+ }
+ }
+
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,p1_7); /* 0x07 Horizontal Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x08,p1_8); /* 0x08 Horizontal Retrace End */
++
++
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x03); /* 0x18 SR08 (FIFO Threshold?) */
+
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
+
+- tempbx = SiS_Pr->SiS_VGAVT;
+- push1 = tempbx;
+-
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x09,0xFF); /* 0x09 Set Max VT */
+
+ tempcx = 0x121;
+ tempbx = SiS_Pr->SiS_VGAVDE; /* 0x0E Vertical Display End */
+- if(tempbx == 357) tempbx = 350;
+- if(tempbx == 360) tempbx = 350;
+- if(tempbx == 375) tempbx = 350;
+- if(tempbx == 405) tempbx = 400;
+- if(tempbx == 420) tempbx = 400;
+- if(tempbx == 525) tempbx = 480;
++ if (tempbx == 357) tempbx = 350;
++ else if(tempbx == 360) tempbx = 350;
++ else if(tempbx == 375) tempbx = 350;
++ else if(tempbx == 405) tempbx = 400;
++ else if(tempbx == 420) tempbx = 400;
++ else if(tempbx == 525) tempbx = 480;
+ push2 = tempbx;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+- if(tempbx == 350) tempbx += 5;
+- if(tempbx == 480) tempbx += 5;
+- }
+- }
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
++ if (tempbx == 350) tempbx += 5;
++ else if(tempbx == 480) tempbx += 5;
++ }
++ }
+ }
+- tempbx--;
+- temp = tempbx & 0x00FF;
+- tempbx--;
++ tempbx -= 2;
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp); /* 0x10 vertical Blank Start */
+
+@@ -945,126 +967,91 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+ tempbx--;
+ temp = tempbx & 0x00FF;
+ #if 0
+- /* TW: Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
++ /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
+ if(xxx()) {
+ if(temp == 0xdf) temp = 0xda;
+ }
+ #endif
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0E,temp);
+
+- if(tempbx & 0x0100) {
+- tempcx |= 0x0002;
+- if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x000a;
+- }
++ if(tempbx & 0x0100) tempcx |= 0x0002;
+
+ tempax = 0x000B;
+ if(modeflag & DoubleScanMode) tempax |= 0x8000;
+
+- if(tempbx & 0x0200) {
+- tempcx |= 0x0040;
+- if(SiS_Pr->SiS_VBType & VB_SIS301) tempax |= 0x2000;
+- }
+-
+- if(SiS_Pr->SiS_VBType & VB_SIS301) {
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- if(SiS_Pr->SiS_VGAVDE == 480) {
+- tempax = (tempax & 0x00ff) | 0x2000;
+- if(modeflag & DoubleScanMode) tempax |= 0x8000;
+- }
+- }
+- }
++ if(tempbx & 0x0200) tempcx |= 0x0040;
+
+ temp = (tempax & 0xFF00) >> 8;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0B,temp);
+
+- if(tempbx & 0x0400) tempcx |= 0x0600;
++ if(tempbx & 0x0400) tempcx |= 0x0600;
+
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x11,0x00); /* 0x11 Vertical Blank End */
+
+- tempax = push1;
+- tempax -= tempbx;
+- tempax >>= 2;
+- push1 = tempax;
++ tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
+
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- /* TW: 650/30xLV 1.10.6s */
+- if(ModeNo > 0x13) {
+- if(resinfo != 0x09) { /* 1280x1024 */
+- tempax <<= 1;
+- tempbx += tempax;
+- }
+- } else {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+- tempax <<= 1;
+- tempbx += tempax;
+- }
+- }
+- } else if((resinfo != 0x09) || (SiS_Pr->SiS_VBType & VB_SIS301)) {
+- tempax <<= 1;
+- tempbx += tempax;
++ if((ModeNo > 0x13) || (HwDeviceExtension->jChipType < SIS_315H)) {
++ if(resinfo != SIS_RI_1280x1024) {
++ tempbx += (tempax << 1);
++ }
++ } else if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
++ tempbx += (tempax << 1);
++ }
+ }
+
+- if( (SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+- (SiS_Pr->SiS_HiVision == 3) ) {
+- tempbx -= 10;
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
++ (SiS_Pr->SiS_HiVision == 3)) {
++ tempbx -= 10;
+ } else {
+- if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- if(!(SiS_Pr->SiS_HiVision & 0x03)) {
+- tempbx += 40;
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
+- }
+- }
+- }
+- }
++ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
++ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
++ if(!(SiS_Pr->SiS_HiVision & 0x03)) {
++ tempbx += 40;
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
++ }
++ }
++ }
++ }
+ }
+- tempax = push1;
+ tempax >>= 2;
+ tempax++;
+ tempax += tempbx;
+ push1 = tempax;
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- if(tempbx <= 513) {
+- if(tempax >= 513) tempbx = 513;
+- }
++ if(tempbx <= 513) {
++ if(tempax >= 513) tempbx = 513;
++ }
+ }
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0C,temp); /* 0x0C Vertical Retrace Start */
+
+- if(!(SiS_Pr->SiS_VBType & VB_SIS301)) {
+- tempbx--;
+- temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp);
+-
+- if(tempbx & 0x0100) tempcx |= 0x0008;
++ tempbx--;
++ temp = tempbx & 0x00FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x10,temp);
+
+- if(tempbx & 0x0200) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
+- }
++ if(tempbx & 0x0100) tempcx |= 0x0008;
+
+- tempbx++;
++ if(tempbx & 0x0200) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
+ }
++ tempbx++;
++
+ if(tempbx & 0x0100) tempcx |= 0x0004;
+ if(tempbx & 0x0200) tempcx |= 0x0080;
+ if(tempbx & 0x0400) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
+- else tempcx |= 0x0C00;
++ if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
++ else tempcx |= 0x0C00;
+ }
+
+ tempbx = push1;
+- temp = tempbx & 0x00FF;
+- temp &= 0x0F;
++ temp = tempbx & 0x000F;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0D,temp); /* 0x0D vertical Retrace End */
+
+ if(tempbx & 0x0010) tempcx |= 0x2000;
+
+ temp = tempcx & 0x00FF;
+- if(SiS_Pr->SiS_VBType & VB_SIS301) {
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- if(SiS_Pr->SiS_VGAVDE == 480) temp = 0xa3;
+- }
+- }
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0A,temp); /* 0x0A CR07 */
+
+ temp = (tempcx & 0xFF00) >> 8;
+@@ -1074,8 +1061,8 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+ temp = (tempax & 0xFF00) >> 8;
+ temp = (temp >> 1) & 0x09;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS301)) {
+- /* Only use 8 dot clock */
+- temp |= 0x01;
++ /* Only use 8 dot clock */
++ temp |= 0x01;
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* 0x16 SR01 */
+
+@@ -1084,16 +1071,15 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, U
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x12,0x00); /* 0x12 CR17 */
+
+ if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+- if(IS_SIS650) {
+- /* TW: 650/30xLV 1.10.6s */
+- if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
+- temp = 0x80;
+- }
+- } else temp = 0x80;
+- } else temp = 0x00;
++ if(IS_SIS650) {
++ /* 650/30xLV 1.10.6s */
++ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
++ temp = 0x80;
++ }
++ } else temp = 0x80;
++ } else temp = 0x00;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* 0x1A SR0E */
+
+- return;
+ }
+
+ void
+@@ -1108,40 +1094,52 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ #endif
+ ULONG tempeax=0, tempebx, tempecx, tempvcfact=0;
+
++ /* This is not supported on LVDS */
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
++ if(SiS_Pr->UseCustomMode) return;
++
+ if(ModeNo <= 0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
+- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+
+- /* TW: Set up Panel Link */
++ /* Set up Panel Link */
+
+ /* 1. Horizontal setup */
+
+ tempax = SiS_Pr->SiS_LCDHDES;
+
+- if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) &&
+- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
+- tempax -= 8;
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
++ if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) &&
++ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
++ tempax -= 8;
++ }
+ }
+
+ tempcx = SiS_Pr->SiS_HT; /* Horiz. Total */
+
+ tempbx = SiS_Pr->SiS_HDE; /* Horiz. Display End */
+
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
++ tempbx >>= 1;
++ }
++
+ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- if((!SiS_Pr->SiS_IF_DEF_DSTN) && (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempbx = 800;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempbx = 1024; /* TW */
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 1024;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempbx = 1152; /* TW */
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempbx = 1280;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 1280;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 1400;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 1600;
++ if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
++ tempbx = SiS_Pr->PanelXRes;
++ } else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ tempbx = SiS_Pr->PanelXRes;
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
++ tempbx = 800;
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
++ tempbx = 1024;
++ }
++ }
+ }
+ }
+ }
+@@ -1154,13 +1152,18 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
+
+ push2 = tempax;
+-
+- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if((!SiS_Pr->SiS_IF_DEF_DSTN) && (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0028;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0018;
+- else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
++
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) &&
++ (!SiS_Pr->SiS_IF_DEF_DSTN) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
++ (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
++ if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0028;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0018;
++ else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) {
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+@@ -1174,11 +1177,12 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ } else {
+ tempcx = 0x0018;
+ }
++ }
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempcx = 0x0028;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0030;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040;
+ }
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempcx = 0x0028;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0030;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040;
+ }
+ }
+ }
+@@ -1188,14 +1192,18 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ tempax = tempcx >> 3; /* BPLHRS */
+ temp = tempax & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,temp); /* Part1_14h; TW: Panel Link Horizontal Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,temp); /* Part1_14h; Panel Link Horizontal Retrace Start */
+
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ temp = (tempax & 0x00FF) + 2;
+ } else {
+ temp = (tempax & 0x00FF) + 10;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(!SiS_Pr->SiS_IF_DEF_DSTN) {
++ if((!SiS_Pr->SiS_IF_DEF_DSTN) &&
++ (!SiS_Pr->SiS_IF_DEF_FSTN) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
++ (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+ temp += 6;
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
+@@ -1219,47 +1227,57 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ temp &= 0x1F;
+ temp |= ((tempcx & 0x0007) << 5);
+- if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,temp); /* Part1_15h; TW: Panel Link Horizontal Retrace End/Skew */
++#if 0
++ if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20; /* WRONG? BIOS loads cl, not ah */
++#endif
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,temp); /* Part1_15h; Panel Link Horizontal Retrace End/Skew */
+
+ tempbx = push2;
+ tempcx = push1; /* lcdhdes */
+
+ temp = (tempcx & 0x0007); /* BPLHDESKEW */
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* Part1_1Ah; TW: Panel Link Vertical Retrace Start (2:0) */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1A,temp); /* Part1_1Ah; Panel Link Vertical Retrace Start (2:0) */
+
+ tempcx >>= 3; /* BPLHDES */
+ temp = (tempcx & 0x00FF);
+- if(ModeNo == 0x5b) temp--;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* Part1_16h; TW: Panel Link Horizontal Display Enable Start */
++#if 0 /* Not 550 FSTN */
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(ModeNo == 0x5b) temp--; */
++ }
++#endif
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x16,temp); /* Part1_16h; Panel Link Horizontal Display Enable Start */
+
+- if(HwDeviceExtension->jChipType < SIS_315H) {
++ if((HwDeviceExtension->jChipType < SIS_315H) ||
++ (SiS_Pr->SiS_IF_DEF_FSTN) ||
++ (SiS_Pr->SiS_IF_DEF_DSTN)) {
+ if(tempbx & 0x07) tempbx += 8;
+ }
+ tempbx >>= 3; /* BPLHDEE */
+ temp = tempbx & 0x00FF;
+- if(ModeNo == 0x5b) temp--;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,temp); /* Part1_17h; TW: Panel Link Horizontal Display Enable End */
++#if 0 /* Not 550 FSTN */
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(ModeNo == 0x5b) temp--;
++ }
++#endif
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x17,temp); /* Part1_17h; Panel Link Horizontal Display Enable End */
+
+ /* 2. Vertical setup */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ tempcx = SiS_Pr->SiS_VGAVT;
+ tempbx = SiS_Pr->SiS_VGAVDE;
+- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempbx = 600;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempbx = 600;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempbx = 768;
+- else tempbx = 1024;
+- }
++ if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) && (SiS_Pr->SiS_CustomT != CUT_BARCO1024)) {
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ tempbx = SiS_Pr->PanelYRes;
++ }
++ }
+ }
+ tempcx -= tempbx;
+
+ } else {
+
+- tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE; /* VGAVT-VGAVDE */
++ tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE; /* VGAVT-VGAVDE */
+
+ }
+
+@@ -1268,18 +1286,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ tempax = SiS_Pr->SiS_VGAVDE;
+
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+- if( (SiS_Pr->SiS_IF_DEF_TRUMPION == 0) &&
+- (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) ) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempax = 600;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempax = 600;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempax = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempax = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempax = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempax = 1024;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempax = 1050;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempax = 1200;
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ tempax = 600;
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
++ tempax = 768;
++ }
++ }
++ } else if( (SiS_Pr->SiS_IF_DEF_TRUMPION == 0) &&
++ (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
++ ((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) ||
++ (SiS_Pr->SiS_IF_DEF_FSTN) ||
++ (SiS_Pr->SiS_IF_DEF_DSTN)) ) {
++ tempax = SiS_Pr->PanelYRes;
+ }
+ }
+
+@@ -1290,11 +1310,25 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ tempcx >>= 1;
+
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)) {
+- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+- if(!SiS_Pr->SiS_IF_DEF_DSTN) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0001;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0001;
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
++ (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
++ (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
++ tempcx = 0x0017;
++ } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
++ if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0003;
++ else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)) tempcx = 0x0003;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0001;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0001;
++ else tempcx = 0x0057;
++ } else {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0001;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0001;
+ else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)) {
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+@@ -1304,7 +1338,7 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ tempcx = 0x0003;
+ #endif
+ } else {
+- tempcx = 0x0002; /* TW: A901; sometimes 0x0003; */
++ tempcx = 0x0002; /* A901; sometimes 0x0003; */
+ }
+ } else tempcx = 0x0003;
+ }
+@@ -1319,26 +1353,33 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ tempbx += tempcx; /* BPLVRS */
+
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- tempbx++;
++ if((HwDeviceExtension->jChipType < SIS_315H) ||
++ (SiS_Pr->SiS_IF_DEF_FSTN) ||
++ (SiS_Pr->SiS_IF_DEF_DSTN)) {
++ tempbx++;
+ }
+
+ if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+
+ temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,temp); /* Part1_18h; TW: Panel Link Vertical Retrace Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,temp); /* Part1_18h; Panel Link Vertical Retrace Start */
+
+ tempcx >>= 3;
+
+- if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
++ if((!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
++ (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
++ (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if( (HwDeviceExtension->jChipType < SIS_315H) &&
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) ) tempcx = 0x0001;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) tempcx = 0x0002;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempcx = 0x0002;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) tempcx = 0x0003;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) tempcx = 0x0005;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) tempcx = 0x0005;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempcx = 0x0011;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0005;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0005;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0002;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0011;
+ else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+@@ -1360,26 +1401,37 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+
+ tempcx = tempcx + tempbx + 1; /* BPLVRE */
+ temp = tempcx & 0x000F;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; TW: Panel Link Vertical Retrace End (3:0); Misc. */
++ if(SiS_Pr->SiS_IF_DEF_FSTN ||
++ SiS_Pr->SiS_IF_DEF_DSTN ||
++ (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
++ (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
++ (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
++ temp |= 0x30;
++ }
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; Panel Link Vertical Retrace End (3:0); Misc. */
+
+ temp = ((tempbx & 0x0700) >> 8) << 3; /* BPLDESKEW =0 */
+- if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
+- if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
++ if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
++ if(SiS_Pr->SiS_HDE != 640) {
++ if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
++ }
++ } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
++ if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) temp |= 0x40;
+ if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
+- temp |= 0x80;
+- }
+- } else {
+- if( (HwDeviceExtension->jChipType == SIS_630) ||
+- (HwDeviceExtension->jChipType == SIS_730) ) {
+- if(HwDeviceExtension->jChipRevision >= 0x30) {
+- temp |= 0x80;
+- }
+- }
+- }
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
++ temp |= 0x80;
++ }
++ } else {
++ if( (HwDeviceExtension->jChipType == SIS_630) ||
++ (HwDeviceExtension->jChipType == SIS_730) ) {
++ if(HwDeviceExtension->jChipRevision >= 0x30) {
++ temp |= 0x80;
++ }
++ }
++ }
+ }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp); /* Part1_1Ah; TW: Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp); /* Part1_1Ah; Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */
+
+ if (HwDeviceExtension->jChipType < SIS_315H) {
+
+@@ -1396,19 +1448,19 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ }
+
+ temp = (USHORT)(tempebx & 0x00FF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,temp); /* Part1_1Eh; TW: Panel Link Vertical Scaling Factor */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,temp); /* Part1_1Eh; Panel Link Vertical Scaling Factor */
+
+ #endif /* SIS300 */
+
+ } else {
+
+-#ifdef SIS315H /* 310/325 series */
++#ifdef SIS315H /* 315 series */
+
+-#ifdef NEWCH701x
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x03);
+-#else
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,0x23);
+-#endif
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x03);
++ } else {
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,0x23);
++ }
+
+ tempeax = SiS_Pr->SiS_VGAVDE << 18;
+ temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
+@@ -1417,12 +1469,13 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ tempebx = tempeax; /* BPLVCFACT */
+ tempvcfact = tempeax;
+ temp = (USHORT)(tempebx & 0x00FF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x37,temp); /* Part1_37h; TW: Panel Link Vertical Scaling Factor */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x37,temp); /* Part1_37h; Panel Link Vertical Scaling Factor */
+ temp = (USHORT)((tempebx & 0x00FF00) >> 8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x36,temp); /* Part1_36h; TW: Panel Link Vertical Scaling Factor */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x36,temp); /* Part1_36h; Panel Link Vertical Scaling Factor */
+ temp = (USHORT)((tempebx & 0x00030000) >> 16);
++ temp &= 0x03;
+ if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x35,temp); /* Part1_35h; TW: Panel Link Vertical Scaling Factor */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x35,temp); /* Part1_35h; Panel Link Vertical Scaling Factor */
+
+ #endif /* SIS315H */
+
+@@ -1434,47 +1487,50 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ push1 = temp;
+
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(!SiS_Pr->SiS_IF_DEF_DSTN){
++ if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+- if(resinfo == 15) tempcx++;
++ if(resinfo == SIS_RI_1024x600) tempcx++;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- if(resinfo == 7) tempcx++;
++ if(resinfo == SIS_RI_800x600) tempcx++;
+ }
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- if(resinfo == 7) tempcx++;
+- if(resinfo == 8) tempcx++; /* TW: Doesnt make sense anyway... */
+- } else if(resinfo == 8) tempcx++;
++ if(resinfo == SIS_RI_800x600) tempcx++;
++ if(resinfo == SIS_RI_1024x768) tempcx++; /* Doesnt make sense anyway... */
++ } else if(resinfo == SIS_RI_1024x768) tempcx++;
+ } else {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- if(resinfo == 7) tempcx++;
++ if(resinfo == SIS_RI_800x600) tempcx++;
+ }
+ }
+ }
+ }
+
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+- tempcx = SiS_Pr->SiS_VGAVDE;
+- tempbx = SiS_Pr->SiS_VGAVDE - 1;
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
++ tempcx = SiS_Pr->SiS_VGAVDE;
++ tempbx = SiS_Pr->SiS_VGAVDE - 1;
++ }
+ }
+
+ temp = ((tempbx & 0x0700) >> 8) << 3;
+ temp |= ((tempcx & 0x0700) >> 8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1D,temp); /* Part1_1Dh; TW: Vertical Display Overflow; Control Signal */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1D,temp); /* Part1_1Dh; Vertical Display Overflow; Control Signal */
+
+ temp = tempbx & 0x00FF;
+- if(SiS_Pr->SiS_IF_DEF_FSTN) temp++;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1C,temp); /* Part1_1Ch; TW: Panel Link Vertical Display Enable End */
++ /* if(SiS_Pr->SiS_IF_DEF_FSTN) temp++; */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1C,temp); /* Part1_1Ch; Panel Link Vertical Display Enable End */
+
+ temp = tempcx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1B,temp); /* Part1_1Bh; TW: Panel Link Vertical Display Enable Start */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1B,temp); /* Part1_1Bh; Panel Link Vertical Display Enable Start */
+
+ /* 3. Additional horizontal setup (scaling, etc) */
+
+ tempecx = SiS_Pr->SiS_VGAHDE;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(modeflag & HalfDCLK)
+- tempecx >>= 1;
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
++ if(modeflag & HalfDCLK) tempecx >>= 1;
++ }
+ }
+ tempebx = SiS_Pr->SiS_HDE;
+ if(tempecx == tempebx) tempeax = 0xFFFF;
+@@ -1484,139 +1540,165 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr,U
+ temp = (USHORT)(tempeax % tempebx);
+ tempeax = tempeax / tempebx;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(temp) tempeax++;
++ if(temp) tempeax++;
+ }
+ }
+ tempecx = tempeax;
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- tempeax = SiS_Pr->SiS_VGAHDE;
+- if(modeflag & HalfDCLK) tempeax >>= 1;
+- tempeax <<= 16;
+- tempeax = (tempeax / tempecx) - 1;
++ tempeax = SiS_Pr->SiS_VGAHDE;
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
++ if(modeflag & HalfDCLK) tempeax >>= 1;
++ }
++ tempeax <<= 16;
++ tempeax = (tempeax / tempecx) - 1;
+ } else {
+- tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
++ tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
+ }
+ tempecx <<= 16;
+ tempecx |= (tempeax & 0xFFFF);
+ temp = (USHORT)(tempecx & 0x00FF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1F,temp); /* Part1_1Fh; TW: Panel Link DDA Operational Number in each horiz. line */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1F,temp); /* Part1_1Fh; Panel Link DDA Operational Number in each horiz. line */
+
+ tempbx = SiS_Pr->SiS_VDE;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
+- tempbx = (USHORT)(tempeax & 0x0FFFF);
++ tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
++ tempbx = (USHORT)(tempeax & 0x0FFFF);
+ } else {
+- tempax = SiS_Pr->SiS_VGAVDE << 6;
+- tempbx = push1;
+- tempbx &= 0x3f;
+- if(tempbx == 0) tempbx = 64;
+- tempax = tempax / tempbx;
+- tempbx = tempax;
++ tempeax = SiS_Pr->SiS_VGAVDE << 6;
++ tempbx = push1 & 0x3f;
++ if(tempbx == 0) tempbx = 64;
++ tempeax /= tempbx;
++ tempbx = (USHORT)(tempeax & 0x0FFFF);
+ }
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
+- if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempbx = 1;
++ if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
++ if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
++ else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempbx = 1;
++ }
+
+ temp = ((tempbx & 0xFF00) >> 8) << 3;
+ temp |= (USHORT)((tempecx & 0x0700) >> 8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x20,temp); /* Part1_20h; TW: Overflow register */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x20,temp); /* Part1_20h; Overflow register */
+
+ temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x21,temp); /* Part1_21h; TW: Panel Link Vertical Accumulator Register */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x21,temp); /* Part1_21h; Panel Link Vertical Accumulator Register */
+
+ tempecx >>= 16; /* BPLHCFACT */
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(modeflag & HalfDCLK) tempecx >>= 1;
++ if((HwDeviceExtension->jChipType < SIS_315H) || (SiS_Pr->SiS_IF_DEF_FSTN) || (SiS_Pr->SiS_IF_DEF_DSTN)) {
++ if(modeflag & HalfDCLK) tempecx >>= 1;
+ }
+ temp = (USHORT)((tempecx & 0xFF00) >> 8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x22,temp); /* Part1_22h; TW: Panel Link Horizontal Scaling Factor High */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x22,temp); /* Part1_22h; Panel Link Horizontal Scaling Factor High */
+
+ temp = (USHORT)(tempecx & 0x00FF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x23,temp); /* Part1_22h; TW: Panel Link Horizontal Scaling Factor Low */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x23,temp); /* Part1_22h; Panel Link Horizontal Scaling Factor Low */
+
+ /* 630/301B and 630/LVDS do something for 640x480 panels here */
+
+ #ifdef SIS315H
+- /* TW: DSTN/FSTN initialisation - hardcoded for 320x480 panel */
+- if(SiS_Pr->SiS_IF_DEF_DSTN) {
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1E,0x01);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x25,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x26,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x27,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x28,0x87);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x29,0x5A);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03);
+- tempbx = SiS_Pr->SiS_HDE + 64; /*Blps = lcdhdee(lcdhdes+HDE) + 64*/
+- temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x38,temp);
+- temp=((tempbx & 0xFF00) >> 8) << 3;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
+- tempbx += 32; /*Blpe=lBlps+32*/
+- temp = tempbx & 0x00FF;
+- if(SiS_Pr->SiS_IF_DEF_FSTN) temp=0;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x39,temp);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3A,0x00); /*Bflml=0*/
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
+- tempbx = SiS_Pr->SiS_VDE / 2;
+- temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3B,temp);
+- temp = ((tempbx & 0xFF00) >> 8) << 3;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
+- tempeax = SiS_Pr->SiS_HDE << 2; /* BDxFIFOSTOP = (HDE*4)/128 */
+- tempebx = 128;
+- temp = (USHORT)(tempeax % tempebx);
+- tempeax = tempeax / tempebx;
+- if(temp != 0) tempeax++;
+- temp = (USHORT)(tempeax & 0x003F);
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3E,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3D,0x10);
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
+- tempax = SiS_Pr->SiS_HDE >> 4; /* BDxWadroff = HDE*4/8/8 */
+- pushcx = tempax;
+- temp = tempax & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x43,temp);
+- temp = ((tempax & 0xFF00) >> 8) << 3;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
+- tempax = SiS_Pr->SiS_VDE; /*BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
+- tempeax = (tempax * pushcx);
+- tempebx = 0x00100000 + tempeax;
+- temp = (USHORT)tempebx & 0x000000FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x42,temp);
+- temp = (USHORT)((tempebx & 0x0000FF00)>>8);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x41,temp);
+- temp = (USHORT)((tempebx & 0x00FF0000)>>16);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x40,temp);
+- temp = (USHORT)(((tempebx & 0x01000000)>>24) << 7);
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x03);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0x50);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x04,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x01);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x13,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86); /* Unlock */
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1e,0x62);
+- if(SiS_Pr->SiS_IF_DEF_FSTN){
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2b,0x1b);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2c,0xe3);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1e,0x62);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2e,0x04);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x2f,0x42);
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,0x01);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2b,0x02);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2c,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x00);
+- }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,0x30);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1e,0x7d);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2e,0xe0);
++ if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x25,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x26,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x27,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x28,0x87);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x29,0x5A);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03);
++ tempax = SiS_Pr->SiS_HDE; /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
++ tempax += 64;
++ temp = tempax & 0x00FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x38,temp);
++ temp = ((tempax & 0xFF00) >> 8) << 3;
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
++ tempax += 32; /* Blpe=lBlps+32 */
++ temp = tempax & 0x00FF;
++ if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x39,temp);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3A,0x00); /* Bflml=0 */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
++
++ tempax = SiS_Pr->SiS_VDE;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
++ tempax >>= 1;
++ temp = tempax & 0x00FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3B,temp);
++ temp = ((tempax & 0xFF00) >> 8) << 3;
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
++
++ tempeax = SiS_Pr->SiS_HDE;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempeax >>= 1;
++ tempeax <<= 2; /* BDxFIFOSTOP = (HDE*4)/128 */
++ tempebx = 128;
++ temp = (USHORT)(tempeax % tempebx);
++ tempeax = tempeax / tempebx;
++ if(temp) tempeax++;
++ temp = (USHORT)(tempeax & 0x003F);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3F,0x00); /* BDxWadrst0 */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3E,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3D,0x10);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
++
++ tempax = SiS_Pr->SiS_HDE;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
++ tempax >>= 4; /* BDxWadroff = HDE*4/8/8 */
++ pushcx = tempax;
++ temp = tempax & 0x00FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x43,temp);
++ temp = ((tempax & 0xFF00) >> 8) << 3;
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
++
++ tempax = SiS_Pr->SiS_VDE; /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
++ tempeax = (tempax * pushcx);
++ tempebx = 0x00100000 + tempeax;
++ temp = (USHORT)tempebx & 0x000000FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x42,temp);
++ temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x41,temp);
++ temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x40,temp);
++ temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
++
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x03);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0x50);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x04,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2F,0x01);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x19,0x38);
++
++ if(SiS_Pr->SiS_IF_DEF_FSTN) {
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2b,0x02);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2c,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x35,0x0c);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x36,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x37,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x38,0x80);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x39,0xA0);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3a,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3b,0xf0);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3c,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3d,0x10);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3e,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x3f,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x40,0x10);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x41,0x25);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x42,0x80);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x43,0x14);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x44,0x03);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x45,0x0a);
++ }
+ }
+ #endif /* SIS315H */
+
+- return;
+-
+ }
+
+ #ifdef SIS315H
+@@ -1629,7 +1711,7 @@ SiS_CRT2AutoThreshold(SiS_Private *SiS_P
+
+
+ #ifdef SIS315H
+-/* TW: For LVDS / 302B/30xLV - LCDA (this must only be called on 310/325 series!) */
++/* For LVDS / 302B/30xLV - LCDA (this must only be called on 315 series!) */
+ void
+ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex)
+@@ -1638,6 +1720,10 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ USHORT push1,push2,tempax,tempbx,tempcx,temp;
+ ULONG tempeax=0,tempebx,tempecx,tempvcfact;
+
++ /* This is not supported with LCDA */
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
++ if(SiS_Pr->UseCustomMode) return;
++
+ if(IS_SIS330) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); /* Xabre 1.01.03 */
+ } else if(IS_SIS740) {
+@@ -1645,7 +1731,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04); /* 740/LVDS */
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
+ } else {
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); /* 740/301LV 1.10.1i */
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10); /* 740/301LV, 301BDH */
+ }
+ } else {
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 650/LVDS */
+@@ -1669,10 +1755,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ tempcx = SiS_Pr->SiS_HT;
+
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 1024;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 1400;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 1600;
+- else tempbx = 1280;
++ tempbx = SiS_Pr->PanelXRes;
+ }
+ tempcx -= tempbx; /* HT-HDE */
+ push1 = tempax;
+@@ -1684,7 +1767,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+
+ tempcx >>= 2;
+
+- /* TW: 650/30xLV 1.10.6s, 740/LVDS */
++ /* 650/30xLV 1.10.6s, 740/LVDS */
+ if( ((SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
+ ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+@@ -1748,13 +1831,10 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ tempbx = SiS_Pr->SiS_LCDVDES; /* VGAVDES */
+ push1 = tempbx;
+ if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempax = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) tempax = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempax = 1024;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempax = 1050;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempax = 1200;
+- else tempax = 960;
+- } else tempax = SiS_Pr->SiS_VGAVDE; /* Trumpion */
++ tempax = SiS_Pr->PanelYRes;
++ } else {
++ tempax = SiS_Pr->SiS_VGAVDE;
++ }
+
+ tempbx += tempax;
+ tempax = SiS_Pr->SiS_VT; /* VT */
+@@ -1764,7 +1844,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+
+ tempcx >>= 2;
+
+- /* TW: 650/30xLV 1.10.6s, 740/LVDS */
++ /* 650/30xLV 1.10.6s, 740/LVDS */
+ if( ((SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
+ ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+@@ -1806,7 +1886,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);
+ } else {
+- /* TW: 650/30xLV 1.10.6s, Xabre */
++ /* 650/30xLV 1.10.6s, Xabre */
+ temp |= 0xC0;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); /* Part1_19h */
+ }
+@@ -1823,7 +1903,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ }
+ } else {
+ if(IS_SIS650) {
+- /* TW: 650/30xLV 1.10.6s */
++ /* 650/30xLV 1.10.6s */
+ if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
+ }
+@@ -1839,7 +1919,7 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- if(resinfo == 7) tempcx++;
++ if(resinfo == SIS_RI_800x600) tempcx++;
+ }
+ }
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+@@ -1925,18 +2005,17 @@ SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr,
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x23,temp);
+
+ #if 0
+- /* TW: Missing code (calles int 2f) (650/302LV 1.10.6s; 1.10.7w doesn't do this) */
++ /* Missing code (calles int 2f) (650/302LV 1.10.6s; 1.10.7w doesn't do this) */
+ if(xxx()) {
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x0e,0xda);
+ }
+ #endif
+
+- /* TW: Only for LVDS and 301LV/302LV */
++ /* Only for LVDS and 301LV/302LV */
+ if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)){
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1e,0x20);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+ }
+
+- return;
+ }
+ #endif /* SIS 315 */
+
+@@ -1951,10 +2030,10 @@ void SiS_SetCRT2Offset(SiS_Private *SiS_
+
+ offset = SiS_GetOffset(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ HwDeviceExtension);
+-#if 0
+- if(SiS_Pr->LCDResInfo == 13) offset >>= 1;
+- if(SiS_Pr->LCDResInfo == 12) offset >>= 1;
+-#endif
++
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) offset >>= 1;
++
+ temp = (UCHAR)(offset & 0xFF);
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x07,temp);
+ temp = (UCHAR)((offset & 0xFF00) >> 8);
+@@ -1976,13 +2055,7 @@ SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR
+ } else {
+ infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+ modeinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+-
+- if(HwDeviceExtension->jChipType < SIS_315H ) {
+- index = (modeinfo >> 4) & 0xFF;
+- } else {
+- index = (modeinfo >> 8) & 0xFF;
+- }
+-
++ index = (modeinfo >> 8) & 0xFF;
+ temp = SiS_Pr->SiS_ScreenOffset[index];
+ }
+
+@@ -1992,9 +2065,8 @@ SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR
+
+ temp *= colordepth;
+
+- /* TW: For 1400x1050 and 856x480 */
+- if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) ||
+- ModeNo == 0x3f ||
++ if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) ||
++ ModeNo == 0x3f ||
+ ModeNo == 0x42 ||
+ ModeNo == 0x45 ) ||
+ (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) {
+@@ -2012,7 +2084,8 @@ SiS_GetColorDepth(SiS_Private *SiS_Pr, U
+ SHORT index;
+ USHORT modeflag;
+
+- if(SiS_Pr->UseCustomMode) {
++ /* Do NOT check UseCustomMode, will skrew up FIFO */
++ if(ModeNo == 0xfe) {
+ modeflag = SiS_Pr->CModeFlag;
+ } else {
+ if(ModeNo <= 0x13)
+@@ -2035,7 +2108,11 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+ flag = 0;
+ tempbl = 0xC0;
+
+- infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
++ if(SiS_Pr->UseCustomMode) {
++ infoflag = SiS_Pr->CInfoFlag;
++ } else {
++ infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
++ }
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* LVDS */
+
+@@ -2044,12 +2121,19 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+ } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
+ tempah = SiS_Pr->SiS_LCDInfo;
+ } else tempah = infoflag >> 8;
+-
++
+ tempah &= 0xC0;
+-
++
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
++ (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
++ tempah |= 0xc0;
++ }
++ }
++
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ tempah >>= 3;
+@@ -2079,9 +2163,11 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+
++#if 0
+ if (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+- /* TW: BIOS does something here @@@ */
++ /* BIOS does something here @@@ */
+ }
++#endif
+
+ tempah &= 0x3f;
+ tempah |= tempbl;
+@@ -2089,16 +2175,11 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+
+ } else { /* 630 - 301 */
+
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- tempah = SiS_Pr->SiS_LCDInfo;
+- if(SiS_Pr->SiS_LCDInfo & DontExpandLCDShift) { /* ! */
+- flag = 1;
+- }
+- }
+- if(flag != 1) tempah = infoflag >> 8;
++ tempah = infoflag >> 8;
+ tempah &= 0xC0;
+- tempah |= 0x30;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x3F,tempah);
++ tempah |= 0x20;
++ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+
+ }
+
+@@ -2106,34 +2187,50 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+
+ } else {
+
+-#ifdef SIS315H /* ----- 310/325 series ---- */
++#ifdef SIS315H /* ------- 315 series ------ */
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 310/325 - 30xLV */
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 315 - 30xLV */
++
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ tempah = infoflag >> 8;
++ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
++ tempah = SiS_Pr->SiS_LCDInfo;
++ }
++ } else {
++ tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37);
++ }
++ tempah &= 0xC0;
+
+- tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37);
+- tempah &= 0xC0;
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+
+- } else { /* 310/325 - 301, 301B */
++ } else { /* 315 - 301, 301B */
+
+ tempah = infoflag >> 8;
+- tempah &= 0xC0;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+- tempah = SiS_Pr->SiS_LCDInfo;
+- tempah &= 0xC0;
++ if(!SiS_Pr->UseCustomMode) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
++ tempah = SiS_Pr->SiS_LCDInfo;
++ }
+ }
+ }
++ tempah &= 0xC0;
+
+ tempah |= 0x20;
+ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
++
+ #if 0
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+- /* TW: BIOS does something here @@@ */
++ /* BIOS does something here @@@ */
+ }
+-#endif
++#endif
++
++ if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* TEST, imitate BIOS bug */
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ tempah |= 0xc0;
++ }
++ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+
+ }
+@@ -2143,7 +2240,7 @@ SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USH
+ }
+ }
+
+-/* TW: Set CRT2 FIFO on 300/630/730 */
++/* Set CRT2 FIFO on 300/630/730 */
+ #ifdef SIS300
+ void
+ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,
+@@ -2197,7 +2294,7 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+
+ if(!SiS_Pr->CRT1UsesCustomMode) {
+
+- CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
++ CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
+ SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT1ModeNo,&modeidindex);
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+ SiS_Pr->SiS_SelectCRT2Rate = 0;
+@@ -2205,20 +2302,32 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ modeidindex,HwDeviceExtension);
+
+ if(CRT1ModeNo >= 0x13) {
+- index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
+- index &= 0x3F;
+- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+- data2 = SiS_Pr->SiS_ModeType - 2;
++ index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
++ index &= 0x3F;
++ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
++
++ colorth = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT1ModeNo,modeidindex); /* Get colordepth */
++ colorth >>= 1;
++ if(!colorth) colorth++;
+ }
+-
++
+ } else {
+
+ CRT1ModeNo = 0xfe;
+- VCLK = SiS_Pr->CSRClock; /* Get VCLK */
+- data2 = (SiS_Pr->CModeFlag & ModeInfoFlag) - 2;
+-
+- }
+-
++ VCLK = SiS_Pr->CSRClock_CRT1; /* Get VCLK */
++ data2 = (SiS_Pr->CModeFlag_CRT1 & ModeInfoFlag) - 2;
++ switch(data2) { /* Get color depth */
++ case 0 : colorth = 1; break;
++ case 1 : colorth = 1; break;
++ case 2 : colorth = 2; break;
++ case 3 : colorth = 2; break;
++ case 4 : colorth = 3; break;
++ case 5 : colorth = 4; break;
++ default: colorth = 2;
++ }
++
++ }
++
+ if(CRT1ModeNo >= 0x13) {
+ if(HwDeviceExtension->jChipType == SIS_300) {
+ index = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A);
+@@ -2227,22 +2336,8 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ }
+ index &= 0x07;
+ MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK; /* Get MCLK */
+-
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: CRT1Mode 0x%x VCLK %d MCLK %d modetype-2 = %d\n",
+- CRT1ModeNo, VCLK, MCLK, data2);
+-#endif
+-
+- switch(data2) { /* Get color depth */
+- case 0 : colorth = 1; break;
+- case 1 : colorth = 1; break;
+- case 2 : colorth = 2; break;
+- case 3 : colorth = 2; break;
+- case 4 : colorth = 3; break;
+- case 5 : colorth = 4; break;
+- default: colorth = 2; break;
+- }
+- data2 = (colorth * VCLK) / MCLK;
++
++ data2 = (colorth * VCLK) / MCLK;
+
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14);
+ temp = ((temp & 0x00FF) >> 6) << 1;
+@@ -2252,22 +2347,12 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+
+ data2 = temp - data2;
+
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: data2 (step1) = %d\n",
+- data2);
+-#endif
+-
+ if((28 * 16) % data2) {
+ data2 = (28 * 16) / data2;
+ data2++;
+ } else {
+ data2 = (28 * 16) / data2;
+ }
+-
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: data2 (step2) = %d\n",
+- data2);
+-#endif
+
+ if(HwDeviceExtension->jChipType == SIS_300) {
+
+@@ -2313,10 +2398,6 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ temp &= 0x0F;
+ tempal |= temp;
+
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: Latencyfactorindex = 0x%x\n", tempal);
+-#endif
+-
+ tempbx = tempal; /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
+ tempbx = 0; /* -- do it like the BIOS anyway... */
+ tempax = tempbx;
+@@ -2341,7 +2422,7 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ SiS_SetReg4(0xcf8,0x800000A0);
+ eax = SiS_GetReg3(0xcfc);
+ #else
+- /* TW: We use pci functions X offers. We use tag 0, because
++ /* We use pci functions X offers. We use tag 0, because
+ * we want to read/write to the host bridge (which is always
+ * 00:00.0 on 630, 730 and 540), not the VGA device.
+ */
+@@ -2368,43 +2449,41 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ if(!(temp & 0x80)) data += 5;
+ }
+
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: latencyfactor (CRT1) = %d\n", data);
+-#endif
+-
+ data += data2; /* CRT1 Request Period */
+
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: CRT1 request period = %d\n", data);
+-#endif
+-
+- CRT2ModeNo = ModeNo;
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+- SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&modeidindex);
+
+- refreshratetableindex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo,
+- modeidindex,HwDeviceExtension);
++ if(!SiS_Pr->UseCustomMode) {
++
++ CRT2ModeNo = ModeNo;
++ SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&modeidindex);
++
++ refreshratetableindex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo,
++ modeidindex,HwDeviceExtension);
++
++ index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,modeidindex,
++ refreshratetableindex,HwDeviceExtension);
++ VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
++
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
++ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
++ if(ROMAddr[0x220] & 0x01) {
++ VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
++ }
++ }
++ }
++
++ } else {
++
++ CRT2ModeNo = 0xfe;
++ VCLK = SiS_Pr->CSRClock; /* Get VCLK */
+
+- index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,modeidindex,
+- refreshratetableindex,HwDeviceExtension);
+- VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+-
+- data2 = SiS_Pr->SiS_ModeType - 2;
+- switch(data2) { /* Get color depth */
+- case 0 : colorth = 1; break;
+- case 1 : colorth = 1; break;
+- case 2 : colorth = 2; break;
+- case 3 : colorth = 2; break;
+- case 4 : colorth = 3; break;
+- case 5 : colorth = 4; break;
+- default: colorth = 2; break;
+ }
+-
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: CRT2Mode 0x%x VCLK %d MCLK %d modetype-2 = %d, colorth %d\n",
+- CRT2ModeNo, VCLK, MCLK, data2, colorth);
+-#endif
++
++ colorth = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT2ModeNo,modeidindex); /* Get colordepth */
++ colorth >>= 1;
++ if(!colorth) colorth++;
+
+ data = data * VCLK * colorth;
+ if(data % (MCLK << 4)) {
+@@ -2414,10 +2493,6 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ data = data / (MCLK << 4);
+ }
+
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "FIFO2: data (unclipped) = 0x%x\n", data);
+-#endif
+-
+ if(data <= 6) data = 6;
+ if(data > 0x14) data = 0x14;
+
+@@ -2456,13 +2531,13 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
+ }
+ #endif
+
+-/* TW: Set FIFO on 310/325/330 series */
++/* Set FIFO on 315/330 series */
+ #ifdef SIS315H
+ void
+ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+-
++#if 0 /* This code is obsolete */
+ UCHAR CombCode[] = { 1, 1, 1, 4, 3, 1, 3, 4,
+ 4, 1, 4, 4, 5, 1, 5, 4};
+ UCHAR CRT2ThLow[] = { 39, 63, 55, 79, 78,102, 90,114,
+@@ -2474,11 +2549,13 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr,
+ USHORT ModeIdIndex;
+ USHORT RefreshRateTableIndex;
+ USHORT SelectRate_backup;
+-
++
+ SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
+-
++#endif
++
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x01,0x3B);
+
++#if 0
+ if(!SiS_Pr->CRT1UsesCustomMode) {
+
+ CRT1ModeNo = SiS_Pr->SiS_CRT1Mode; /* get CRT1 ModeNo */
+@@ -2489,28 +2566,27 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr,
+
+ /* Get REFIndex for crt1 refreshrate */
+ RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT1ModeNo,
+- ModeIdIndex,HwDeviceExtension);
++ ModeIdIndex,HwDeviceExtension);
++ index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
++ tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+
+- index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT1ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,HwDeviceExtension);
+- tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+-
+ tempbx = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT1ModeNo,ModeIdIndex); /* Get colordepth */
+ tempbx >>= 1;
+- if(!tempbx) tempbx++;
+-
++ if(!tempbx) tempbx++;
++
+ } else {
+-
+- tempax = SiS_Pr->CSRClock; /* Get VCLK */
+- tempbx = (SiS_Pr->CModeFlag & ModeInfoFlag) - 2;
++
++ CRT1ModeNo = 0xfe;
++ tempax = SiS_Pr->CSRClock_CRT1; /* Get VCLK */
++ tempbx = (SiS_Pr->CModeFlag_CRT1 & ModeInfoFlag) - 2;
+ switch(tempbx) { /* Get color depth */
+- case 0 : tempbx = 1; break;
+- case 1 : tempbx = 1; break;
+- case 2 : tempbx = 2; break;
+- case 3 : tempbx = 2; break;
+- case 4 : tempbx = 3; break;
+- case 5 : tempbx = 4; break;
+- default: tempbx = 2; break;
++ case 0 : tempbx = 1; break;
++ case 1 : tempbx = 1; break;
++ case 2 : tempbx = 2; break;
++ case 3 : tempbx = 2; break;
++ case 4 : tempbx = 3; break;
++ case 5 : tempbx = 4; break;
++ default: tempbx = 2;
+ }
+
+ }
+@@ -2523,13 +2599,6 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr,
+
+ tempbx = tempax;
+
+-#if 0 /* TW: BIOS code is skrewed */
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x02) {
+- tempax = 16;
+- } else {
+- tempax = 8;
+- }
+-#endif
+ tempax = 16;
+
+ tempax -= tempbx;
+@@ -2556,24 +2625,33 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr,
+
+ tempcx += temp3; /* CRT1 Request Period */
+
+- CRT2ModeNo = ModeNo; /* get CRT2 ModeNo */
+- SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&ModeIdIndex); /* Get ModeID Table */
+-
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+
+- RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo,
+- ModeIdIndex,HwDeviceExtension);
++ if(!SiS_Pr->UseCustomMode) {
++
++ CRT2ModeNo = ModeNo; /* get CRT2 ModeNo */
++ SiS_SearchModeID(SiS_Pr,ROMAddr,&CRT2ModeNo,&ModeIdIndex);
++
++ RefreshRateTableIndex = SiS_GetRatePtrCRT2(SiS_Pr,ROMAddr,CRT2ModeNo,
++ ModeIdIndex,HwDeviceExtension);
++
++ index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex,
++ RefreshRateTableIndex,HwDeviceExtension);
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
++ tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
++ } else {
++ tempax = SiS_Pr->SiS_VBVCLKData[index].CLOCK;
++ }
+
+- index = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,HwDeviceExtension);
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+- tempax = SiS_Pr->SiS_VCLKData[index].CLOCK; /* Get VCLK */
+ } else {
+- tempax = SiS_Pr->SiS_VBVCLKData[index].CLOCK; /* Get VCLK */
++
++ CRT2ModeNo = 0xfe; /* Get VCLK */
++ tempax = SiS_Pr->CSRClock;
++
+ }
+
+- tempbx = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex); /* Get colordepth */
++ tempbx = SiS_GetColorDepth(SiS_Pr,ROMAddr,CRT2ModeNo,ModeIdIndex); /* Get colordepth */
+ tempbx >>= 1;
+ if(!tempbx) tempbx++;
+
+@@ -2590,12 +2668,16 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr,
+
+ if (tempax > 0x37) tempax = 0x37;
+
+- /* TW: 650/LVDS (1.10.07, 1.10.00), 650/301LV, 740, 330 overrule calculated value; 315 does not */
++ /* 650/LVDS, 650/301LV, 740, 330 overrule calculated value; 315 does not */
+ if(HwDeviceExtension->jChipType >= SIS_650) {
+ tempax = 0x04;
+ }
+-
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,tempax);
++#else
++
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,0x04);
++
++#endif
+ }
+
+ USHORT
+@@ -2611,9 +2693,10 @@ SiS_GetMCLK(SiS_Private *SiS_Pr, UCHAR *
+ return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+ }
+ }
++
+ #endif
+
+-/* TW: Checked against 650/LVDS 1.10.07 BIOS */
++/* Checked against 650/LVDS 1.10.07 BIOS */
+ void
+ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,
+@@ -2623,7 +2706,15 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr,
+ USHORT PanelIndex,ResIndex;
+ const SiS_LVDSDesStruct *PanelDesPtr = NULL;
+
+- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ) {
++ if((SiS_Pr->UseCustomMode) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) ||
++ (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
++ SiS_Pr->SiS_LCDHDES = 0;
++ SiS_Pr->SiS_LCDVDES = 0;
++ return;
++ }
++
++ if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+
+ #ifdef SIS315H
+ SiS_GetLVDSDesPtrA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+@@ -2689,11 +2780,11 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr,
+ case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData; break;
+ case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData; break;
+ default:
+- if(HwDeviceExtension->jChipType < SIS_315H)
+- PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;
+- else
+- PanelDesPtr = SiS_Pr->SiS_PanelType01_1;
+- break;
++ if(HwDeviceExtension->jChipType < SIS_315H)
++ PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;
++ else
++ PanelDesPtr = SiS_Pr->SiS_PanelType01_1;
++ break;
+ }
+ }
+ SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+@@ -2710,7 +2801,7 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr,
+ } else {
+ if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+ if( (HwDeviceExtension->jChipType < SIS_315H) ||
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) ) {
++ (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) ) {
+ if(SiS_Pr->SiS_LCDResInfo >= SiS_Pr->SiS_Panel1024x768){
+ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+@@ -2737,7 +2828,7 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr,
+ }
+ }
+ }
+- return;
++
+ }
+
+ void
+@@ -2757,11 +2848,11 @@ SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, U
+
+ tempbx = 0;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ tempbx = 50;
+ if((SiS_Pr->SiS_VBInfo & SetPALTV) && (!SiS_Pr->SiS_CHPALM)) tempbx += 2;
+ if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
+- /* TW: Nothing special needed for SOverscan */
++ /* Nothing special needed for SOverscan */
+ /* PALM uses NTSC data, PALN uses PAL data */
+ }
+ }
+@@ -2773,7 +2864,7 @@ SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, U
+ if(modeflag & HalfDCLK) tempbx++;
+ }
+ }
+- /* TW: 630/LVDS and 650/LVDS (1.10.07) BIOS */
++ /* 630/LVDS and 650/LVDS (1.10.07) BIOS */
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+ tempal = 0x07;
+@@ -2833,14 +2924,13 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ }
+ }
+
+- /* TW: BIOS does not do this (neither 301 nor LVDS) */
++ /* BIOS does not do this (neither 301 nor LVDS) */
+ /* (But it's harmless; see SetCRT2Offset) */
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x03,0x00); /* fix write part1 index 0 BTDRAM bit Bug */
+
+- /* TW: Removed 301B302B301LV302LV check here to match 650/LVDS BIOS */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+
+- /* TW: 1. for LVDS/302B/302LV **LCDA** */
++ /* 1. for LVDS/302B/302LV **LCDA** */
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xAF,0x40); /* FUNCTION CONTROL */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2E,0xF7);
+@@ -2855,23 +2945,23 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ #ifdef SIS300 /* ---- 300 series ---- */
+
+- /* For 301BDH: */
++ /* For 301BDH: (with LCD via LVDS) */
+ if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32);
+- temp &= 0xef;
+- temp |= 0x02;
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+- temp |= 0x10;
+- temp &= 0xfd;
+- }
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32);
++ temp &= 0xef;
++ temp |= 0x02;
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
++ temp |= 0x10;
++ temp &= 0xfd;
++ }
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
+ }
+
+ if(ModeNo > 0x13) {
+- tempcl -= ModeVGA;
+- if((tempcl > 0) || (tempcl == 0)) { /* TW: tempcl is USHORT -> always true! */
+- tempah = ((0x10 >> tempcl) | 0x80);
+- }
++ tempcl -= ModeVGA;
++ if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
++ tempah = ((0x10 >> tempcl) | 0x80);
++ }
+ } else tempah = 0x80;
+
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0xA0;
+@@ -2880,7 +2970,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ } else {
+
+-#ifdef SIS315H /* ---- 310/325/330 series ---- */
++#ifdef SIS315H /* ------- 315/330 series ------ */
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBInfo & CRT2DisplayFlag) {
+@@ -2889,12 +2979,12 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ }
+
+ if(ModeNo > 0x13) {
+- tempcl -= ModeVGA;
+- if((tempcl > 0) || (tempcl == 0)) { /* TW: tempcl is USHORT -> always true! */
+- tempah = (0x08 >> tempcl);
+- if (tempah == 0) tempah = 1;
+- tempah |= 0x40;
+- }
++ tempcl -= ModeVGA;
++ if((tempcl > 0) || (tempcl == 0)) { /* tempcl is USHORT -> always true! */
++ tempah = (0x08 >> tempcl);
++ if (tempah == 0) tempah = 1;
++ tempah |= 0x40;
++ }
+ } else tempah = 0x40;
+
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
+@@ -2921,7 +3011,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+- /* TW: 2. for 301 (301B, 302B 301LV, 302LV non-LCDA) */
++ /* 2. for 301 (301B, 302B 301LV, 302LV non-LCDA) */
+
+ tempah = 0x01;
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+@@ -2938,7 +3028,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+
+- /* --- 300 series --- */
++ /* ---- 300 series ---- */
+
+ tempah = (tempah << 5) & 0xFF;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x01,tempah);
+@@ -2946,7 +3036,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ } else {
+
+- /* --- 310 series --- */
++ /* ---- 315 series ---- */
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
+
+@@ -2956,9 +3046,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ tempah |= 0x10;
+ }
+
+- /* TW: 630/301 BIOS */
+ if((HwDeviceExtension->jChipType < SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301)) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) {
+ tempah |= 0x80;
+ }
+ } else {
+@@ -2996,28 +3086,31 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ }
+ }
+ }
+- /* TW: For 302LV dual-channel */
++
++ /* For 302LV dual-channel */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04)
+- tempah |= 0x40;
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04)
++ tempah |= 0x40;
++ }
+ }
+
+ if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
+- (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) {
+- tempah |= 0x80;
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) ||
++ ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) &&
++ (SiS_Pr->CP_MaxX >= 1280) && (SiS_Pr->CP_MaxY >= 960))) {
++ tempah |= 0x80;
+ }
+
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0C,tempah);
+
+ } else {
+
+- /* TW: 3. for LVDS */
++ /* 3. for LVDS */
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+
+- /* TW: Inserted this entire section (BIOS 650/LVDS); added ModeType check
++ /* Inserted this entire section (BIOS 650/LVDS); added ModeType check
+ * (LVDS can only be slave in 8bpp modes)
+ */
+ tempah = 0x80;
+@@ -3043,7 +3136,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ } else {
+
+- /* TW: (added ModeType check) */
++ /* (added ModeType check) */
+ tempah = 0;
+ if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
+ tempah |= 0x02;
+@@ -3060,50 +3153,69 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+
+ }
+
+- /* TW: Inserted the entire following section */
++ /* Inserted the entire following section */
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+
+ #ifdef SIS315H
++
++ unsigned char bridgerev = SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x01);;
++
++ /* The following is nearly unpreditable and varies from machine
++ * to machine. Especially the 301DH seems to be a real trouble
++ * maker. Some BIOSes simply set the registers (like in the
++ * NoLCD-if-statements here), some set them according to the
++ * LCDA stuff. It is very likely that some machines are not
++ * treated correctly in the following, very case-orientated
++ * code. What do I do then...?
++ */
++
++ /* 740 variants match for 30xB, 301B-DH, 30xLV */
++
+ if(!(IS_SIS740)) {
+ tempah = 0x04; /* For all bridges */
+ tempbl = 0xfb;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+- if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))
++ if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
+ tempbl = 0xff;
++ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+ }
+-
+- if(IS_SIS740) {
++
++ /* The following two are responsible for eventually wrong colors
++ * in TV output. The DH (VB_NoLCD) conditions are unknown; the
++ * b0 was found in some 651 machine (Pim); the b1 version in a
++ * 650 box (Jake). What is the criteria?
++ */
++
++ if(IS_SIS740) {
+ tempah = 0x30;
+ tempbl = 0xcf;
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+ tempah = 0x00;
+ }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
++ } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
++ /* Fixes "TV-blue-bug" on 315+301 */
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xCF); /* For 301 */
++ } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xCF,0x30); /* For 30xLV */
++ } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xCF,0x30); /* For 30xB-DH rev b0 (or "DH on 651"?) */
+ } else {
+- /* TW: This in order to fix "TV-blue-bug" on 315+301 */
+- if(SiS_Pr->SiS_VBType & VB_SIS301) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xCF); /* For 301 */
+- } else {
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xCF,0x30); /* For 30xLV */
+- } else {
+- tempah = 0x30; /* For 301B */
+- tempbl = 0xcf;
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+- tempah = 0x00;
+- if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
+- tempbl = 0xff;
+- }
+- }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
++ tempah = 0x30; /* For 30xB (and 301BDH rev b1) */
++ tempbl = 0xcf;
++ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
++ tempah = 0x00;
++ if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
++ tempbl = 0xff;
+ }
+ }
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+ }
+
+ if(IS_SIS740) {
+@@ -3111,25 +3223,25 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ tempbl = 0x3f;
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+ tempah = 0x00;
+- }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl,tempah);
++ }
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl,tempah);
++ } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,0xc0); /* For 30xLV */
++ } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,0xc0); /* For 30xB-DH rev b0 (or "DH on 651"? */
+ } else {
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* For 30xLV */
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,0xc0);
+- } else { /* For 301, 301B */
+- tempah = 0xc0;
+- tempbl = 0x3f;
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+- tempah = 0x00;
+- if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
+- tempbl = 0xff;
+- }
+- }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl,tempah);
++ tempah = 0xc0; /* For 301, 301B (and 301BDH rev b1) */
++ tempbl = 0x3f;
++ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
++ tempah = 0x00;
++ if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
++ tempbl = 0xff;
++ }
+ }
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl,tempah);
+ }
+
+- if(IS_SIS740) {
++ if(IS_SIS740) {
+ tempah = 0x80;
+ tempbl = 0x7f;
+ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+@@ -3141,8 +3253,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ tempbl = 0x7f;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempbl = 0xff;
+- if(!(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)))
++ if(!(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))) {
+ tempah |= 0x80;
++ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
+ }
+@@ -3174,16 +3287,32 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
+ tempbl = 0xfb;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ tempah = 0x00;
+- if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr))
++ if(SiS_IsDualEdge(SiS_Pr, HwDeviceExtension, BaseAddr)) {
+ tempbl = 0xff;
++ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+
+- if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)
++ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x00);
++ }
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,0x30);
+
++ } else if(HwDeviceExtension->jChipType == SIS_550) {
++
++#if 0
++ tempah = 0x00;
++ tempbl = 0xfb;
++ if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
++ tempah = 0x00;
++ tempbl = 0xfb;
++ }
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
++#endif
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
++
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,0xcf,0x30);
+ }
+
+ }
+@@ -3209,10 +3338,9 @@ SiS_GetCRT2Data(SiS_Private *SiS_Pr, UCH
+ HwDeviceExtension);
+ } else {
+
+- if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+- (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
+-
+- /* TW: Need LVDS Data for LCD on 301BDH */
++ if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
++
++ /* Need LVDS Data for LCD on 301B-DH */
+ SiS_GetCRT2DataLVDS(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ HwDeviceExtension);
+
+@@ -3282,18 +3410,16 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
+
+ } else {
+
+- /* TW: 301BDH needs LVDS Data */
+- if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+- (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
++ /* 301BDH needs LVDS Data */
++ if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
+ SiS_Pr->SiS_IF_DEF_LVDS = 1;
+ }
+
+ SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ &CRT2Index,&ResIndex,HwDeviceExtension);
+
+- /* TW: 301BDH needs LVDS Data */
+- if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+- (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
++ /* 301BDH needs LVDS Data */
++ if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD) ) {
+ SiS_Pr->SiS_IF_DEF_LVDS = 0;
+ }
+
+@@ -3321,11 +3447,18 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
+ case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2; break;
+ case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1; break;
+ case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2; break;
++ case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2; break;
++ case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1; break;
++ case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2; break;
++ case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1; break;
++ case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2; break;
++ case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1; break;
++ case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2; break;
+ case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData; break;
+ case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData; break;
+ case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData; break;
+ case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData; break;
+- case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break; /* TW: Super Overscan */
++ case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData; break; /* Super Overscan */
+ default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1; break;
+ }
+ }
+@@ -3337,67 +3470,36 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+- if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)){
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768){
+- SiS_Pr->SiS_HDE = 1024;
+- SiS_Pr->SiS_VDE = 768;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024){
+- SiS_Pr->SiS_HDE = 1280;
+- SiS_Pr->SiS_VDE = 1024;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050){
+- SiS_Pr->SiS_HDE = 1400;
+- SiS_Pr->SiS_VDE = 1050;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200){
+- SiS_Pr->SiS_HDE = 1600;
+- SiS_Pr->SiS_VDE = 1200;
+- } else {
+- SiS_Pr->SiS_HDE = 1280;
+- SiS_Pr->SiS_VDE = 960;
+- }
+- }
++ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
++ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
++ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
++ }
+
+ } else {
+
+- if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+- if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- SiS_Pr->SiS_HDE = 800;
+- SiS_Pr->SiS_VDE = 600;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+- SiS_Pr->SiS_HDE = 1024;
+- SiS_Pr->SiS_VDE = 600;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- SiS_Pr->SiS_HDE = 1024;
+- SiS_Pr->SiS_VDE = 768;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
+- SiS_Pr->SiS_HDE = 1152;
+- SiS_Pr->SiS_VDE = 768;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x864) {
+- SiS_Pr->SiS_HDE = 1152;
+- SiS_Pr->SiS_VDE = 864;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
+- SiS_Pr->SiS_HDE = 1280;
+- SiS_Pr->SiS_VDE = 768;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- SiS_Pr->SiS_HDE = 1280;
+- SiS_Pr->SiS_VDE = 1024;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- SiS_Pr->SiS_HDE = 1400;
+- SiS_Pr->SiS_VDE = 1050;
+- } else {
+- SiS_Pr->SiS_HDE = 1600;
+- SiS_Pr->SiS_VDE = 1200;
+- }
+- if(SiS_Pr->SiS_IF_DEF_FSTN) {
+- SiS_Pr->SiS_HDE = 320;
+- SiS_Pr->SiS_VDE = 480;
+- }
+- }
++ if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
++ if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
++ SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
++ SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
++
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
++ if(ResIndex < 0x08) {
++ SiS_Pr->SiS_HDE = 1280;
++ SiS_Pr->SiS_VDE = 1024;
++ }
++ }
++#if 0
++ if(SiS_Pr->SiS_IF_DEF_FSTN) {
++ SiS_Pr->SiS_HDE = 320;
++ SiS_Pr->SiS_VDE = 480;
++ }
++#endif
++ }
++ }
+ }
+- }
+- }
++ }
+ }
+ }
+
+@@ -3413,11 +3515,16 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,
+ const SiS_TVDataStruct *TVPtr = NULL;
+
+ if(ModeNo <= 0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ resinfo = 0;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ }
+ }
+
+ SiS_Pr->SiS_NewFlickerMode = 0;
+@@ -3429,17 +3536,26 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,
+
+ SiS_GetCRT2ResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
+
+- /* TW: For VGA2 ("RAMDAC2") */
+-
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+- SiS_GetRAMDAC2DATA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+- HwDeviceExtension);
+- return;
+- }
+
+- /* TW: For TV */
++ if(SiS_Pr->UseCustomMode) {
+
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ SiS_Pr->SiS_RVBHCMAX = 1;
++ SiS_Pr->SiS_RVBHCFACT = 1;
++ SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
++ SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
++ SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
++ SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
++ SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
++ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
++
++ } else {
++
++ SiS_GetRAMDAC2DATA(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
++ HwDeviceExtension);
++ }
++
++ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+ SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+ &CRT2Index,&ResIndex,HwDeviceExtension);
+@@ -3452,7 +3568,7 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,
+ case 4: TVPtr = SiS_Pr->SiS_ExtNTSCData; break;
+ case 8: TVPtr = SiS_Pr->SiS_StPALData; break;
+ case 9: TVPtr = SiS_Pr->SiS_StNTSCData; break;
+- default: TVPtr = SiS_Pr->SiS_StPALData; break; /* TW: Just to avoid a crash */
++ default: TVPtr = SiS_Pr->SiS_StPALData; break; /* Just to avoid a crash */
+ }
+
+ SiS_Pr->SiS_RVBHCMAX = (TVPtr+ResIndex)->RVBHCMAX;
+@@ -3464,18 +3580,16 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,
+ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->RVBHRS;
+ SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
+ if(modeflag & HalfDCLK) {
+- SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
++ SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+
+ if(SiS_Pr->SiS_HiVision != 3) {
+-
+- if(resinfo == 0x08) SiS_Pr->SiS_NewFlickerMode = 0x40;
+- if(resinfo == 0x09) SiS_Pr->SiS_NewFlickerMode = 0x40;
+- if(resinfo == 0x12) SiS_Pr->SiS_NewFlickerMode = 0x40;
+-
+- }
++ if(resinfo == SIS_RI_1024x768) SiS_Pr->SiS_NewFlickerMode = 0x40;
++ if(resinfo == SIS_RI_1280x1024) SiS_Pr->SiS_NewFlickerMode = 0x40;
++ if(resinfo == SIS_RI_1280x720) SiS_Pr->SiS_NewFlickerMode = 0x40;
++ }
+
+ switch(SiS_Pr->SiS_HiVision) {
+ case 2:
+@@ -3504,119 +3618,136 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,
+
+ } else {
+
+- SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
+- SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
+- SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
+- SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
+-
+- if(modeflag & HalfDCLK) {
+- SiS_Pr->SiS_RY1COE = 0x00;
+- SiS_Pr->SiS_RY2COE = 0xf4;
+- SiS_Pr->SiS_RY3COE = 0x10;
+- SiS_Pr->SiS_RY4COE = 0x38;
+- }
+-
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- SiS_Pr->SiS_HT = NTSCHT;
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if((ModeNo == 0x4a) || (ModeNo == 0x38)) SiS_Pr->SiS_HT = NTSC2HT;
+- }
+- SiS_Pr->SiS_VT = NTSCVT;
+- } else {
+- SiS_Pr->SiS_HT = PALHT;
+- SiS_Pr->SiS_VT = PALVT;
+- }
++ SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
++ SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
++ SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
++ SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
++
++ if(modeflag & HalfDCLK) {
++ SiS_Pr->SiS_RY1COE = 0x00;
++ SiS_Pr->SiS_RY2COE = 0xf4;
++ SiS_Pr->SiS_RY3COE = 0x10;
++ SiS_Pr->SiS_RY4COE = 0x38;
++ }
++
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ SiS_Pr->SiS_HT = NTSCHT;
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if((ModeNo == 0x64) || (ModeNo == 0x4a) || (ModeNo == 0x38)) SiS_Pr->SiS_HT = NTSC2HT;
++ }
++ SiS_Pr->SiS_VT = NTSCVT;
++ } else {
++ SiS_Pr->SiS_HT = PALHT;
++ SiS_Pr->SiS_VT = PALVT;
++ }
+
+ }
+
+- return;
+- }
++ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+- /* TW: For LCD */
++ if(SiS_Pr->UseCustomMode) {
+
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ SiS_Pr->SiS_RVBHCMAX = 1;
++ SiS_Pr->SiS_RVBHCFACT = 1;
++ SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
++ SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
++ SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
++ SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
++ SiS_Pr->SiS_HDE = SiS_Pr->SiS_VGAHDE;
++ SiS_Pr->SiS_VDE = SiS_Pr->SiS_VGAVDE;
+
+- SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+- &CRT2Index,&ResIndex,HwDeviceExtension);
++ } else {
++
++ SiS_GetCRT2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
++ &CRT2Index,&ResIndex,HwDeviceExtension);
++
++ switch(CRT2Index) {
++ case 0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* VESA Timing */
++ case 1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break; /* VESA Timing */
++ case 5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data; break; /* Obviously unused */
++ case 6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data; break; /* Obviously unused */
++ case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break; /* Non-VESA Timing */
++ case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; /* Non-VESA Timing */
++ case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768; break; /* Non-expanding */
++ case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024; break; /* Non-expanding */
++ case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break; /* 1280x960 */
++ case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break; /* VESA Timing */
++ case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050; break; /* Non-expanding (let panel scale) */
++ case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break; /* Non-VESA Timing (let panel scale) */
++ case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break; /* VESA Timing */
++ case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200; break; /* Non-expanding */
++ case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break; /* Non-VESA Timing */
++ case 26: LCDPtr = SiS_Pr->SiS_ExtLCD1280x768Data; break; /* VESA Timing */
++ case 27: LCDPtr = SiS_Pr->SiS_NoScaleData1280x768; break; /* Non-expanding */
++ case 28: LCDPtr = SiS_Pr->SiS_StLCD1280x768Data; break; /* Non-VESA Timing */
++ case 29: LCDPtr = SiS_Pr->SiS_NoScaleData; break; /* Generic no-scale data */
++#ifdef SIS315H
++ case 50: LCDPtr = (SiS_LCDDataStruct *)SiS310_ExtCompaq1280x1024Data; break;
++ case 51: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024; break;
++ case 52: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break;
++#endif
++ default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* Just to avoid a crash */
++ }
++
++ SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
++ SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
++ SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
++ SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
++ SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
++ SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
+
+- switch (CRT2Index) {
+- case 0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* VESA Timing */
+- case 1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data; break; /* VESA Timing */
+- case 5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data; break; /* Obviously unused */
+- case 6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data; break; /* Obviously unused */
+- case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data; break; /* Non-VESA Timing */
+- case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data; break; /* Non-VESA Timing */
+- case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768; break; /* Non-expanding */
+- case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024; break; /* Non-expanding */
+- case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data; break; /* 1280x960 */
+- case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data; break; /* VESA Timing */
+- case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050; break; /* Non-expanding (let panel scale) */
+- case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data; break; /* Non-VESA Timing (let panel scale) */
+- case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data; break; /* VESA Timing */
+- case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200; break; /* Non-expanding */
+- case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data; break; /* Non-VESA Timing */
+- default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data; break; /* Just to avoid a crash */
+- }
+-
+- SiS_Pr->SiS_RVBHCMAX = (LCDPtr+ResIndex)->RVBHCMAX;
+- SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+- SiS_Pr->SiS_VGAHT = (LCDPtr+ResIndex)->VGAHT;
+- SiS_Pr->SiS_VGAVT = (LCDPtr+ResIndex)->VGAVT;
+- SiS_Pr->SiS_HT = (LCDPtr+ResIndex)->LCDHT;
+- SiS_Pr->SiS_VT = (LCDPtr+ResIndex)->LCDVT;
+-
+ #ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO,
+- "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+-#endif
++ xf86DrvMsg(0, X_INFO,
++ "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
++#endif
+
+- tempax = 1024;
+- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+- else tempbx = 768;
+- } else {
+- tempbx = 768;
+- }
+- } else {
+- if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
+- else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
+- else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
+- else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
+- else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+- else tempbx = 768;
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- tempax = 1280;
+- if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+- else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+- else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+- else tempbx = 1024;
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
+- tempax = 1280;
+- if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
+- else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
+- else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
+- else tempbx = 960;
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- tempax = 1400;
+- tempbx = 1050;
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
+- tempax = 1600;
+- tempbx = 1200;
+- }
+- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- tempax = SiS_Pr->SiS_VGAHDE;
+- tempbx = SiS_Pr->SiS_VGAVDE;
+- }
+- SiS_Pr->SiS_HDE = tempax;
+- SiS_Pr->SiS_VDE = tempbx;
+- return;
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ tempax = 1024;
++ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
++ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
++ else tempbx = 768;
++ } else {
++ tempbx = 768;
++ }
++ } else {
++ if (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
++ else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
++ else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
++ else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
++ else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
++ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
++ else tempbx = 768;
++ }
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ tempax = 1280;
++ if (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
++ else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
++ else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
++ else tempbx = 1024;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
++ tempax = 1280;
++ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 700;
++ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 800;
++ else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
++ else tempbx = 960;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
++ tempax = 1600;
++ if (SiS_Pr->SiS_VGAVDE == 350) tempbx = 875;
++ else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 1000;
++ else tempbx = 1200;
++ } else {
++ tempax = SiS_Pr->PanelXRes;
++ tempbx = SiS_Pr->PanelYRes;
++ }
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
++ tempax = SiS_Pr->SiS_VGAHDE;
++ tempbx = SiS_Pr->SiS_VGAVDE;
++ }
++ SiS_Pr->SiS_HDE = tempax;
++ SiS_Pr->SiS_VDE = tempbx;
++ }
+ }
+ }
+
+@@ -3626,9 +3757,9 @@ SiS_GetResInfo(SiS_Private *SiS_Pr, UCHA
+ USHORT resindex;
+
+ if(ModeNo <= 0x13)
+- resindex=SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ resindex=SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ else
+- resindex=SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ resindex=SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+
+ return(resindex);
+ }
+@@ -3639,41 +3770,46 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,
+ {
+ USHORT xres,yres,modeflag=0,resindex;
+
++ if(SiS_Pr->UseCustomMode) {
++ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = SiS_Pr->CHDisplay;
++ SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
++ return;
++ }
++
+ resindex = SiS_GetResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex);
+
+ if(ModeNo <= 0x13) {
+- xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
+- yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
++ xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
++ yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
+ } else {
+- xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+- yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
+- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
++ yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
++ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
+- if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
+- if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+- if(yres == 350) yres = 400;
+- }
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
+- if(ModeNo == 0x12) yres = 400;
+- }
+- }
++ if((!SiS_Pr->SiS_IF_DEF_DSTN) && (!SiS_Pr->SiS_IF_DEF_FSTN)) {
++
++ if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
++ if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
++ if(yres == 350) yres = 400;
++ }
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
++ if(ModeNo == 0x12) yres = 400;
++ }
++ }
++
++ if(ModeNo > 0x13) {
++ if(modeflag & HalfDCLK) xres *= 2;
++ if(modeflag & DoubleScanMode) yres *= 2;
++ }
+
+- if(ModeNo > 0x13) {
+- if(SiS_Pr->SiS_IF_DEF_FSTN == 1){
+- xres *= 2;
+- yres *= 2;
+- } else {
+- if(modeflag & HalfDCLK) xres *= 2;
+- if(modeflag & DoubleScanMode) yres *= 2;
+- }
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ if(xres == 720) xres = 640;
+ } else {
+- if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* TW: 301BDH */
++ if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* 301BDH */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(xres == 720) xres = 640;
+ }
+@@ -3694,17 +3830,16 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,
+ if(xres == 720) xres = 640;
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(ModeNo <= 0x13) {
+- /* TW: This is wrong for 640x400 *graphics* mode */
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
++ /* BIOS bug - does this regardless of scaling */
+ if(yres == 400) yres = 405;
+ }
+ if(yres == 350) yres = 360;
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ if(yres == 360) yres = 375;
+ }
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768){
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ if(yres == 350) yres = 357;
+@@ -3719,12 +3854,15 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,
+ } else {
+ if(xres == 720) xres = 640;
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+- yres = 400;
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+- } else {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+- }
++ yres = 400;
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
++ } else {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
++ }
++ if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
++ yres = 480;
++ }
+ }
+ }
+ SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+@@ -3739,6 +3877,13 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ USHORT tempbx=0,tempal=0;
+ USHORT Flag,resinfo=0;
+
++ if(ModeNo <= 0x13) {
++ tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
++ } else {
++ tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
++ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ }
++
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
+@@ -3753,19 +3898,44 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ tempbx = 23;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx = 24;
+ else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 25;
++#if 0
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
++ tempbx = 26;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx = 27;
++ else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 28;
++#endif
+ } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- tempbx = 13;
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx++;
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 13;
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 14;
++ else tempbx = 29;
++ } else {
++ tempbx = 29;
++ if(ModeNo >= 0x13) {
++ /* 1280x768 and 1280x960 have same CRT2CRTC,
++ * so we change it here if 1280x960 is chosen
++ */
++ if(resinfo == SIS_RI_1280x960) tempal = 10;
++ }
++ }
+ } else {
+ tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_Panel1024x768;
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+ tempbx += 5;
+ /* GetRevisionID(); */
+- /* TW: BIOS only adds 5 once */
++ /* BIOS only adds 5 once */
+ tempbx += 5;
+ }
+ }
+
++#ifdef SIS315H
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ tempbx = 50;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx = 51;
++ else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 52;
++ }
++#endif
++
+ } else { /* TV */
+
+ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) &&
+@@ -3773,7 +3943,7 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_SetFlag &= (~TVSimuMode);
+ tempbx = 2;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if(!(SiS_Pr->SiS_SetFlag & TVSimuMode)) tempbx = 12;
++ if(!(SiS_Pr->SiS_SetFlag & TVSimuMode)) tempbx = 12;
+ }
+ } else {
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) tempbx = 3;
+@@ -3783,34 +3953,18 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+
+ }
+
+- if(ModeNo <= 0x13) {
+- tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+- } else {
+- tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+- }
+-
+- tempal &= 0x3F;
+-
+- if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+- (SiS_Pr->SiS_VBInfo & (SetCRT2ToTV-SetCRT2ToHiVisionTV))) {
+- if(tempal == 0x06) tempal = 0x07;
+- }
+-
+- /* TW: 300/301LV BIOS */
+- if((HwDeviceExtension->jChipType == SIS_300) &&
+- (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+- if(ModeNo > 0x13) {
+- if((resinfo == 0x0c) || (resinfo == 0x0d)) /* 720 (index diff. on 310/325!) */
+- tempal = 6;
+- }
+- }
++ tempal &= 0x3F;
+
+- if(HwDeviceExtension->jChipType != SIS_300) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if((ModeNo == 0x31) || (ModeNo == 0x32)) tempal = 6;
++ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) {
++ if(ModeNo > 0x13) {
++ if(tempal == 6) tempal = 7;
++ if((resinfo == SIS_RI_720x480) ||
++ (resinfo == SIS_RI_720x576) ||
++ (resinfo == SIS_RI_768x576)) {
++ tempal = 6;
++ }
+ }
+- }
++ }
+
+ *CRT2Index = tempbx;
+ *ResIndex = tempal;
+@@ -3820,25 +3974,22 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ Flag = 1;
+ tempbx = 0;
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+-
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+- Flag = 0;
+- tempbx = 10;
+- if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- tempbx += 2;
+- if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
+- if(SiS_Pr->SiS_CHPALM) {
+- tempbx = 90;
+- if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
+- } else if(SiS_Pr->SiS_CHPALN) {
+- tempbx = 92;
+- if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
+- }
+-
+- }
+- }
+-
++ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
++ Flag = 0;
++ tempbx = 10;
++ if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
++ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
++ tempbx += 2;
++ if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
++ if(SiS_Pr->SiS_CHPALM) {
++ tempbx = 90;
++ if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
++ } else if(SiS_Pr->SiS_CHPALN) {
++ tempbx = 92;
++ if(SiS_Pr->SiS_VBInfo & SetCHTVOverScan) tempbx += 1;
++ }
++ }
++ }
+ }
+
+ if(Flag) {
+@@ -3846,11 +3997,19 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
+ tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
++ tempbx = 82;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
++ }
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
+ tempbx = 18;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+ tempbx = 6;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
++ tempbx = 30;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
++ tempbx = 30;
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+ tempbx = 15;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
+@@ -3863,27 +4022,30 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
+ tempbx = 21;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelBarco1366) {
++ tempbx = 80;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
+ }
+-
++
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ tempbx = 7;
+ }
+-
+- }
+
+- if(ModeNo <= 0x13)
+- tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+- else {
+- tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
++ tempbx = 84;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
++ }
++
+ }
+
++#if 0
+ if(SiS_Pr->SiS_IF_DEF_FSTN){
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
+ tempbx = 14;
+ tempal = 6;
+ }
+ }
++#endif
+
+ if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempal = 7;
+@@ -3895,13 +4057,10 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr, UCHA
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(ModeNo > 0x13) {
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- if((resinfo == 0x0c) || (resinfo == 0x0d)) /* 720 */
+- tempal = 6;
+- } else {
+- if((resinfo == 0x0d) || (resinfo == 0x0e)) /* 720 */
+- tempal = 6;
+- }
++ if((resinfo == SIS_RI_720x480) ||
++ (resinfo == SIS_RI_720x576) ||
++ (resinfo == SIS_RI_768x576))
++ tempal = 6;
+ }
+ }
+
+@@ -3940,7 +4099,7 @@ SiS_GetCRT2PtrA(SiS_Private *SiS_Pr, UCH
+ void
+ SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,USHORT *CRT2Index,
+- USHORT *ResIndex)
++ USHORT *ResIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT tempbx,tempal;
+
+@@ -3954,6 +4113,16 @@ SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 16;
+ else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx += 32;
+
++#ifdef SIS315H
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ tempbx = 100;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx = 101;
++ else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 102;
++ }
++ }
++#endif
++
+ *CRT2Index = tempbx;
+ *ResIndex = tempal & 0x3F;
+ }
+@@ -3962,15 +4131,17 @@ USHORT
+ SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+- SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x03, 0x01,
++ SHORT LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01,
+- 0x01, 0x01, 0x01, 0x01 };
++ 0x01, 0x01, 0x01, 0x01,
++ 0x00, 0x00, 0x00, 0x00 };
+ USHORT RefreshRateTableIndex,i,backup_i;
+ USHORT modeflag,index,temp,backupindex;
+
+- if(SiS_Pr->UseCustomMode) return 0;
+-
++ /* Do NOT check for UseCustomMode here, will skrew up FIFO */
++ if(ModeNo == 0xfe) return 0;
++
+ if(ModeNo <= 0x13)
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ else
+@@ -3984,7 +4155,7 @@ SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr,
+
+ if(ModeNo < 0x14) return(0xFFFF);
+
+- /* TW: CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4].
++ /* CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4].
+ * On LVDS machines, CRT2 index is always 0 and will be
+ * set to 0 by the following code; this causes the function
+ * to take the first non-interlaced mode in SiS_Ext2Struct
+@@ -3998,40 +4169,38 @@ SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr,
+ if(index > 0) index--;
+
+ if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
+- } else {
++ } else {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_Pr->SiS_VBType & VB_NoLCD)
+- index = 0;
+- else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)
+- index = backupindex = 0;
++ if(SiS_Pr->SiS_VBType & VB_NoLCD)
++ index = 0;
++ else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)
++ index = backupindex = 0;
+ }
+- }
+- }
++ }
+
+- if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+- if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- index = 0;
+- }
+- }
+- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
+- temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo];
+- if(index > temp) index = temp;
+- }
+- } else {
+- index = 0;
+- }
+- }
++ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ index = 0;
++ }
++ }
++ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++ if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
++ temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo];
++ if(index > temp) index = temp;
++ }
++ } else {
++ index = 0;
++ }
++ }
+ }
+
+ RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+ ModeNo = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID;
+
+- /* TW: 650/LVDS 1.10.07, 650/30xLV 1.10.6s */
++ /* 650/LVDS 1.10.07, 650/30xLV 1.10.6s */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
+ if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
+@@ -4066,7 +4235,7 @@ SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr,
+ backup_i = i;
+ if (!(SiS_AdjustCRT2Rate(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+ RefreshRateTableIndex,&i,HwDeviceExtension))) {
+- /* TW: This is for avoiding random data to be used; i is
++ /* This is for avoiding random data to be used; i is
+ * in an undefined state if no matching CRT2 mode is
+ * found.
+ */
+@@ -4085,196 +4254,199 @@ SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr,
+ USHORT tempax,tempbx,resinfo;
+ USHORT modeflag,infoflag;
+
+- if (ModeNo <= 0x13)
++ if(ModeNo <= 0x13) {
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- else
++ resinfo = 0;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ }
+
+- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ tempbx = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+
+ tempax = 0;
++
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+ tempax |= SupportRAMDAC2;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- tempax |= SupportTV;
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(resinfo == 0x0a) tempax |= SupportTV1024;
+- }
+- }
++ tempax |= SupportTV;
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if(resinfo == SIS_RI_1600x1200) tempax |= SupportTV1024;
++ }
++ }
+ }
+- }
+- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
++ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ tempax |= SupportLCD;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+- if((resinfo == 6) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
++ if((resinfo == SIS_RI_640x480) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+ (*i) = 0;
+ return(1);
+ } else {
+ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) {
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) {
+- if((resinfo == 6) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+- return(0);
+- } else {
+- if((resinfo >= 9) && (resinfo != 0x14)) {
++ if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) {
++ if((resinfo == SIS_RI_640x480) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
++ return(0);
++ } else {
++ if((resinfo >= SIS_RI_1280x1024) && (resinfo != SIS_RI_1280x768)) {
+ return(0);
+- }
+- }
+- }
++ }
++ }
++ }
+ }
+ }
+ }
+ }
+ } else {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+- if((resinfo != 0x0f) && ((resinfo == 4) || (resinfo >= 8))) return(0);
++ if( (resinfo != SIS_RI_1024x600) &&
++ ((resinfo == SIS_RI_512x384) || (resinfo >= SIS_RI_1024x768))) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
+- if((resinfo != 0x10) && (resinfo > 8)) return(0);
++ if((resinfo != SIS_RI_1152x768) && (resinfo > SIS_RI_1024x768)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
+- if((resinfo != 0x0e) && (resinfo > 8)) return(0);
++ if((resinfo != SIS_RI_1280x960) && (resinfo > SIS_RI_1024x768)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(resinfo > 9) return(0);
++ if(resinfo > SIS_RI_1280x1024) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if(resinfo > 8) return(0);
++ if(resinfo > SIS_RI_1024x768) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- if((resinfo == 4) || (resinfo > 7)) return(0);
++ if((resinfo == SIS_RI_512x384) || (resinfo > SIS_RI_800x600)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
+- if((resinfo == 4) || (resinfo == 3) || (resinfo > 6)) return(0);
++ if((resinfo == SIS_RI_512x384) ||
++ (resinfo == SIS_RI_400x300) ||
++ (resinfo > SIS_RI_640x480)) return(0);
+ }
+ }
+- }
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
++ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+ if(SiS_Pr->SiS_HiVision == 3) {
+ tempax |= SupportHiVisionTV2;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode){
+- if(resinfo == 4) return(0);
+- if(resinfo == 3) return(0);
+- if(resinfo == 7) {
++ if(resinfo == SIS_RI_512x384) return(0);
++ if(resinfo == SIS_RI_400x300) return(0);
++ if(resinfo == SIS_RI_800x600) {
+ if(SiS_Pr->SiS_SetFlag & TVSimuMode) return(0);
+ }
+- if(resinfo > 7) return(0);
++ if(resinfo > SIS_RI_800x600) return(0);
+ }
+ } else {
+ tempax |= SupportHiVisionTV;
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode){
+- if(resinfo == 4) return(0);
+- if((resinfo == 3) || (resinfo == 7)) {
++ if(resinfo == SIS_RI_512x384) return(0);
++ if((resinfo == SIS_RI_400x300) || (resinfo == SIS_RI_800x600)) {
+ if(SiS_Pr->SiS_SetFlag & TVSimuMode) return(0);
+ }
+- if(resinfo > 7) return(0);
++ if(resinfo > SIS_RI_800x600) return(0);
+ }
+ }
+- } else {
+- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
++ } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
+ tempax |= SupportTV;
+ tempax |= SupportTV1024;
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if((SiS_Pr->SiS_VBInfo & SetNotSimuMode) && (SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if(resinfo != 8) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 4)) ) {
+- tempax &= ~(SupportTV1024);
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
+- }
+- }
+- } else {
+- if( (resinfo != 3) ||
+- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(resinfo == 3) return(0);
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
+- }
+- }
+- } else return(0);
+- }
+- }
+- }
+- } else {
+- tempax &= ~(SupportTV1024);
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) {
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ if((SiS_Pr->SiS_VBInfo & SetNotSimuMode) && (SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if(resinfo != SIS_RI_1024x768) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_512x384)) ) {
++ tempax &= ~(SupportTV1024);
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_800x600)) ) {
+ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
+- }
+- }
+- } else {
+- if( (resinfo != 3) ||
+- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(resinfo == 3) return(0);
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
+- }
+ }
+- } else return(0);
+- }
+- }
+- } else { /* slavemode */
+- if(resinfo != 8) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 4) ) ) {
+- tempax &= ~(SupportTV1024);
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
+- }
++ }
++ } else {
++ if( (resinfo != SIS_RI_400x300) ||
++ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if(resinfo == SIS_RI_400x300) return(0);
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
++ }
+ }
+- } else {
+- if( (resinfo != 3) ||
+- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(resinfo == 3) return(0);
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
+- }
+- }
+- } else return(0);
+- }
++ } else return(0);
++ }
+ }
+- }
+- }
+- } else { /* 301 */
+- tempax &= ~(SupportTV1024);
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
+- ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != 7)) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
+- }
+- }
+- } else {
+- if( (resinfo != 3) ||
+- (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- if(resinfo == 3) return(0);
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
+- }
++ }
++ } else {
++ tempax &= ~(SupportTV1024);
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_800x600)) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
++ }
+ }
+- } else return(0);
+- }
+- }
+- }
+- }
+-
+- } else { /* TW: for LVDS */
++ } else {
++ if( (resinfo != SIS_RI_400x300) ||
++ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if(resinfo == SIS_RI_400x300) return(0);
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
++ }
++ }
++ } else return(0);
++ }
++ }
++ } else { /* slavemode */
++ if(resinfo != SIS_RI_1024x768) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_512x384) ) ) {
++ tempax &= ~(SupportTV1024);
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_800x600)) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
++ }
++ }
++ } else {
++ if( (resinfo != SIS_RI_400x300) ||
++ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if(resinfo == SIS_RI_400x300) return(0);
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
++ }
++ }
++ } else return(0);
++ }
++ }
++ }
++ }
++ } else { /* 301 */
++ tempax &= ~(SupportTV1024);
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if( (!(SiS_Pr->SiS_VBInfo & SetPALTV)) ||
++ ((SiS_Pr->SiS_VBInfo & SetPALTV) && (resinfo != SIS_RI_800x600)) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return(0);
++ }
++ }
++ } else {
++ if( (resinfo != SIS_RI_400x300) ||
++ (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_VBInfo & SetNotSimuMode) ) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if((modeflag & NoSupportSimuTV) && (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ if(resinfo == SIS_RI_400x300) return(0);
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) return (0);
++ }
++ }
++ } else return(0);
++ }
++ }
++ }
++
++ } else { /* for LVDS */
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+@@ -4284,24 +4456,33 @@ SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr,
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ tempax |= SupportLCD;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
+- if((resinfo != 0x14) && (resinfo > 0x09)) return(0);
++ if((resinfo != SIS_RI_1280x768) && (resinfo >= SIS_RI_1280x1024)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+- if((resinfo != 0x0f) && (resinfo > 0x08)) return(0);
++ if((resinfo != SIS_RI_1024x600) && (resinfo >= SIS_RI_1024x768)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
+- if((resinfo != 0x10) && (resinfo > 0x08)) return(0);
++ if((resinfo != SIS_RI_1152x768) && (resinfo > SIS_RI_1024x768)) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- if((resinfo != 0x15) && (resinfo > 0x09)) return(0);
++ if((resinfo != SIS_RI_1400x1050) && (resinfo > SIS_RI_1280x1024)) return(0);
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
++ if(resinfo > SIS_RI_1600x1200) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(resinfo > 0x09) return(0);
++ if(resinfo > SIS_RI_1280x1024) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if(resinfo > 0x08) return(0);
++ if(resinfo > SIS_RI_1024x768) return(0);
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600){
+- if(resinfo > 0x07) return(0);
+- if(resinfo == 0x04) return(0);
++ if(resinfo > SIS_RI_800x600) return(0);
++ if(resinfo == SIS_RI_512x384) return(0);
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelBarco1366) {
++ if((resinfo != SIS_RI_1360x1024) && (resinfo > SIS_RI_1280x1024)) return(0);
++ } else if(SiS_Pr->SiS_LCDResInfo == Panel_848x480) {
++ if((resinfo != SIS_RI_1360x768) &&
++ (resinfo != SIS_RI_848x480) &&
++ (resinfo > SIS_RI_1024x768)) return(0);
+ }
+ }
+ }
+- /* TW: Look backwards in table for matching CRT2 mode */
++
++ /* Look backwards in table for matching CRT2 mode */
+ for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == tempbx; (*i)--) {
+ infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
+ if(infoflag & tempax) {
+@@ -4309,7 +4490,7 @@ SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr,
+ }
+ if ((*i) == 0) break;
+ }
+- /* TW: Look through the whole mode-section of the table from the beginning
++ /* Look through the whole mode-section of the table from the beginning
+ * for a matching CRT2 mode if no mode was found yet.
+ */
+ for((*i) = 0; ; (*i)++) {
+@@ -4329,7 +4510,7 @@ SiS_SaveCRT2Info(SiS_Private *SiS_Pr, US
+ {
+ USHORT temp1,temp2;
+
+- /* TW: We store CRT1 ModeNo in CR34 */
++ /* We store CRT1 ModeNo in CR34 */
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x34,ModeNo);
+ temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
+ temp2 = ~(SetInSlaveMode >> 8);
+@@ -4345,16 +4526,16 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ USHORT modeflag, resinfo=0;
+ UCHAR OutputSelect = *SiS_Pr->pSiS_OutputSelect;
+
+- if(SiS_Pr->UseCustomMode) {
+- modeflag = SiS_Pr->CModeFlag;
++ if(ModeNo <= 0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+- if (ModeNo <= 0x13)
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+- }
+- }
++ }
++ }
+
+ SiS_Pr->SiS_SetFlag = 0;
+
+@@ -4364,22 +4545,24 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ if(SiS_BridgeIsOn(SiS_Pr,BaseAddr,HwDeviceExtension) == 0) {
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
+ #if 0
+- /* SiS_HiVision is only used on 310/325/330+30xLV */
++ /* SiS_HiVision is only used on 315/330+30xLV */
+ if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV)) {
+- if(SiS_Pr->SiS_HiVision & 0x03) { /* TW: New from 650/30xLV 1.10.6s */
++ if(SiS_Pr->SiS_HiVision & 0x03) { /* New from 650/30xLV 1.10.6s */
+ temp &= (SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode); /* 0x83 */
+ temp |= SetCRT2ToHiVisionTV; /* 0x80 */
+ }
+- if(SiS_Pr->SiS_HiVision & 0x04) { /* TW: New from 650/30xLV 1.10.6s */
++ if(SiS_Pr->SiS_HiVision & 0x04) { /* New from 650/30xLV 1.10.6s */
+ temp &= (SetCRT2ToHiVisionTV | SwitchToCRT2 | SetSimuScanMode); /* 0x83 */
+ temp |= SetCRT2ToSVIDEO; /* 0x08 */
+ }
+ }
+-#endif
++#endif
++#if 0
+ if(SiS_Pr->SiS_IF_DEF_FSTN) { /* fstn must set CR30=0x21 */
+ temp = (SetCRT2ToLCD | SetSimuScanMode);
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,temp);
+ }
++#endif
+ tempbx |= temp;
+ tempax = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) << 8;
+ tempax &= (LoadDACFlag | DriverMode | SetDispDevSwitch | SetNotSimuMode | SetPALTV);
+@@ -4519,7 +4702,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ tempbx |= SetSimuScanMode;
+ }
+
+- /* TW: LVDS (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
++ /* LVDS (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
+ if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+ if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+ ((tempbx & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD)) ) {
+@@ -4527,12 +4710,12 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ }
+ }
+
+- if(!(tempbx & SetSimuScanMode)){
++ if(!(tempbx & SetSimuScanMode)) {
+ if(tempbx & SwitchToCRT2) {
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if( (HwDeviceExtension->jChipType >= SIS_315H) &&
+ (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
+- if(resinfo != 0x0a)
++ if(resinfo != SIS_RI_1600x1200)
+ tempbx |= SetSimuScanMode;
+ } else {
+ tempbx |= SetSimuScanMode;
+@@ -4555,7 +4738,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+ if( (HwDeviceExtension->jChipType >= SIS_315H) &&
+ (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
+- if(resinfo != 0x0a) { /* TW: 650/301 BIOS */
++ if(resinfo != SIS_RI_1600x1200) { /* 650/301 BIOS */
+ tempbx |= SetInSlaveMode;
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+ if(tempbx & SetCRT2ToTV) {
+@@ -4563,7 +4746,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ SiS_Pr->SiS_SetFlag |= TVSimuMode;
+ }
+ }
+- } /* TW: 650/301 BIOS */
++ } /* 650/301 BIOS */
+ } else {
+ tempbx |= SetInSlaveMode;
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+@@ -4621,7 +4804,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(ROMAddr && SiS_Pr->SiS_UseROM) {
+ OutputSelect = ROMAddr[0xf3];
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ OutputSelect = ROMAddr[0x11b];
+ }
+ }
+@@ -4652,7 +4835,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ SiS_Pr->SiS_VBInfo = tempbx;
+
+ if(HwDeviceExtension->jChipType == SIS_630) {
+- SiS_WhatIsThis(SiS_Pr, SiS_Pr->SiS_VBInfo);
++ SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
+ }
+
+ #ifdef TWDEBUG
+@@ -4666,61 +4849,35 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
+ #endif
+ #endif
+
+-#if 0 /* TW: Incomplete! (But does not seem to be required) */
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- /* TW: From A901/630+301B BIOS */
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80)
+- }
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x80)
+- if( [si] == 3) ModeIdIndex = 0x3f2b;
+- }
+- }
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4, 0x31, 0xF7);
+- if(ModeNo == 0x13) bp+4 = 0x03;
+- } else {
+- /* From 650/30xLV BIOS: */
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4, 0x31, 0xF7);
+- if(ModeNo == 0x13) bp+4 = 0x03;
+- else bp+4 = ModeNo;
+- }
+-#endif
+-
+- /* TW: 630/301B and 650/301 (not 301LV!) BIOSes do more here, but this seems for DOS mode */
+-
+ }
+
++/* Setup general purpose IO for Chrontel communication */
+ void
+-SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo)
++SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
+ {
+- unsigned long eax, temp;
+- unsigned short temp1;
++ unsigned long acpibase;
++ unsigned short temp;
+
+ if(!(SiS_Pr->SiS_ChSW)) return;
+
+ #ifndef LINUX_XF86
+- SiS_SetReg4(0xcf8,0x80000874);
+- eax = SiS_GetReg3(0xcfc);
++ SiS_SetReg4(0xcf8,0x80000874); /* get ACPI base */
++ acpibase = SiS_GetReg3(0xcfc);
+ #else
+- eax = pciReadLong(0x00000800, 0x74);
++ acpibase = pciReadLong(0x00000800, 0x74);
+ #endif
+- eax &= 0xFFFF;
+- temp = eax;
+- eax += 0x3c;
+- temp1 = SiS_GetReg4((USHORT)eax);
+- temp1 &= 0xFEFF;
+- SiS_SetReg5((USHORT)eax, temp1);
+- temp1 = SiS_GetReg4((USHORT)eax);
+- eax = temp;
+- eax += 0x3a;
+- temp1 = SiS_GetReg4((USHORT)eax);
+- temp1 &= 0xFEFF;
++ acpibase &= 0xFFFF;
++ temp = SiS_GetReg4((USHORT)(acpibase + 0x3c)); /* ACPI register 0x3c: GP Event 1 I/O mode select */
++ temp &= 0xFEFF;
++ SiS_SetReg5((USHORT)(acpibase + 0x3c), temp);
++ temp = SiS_GetReg4((USHORT)(acpibase + 0x3c));
++ temp = SiS_GetReg4((USHORT)(acpibase + 0x3a)); /* ACPI register 0x3a: GP Pin Level (low/high) */
++ temp &= 0xFEFF;
+ if(!(myvbinfo & SetCRT2ToTV)) {
+- temp1 |= 0x0100;
++ temp |= 0x0100;
+ }
+- SiS_SetReg5((USHORT)eax, temp1);
+- temp1 = SiS_GetReg4((USHORT)eax);
++ SiS_SetReg5((USHORT)(acpibase + 0x3a), temp);
++ temp = SiS_GetReg4((USHORT)(acpibase + 0x3a));
+ }
+
+ void
+@@ -4731,14 +4888,14 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,
+ USHORT temp1=0,modeflag=0,tempcx=0;
+ USHORT StandTableIndex,CRT1Index;
+ #ifdef SIS315H
+- USHORT ResInfo,DisplayType,temp=0;
++ USHORT ResIndex,DisplayType,temp=0;
+ const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr = NULL;
+ #endif
+
+ SiS_Pr->SiS_RVBHCMAX = 1;
+ SiS_Pr->SiS_RVBHCFACT = 1;
+
+- if(ModeNo <= 0x13){
++ if(ModeNo <= 0x13) {
+
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ StandTableIndex = SiS_GetModePtr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex);
+@@ -4752,7 +4909,7 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,
+
+ #ifdef SIS315H
+ temp = SiS_GetLVDSCRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,&ResInfo,&DisplayType);
++ RefreshRateTableIndex,&ResIndex,&DisplayType);
+
+ if(temp == 0) return;
+
+@@ -4795,16 +4952,16 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,
+ case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL; break;
+ default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
+ }
+- tempax = (LVDSCRT1Ptr+ResInfo)->CR[0];
+- tempax |= (LVDSCRT1Ptr+ResInfo)->CR[14] << 8;
++ tempax = (LVDSCRT1Ptr+ResIndex)->CR[0];
++ tempax |= (LVDSCRT1Ptr+ResIndex)->CR[14] << 8;
+ tempax &= 0x03FF;
+- tempbx = (LVDSCRT1Ptr+ResInfo)->CR[6];
+- tempcx = (LVDSCRT1Ptr+ResInfo)->CR[13] << 8;
++ tempbx = (LVDSCRT1Ptr+ResIndex)->CR[6];
++ tempcx = (LVDSCRT1Ptr+ResIndex)->CR[13] << 8;
+ tempcx &= 0x0100;
+ tempcx <<= 2;
+ tempbx |= tempcx;
+- temp1 = (LVDSCRT1Ptr+ResInfo)->CR[7];
+-#endif
++ temp1 = (LVDSCRT1Ptr+ResIndex)->CR[7];
++#endif
+
+ } else {
+
+@@ -4840,11 +4997,12 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,
+ if(modeflag & Charx8Dot) tempax *= 8;
+ else tempax *= 9;
+
+- /* TW: From 650/30xLV 1.10.6s */
++ /* From 650/30xLV 1.10.6s */
+ if(modeflag & HalfDCLK) tempax <<= 1;
+
+- SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ tempbx++;
++
++ SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+ SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = tempbx;
+ }
+
+@@ -4852,18 +5010,18 @@ void
+ SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
+ {
+ if(HwDeviceExtension->jChipType >= SIS_315H)
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+ else
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
+ }
+
+ void
+ SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
+ {
+ if(HwDeviceExtension->jChipType >= SIS_315H)
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
+ else
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
+ }
+
+ void
+@@ -4872,7 +5030,6 @@ SiS_EnableCRT2(SiS_Private *SiS_Pr)
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+ }
+
+-/* Checked against all BIOSes */
+ void
+ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
+ {
+@@ -4882,9 +5039,9 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ USHORT temp=0;
+ UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+
+- if (SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== TW: For 30xB/LV ===== */
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ===== For 30xB/LV ===== */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+
+@@ -4940,9 +5097,9 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ } else {
+
+-#ifdef SIS315H /* 310/325 series */
++#ifdef SIS315H /* 315 series */
+
+- if(IS_SIS650740) { /* 650, 740 */
++ if(IS_SIS550650740660) { /* 550, 650, 740, 660 */
+
+ #if 0
+ if(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00) != 1) return; /* From 1.10.7w */
+@@ -4950,40 +5107,67 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ modenum = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34);
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* LV */
+
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+
+ if( (modenum <= 0x13) ||
+ (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
+ (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00);
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
++ }
+ }
+- SiS_DDC2Delay(SiS_Pr,0xff00);
+- SiS_DDC2Delay(SiS_Pr,0x6000);
+- SiS_DDC2Delay(SiS_Pr,0x8000);
+
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ SiS_DDC2Delay(SiS_Pr,0xff00);
++ SiS_DDC2Delay(SiS_Pr,0x6000);
++ SiS_DDC2Delay(SiS_Pr,0x8000);
+
+- pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
+-
+- if(IS_SIS740) {
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
++ SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
++
++ pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
++
++ if(IS_SIS740) {
++ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
++ }
++
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
++
++ if(!(IS_SIS740)) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ tempah = 0xef;
++ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ tempah = 0xf7;
++ }
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ }
++ }
+ }
+
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
+-
+- if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- tempah = 0xef;
+- if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- tempah = 0xf7;
+- }
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+- }
++ } else if(SiS_Pr->SiS_VBType & VB_NoLCD) { /* B-DH */
++ /* This is actually bullshit. The B-DH bridge has cetainly no
++ * Part4 Index 26, since it has no ability to drive LCD panels
++ * at all. But as the BIOS does it, we do it, too...
++ */
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,0xef);
++ }
++ if((!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
++ (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00);
++ }
++ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 3);
++ }
++ }
+
+- }
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0xef);
++ }
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+ tempah = 0x3f;
+ if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ tempah = 0x7f;
+@@ -4997,7 +5181,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ if((SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+ ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
+ SiS_DisplayOff(SiS_Pr);
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+@@ -5020,7 +5204,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ } else {
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+ if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+ SiS_DisplayOff(SiS_Pr);
+@@ -5044,10 +5228,10 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ }
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (SiS_Pr->SiS_CustomT != CUT_COMPAQ1280)) {
++
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,~0x10); /* 1.10.8r, 8m */
+
+- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,~0x10); /* 1.10.8r */
+-
+ tempah = 0x3f;
+ if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ tempah = 0x7f;
+@@ -5057,9 +5241,9 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ }
+ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+
+- if(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) { /* 1.10.8r */
++ if(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) { /* 1.10.8r, 8m */
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+- } /* 1.10.8r */
++ } /* 1.10.8r, 8m */
+
+ if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+@@ -5075,80 +5259,47 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax);
+
+- }
++ } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+
+-#if 0
+- } else if(IS_SIS740) { /* 740 */
+-
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 30xLV */
+-
+- if( (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
+- (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00);
+- }
+-
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if((SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
++ (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)))) {
++ if((!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
++ (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)))) {
++ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 2);
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
++ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 4);
++ }
++ }
++ }
+
+- pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
+-
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
++ } else if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
+-
+- if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_DisplayOff(SiS_Pr);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
+- } else {
+- SiS_DisplayOff(SiS_Pr);
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00);
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp);
+- }
+-
+- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0x3F);
+- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0xEF); /* (from 650) */
+-
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+-
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+- }
+-
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- if(!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) {
+- if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFD,0x00);
+- }
+- }
+- }
+- }
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax);
+-
+- } else { /* (301,) 301B */
+-
+- if(SiS_Is301B(SiS_Pr,BaseAddr)) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0x3F);
+- }
+-
+- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
+- SiS_DisplayOff(SiS_Pr);
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ tempah = 0xef;
++ if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ if(modenum > 0x13) {
++ tempah = 0xf7;
++ }
++ }
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ }
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ if((SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
++ (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)))) {
++ if((!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
++ (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)))) {
++ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 2);
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
++ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 4);
++ }
++ }
++ }
++ }
++
++ }
+
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00);
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp);
+-
+- }
+-#endif
+ } else { /* 315, 330 - all bridge types */
+
+ if(SiS_Is301B(SiS_Pr,BaseAddr)) {
+@@ -5193,13 +5344,13 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ }
+
+- } else { /* ============ TW: For 301 ================ */
++ } else { /* ============ For 301 ================ */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x0B);
+- SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 1);
+- }
++ if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
++ }
+ }
+
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF); /* disable VB */
+@@ -5218,18 +5369,23 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x00,temp);
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF); /* disable CRT2 */
++ if( (!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) ||
++ (!(SiS_CR36BIOSWord23d(SiS_Pr,HwDeviceExtension))) ) {
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
++ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
++ }
+ }
+
+ }
+
+- } else { /* ============ TW: For LVDS =============*/
++ } else { /* ============ For LVDS =============*/
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+
+ #ifdef SIS300 /* 300 series */
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+- SiS_SetCH700x(SiS_Pr,0x090E);
++ SiS_SetCH700x(SiS_Pr,0x090E);
+ }
+
+ if(HwDeviceExtension->jChipType == SIS_730) {
+@@ -5245,17 +5401,17 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+
+- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) {
++ if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) {
+
+- SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
++ SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
+
+- if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
+- SiS_DisplayOff(SiS_Pr);
+- }
++ if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
++ SiS_DisplayOff(SiS_Pr);
++ }
+
+- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
+- }
++ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
++ }
+ }
+ }
+ }
+@@ -5279,29 +5435,40 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ } else {
+
+-#ifdef SIS315H /* 310/325 series */
++#ifdef SIS315H /* 315 series */
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+- temp = SiS_GetCH701x(SiS_Pr,0x61);
+- if(temp < 1) {
+- SiS_SetCH701x(SiS_Pr,0xac76);
+- SiS_SetCH701x(SiS_Pr,0x0066);
+- }
+-
+- if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ temp = SiS_GetCH701x(SiS_Pr,0x61);
++ if(temp < 1) {
++ SiS_SetCH701x(SiS_Pr,0xac76);
++ SiS_SetCH701x(SiS_Pr,0x0066);
++ }
++
++ if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_SetCH701x(SiS_Pr,0x3e49);
+- } else if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ } else if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ SiS_SetCH701x(SiS_Pr,0x3e49);
++ }
+ }
+-
++
+ if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_Chrontel701xBLOff(SiS_Pr);
+- SiS_Chrontel701xOff(SiS_Pr);
++ SiS_Chrontel701xOff(SiS_Pr,HwDeviceExtension);
+ } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ SiS_Chrontel701xBLOff(SiS_Pr);
+- SiS_Chrontel701xOff(SiS_Pr);
++ SiS_Chrontel701xOff(SiS_Pr,HwDeviceExtension);
+ }
+-
++
++ if(HwDeviceExtension->jChipType != SIS_740) {
++ if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ SiS_SetCH701x(SiS_Pr,0x0149);
++ } else if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_SetCH701x(SiS_Pr,0x0149);
++ }
++ }
++
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+@@ -5325,6 +5492,10 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+ }
+
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
++ }
++
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+@@ -5337,15 +5508,27 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ if(SiS_CRT2IsLCD(SiS_Pr, BaseAddr,HwDeviceExtension)) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
++ if(HwDeviceExtension->jChipType == SIS_550) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
++ }
++ }
++ } else {
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+ }
+- } else if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
++ } else {
++ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
++ }
++ }
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+ if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff);
++ /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
+ }
+@@ -5353,7 +5536,10 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr);
+
+- if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
++ if(HwDeviceExtension->jChipType == SIS_550) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
++ } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
+ } else if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
+@@ -5361,7 +5547,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
+ }
+
+-#if 0 /* TW: BIOS code makes no sense */
++#if 0 /* BIOS code makes no sense */
+ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ if(!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+@@ -5387,7 +5573,6 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
+
+ }
+
+-/* TW: Checked against all BIOSes */
+ void
+ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+ {
+@@ -5400,7 +5585,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* TW: ====== For 301B et al ====== */
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* ====== For 301B et al ====== */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+
+@@ -5497,48 +5682,95 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+
+ } else {
+
+-#ifdef SIS315H /* 310/325 series */
++#ifdef SIS315H /* 315 series */
+
+- if(IS_SIS650740) { /* 650 */
++ if(IS_SIS550650740660) { /* 550, 650, 740, 660 */
+
+ #if 0
+ if(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x00) != 1) return; /* From 1.10.7w */
+ #endif
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+-
+- SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef); /* 1.10.7u */
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); /* 1.10.7u */
++
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef); /* 1.10.7u */
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); /* 1.10.7u */
++ }
+
+ if(!(IS_SIS740)) {
+ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ tempah = 0x10;
+- if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- tempah = 0x08;
+- }
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
++ if((SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
++ tempah = 0x08;
++ } else {
++ tempah = 0x18;
++ }
++ }
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ } else {
++ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ tempah = 0x08;
++ }
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ }
+ }
+ }
+
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
+- SiS_DisplayOff(SiS_Pr);
+- pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
+- if(IS_SIS740) {
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
++ SiS_DisplayOff(SiS_Pr);
++ pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
++ if(IS_SIS740) {
++ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
++ }
+ }
+
+ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
+- if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 2);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 2);
+- }
++ if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 2);
++ }
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
++ SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 2);
++ }
++ }
++
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ if(!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
++ SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
++ delaylong = TRUE;
++ }
++ }
++
++ } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
++
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x10);
++ }
++ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
++ (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 0);
++ }
+ }
+
+- if(!(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
+- delaylong = TRUE;
++ } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ tempah = 0x10;
++ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
++ tempah = 0x18;
++ if((SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
++ tempah = 0x08;
++ }
++ }
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
++ }
+ }
+
+ }
+@@ -5547,13 +5779,17 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+ if(SiS_BridgeInSlave(SiS_Pr)) {
+ tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
+- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
++ if(!(tempah & SetCRT2ToRAMDAC)) {
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ if(!(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x13) & 0x04)) temp |= 0x20;
++ } else temp |= 0x20;
++ }
+ }
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
+
+ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+ temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2e);
+ if(!(temp & 0x80)) {
+@@ -5565,12 +5801,12 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ }
+
+ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+ }
+
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) || (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280)) {
+ temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2e);
+ if(!(temp & 0x80)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+@@ -5586,7 +5822,9 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ }
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
++ ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
++ (!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+ }
+
+@@ -5595,186 +5833,144 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00); /* All this from 1.10.7u */
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x05);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x60);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
+-
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
+-
++
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x08);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x10);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x4d);
++ if((SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0x0f) != 0x02) {
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x0d);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x70);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x6b);
++ }
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
++
++ } else {
++
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x12);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0xd0);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x6b);
++ if((SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0x0f) == 0x02) { /* @@@@ really == ? */
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x0d);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x70);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x40);
++ if(((SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xf0) != 0x03)) {
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x05);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x60);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x33); /* 00 */
++ }
++ }
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
++ if((SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0x0f) != 0x03) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
++ }
++ }
++
++ if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
++ }
++
+ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10); /* 1.10.8r */
+
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+ ((SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) ) {
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
+- if(delaylong) {
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
+- }
+- SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01);
+- }
+- }
++ SiS_DisplayOn(SiS_Pr);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
++ SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
++ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01);
++ }
++ }
+
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax);
+- SiS_DisplayOn(SiS_Pr);
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff);
++ } else {
+
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+- }
+-#if 0
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x31,0x05); /* 1.10.8r: 0x0d */
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x32,0x60); /* 1.10.8r: 0x70 */
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x33,0x00); /* 1.10.8r: 0x40 */
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
+-#endif
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+- }
++ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
++ ((SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) ) {
++ SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
++ if(delaylong) {
++ SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
++ }
++ SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01);
++ }
++ }
+
+-#if 0
+- } else if(IS_SIS740) { /* 740 */
+-
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) { /* 30xLV */
+-
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0x00);
+- SiS_DisplayOff(SiS_Pr);
+- pushax = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x06);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+-
+- if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+- (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
+- if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 3);
+- }
+- }
+-
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+- if(SiS_BridgeInSlave(SiS_Pr)) {
+- tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
+- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+- }
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax);
++ SiS_DisplayOn(SiS_Pr);
++ SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff);
+
+- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 2);
+- }
+-
+- if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+- }
+-
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0x10); /* (taken from 650 1.10.8r) */
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+-
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+- (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+- SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
+- }
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xfe,0x01);
+- SiS_SetPanelDelayLoop(SiS_Pr,ROMAddr, HwDeviceExtension, 3, 10);
+- SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
+- }
+- }
+-
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x06,pushax);
+- SiS_DisplayOn(SiS_Pr);
+- SiS_SetReg3(SiS_Pr->SiS_P3c6,0xff);
+-
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+- }
+-
+- } else { /* (301), 301B */
+-
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+- if(SiS_BridgeInSlave(SiS_Pr)) {
+- tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
+- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+- }
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
++ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
++ }
+
+- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
++ }
+
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
+- if(!(temp & 0x80))
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+- }
++ } if(SiS_Pr->SiS_VBType & VB_NoLCD) {
++
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
++ (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
++ }
++ }
++ }
+
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
++ }
+
+- if(SiS_Is301B(SiS_Pr,BaseAddr)) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+- } else {
+- SiS_VBLongWait(SiS_Pr);
+- SiS_DisplayOn(SiS_Pr);
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F);
+- SiS_VBLongWait(SiS_Pr);
+- }
+-
+- }
+-#endif
+-
+ } else { /* 315, 330 */
+
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+- if(SiS_BridgeInSlave(SiS_Pr)) {
+- tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
+- if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+- }
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
++ if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
++ if(SiS_BridgeInSlave(SiS_Pr)) {
++ tempah = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x30);
++ if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
++ }
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x32,temp);
+
+- SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
++ SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20); /* enable CRT2 */
+
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
+- if(!(temp & 0x80))
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+- }
++ temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
++ if(!(temp & 0x80))
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
++ }
+
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+
+- if(SiS_Is301B(SiS_Pr,BaseAddr)) {
++ if(SiS_Is301B(SiS_Pr,BaseAddr)) {
+
+- temp=SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
+- if (!(temp & 0x80))
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
++ temp=SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
++ if(!(temp & 0x80))
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
++
++ tempah = 0xc0;
++ if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ tempah = 0x80;
++ if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ tempah = 0x40;
++ }
++ }
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+
+- tempah = 0xc0;
+- if(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- tempah = 0x80;
+- if(!(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- tempah = 0x40;
+- }
+- }
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
++ } else {
+
+- } else {
+-
+- SiS_VBLongWait(SiS_Pr);
+- SiS_DisplayOn(SiS_Pr);
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F);
+- SiS_VBLongWait(SiS_Pr);
++ SiS_VBLongWait(SiS_Pr);
++ SiS_DisplayOn(SiS_Pr);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F);
++ SiS_VBLongWait(SiS_Pr);
+
+- }
++ }
+
+ } /* 315, 330 */
+
+@@ -5782,11 +5978,11 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+
+ }
+
+- } else { /* ============ TW: For 301 ================ */
++ } else { /* ============ For 301 ================ */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) {
+- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x0B);
++ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 0);
+ }
+ }
+@@ -5818,13 +6014,13 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) {
+ SiS_SetPanelDelay(SiS_Pr, ROMAddr, HwDeviceExtension, 1);
+- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF0,0x03);
++ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+ }
+ }
+
+ }
+
+- } else { /* =================== TW: For LVDS ================== */
++ } else { /* =================== For LVDS ================== */
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+
+@@ -5847,35 +6043,35 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension, BaseAddr);
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+ if(SiS_BridgeInSlave(SiS_Pr)) {
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+ } else {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+- if(!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) {
+- SiS_SetCH700x(SiS_Pr,0x0B0E);
+- }
++ if(!(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension))) {
++ SiS_SetCH700x(SiS_Pr,0x0B0E);
++ }
+ }
+
+ if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) {
+- if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+- if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+- if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) {
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
+- SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
+- }
+- SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
+- SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+- }
+- }
++ if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
++ if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
++ if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwDeviceExtension))) {
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
++ SiS_SetPanelDelay(SiS_Pr,ROMAddr, HwDeviceExtension, 1);
++ }
++ SiS_WaitVBRetrace(SiS_Pr,HwDeviceExtension);
++ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
++ }
++ }
+ }
+
+ #endif /* SIS300 */
+
+ } else {
+
+-#ifdef SIS315H /* 310/325 series */
++#ifdef SIS315H /* 315 series */
+
+ #if 0 /* BIOS code makes no sense */
+ if(SiS_IsVAMode()) {
+@@ -5902,36 +6098,41 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ SiS_Chrontel701xBLOff(SiS_Pr);
+ }
+
+- SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+-
+-#ifdef NEWCH701x
+- if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+- if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension,BaseAddr)) {
++ if(HwDeviceExtension->jChipType != SIS_550) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
++ }
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
++ if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension,BaseAddr)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+- }
++ }
++ }
+ }
+-#endif
+
+ temp1 = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x2E);
+- if (!(temp1 & 0x80))
++ if(!(temp1 & 0x80))
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(temp) {
+- SiS_Chrontel701xBLOn(SiS_Pr);
++ SiS_Chrontel701xBLOn(SiS_Pr, HwDeviceExtension);
+ }
+ }
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ if(SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) {
+ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
++ if(HwDeviceExtension->jChipType == SIS_550) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
++ }
++ }
++ } else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ if(HwDeviceExtension->jChipType != SIS_740) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ }
+- }
+-#ifndef NEWCH701x
+- else if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+ }
+-#endif
+
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+@@ -5954,10 +6155,10 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_Chrontel701xBLOn(SiS_Pr);
++ SiS_Chrontel701xBLOn(SiS_Pr, HwDeviceExtension);
+ SiS_ChrontelDoSomething4(SiS_Pr,HwDeviceExtension, BaseAddr);
+ } else if(SiS_IsLCDOrLCDA(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_Chrontel701xBLOn(SiS_Pr);
++ SiS_Chrontel701xBLOn(SiS_Pr, HwDeviceExtension);
+ SiS_ChrontelDoSomething4(SiS_Pr,HwDeviceExtension, BaseAddr);
+ }
+ }
+@@ -5983,7 +6184,7 @@ SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS
+ {
+ USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress;
+
+- /* TW: Switch on LCD backlight on SiS30xLV */
++ /* Switch on LCD backlight on SiS30xLV */
+ if( (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ||
+ (SiS_CRT2IsLCD(SiS_Pr,BaseAddr,HwDeviceExtension)) ) {
+ if(!(SiS_GetReg1(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+@@ -6001,7 +6202,7 @@ SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSI
+ {
+ USHORT BaseAddr = (USHORT)HwDeviceExtension->ulIOAddress;
+
+- /* TW: Switch off LCD backlight on SiS30xLV */
++ /* Switch off LCD backlight on SiS30xLV */
+ if( (!(SiS_IsDualEdge(SiS_Pr,HwDeviceExtension, BaseAddr))) ||
+ (SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) ) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xFE,0x00);
+@@ -6023,12 +6224,14 @@ SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr,
+ UCHAR *ROMAddr;
+
+ if((ROMAddr = (UCHAR *)HwDeviceExtension->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff;
+- temp >>= 4;
+- temp = 1 << temp;
+- temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b];
+- if(temp1 & temp) return(1);
+- else return(0);
++ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff;
++ temp >>= 4;
++ temp = 1 << temp;
++ temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b];
++ if(temp1 & temp) return(1);
++ else return(0);
++ } else return(0);
+ } else {
+ return(0);
+ }
+@@ -6041,12 +6244,14 @@ SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr,
+ UCHAR *ROMAddr;
+
+ if((ROMAddr = (UCHAR *)HwDeviceExtension->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff;
+- temp >>= 4;
+- temp = 1 << temp;
+- temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d];
+- if(temp1 & temp) return(1);
+- else return(0);
++ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xff;
++ temp >>= 4;
++ temp = 1 << temp;
++ temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d];
++ if(temp1 & temp) return(1);
++ else return(0);
++ } else return(0);
+ } else {
+ return(0);
+ }
+@@ -6143,7 +6348,7 @@ SiS_SetPanelDelay(SiS_Private *SiS_Pr, U
+
+ #ifdef SIS315H
+
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 310/325 series, LVDS */
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 315 series, LVDS */
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+ PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36);
+@@ -6171,7 +6376,7 @@ SiS_SetPanelDelay(SiS_Private *SiS_Pr, U
+ SiS_ShortDelay(SiS_Pr,Delay);
+ }
+
+- } else { /* 310/325 series, 301(B) */
++ } else { /* 315 series, 301(B) */
+
+ PanelID = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36);
+ DelayIndex = PanelID >> 4;
+@@ -6271,14 +6476,7 @@ SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_H
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38);
+ if((flag & EnableDualEdge) && (flag & SetToLCDA)) return(1);
+-#if 0 /* Not done in 650/30xLV 1.10.6s, but in 650/301LV */
+- else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(flag) return(1);
+- else return(0);
+- }
+-#endif
+- else
+- return(0);
++ else return(0);
+ } else
+ #endif
+ return(0);
+@@ -6325,7 +6523,9 @@ SiS_IsNotM650or651(SiS_Private *SiS_Pr,
+ if(HwDeviceExtension->jChipType == SIS_650) {
+ flag = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f);
+ flag &= 0xF0;
+- if((flag == 0xb0) || (flag == 0x90)) return 0;
++ /* Check for revision != A0 only */
++ if((flag == 0xe0) || (flag == 0xc0) ||
++ (flag == 0xb0) || (flag == 0x90)) return 0;
+ else return 1;
+ } else
+ #endif
+@@ -6443,7 +6643,7 @@ SiS_BridgeIsEnable(SiS_Private *SiS_Pr,
+ if((flag == 0x80) || (flag == 0x20)) return 0;
+ else return 1;
+ } else {
+- /* 310/325 series (650/30xLV 1.10.6s) */
++ /* 315 series (650/30xLV 1.10.6s) */
+ flag &= 0x50;
+ if((flag == 0x40) || (flag == 0x10)) return 0;
+ else return 1;
+@@ -6487,14 +6687,14 @@ SiS_SetHiVision(SiS_Private *SiS_Pr, USH
+ }
+ }
+
+-BOOLEAN
++void
+ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT temp,modeflag,resinfo=0;
+ const unsigned char SiS300SeriesLCDRes[] =
+- { 0, 1, 2, 3, 7, 4, 5, 8,
+- 0, 0, 0, 0, 0, 0, 0, 0 };
++ { 0, 1, 2, 3, 7, 4, 5, 8,
++ 0, 0, 10, 0, 0, 0, 0, 15 };
+
+ SiS_Pr->SiS_LCDResInfo = 0;
+ SiS_Pr->SiS_LCDTypeInfo = 0;
+@@ -6511,17 +6711,19 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ }
+ }
+
+- if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return 0;
++ if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
+
+- if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2))) return 0;
++ if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2))) return;
+
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36);
+
++#if 0
+ /* FSTN: Fake CR36 (TypeInfo 2, ResInfo SiS_Panel320x480) */
+ if(SiS_Pr->SiS_IF_DEF_FSTN) {
+ temp = 0x20 | SiS_Pr->SiS_Panel320x480;
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,temp);
+ }
++#endif
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
+@@ -6530,14 +6732,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ }
+ temp &= 0x0f;
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+- /* TW: Translate 300 series LCDRes to 310/325 series for unified usage */
++ /* Translate 300 series LCDRes to 315 series for unified usage */
+ temp = SiS300SeriesLCDRes[temp];
+ }
+ SiS_Pr->SiS_LCDResInfo = temp;
+
++#if 0
+ if(SiS_Pr->SiS_IF_DEF_FSTN){
+ SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel320x480;
+ }
++#endif
+
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+ if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
+@@ -6547,75 +6751,115 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+ }
+
+- if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax)
++ if((!SiS_Pr->CP_HaveCustomData) || (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_PanelCustom)) {
++ if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax)
+ SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel1024x768;
++ }
++
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
++ SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
++ } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
++ SiS_Pr->SiS_LCDResInfo = Panel_848x480;
++ }
++ }
++
++ switch(SiS_Pr->SiS_LCDResInfo) {
++ case Panel_800x600: SiS_Pr->PanelXRes = 800; SiS_Pr->PanelYRes = 600; break;
++ case Panel_1024x768: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; break;
++ case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; break;
++ case Panel_640x480_3:
++ case Panel_640x480_2:
++ case Panel_640x480: SiS_Pr->PanelXRes = 640; SiS_Pr->PanelYRes = 480; break;
++ case Panel_1024x600: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 600; break;
++ case Panel_1152x864: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 864; break;
++ case Panel_1280x960: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 960; break;
++ case Panel_1152x768: SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes = 768; break;
++ case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; break;
++ case Panel_1280x768: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 768; break;
++ case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; break;
++ case Panel_320x480: SiS_Pr->PanelXRes = 320; SiS_Pr->PanelYRes = 480; break;
++ case Panel_Custom: SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
++ SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
++ break;
++ case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; break;
++ case Panel_848x480: SiS_Pr->PanelXRes = 848; SiS_Pr->PanelYRes = 480; break;
++ default: SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes = 768; break;
++ }
+
+ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37);
++#if 0
+ if(SiS_Pr->SiS_IF_DEF_FSTN){
+- /* TW: Fake LVDS bridge for FSTN */
++ /* Fake LVDS bridge for FSTN */
+ temp = 0x04;
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,temp);
+ }
++#endif
+ SiS_Pr->SiS_LCDInfo = temp;
+-
++
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
++ if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
++ SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20; /* neg sync, RGB24 */
++ }
++ }
++
+ if(!(SiS_Pr->UsePanelScaler)) SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+ else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+
+- /* TW: Inserted entire 315-block from 650/LVDS/30xLV BIOSes */
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
++ /* For non-standard LCD resolution, we let the panel scale */
++ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e) {
++ /* Bridge does not scale to 1280x960 */
++ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
++ }
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
++ /* TEMP - no idea about the timing and zoom factors */
++ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
++ if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
++ /* Bridge does not scale to 1280x1024 */
++ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
++ }
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
++ /* TEMP - no idea about the timing and zoom factors */
++ SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
++ }
++ }
++ }
++
++
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ #ifdef SIS315H
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
+- /* Bridge does not scale to 1280x1024 */
+- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+- }
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e) {
+- /* TW: Bridge does not scale to 1280x960 */
+- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+- }
+- if(ModeNo == 0x2f || ModeNo == 0x5d || ModeNo == 0x5e) {
+- /* TW: Bridge does not scale to 640x400 */
+- SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+- }
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if(ModeNo == 0x2f || ModeNo == 0x5d || ModeNo == 0x5e) {
+- /* TW: Most panels can't scale to 640x400 */
+- SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+- }
+- }
+- }
+- }
+ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x01) {
+- SiS_Pr->SiS_LCDInfo &= 0xFFEF;
+- SiS_Pr->SiS_LCDInfo |= LCDPass11;
++ SiS_Pr->SiS_LCDInfo &= 0xFFEF;
++ SiS_Pr->SiS_LCDInfo |= LCDPass11;
+ }
+ #endif
+ } else {
+ #ifdef SIS300
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+- if(!(ROMAddr[0x235] & 0x02)) {
+- SiS_Pr->SiS_LCDInfo &= 0xEF;
++ if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
++ if(!(ROMAddr[0x235] & 0x02)) {
++ SiS_Pr->SiS_LCDInfo &= 0xEF;
++ }
+ }
+ }
+- } else {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
+- SiS_Pr->SiS_LCDInfo &= 0xEF;
+- }
++ } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
++ SiS_Pr->SiS_LCDInfo &= 0xEF;
+ }
+ }
+ #endif
+ }
+-
+- /* TW: With Trumpion, always Expanding */
+- if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0){
+- SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
++
++ /* Trumpion: Assume non-expanding */
++ if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
++ SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+ }
+
+ if(!((HwDeviceExtension->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
+@@ -6624,7 +6868,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+ if(ModeNo > 0x13) {
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+- if((resinfo == 7) || (resinfo == 3)) {
++ if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+ SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ }
+ }
+@@ -6644,9 +6888,9 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480))) {
+ if(ModeNo > 0x13) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if(resinfo == 4) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; /* 512x384 */
++ if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+- if(resinfo == 3) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA; /* 400x300 */
++ if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+ }
+ }
+ } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+@@ -6665,19 +6909,21 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ }
+
+ #ifdef SIS315H
+- /* TW: 650/30xLV 1.10.6s */
++ /* 650/30xLV 1.10.6s */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_VBType & (VB_SIS302B | VB_SIS302LV)) {
+- /* Enable 302B/302LV dual link mode */
+- /* (302B is a theory - not in any BIOS */
+- temp = 0x00;
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) temp = 0x04;
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x04;
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) temp = 0x04;
+- SiS_SetReg1(SiS_Pr->SiS_P3d4,0x39,temp);
+- } else if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- SiS_SetReg1(SiS_Pr->SiS_P3d4,0x39,0x00);
+- }
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,~0x04);
++ if(SiS_Pr->SiS_VBType & (VB_SIS302B | VB_SIS302LV)) {
++ /* Enable 302B/302LV dual link mode.
++ * (302B is a theory - not in any BIOS)
++ */
++ if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
++ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x39,0x04);
++ }
++ }
++ }
+ }
+ #endif
+
+@@ -6693,20 +6939,6 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
+ SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
+ #endif
+
+- return 1;
+-}
+-
+-void
+-SiS_PresetScratchregister(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+-{
+- return;
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x30,0x21); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x31,0x41); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x32,0x28); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x33,0x22); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x35,0x43); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x36,0x01); */
+- /*SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x00); */
+ }
+
+ void
+@@ -6736,7 +6968,6 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
+ } else {
+ SiS_LongWait(SiS_Pr);
+ }
+- return;
+ }
+
+ void
+@@ -6803,7 +7034,7 @@ SiS_WaitRetrace1(SiS_Private *SiS_Pr, PS
+ #endif
+ } else {
+ #ifdef SIS300
+-#if 0 /* TW: Not done in A901 BIOS */
++#if 0 /* Not done in A901 BIOS */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
+ }
+@@ -6898,7 +7129,51 @@ void SiS_SetRegOR(USHORT Port,USHORT Ind
+
+ /* ========================================================= */
+
+-/* TW: Set 301 TV Encoder (and some LCD relevant) registers */
++static void
++SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
++{
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
++ if((ModeNo == 0x64) || (ModeNo == 0x4a) || (ModeNo == 0x38)) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1c,0xa7);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1d,0x07);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1e,0xf2);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1f,0x6e);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x20,0x17);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,0x8b);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x22,0x73);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,0x53);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,0x13);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x25,0x40);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x26,0x34);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,0xf4);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x28,0x63);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x29,0xbb);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2a,0xcc);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2b,0x7a);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2c,0x58); /* 48 */
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2d,0xe4);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2e,0x73);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,0xda); /* de */
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0x13);
++ if((SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38)) & 0x40) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x14);
++ } else {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x15);
++ }
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x1b);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,0x72);
++ }
++ } else {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x21);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x5a);
++ }
++ }
++ }
++}
++
++/* Set 301 TV Encoder (and some LCD relevant) registers */
+ void
+ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr, USHORT ModeNo,
+ USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
+@@ -6911,67 +7186,46 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ #ifdef SIS315H
+ const SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+ USHORT resindex, CRT2Index;
+-#endif
++#endif
+ USHORT modeflag, resinfo, crt2crtc;
+- ULONG longtemp, tempeax, tempebx, temp2, tempecx;
++ ULONG longtemp, tempeax;
++#ifdef SIS300
+ const UCHAR atable[] = {
+ 0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
+ 0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
+ };
++#endif
+
+ #ifdef SIS315H
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+- /* TW: 650/30xLV 1.10.6s: (Is at end of SetGroup2!) */
++ /* 650/30xLV 1.10.6s: (Is at end of SetGroup2!) */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xfc,0x03);
+- temp = 1;
+- if(ModeNo <= 0x13) temp = 3;
++ temp = 0x01;
++ if(ModeNo <= 0x13) temp = 0x03;
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0b,temp);
+ }
+ }
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((ModeNo == 0x4a) || (ModeNo == 0x38)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1c,0xa7);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1d,0x07);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1e,0xf2);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1f,0x6e);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x20,0x17);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,0x8b);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x22,0x73);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,0x53);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,0x13);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x25,0x40);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x26,0x34);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,0xf4);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x28,0x63);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x29,0xbb);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2a,0xcc);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2b,0x7a);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2c,0x58);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2d,0xe4);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2e,0x73);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,0xda);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0x13);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,0x72);
+- }
+- }
+- }
+- }
++ SiS_SetTVSpecial(SiS_Pr, ModeNo);
+ return;
+ }
+-#endif
++#endif
+
+- if(ModeNo<=0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+- crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
++ if(ModeNo <= 0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ resinfo = 0;
++ crt2crtc = 0;
++ } else {
++ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
++ }
+ }
+
+ tempcx = SiS_Pr->SiS_VBInfo;
+@@ -6984,9 +7238,9 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ temp |= ((tempbx & 0x00FF) >> 3);
+ temp ^= 0x0C;
+
+- /* TW: From 1.10.7w (no vb check there; don't care - this only disables SVIDEO and CVBS signal) */
++ /* From 1.10.7w (no vb check there; don't care - this only disables SVIDEO and CVBS signal) */
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- temp |= 0x0c;
++ temp |= 0x0c;
+ }
+
+ PhasePoint = SiS_Pr->SiS_PALPhase;
+@@ -6994,44 +7248,44 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+
+- temp ^= 0x01;
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
+- if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- if(modeflag & Charx8Dot) TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
+- else TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
+- }
+- } else TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
+-
+- if(SiS_Pr->SiS_HiVision & 0x03) temp &= 0xfe;
+-
++ temp ^= 0x01;
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
++ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
++ if(modeflag & Charx8Dot) TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
++ else TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
++ }
++ } else TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
++
++ if(SiS_Pr->SiS_HiVision & 0x03) temp &= 0xfe;
++
+ } else {
+-
+- if(SiS_Pr->SiS_VBInfo & SetPALTV){
+
+- TimingPoint = SiS_Pr->SiS_PALTiming;
+- PhasePoint = SiS_Pr->SiS_PALPhase;
++ if(SiS_Pr->SiS_VBInfo & SetPALTV){
+
+- if( (SiS_Pr->SiS_VBType & VB_SIS301B302B) &&
+- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
+- PhasePoint = SiS_Pr->SiS_PALPhase2;
+- }
++ TimingPoint = SiS_Pr->SiS_PALTiming;
++ PhasePoint = SiS_Pr->SiS_PALPhase;
+
+- } else {
++ if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
++ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
++ PhasePoint = SiS_Pr->SiS_PALPhase2;
++ }
++
++ } else {
+
+ temp |= 0x10;
+- TimingPoint = SiS_Pr->SiS_NTSCTiming;
+- PhasePoint = SiS_Pr->SiS_NTSCPhase;
++ TimingPoint = SiS_Pr->SiS_NTSCTiming;
++ PhasePoint = SiS_Pr->SiS_NTSCPhase;
+
+- if( (SiS_Pr->SiS_VBType & VB_SIS301B302B) &&
++ if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+ (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
+- PhasePoint = SiS_Pr->SiS_NTSCPhase2;
++ PhasePoint = SiS_Pr->SiS_NTSCPhase2;
+ }
+
+- }
+-
++ }
++
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,temp);
+
+@@ -7044,36 +7298,35 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ temp = 0x38;
+ }
+ if(temp) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
+- temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,temp);
+- if(temp1 & EnablePALM) { /* 0x40 */
+- PhasePoint = SiS_Pr->SiS_PALMPhase;
+- if( (SiS_Pr->SiS_VBType & VB_SIS301B302B) &&
+- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
+- PhasePoint = SiS_Pr->SiS_PALMPhase2;
+- }
+- }
+- if(temp1 & EnablePALN) { /* 0x80 */
+- PhasePoint = SiS_Pr->SiS_PALNPhase;
+- if( (SiS_Pr->SiS_VBType & VB_SIS301B302B) &&
+- ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+- (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
+- PhasePoint = SiS_Pr->SiS_PALNPhase2;
+- }
+- }
+- }
+- }
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
++ temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,temp);
++ if(temp1 & EnablePALM) { /* 0x40 */
++ PhasePoint = SiS_Pr->SiS_PALMPhase;
++ if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
++ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
++ PhasePoint = SiS_Pr->SiS_PALMPhase2;
++ }
++ }
++ if(temp1 & EnablePALN) { /* 0x80 */
++ PhasePoint = SiS_Pr->SiS_PALNPhase;
++ if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
++ ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
++ (SiS_Pr->SiS_SetFlag & TVSimuMode) ) ) {
++ PhasePoint = SiS_Pr->SiS_PALNPhase2;
++ }
++ }
++ }
++ }
+ }
+
+ #ifdef SIS315H
+- /* TW: 650/301LV BIOS */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((ModeNo == 0x4a) || (ModeNo == 0x38)) {
++ if((ModeNo == 0x64) || (ModeNo == 0x4a) || (ModeNo == 0x38)) {
+ PhasePoint = SiS_Pr->SiS_SpecialPhase;
+ }
+ }
+@@ -7094,12 +7347,12 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(!(SiS_Pr->SiS_ModeType & 0x07))
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(!(SiS_Pr->SiS_ModeType & 0x07))
++ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
++ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
+- } else {
+- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x3A,0x1F);
+- }
++ }
+ }
+
+ SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x0A,SiS_Pr->SiS_NewFlickerMode);
+@@ -7110,11 +7363,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+- if(SiS_Pr->SiS_HiVision == 3) tempax = 950;
+- else tempax = 440;
++ if(SiS_Pr->SiS_HiVision == 3) tempax = 950;
++ else tempax = 440;
+ } else {
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) tempax = 520;
+- else tempax = 440;
++ if(SiS_Pr->SiS_VBInfo & SetPALTV) tempax = 520;
++ else tempax = 440;
+ }
+
+ if( ( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_HiVision == 3) ) && (SiS_Pr->SiS_VDE <= tempax) ) ||
+@@ -7134,18 +7387,18 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,temp);
+
+ if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) &&
+- (SiS_Pr->SiS_HiVision != 3) &&
+- (SiS_Pr->SiS_VGAHDE >= 1024) ) {
++ (SiS_Pr->SiS_HiVision != 3) &&
++ (SiS_Pr->SiS_VGAHDE >= 1024) ) {
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x19);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x52);
+ } else {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x17);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x1d);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x17);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x1d);
+ } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x0b);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x11);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x0b);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x11);
+ }
+ }
+ }
+@@ -7154,7 +7407,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+
+ tempcx = SiS_Pr->SiS_HT;
+
+- /* TW: 650/30xLV 1.10.6s */
++ /* 650/30xLV 1.10.6s */
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) {
+ tempcx >>= 1;
+@@ -7181,7 +7434,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ tempcx += 7;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+ (SiS_Pr->SiS_HiVision == 3)) {
+- tempcx -= 4;
++ tempcx -= 4;
+ }
+ temp = (tempcx & 0x00FF) << 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,temp);
+@@ -7201,8 +7454,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ tempbx += 8;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+ (SiS_Pr->SiS_HiVision == 3)) {
+- tempbx -= 4;
+- tempcx = tempbx;
++ tempbx -= 4;
++ tempcx = tempbx;
+ }
+ temp = (tempbx & 0x00FF) << 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
+@@ -7231,8 +7484,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+
+ tempcx -= 11;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+- tempax = SiS_GetVGAHT2(SiS_Pr) - 1;
+- tempcx = tempax;
++ tempax = SiS_GetVGAHT2(SiS_Pr) - 1;
++ tempcx = tempax;
+ }
+ temp = tempcx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2E,temp);
+@@ -7242,38 +7495,38 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
+ if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1;
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1;
+ } else {
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) {
+- tempbx >>= 1;
+- if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- if(ModeNo <= 0x13) {
+- if(crt2crtc == 1) {
+- tempbx++;
+- }
+- }
+- } else {
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if(crt2crtc == 4) /* TW: BIOS calls GetRatePtrCRT2 here - does not make sense */
+- if(SiS_Pr->SiS_ModeType <= 3) tempbx++;
+- }
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) {
++ tempbx >>= 1;
++ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
++ if(ModeNo <= 0x13) {
++ if(crt2crtc == 1) {
++ tempbx++;
++ }
+ }
+- }
++ } else {
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ if(crt2crtc == 4) /* BIOS calls GetRatePtrCRT2 here - does not make sense */
++ if(SiS_Pr->SiS_ModeType <= 3) tempbx++;
++ }
++ }
++ }
+ }
+ tempbx -= 2;
+ temp = tempbx & 0x00FF;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+ (SiS_Pr->SiS_HiVision == 3)) {
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if(ModeNo == 0x2f) temp++;
+- }
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) temp++;
++ }
+ }
+- /* TW: From 1.10.7w - doesn't make sense */
++ /* From 1.10.7w - doesn't make sense */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) { /* SetFlag?? */
+- if(ModeNo == 0x03) temp++;
++ if(ModeNo == 0x03) temp++;
+ }
+ }
+ }
+@@ -7285,15 +7538,15 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ tempax |= (tempbx & 0xFF00);
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) {
+- if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)) { /* TW: New from 630/301B (II) BIOS */
++ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)) { /* New from 630/301B (II) BIOS */
+ tempax |= 0x1000;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) tempax |= 0x2000;
+ }
+ }
+ } else {
+ /* TODO Check this with other BIOSes */
+- if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV)) &&
+- (SiS_Pr->SiS_HiVision == 3)) {
++ if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV))
++ /* && (SiS_Pr->SiS_HiVision == 3) */ ) {
+ tempax |= 0x1000;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) tempax |= 0x2000;
+ }
+@@ -7301,12 +7554,12 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ temp = (tempax & 0xFF00) >> 8;
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,temp);
+
+- /* TW: 650/30xLV 1.10.6s */
++ /* 650/30xLV 1.10.6s */
+ if(HwDeviceExtension->jChipType > SIS_315H) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
+ }
+ }
+ }
+@@ -7322,79 +7575,70 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ }
+ }
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- tempbx = SiS_Pr->SiS_VDE;
+- if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) {
+- tempbx >>= 1;
+- }
+- tempbx -= 3;
+- tempbx &= 0x03ff;
+- temp = ((tempbx & 0xFF00) >> 8) << 5;
+- temp |= 0x18;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x46,temp);
+- temp = tempbx & 0x00FF;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x47,temp); /* tv gatingno */
+- if(HwDeviceExtension->jChipType >= SIS_315H) { /* TW: 650/30xLV 1.10.6s */
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- tempax = 0;
+- if(SiS_Pr->SiS_HiVision & 0x03) {
+- tempax = 0x3000;
+- if(SiS_Pr->SiS_HiVision & 0x01) tempax = 0x5000;
+- }
+- temp = (tempax & 0xFF00) >> 8;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4d,temp);
+- }
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ tempbx = SiS_Pr->SiS_VDE;
++ if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (!(SiS_Pr->SiS_HiVision & 0x03))) {
++ tempbx >>= 1;
++ }
++ tempbx -= 3;
++ tempbx &= 0x03ff;
++ temp = ((tempbx & 0xFF00) >> 8) << 5;
++ temp |= 0x18;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x46,temp);
++ temp = tempbx & 0x00FF;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x47,temp); /* tv gatingno */
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ tempax = 0;
++ if(SiS_Pr->SiS_HiVision & 0x03) {
++ tempax = 0x3000;
++ if(SiS_Pr->SiS_HiVision & 0x01) tempax = 0x5000;
++ }
++ temp = (tempax & 0xFF00) >> 8;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4d,temp);
++ }
++ }
+ }
+
+ tempbx &= 0x00FF;
+ if(!(modeflag & HalfDCLK)) {
+- tempcx = SiS_Pr->SiS_VGAHDE;
+- if(tempcx >= SiS_Pr->SiS_HDE) {
+- tempbx |= 0x2000;
+- tempax &= 0x00FF;
+- }
++ if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
++ tempbx |= 0x2000;
++ tempax &= 0x00FF;
++ }
+ }
+
+ tempcx = 0x0101;
+-/*if(SiS_Pr->SiS_VBInfo & (SetPALTV | SetCRT2ToTV)) { */ /*301b- TW: BIOS BUG? */
++/*if(SiS_Pr->SiS_VBInfo & (SetPALTV | SetCRT2ToTV)) { */ /* BIOS BUG? */
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) {
+- if(!(SiS_Pr->SiS_HiVision & 0x03)) {
+- if(SiS_Pr->SiS_VGAHDE >= 1024) {
+- if((!(modeflag & HalfDCLK)) || (HwDeviceExtension->jChipType < SIS_315H)) { /* TW: This check not in 630/301B */
+- tempcx = 0x1920;
+- if(SiS_Pr->SiS_VGAHDE >= 1280) {
+- tempcx = 0x1420;
+- tempbx &= 0xDFFF;
+- }
++ if(!(SiS_Pr->SiS_HiVision & 0x03)) {
++ if(SiS_Pr->SiS_VGAHDE >= 1024) {
++ if((!(modeflag & HalfDCLK)) || (HwDeviceExtension->jChipType < SIS_315H)) {
++ tempcx = 0x1920;
++ if(SiS_Pr->SiS_VGAHDE >= 1280) {
++ tempcx = 0x1420;
++ tempbx &= 0xDFFF;
++ }
++ }
+ }
+- }
+- }
++ }
+ }
+
+ if(!(tempbx & 0x2000)) {
+- if(modeflag & HalfDCLK) {
+- tempcx = (tempcx & 0xFF00) | (((tempcx & 0x00FF) << 1) & 0xff);
+- }
+- push1 = tempbx;
+- tempeax = SiS_Pr->SiS_VGAHDE;
+- tempebx = (tempcx & 0xFF00) >> 8;
+- longtemp = tempeax * tempebx;
+- tempecx = tempcx & 0x00FF;
+- longtemp /= tempecx;
+- longtemp <<= 0x0d;
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ if(modeflag & HalfDCLK) {
++ tempcx = (tempcx & 0xFF00) | ((tempcx << 1) & 0x00FF);
++ }
++ longtemp = (SiS_Pr->SiS_VGAHDE * ((tempcx & 0xFF00) >> 8)) / (tempcx & 0x00FF);
++ longtemp <<= 13;
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ longtemp <<= 3;
+- }
+- tempecx = SiS_Pr->SiS_HDE;
+- temp2 = longtemp % tempecx;
+- tempeax = longtemp / tempecx;
+- if(temp2 != 0) tempeax++;
+- tempax = (USHORT)tempeax;
+- tempbx = push1;
+- tempcx = (tempcx & 0xff00) | (((tempax & 0xFF00) >> 8) >> 5);
+- tempbx |= (tempax & 0x1F00);
+- tempax = ((tempax & 0x00FF) << 8) | (tempax & 0x00FF);
++ }
++ tempeax = longtemp / SiS_Pr->SiS_HDE;
++ if(longtemp % SiS_Pr->SiS_HDE) tempeax++;
++ tempax = (USHORT)tempeax;
++ tempcx = (tempcx & 0xFF00) | ((tempax & 0xFF00) >> (8 + 5));
++ tempbx |= (tempax & 0x1F00);
++ tempax = ((tempax & 0x00FF) << 8) | (tempax & 0x00FF);
+ }
+
+ temp = (tempax & 0xFF00) >> 8;
+@@ -7403,33 +7647,32 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,temp);
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- temp = tempcx & 0x00FF;
+- if(tempbx & 0x2000) temp = 0;
+- temp |= 0x18;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp);
+- if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- tempbx = 0x0382;
+- tempcx = 0x007e;
+- } else {
+- tempbx = 0x0369;
+- tempcx = 0x0061;
+- }
+- temp = (tempbx & 0x00FF) ;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4B,temp);
+- temp = (tempcx & 0x00FF) ;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4C,temp);
+- tempbx &= 0x03FF;
+- temp = (tempcx & 0xFF00) >> 8;
+- temp = (temp & 0x0003) << 2;
+- temp |= (tempbx >> 8);
+- if(HwDeviceExtension->jChipType < SIS_315H) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4D,temp);
+- } else {
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4D,0xF0,temp);
+- }
++ temp = tempcx & 0x00FF;
++ if(tempbx & 0x2000) temp = 0;
++ temp |= 0x18;
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp);
+
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x43);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3));
++ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
++ tempbx = 0x0382;
++ tempcx = 0x007e;
++ } else {
++ tempbx = 0x0369;
++ tempcx = 0x0061;
++ }
++ temp = (tempbx & 0x00FF) ;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4B,temp);
++ temp = (tempcx & 0x00FF) ;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4C,temp);
++ temp = (tempcx & 0x0300) >> (8 - 2);
++ temp |= ((tempbx >> 8) & 0x03);
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x4D,temp);
++ } else {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4D,0xF0,temp);
++ }
++
++ temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x43);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3));
+ }
+
+ temp = 0;
+@@ -7440,23 +7683,33 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ temp = 0x38;
+ }
+ if(temp) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM) { /* 0x40 */
+- SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
+- temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp - 1);
+- }
+- }
+- }
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM) { /* 0x40 */
++ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
++ temp = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp - 1);
++ }
++ }
++ }
+ }
+
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((SiS_Pr->SiS_VBType & VB_SIS301B302B) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
++ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,0x00);
++ }
++ }
++ }
++
++#if 0 /* Old: Why HiVision? */
+ if( (SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) &&
+ (!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) ) {
+- if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,0x00);
+- }
++ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,0x00);
++ }
+ }
++#endif
+
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+@@ -7465,74 +7718,43 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ return;
+ }
+ } else {
+- /* TW: !!! The following is a duplicate, done for LCDA as well (see above) */
++ /* !!! The following is a duplicate, done for LCDA as well (see above) */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((ModeNo == 0x4a) || (ModeNo == 0x38)) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1c,0xa7);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1d,0x07);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1e,0xf2);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1f,0x6e);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x20,0x17);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,0x8b);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x22,0x73);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,0x53);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x24,0x13);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x25,0x40);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x26,0x34);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x27,0xf4);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x28,0x63);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x29,0xbb);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2a,0xcc);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2b,0x7a);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2c,0x58);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2d,0xe4);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2e,0x73);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,0xda);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0x13);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x43,0x72);
+- }
+- }
+- }
+- }
+- return;
++ SiS_SetTVSpecial(SiS_Pr, ModeNo);
++ return;
+ }
+ }
+
+- /* TW: From here: Part2 LCD setup */
++ /* From here: Part2 LCD setup */
+
+ tempbx = SiS_Pr->SiS_HDE;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- /* TW: 650/30xLV 1.10.6s */
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1;
++ /* 650/30xLV 1.10.6s */
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1;
+ }
+ tempbx--; /* RHACTE=HDE-1 */
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2C,temp);
+- temp = (tempbx & 0xFF00) >> 8;
+- temp <<= 4;
++ temp = (tempbx & 0xFF00) >> 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
+
+ temp = 0x01;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(SiS_Pr->SiS_ModeType == ModeEGA) {
+- if(SiS_Pr->SiS_VGAHDE >= 1024) {
+- temp = 0x02;
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+- temp = 0x01;
++ if(SiS_Pr->SiS_ModeType == ModeEGA) {
++ if(SiS_Pr->SiS_VGAHDE >= 1024) {
++ temp = 0x02;
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
++ temp = 0x01;
++ }
+ }
+- }
+- }
+- }
++ }
++ }
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x0B,temp);
+
+- tempbx = SiS_Pr->SiS_VDE; /* RTVACTEO=(VDE-1)&0xFF */
+- push1 = tempbx;
+-
++ tempbx = SiS_Pr->SiS_VDE; /* RTVACTEO = VDE - 1 */
++ /* push1 = tempbx; */
+ tempbx--;
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x03,temp);
+@@ -7540,10 +7762,9 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
+
+ tempcx = SiS_Pr->SiS_VT;
+- push2 = tempcx;
+-
++ /* push2 = tempcx; */
+ tempcx--;
+- temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
++ temp = tempcx & 0x00FF; /* RVTVT = VT - 1 */
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x19,temp);
+
+ temp = (tempcx & 0xFF00) >> 8;
+@@ -7551,40 +7772,42 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+
+ /* Enable dithering; newer versions only do this for 32bpp mode */
+ if((HwDeviceExtension->jChipType == SIS_300) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+- if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp |= 0x10;
++ if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) temp |= 0x10;
+ } else if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp |= 0x10;
+- else {
+- if(SiS_Pr->SiS_LCDInfo & LCDSync) /* TW: 630/301 BIOS checks this */
+- temp |= 0x10;
+- }
++ temp |= 0x10;
+ } else {
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- /* TW: 650/30xLV 1.10.6s */
+- if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+- if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { /* 32bpp mode? */
+- temp |= 0x10;
+- }
+- }
+- } else {
+- temp |= 0x10;
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ /* 650/30xLV 1.10.6s */
++ if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
++ if(SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x01) { /* 32bpp mode? */
++ temp |= 0x10;
++ }
++ }
++ } else {
++ temp |= 0x10;
++ }
+ }
+
+ /* 630/301 does not do all this */
+ if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+ if((HwDeviceExtension->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+- /* TW: 650/30xLV 1.10.6s */
+- temp |= (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37) >> 6);
+- temp |= 0x08; /* From 1.10.7w */
+- if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04; /* From 1.10.7w */
+- } else {
+- tempbx = (tempbx & 0xFF00) | (SiS_Pr->SiS_LCDInfo & 0x0FF);
+- if(tempbx & LCDSync) {
+- tempbx &= 0xFFE0;
+- tempbx = (tempbx & 0xFF00) | ((tempbx & 0x00FF) >> 6);
+- temp |= (tempbx & 0x00FF);
+- }
++ if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
++#ifdef SIS315H
++ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
++ temp |= (SiS_Pr->SiS_LCDInfo >> 6);
++ }
++#endif
++ } else {
++ /* 650/30xLV 1.10.6s */
++ temp |= (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37) >> 6);
++ temp |= 0x08; /* From 1.10.7w */
++ if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04; /* From 1.10.7w */
++ }
++ } else {
++ if(SiS_Pr->SiS_LCDInfo & LCDSync) {
++ temp |= (SiS_Pr->SiS_LCDInfo >> 6);
++ }
+ }
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1A,temp);
+@@ -7595,24 +7818,22 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
+
+- /* 1280x960, 1280x1024 and 1600x1200 data invalid/missing in tables, use old calculation */
+- if((HwDeviceExtension->jChipType >= SIS_315H) &&
+- (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) &&
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) &&
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960)) {
++ if((HwDeviceExtension->jChipType >= SIS_315H) &&
++ (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
++ ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) ) {
+
+-#ifdef SIS315H /* ------------- 310/325/330 series ------------ */
++#ifdef SIS315H /* ------------- 315/330 series ------------ */
+
+- /* TW: Inserted this entire section from 650/301LV(x) BIOS */
+-
+ /* Using this on the 301B with an auto-expanding 1024 panel (CR37=1) results
+ * in a black bar in modes < 1024; if the panel is non-expanding, the bridge
+ * scales all modes to 1024. All modes in both variants (exp/non-exp) work.
+ */
+
+ SiS_GetCRT2Part2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+- &CRT2Index,&resindex);
++ &CRT2Index,&resindex,HwDeviceExtension);
+
+ switch(CRT2Index) {
+ case Panel_1024x768 : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1; break; /* "Normal" */
+@@ -7627,6 +7848,9 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ case Panel_1280x1024 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_3; break;
+ case Panel_1400x1050 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_3; break;
+ case Panel_1600x1200 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_3; break;
++ case 100: CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_1; break; /* Custom */
++ case 101: CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_2; break;
++ case 102: CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_3; break;
+ default: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3; break;
+ }
+
+@@ -7653,8 +7877,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0xb3);
+- }
+- if(SiS_Pr->SiS_VGAVDE == 420) {
++ } else if(SiS_Pr->SiS_VGAVDE == 420) {
+ temp = 0x4d;
+ if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+ temp++;
+@@ -7664,7 +7887,6 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ }
+ }
+
+- /* TW: 650/30xLV 1.10.6s: */
+ /* !!! This is a duplicate, done for LCDA as well - see above */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+@@ -7683,59 +7905,46 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ * the bridge scales all modes to 1024.
+ * !!! Malfunction at 640x480 and 640x400 when panel is auto-expanding - black screen !!!
+ */
+-
++
++ /* cx = VT - 1 */
++
+ tempcx++;
+-
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx = 768;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 1024;
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 1200;
+- else if(SiS_Pr->SiS_VDE != 1024) tempbx = 960;
+- else tempbx = 1024;
+-
+-#if 0 /* old */
+- tempbx = 768;
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
+- tempbx = 1024;
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) {
+- tempbx = 1200;
+- if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
+- if(tempbx != SiS_Pr->SiS_VDE) {
+- tempbx = 960;
+- }
+- }
+- }
+- }
+-#endif
+-
++
++ tempbx = SiS_Pr->PanelYRes;
++
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- tempbx = SiS_Pr->SiS_VDE - 1;
+- tempcx--;
++ tempbx = SiS_Pr->SiS_VDE - 1;
++ tempcx--;
+ }
+-
++
+ tempax = 1;
+ if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+- if(tempbx != SiS_Pr->SiS_VDE) {
+- tempax = tempbx;
+-/* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 60; in 650/301B BIOS */
+- if(tempax < SiS_Pr->SiS_VDE) {
+- tempax = 0;
+- tempcx = 0;
+- } else {
+- tempax -= SiS_Pr->SiS_VDE;
+- }
+- tempax >>= 1;
+- }
+- tempcx -= tempax; /* lcdvdes */
+- tempbx -= tempax; /* lcdvdee */
+- } else {
+- tempax >>= 1;
+- tempcx -= tempax; /* lcdvdes */
+- tempbx -= tempax; /* lcdvdee */
++ if(tempbx != SiS_Pr->SiS_VDE) {
++ tempax = tempbx;
++ if(tempax < SiS_Pr->SiS_VDE) {
++ tempax = 0;
++ tempcx = 0;
++ } else {
++ tempax -= SiS_Pr->SiS_VDE;
++ }
++ tempax >>= 1;
++ }
++ tempcx -= tempax; /* lcdvdes */
++ tempbx -= tempax; /* lcdvdee */
+ }
+-
++#if 0 /* meaningless: 1 / 2 = 0... */
++ else {
++ tempax >>= 1;
++ tempcx -= tempax; /* lcdvdes */
++ tempbx -= tempax; /* lcdvdee */
++ }
++#endif
++
++ /* Non-expanding: lcdvdees = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
++
+ #ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "lcdvds 0x%x lcdvde 0x%x\n", tempcx, tempbx);
+-#endif
++ xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
++#endif
+
+ temp = tempcx & 0x00FF; /* RVEQ1EQ=lcdvdes */
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,temp);
+@@ -7746,140 +7955,178 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
+ temp |= ((tempcx & 0xFF00) >> 8);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,temp);
+
+- tempbx = push2;
+- tempax = push1;
+- tempcx = tempbx;
+- tempcx -= tempax;
+- tempcx >>= 4;
++ tempbx = SiS_Pr->SiS_VT; /* push2; */
++ tempax = SiS_Pr->SiS_VDE; /* push1; */
++ tempcx = (tempbx - tempax) >> 4;
+ tempbx += tempax;
+ tempbx >>= 1;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx -= 10;
+-
++
++ /* non-expanding: lcdvrs = tempbx = ((VT + VDE) / 2) - 10 */
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CVSyncStart;
++ }
++
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
+ #endif
+
+- temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
++ temp = tempbx & 0x00FF; /* RTVACTEE = lcdvrs */
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,temp);
+
+ temp = ((tempbx & 0xFF00) >> 8) << 4;
+ tempbx += (tempcx + 1);
+ temp |= (tempbx & 0x000F);
++
++ if(SiS_Pr->UseCustomMode) {
++ temp &= 0xf0;
++ temp |= (SiS_Pr->CVSyncEnd & 0x0f);
++ }
++
++#ifdef TWDEBUG
++ xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
++#endif
++
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,temp);
+
+- /* TW: Code from 630/301B (I+II) BIOS */
++ /* Code from 630/301B (I+II) BIOS */
+
+- if( ( ( (HwDeviceExtension->jChipType == SIS_630) ||
+- (HwDeviceExtension->jChipType == SIS_730) ) &&
+- (HwDeviceExtension->jChipRevision > 2) ) &&
+- (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) &&
+- (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
+- (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+- if(ModeNo == 0x13) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+- } else {
+- if((crt2crtc & 0x3F) == 4) {
++ if(!SiS_Pr->UseCustomMode) {
++ if( ( ( (HwDeviceExtension->jChipType == SIS_630) ||
++ (HwDeviceExtension->jChipType == SIS_730) ) &&
++ (HwDeviceExtension->jChipRevision > 2) ) &&
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) &&
++ (!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) &&
++ (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
++ if(ModeNo == 0x13) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,0xB9);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,0xCC);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xA6);
++ } else {
++ if((crt2crtc & 0x3F) == 4) {
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x13);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x05,0x08);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+- }
+- }
++ }
++ }
++ }
+ }
+
+- /* TW: Inserted missing code from 630/301B BIOS;
+- * Strangely, this is done in all 650 BIOSes as
+- * well (although LCDTypeInfo is not used there
+- * in the same way as on 300 series)
+- */
+-
+- if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+- crt2crtc &= 0x1f;
+- tempcx = 0;
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+- if (SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- tempcx += 7;
+- }
+- }
+- tempcx += crt2crtc;
+- if (crt2crtc >= 4) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xff);
+- }
++#ifdef SIS300
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ if(!SiS_Pr->UseCustomMode) {
++ if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
++ crt2crtc &= 0x1f;
++ tempcx = 0;
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ tempcx += 7;
++ }
++ }
++ tempcx += crt2crtc;
++ if(crt2crtc >= 4) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x06,0xff);
++ }
+
+- if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if(crt2crtc == 4) {
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x28);
++ if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ if(crt2crtc == 4) {
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x01,0x28);
++ }
++ }
+ }
+- }
+- }
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x18);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x02,0x18);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
++ }
++ }
+ }
++#endif
+
+- tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2; /* (HT-HDE)>>2 */
++ tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2; /* (HT - HDE) >> 2 */
+ tempbx = SiS_Pr->SiS_HDE + 7; /* lcdhdee */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- tempbx += 2;
++ tempbx += 2;
+ }
+ push1 = tempbx;
++
+ #ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "lcdhde 0x%x\n", tempbx);
+-#endif
+- temp = tempbx & 0x00FF; /* RHEQPLE=lcdhdee */
++ xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
++#endif
++
++ temp = tempbx & 0x00FF; /* RHEQPLE = lcdhdee */
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x23,temp);
+ temp = (tempbx & 0xFF00) >> 8;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
+
+ temp = 7;
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- temp += 2;
++ temp += 2;
+ }
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1F,temp); /* RHBLKE=lcdhdes[7:0] */
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1F,temp); /* RHBLKE = lcdhdes[7:0] */
+ SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x20,0x0F); /* lcdhdes [11:8] */
+
+ tempbx += tempcx;
+ push2 = tempbx;
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CHSyncStart + 7;
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ tempbx += 2;
++ }
++ }
++
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
+ #endif
+- temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+- if(SiS_Pr->SiS_HDE == 1280) temp = 0x47;
++
++ temp = tempbx & 0x00FF; /* RHBURSTS = lcdhrs */
++ if(!SiS_Pr->UseCustomMode) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
++ if(SiS_Pr->SiS_HDE == 1280) temp = 0x47;
++ }
+ }
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x1C,temp);
+- temp = ((tempbx & 0xFF00) >> 8) << 4;
++ temp = (tempbx & 0x0F00) >> 4;
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
+
+ tempbx = push2;
+ tempcx <<= 1;
+ tempbx += tempcx;
++
++ if(SiS_Pr->UseCustomMode) {
++ tempbx = SiS_Pr->CHSyncEnd + 7;
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ tempbx += 2;
++ }
++ }
++
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
+-#endif
+- temp = tempbx & 0x00FF; /* RHSYEXP2S=lcdhre */
++#endif
++
++ temp = tempbx & 0x00FF; /* RHSYEXP2S = lcdhre */
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x21,temp);
+
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+- if(SiS_Pr->SiS_VGAVDE == 525) {
+- if(SiS_Pr->SiS_ModeType <= ModeVGA)
+- temp=0xC6;
+- else
+- temp=0xC3;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp);
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0xB3);
+- } else if(SiS_Pr->SiS_VGAVDE == 420) {
+- if(SiS_Pr->SiS_ModeType <= ModeVGA)
+- temp=0x4F;
+- else
+- temp=0x4D;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp);
+- }
++ if(SiS_Pr->SiS_VGAVDE == 525) {
++ if(SiS_Pr->SiS_ModeType <= ModeVGA)
++ temp=0xC6;
++ else
++ temp=0xC3;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp);
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x30,0xB3);
++ } else if(SiS_Pr->SiS_VGAVDE == 420) {
++ if(SiS_Pr->SiS_ModeType <= ModeVGA)
++ temp=0x4F;
++ else
++ temp=0x4D;
++ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x2f,temp);
++ }
+ }
+ SiS_Set300Part2Regs(SiS_Pr, HwDeviceExtension, ModeIdIndex,
+ RefreshRateTableIndex, BaseAddr, ModeNo);
+@@ -7898,7 +8145,7 @@ SiS_GetVGAHT2(SiS_Private *SiS_Pr)
+ return((USHORT) tempax);
+ }
+
+-/* TW: New from 300/301LV BIOS 1.16.51 for ECS A907. Seems highly preliminary. */
++/* New from 300/301LV BIOS 1.16.51 for ECS A907. Seems highly preliminary. */
+ void
+ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
+@@ -7910,18 +8157,19 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr,
+
+ if(HwDeviceExtension->jChipType != SIS_300) return;
+ if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
++ if(SiS_Pr->UseCustomMode) return;
+
+- if(ModeNo<=0x13) {
+- crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
++ if(ModeNo <= 0x13) {
++ crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+ } else {
+- crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
++ crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+ }
+
+ resindex = crt2crtc & 0x3F;
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
+ else CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;
+
+- /* TW: The BIOS code (1.16.51) is obviously a fragment! */
++ /* The BIOS code (1.16.51) is obviously a fragment! */
+ if(ModeNo > 0x13) {
+ CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;
+ resindex = 4;
+@@ -7942,7 +8190,6 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr,
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
+ }
+
+-/* TW: Set 301 Macrovision(tm) registers */
+ void
+ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+@@ -7954,24 +8201,35 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHOR
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
+
+- if(ModeNo<=0x13)
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- else
++ if(ModeNo<=0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ } else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ }
++ }
+
++#ifndef SIS_CP
+ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x00,0x00);
++#endif
++
++#ifdef SIS_CP
++ SIS_CP_INIT301_CP
++#endif
+
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA);
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8);
+ } else {
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF5);
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xB7);
+- } else {
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF6);
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xBf);
+- }
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF5);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xB7);
++ } else {
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xF6);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xBf);
++ }
+ }
+
+ temp = 0;
+@@ -7982,38 +8240,41 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHOR
+ temp = 0x38;
+ }
+ if(temp) {
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM){ /* 0x40 */
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA);
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8);
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
+- }
+- }
+- }
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x31) & 0x01) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,temp) & EnablePALM){ /* 0x40 */
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x13,0xFA);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x14,0xC8);
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,0x3D,0xA8);
++ }
++ }
++ }
+ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+- tempdi = SiS_Pr->SiS_HiTVGroup3Data;
+- if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
+- tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
+- if(!(modeflag & Charx8Dot)) {
+- tempdi = SiS_Pr->SiS_HiTVGroup3Text;
+- }
+- }
+- if(SiS_Pr->SiS_HiVision & 0x03) {
+- tempdi = SiS_HiTVGroup3_1;
+- if(SiS_Pr->SiS_HiVision & 0x02) tempdi = SiS_HiTVGroup3_2;
+- }
+- for(i=0; i<=0x3E; i++){
+- SiS_SetReg1(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
+- }
++ tempdi = SiS_Pr->SiS_HiTVGroup3Data;
++ if(SiS_Pr->SiS_SetFlag & TVSimuMode) {
++ tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
++ if(!(modeflag & Charx8Dot)) {
++ tempdi = SiS_Pr->SiS_HiTVGroup3Text;
++ }
++ }
++ if(SiS_Pr->SiS_HiVision & 0x03) {
++ tempdi = SiS_HiTVGroup3_1;
++ if(SiS_Pr->SiS_HiVision & 0x02) tempdi = SiS_HiTVGroup3_2;
++ }
++ for(i=0; i<=0x3E; i++){
++ SiS_SetReg1(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
++ }
+ }
+
+- return;
++#ifdef SIS_CP
++ SIS_CP_INIT301_CP2
++#endif
++
+ }
+
+-/* TW: Set 301 VGA2 registers */
++/* Set 301 VGA2 registers */
+ void
+ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
+@@ -8022,17 +8283,20 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ USHORT tempax,tempcx,tempbx,modeflag,temp,temp2,resinfo;
+ ULONG tempebx,tempeax,templong;
+
+-
+- if(ModeNo<=0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ if(ModeNo <= 0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
++ if(SiS_Pr->UseCustomMode) {
++ modeflag = SiS_Pr->CModeFlag;
++ resinfo = 0;
++ } else {
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ }
+ }
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- /* TW: From 650/302LV 1.10.6s (not for 300/301LV - no LCDA on this combination) */
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+@@ -8049,10 +8313,10 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- /* TW: From 650/301LV (any, incl. 1.10.6s, 1.10.7w) */
+- /* TW: This is a duplicate; done at the end, too */
++ /* From 650/301LV (any, incl. 1.10.6s, 1.10.7w) */
++ /* This is a duplicate; done at the end, too */
+ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+@@ -8090,39 +8354,33 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ tempbx = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) tempbx >>= 1;
+
+- /* TW: New for 650/301LV and 630/301B */
+ temp = 0xA0;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVisionTV) {
+- temp = 0;
+- if(tempbx > 800) {
+- temp = 0xA0;
+- if(tempbx != 1024) {
+- temp = 0xC0;
+- if(tempbx != 1280) temp = 0;
+- }
+- }
+- } else
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- if(tempbx <= 800) {
+- temp = 0x80;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- temp = 0;
+- if(tempbx > 800) temp = 0x60;
+- }
+- }
++ temp = 0;
++ if(tempbx > 800) {
++ temp = 0xA0;
++ if(tempbx != 1024) {
++ temp = 0xC0;
++ if(tempbx != 1280) temp = 0;
++ }
++ }
++ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
++ if(tempbx <= 800) {
++ temp = 0x80;
++ }
+ } else {
+- temp = 0x80;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- temp = 0;
+- if(tempbx > 800) temp = 0x60;
+- }
++ temp = 0x80;
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
++ temp = 0;
++ if(tempbx > 800) temp = 0x60;
++ }
+ }
+ if(SiS_Pr->SiS_HiVision & 0x03) {
+ temp = 0;
+ if(SiS_Pr->SiS_VGAHDE == 1024) temp = 0x20;
+ }
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) temp = 0;
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) temp = 0;
+ }
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301) {
+@@ -8144,10 +8402,10 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+
+ tempeax = SiS_Pr->SiS_VGAVDE;
+ tempcx |= 0x4000;
+- if(tempeax <= tempebx){
+- tempcx ^= 0x4000;
++ if(tempeax <= tempebx) {
++ tempcx ^= 0x4000;
+ } else {
+- tempeax -= tempebx;
++ tempeax -= tempebx;
+ }
+
+ templong = (tempeax * 256 * 1024) % tempebx;
+@@ -8173,64 +8431,64 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ tempax = SiS_Pr->SiS_VGAHDE;
+ if(modeflag & HalfDCLK) tempax >>= 1;
+ if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) || (SiS_Pr->SiS_HiVision & 0x03)) {
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempax >>= 1;
+- else if(tempax > 800) tempax -= 800;
+- } else {
+- if(tempax > 800) tempax -= 800;
+- }
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempax >>= 1;
++ else if(tempax > 800) tempax -= 800;
++ } else {
++ if(tempax > 800) tempax -= 800;
++ }
+ }
+
+ /* if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetPALTV)) && (!(SiS_Pr->SiS_HiVision & 0x03))) { */
+ if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) && (!(SiS_Pr->SiS_HiVision & 0x03))) {
+- if(tempax > 800) {
+- tempbx = 8;
+- if(tempax == 1024)
+- tempax *= 25;
+- else
+- tempax *= 20;
+-
+- temp = tempax % 32;
+- tempax /= 32;
+- tempax--;
+- if (temp!=0) tempax++;
+- }
++ if(tempax > 800) {
++ tempbx = 8;
++ if(tempax == 1024)
++ tempax *= 25;
++ else
++ tempax *= 20;
++
++ temp = tempax % 32;
++ tempax /= 32;
++ tempax--;
++ if (temp!=0) tempax++;
++ }
+ }
+ tempax--;
+ temp = (tempax & 0xFF00) >> 8;
+ temp &= 0x03;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* From 1.10.7w */
+- if(ModeNo > 0x13) { /* From 1.10.7w */
+- if(resinfo == 8) tempax = 0x1f; /* From 1.10.7w */
+- } /* From 1.10.7w */
+- } /* From 1.10.7w */
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* From 1.10.7w */
++ if(ModeNo > 0x13) { /* From 1.10.7w */
++ if(resinfo == SIS_RI_1024x768) tempax = 0x1f; /* From 1.10.7w */
++ } /* From 1.10.7w */
++ } /* From 1.10.7w */
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF);
+ temp <<= 4;
+ temp |= tempbx;
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1E,temp);
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- if(IS_SIS650740) {
+- temp = 0x0026; /* 1.10.7w; 1.10.8r; needs corresponding code in Dis/EnableBridge! */
++ if(IS_SIS550650740660) {
++ temp = 0x0026; /* 1.10.7w; 1.10.8r; needs corresponding code in Dis/EnableBridge! */
+ } else {
+- temp = 0x0036;
++ temp = 0x0036;
+ }
+ } else {
+- temp = 0x0036;
++ temp = 0x0036;
+ }
+ if((SiS_Pr->SiS_VBInfo & (SetCRT2ToTV - SetCRT2ToHiVisionTV)) &&
+ (!(SiS_Pr->SiS_HiVision & 0x03))) {
+- temp |= 0x01;
+- if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+- if(!(SiS_Pr->SiS_SetFlag & TVSimuMode))
+- temp &= 0xFE;
+- }
++ temp |= 0x01;
++ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
++ if(!(SiS_Pr->SiS_SetFlag & TVSimuMode))
++ temp &= 0xFE;
++ }
+ }
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0,temp);
+
+ tempbx = SiS_Pr->SiS_HT;
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1;
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) tempbx >>= 1;
+ }
+ tempbx >>= 1;
+ tempbx -= 2;
+@@ -8238,7 +8496,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
+ temp = tempbx & 0x00FF;
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x22,temp);
+-
++
+ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+@@ -8246,24 +8504,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
+ }
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- /* TW: 650/LV BIOS does this for all bridge types - assumingly wrong */
+- /* 315, 330, 650+301B BIOS don't do this at all */
+- /* TW: This is a duplicate; done for LCDA as well (see above) */
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) {
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+- }
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
+- }
++ /* 650/LV BIOS does this for all bridge types - assumingly wrong */
++ /* 315, 330, 650+301B BIOS don't do this at all */
++ /* This is a duplicate; done for LCDA as well (see above) */
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3d4,0x39) & 0x04) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
++ }
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
++ }
+ } else if(HwDeviceExtension->jChipType == SIS_300) {
+- /* TW: 300/301LV BIOS does this for all bridge types - assumingly wrong */
+- if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
+- }
++ /* 300/301LV BIOS does this for all bridge types - assumingly wrong */
++ if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
++ }
+ }
+
+ } /* 301B */
+@@ -8278,21 +8536,26 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USH
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT vclkindex;
+- USHORT tempah;
++ USHORT temp, reg1, reg2;
+
+- vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+- HwDeviceExtension);
++ if(SiS_Pr->UseCustomMode) {
++ reg1 = SiS_Pr->CSR2B;
++ reg2 = SiS_Pr->CSR2C;
++ } else {
++ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
++ HwDeviceExtension);
++ reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
++ reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
++ }
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,tempah);
+- tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,tempah);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,reg1);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,reg2);
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(!(SiS_Pr->SiS_VBInfo & SetPALTV)) {
+- if((ModeNo == 0x4a) || (ModeNo == 0x38)) {
++ if((ModeNo == 0x64) || (ModeNo == 0x4a) || (ModeNo == 0x38)) {
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0a,0x57);
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0b,0x46);
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
+@@ -8303,15 +8566,13 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USH
+ }
+ } else {
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,0x01);
+- tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,tempah);
+- tempah = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
+- SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,tempah);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0B,reg2);
++ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x0A,reg1);
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x12,0x00);
+- tempah = 0x08;
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) tempah |= 0x20;
+- SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,tempah);
++ temp = 0x08;
++ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
++ SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
+ }
+
+ USHORT
+@@ -8319,23 +8580,24 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT tempbx;
+- const USHORT LCDXlat0VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40};
+- const USHORT LVDSXlat1VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40};
++ const USHORT LCDXlat0VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40};
++ const USHORT LVDSXlat1VCLK[4] = {VCLK40, VCLK40, VCLK40, VCLK40};
++ const USHORT LVDSXlat4VCLK[4] = {VCLK28, VCLK28, VCLK28, VCLK28};
+ #ifdef SIS300
+- const USHORT LCDXlat1VCLK300[4] = {VCLK65, VCLK65, VCLK65, VCLK65};
+- const USHORT LCDXlat2VCLK300[4] = {VCLK108_2,VCLK108_2,VCLK108_2,VCLK108_2};
+- const USHORT LVDSXlat2VCLK300[4]= {VCLK65, VCLK65, VCLK65, VCLK65};
+- const USHORT LVDSXlat3VCLK300[4]= {VCLK65, VCLK65, VCLK65, VCLK65};
++ const USHORT LCDXlat1VCLK300[4] = {VCLK65_300, VCLK65_300, VCLK65_300, VCLK65_300};
++ const USHORT LCDXlat2VCLK300[4] = {VCLK108_2_300,VCLK108_2_300,VCLK108_2_300,VCLK108_2_300};
++ const USHORT LVDSXlat2VCLK300[4]= {VCLK65_300, VCLK65_300, VCLK65_300, VCLK65_300};
++ const USHORT LVDSXlat3VCLK300[4]= {VCLK65_300, VCLK65_300, VCLK65_300, VCLK65_300};
+ #endif
+ #ifdef SIS315H
+- const USHORT LCDXlat1VCLK310[4] = {VCLK65+2, VCLK65+2, VCLK65+2, VCLK65+2};
+- const USHORT LCDXlat2VCLK310[4] = {VCLK108_2+5,VCLK108_2+5,VCLK108_2+5,VCLK108_2+5};
+- const USHORT LVDSXlat2VCLK310[4]= {VCLK65+2, VCLK65+2, VCLK65+2, VCLK65+2};
+- const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2+5,VCLK108_2+5,VCLK108_2+5,VCLK108_2+5};
++ const USHORT LCDXlat1VCLK310[4] = {VCLK65_315, VCLK65_315, VCLK65_315, VCLK65_315};
++ const USHORT LCDXlat2VCLK310[4] = {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
++ const USHORT LVDSXlat2VCLK310[4]= {VCLK65_315, VCLK65_315, VCLK65_315, VCLK65_315};
++ const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
+ #endif
+ USHORT CRT2Index,VCLKIndex=0;
+ USHORT modeflag,resinfo;
+- const UCHAR *CHTVVCLKPtr=NULL;
++ const UCHAR *CHTVVCLKPtr = NULL;
+ const USHORT *LCDXlatVCLK1 = NULL;
+ const USHORT *LCDXlatVCLK2 = NULL;
+ const USHORT *LVDSXlatVCLK2 = NULL;
+@@ -8372,33 +8634,40 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+
+ CRT2Index >>= 6;
+- if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)){ /* LCD */
++ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* LCD */
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
+ VCLKIndex = LCDXlat0VCLK[CRT2Index];
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ VCLKIndex = LCDXlatVCLK1[CRT2Index];
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
+ VCLKIndex = LCDXlatVCLK1[CRT2Index];
+- else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
+ VCLKIndex = LCDXlatVCLK1[CRT2Index];
+- else
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
++ VCLKIndex = VCLK81_300; /* guessed */
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
++ VCLKIndex = VCLK108_3_300;
++ if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_300;
++ } else {
+ VCLKIndex = LCDXlatVCLK2[CRT2Index];
++ }
+ } else {
+- /* TW: 330, 650/301LV BIOS does not check expanding, 315 does */
+- if( (HwDeviceExtension->jChipType > SIS_315PRO) ||
++ if( (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) ||
+ (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- VCLKIndex = 0x19;
++ VCLKIndex = VCLK108_2_315;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
++ VCLKIndex = VCLK81_315; /* guessed */
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- VCLKIndex = 0x19;
++ VCLKIndex = VCLK108_2_315;
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
+- VCLKIndex = 0x21;
++ VCLKIndex = VCLK162_315;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
++ VCLKIndex = VCLK108_3_315;
++ if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_315;
+ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ VCLKIndex = LCDXlatVCLK1[CRT2Index];
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
+- VCLKIndex = 0x45; /* TW: in VBVCLK table */
+- if(resinfo == 0x09) VCLKIndex++;
+ } else {
+ VCLKIndex = LCDXlatVCLK2[CRT2Index];
+ }
+@@ -8408,12 +8677,18 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ if(ModeNo > 0x13) {
+ VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+ }
+- if(ModeNo <= 0x13) { /* TW: 315 BIOS */
+- if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
++ if(ModeNo <= 0x13) {
++ if(HwDeviceExtension->jChipType <= SIS_315PRO) {
++ if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
++ } else {
++ if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
++ }
++ }
++ if(HwDeviceExtension->jChipType <= SIS_315PRO) {
++ if(VCLKIndex == 0) VCLKIndex = 0x41;
++ if(VCLKIndex == 1) VCLKIndex = 0x43;
++ if(VCLKIndex == 4) VCLKIndex = 0x44;
+ }
+- if(VCLKIndex == 0) VCLKIndex = 0x41;
+- if(VCLKIndex == 1) VCLKIndex = 0x43;
+- if(VCLKIndex == 4) VCLKIndex = 0x44;
+ }
+ }
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) { /* TV */
+@@ -8429,9 +8704,11 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ if(SiS_Pr->SiS_SetFlag & RPLLDIV2XO) VCLKIndex = TVVCLKDIV2;
+ else VCLKIndex = TVVCLK;
+ }
+- if(HwDeviceExtension->jChipType >= SIS_315H) {
+- VCLKIndex += 25;
+- }
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ VCLKIndex += TVCLKBASE_300;
++ } else {
++ VCLKIndex += TVCLKBASE_315;
++ }
+ } else { /* RAMDAC2 */
+ VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02));
+ VCLKIndex = ((VCLKIndex >> 2) & 0x03);
+@@ -8441,7 +8718,11 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ VCLKIndex &= 0x3f;
+ if( (HwDeviceExtension->jChipType == SIS_630) &&
+ (HwDeviceExtension->jChipRevision >= 0x30)) {
+- if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
++ /* This is certainly wrong: It replaces clock
++ * 108 by 47...
++ */
++ /* if(VCLKIndex == 0x14) VCLKIndex = 0x2e; */
++ if(VCLKIndex == 0x14) VCLKIndex = 0x34;
+ }
+ }
+ }
+@@ -8505,6 +8786,10 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) ||
+ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480))
+ VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
++ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
++ SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)
++ VCLKIndex = LVDSXlat4VCLK[VCLKIndex];
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
+ VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)
+@@ -8513,6 +8798,21 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
+ else VCLKIndex = LVDSXlatVCLK3[VCLKIndex];
+
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
++ /* Special Timing: Barco iQ Pro R300/400/... */
++ VCLKIndex = 0x44;
++ }
++
++ if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ VCLKIndex = VCLK34_300;
++ /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
++ } else {
++ VCLKIndex = VCLK34_315;
++ /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
++ }
++ }
++
+ } else {
+
+ VCLKIndex = (UCHAR)SiS_GetReg2((USHORT)(SiS_Pr->SiS_P3ca+0x02));
+@@ -8556,11 +8856,11 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, UCH
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
+ #endif
+- return (VCLKIndex);
++ return(VCLKIndex);
+ }
+
+-/* TW: Set 301 Palette address port registers */
+-/* TW: Checked against 650/301LV BIOS */
++/* Set 301 Palette address port registers */
++/* Checked against 650/301LV BIOS */
+ void
+ SiS_SetGroup5(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr,
+ UCHAR *ROMAddr, USHORT ModeNo, USHORT ModeIdIndex)
+@@ -8568,7 +8868,7 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, PSIS_
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
+
+- if(SiS_Pr->SiS_ModeType == ModeVGA){
++ if(SiS_Pr->SiS_ModeType == ModeVGA) {
+ if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))){
+ SiS_EnableCRT2(SiS_Pr);
+ SiS_LoadDAC(SiS_Pr,HwDeviceExtension,ROMAddr,ModeNo,ModeIdIndex);
+@@ -8581,17 +8881,22 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCH
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT temp,tempah,i,modeflag,j;
+- USHORT ResInfo,DisplayType;
++ USHORT ResIndex,DisplayType;
+ const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
+
+ if(ModeNo <= 0x13) {
+- modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+ } else {
+- modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
++ (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
++ (SiS_Pr->SiS_CustomT == CUT_PANEL848))
++ return;
++
+ temp = SiS_GetLVDSCRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+- &ResInfo,&DisplayType);
++ &ResIndex,&DisplayType);
+
+ if(temp == 0) return;
+
+@@ -8639,47 +8944,53 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCH
+ case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H; break;
+ case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2; break;
+ case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H; break;
++ case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1; break;
++ case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H; break;
++ case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2; break;
++ case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H; break;
++ case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3; break;
++ case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H; break;
+ case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL; break;
+ default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1; break;
+ }
+
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f); /*unlock cr0-7 */
+
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[0];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah);
+
+ for(i=0x02,j=1;i<=0x05;i++,j++){
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[j];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x06,j=5;i<=0x07;i++,j++){
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[j];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x10,j=7;i<=0x11;i++,j++){
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[j];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x15,j=9;i<=0x16;i++,j++){
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[j];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x0A,j=11;i<=0x0C;i++,j++){
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[j];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah);
+ }
+
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[14];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
+ tempah &= 0xE0;
+- SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
++ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
+
+- tempah = (LVDSCRT1Ptr+ResInfo)->CR[14];
++ tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
+ tempah &= 0x01;
+ tempah <<= 5;
+ if(modeflag & DoubleScanMode) tempah |= 0x080;
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+
+- /* TW: 650/LVDS BIOS - doesn't make sense */
++ /* 650/LVDS BIOS - doesn't make sense */
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+ if(modeflag & HalfDCLK)
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+@@ -8688,7 +8999,7 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCH
+
+ BOOLEAN
+ SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+- USHORT RefreshRateTableIndex,USHORT *ResInfo,
++ USHORT RefreshRateTableIndex,USHORT *ResIndex,
+ USHORT *DisplayType)
+ {
+ USHORT tempbx,modeflag=0;
+@@ -8757,19 +9068,33 @@ SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr,
+ tempbx = 40;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
+ if(modeflag & HalfDCLK) tempbx++;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
++ tempbx = 54;
++ if(modeflag & HalfDCLK) tempbx++;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
++ tempbx = 52;
++ if(modeflag & HalfDCLK) tempbx++;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
++ tempbx = 50;
++ if(modeflag & HalfDCLK) tempbx++;
+ }
++
+ }
+ if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+ tempbx = 12;
+ if(modeflag & HalfDCLK) tempbx++;
+ }
+ }
+- if(SiS_Pr->SiS_IF_DEF_FSTN){
++
++#if 0
++ if(SiS_Pr->SiS_IF_DEF_FSTN) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
+ tempbx = 22;
+ }
+ }
+- *ResInfo = CRT2CRTC & 0x3F;
++#endif
++
++ *ResIndex = CRT2CRTC & 0x3F;
+ *DisplayType = tempbx;
+ return 1;
+ }
+@@ -8778,54 +9103,54 @@ void
+ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+- USHORT tempah,tempal,pushax;
+- USHORT vclkindex=0;
+-
++ USHORT clkbase, vclkindex=0;
++ UCHAR sr2b, sr2c;
++
+ if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) || (SiS_Pr->SiS_IF_DEF_TRUMPION == 1)) {
+ SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+- tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+- tempal &= 0x3F;
+- if(tempal == 2) RefreshRateTableIndex--;
++ if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
++ RefreshRateTableIndex--;
++ }
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,HwDeviceExtension);
++ RefreshRateTableIndex,HwDeviceExtension);
+ SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+ } else {
+ vclkindex = SiS_GetVCLK2Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,HwDeviceExtension);
++ RefreshRateTableIndex,HwDeviceExtension);
+ }
+-
+- tempal = 0x02B;
++
++ sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
++ sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
++
++ if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
++ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
++ if(ROMAddr[0x220] & 0x01) {
++ sr2b = ROMAddr[0x227];
++ sr2c = ROMAddr[0x228];
++ }
++ }
++ }
++
++ clkbase = 0x02B;
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+ if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+- tempal += 3;
++ clkbase += 3;
+ }
+ }
++
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86);
+- pushax = tempal;
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x20);
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
+- tempal++;
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase,sr2b);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x10);
+- tempal = pushax;
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
+- tempal++;
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase,sr2b);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x31,0x00);
+- tempal = pushax;
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
+- tempal++;
+- tempah = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,tempal,tempah);
+- return;
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase,sr2b);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
+ }
+
+-#if 0 /* TW: Not used */
++#if 0 /* Not used */
+ void
+ SiS_SetDefCRT2ExtRegs(SiS_Private *SiS_Pr, USHORT BaseAddr)
+ {
+@@ -8844,7 +9169,7 @@ SiS_SetDefCRT2ExtRegs(SiS_Private *SiS_P
+ }
+ #endif
+
+-/* TW: Start of Chrontel 70xx functions ---------------------- */
++/* Start of Chrontel 70xx functions ---------------------- */
+
+ /* Set-up the Chrontel Registers */
+ void
+@@ -8890,44 +9215,44 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHA
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+
+ #ifdef SIS300
+-
+- /* Chrontel 7005 - I assume that it does not come with a 310/325 series chip */
+
+- /* TW: We don't support modes >800x600 */
++ /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
++
++ /* We don't support modes >800x600 */
+ if (resindex > 5) return;
+
+ if(SiS_Pr->SiS_VBInfo & SetPALTV) {
+- SiS_SetCH700x(SiS_Pr,0x4304); /* TW: 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
+- SiS_SetCH700x(SiS_Pr,0x6909); /* TW: Black level for PAL (105)*/
++ SiS_SetCH700x(SiS_Pr,0x4304); /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
++ SiS_SetCH700x(SiS_Pr,0x6909); /* Black level for PAL (105)*/
+ } else {
+- SiS_SetCH700x(SiS_Pr,0x0304); /* TW: upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
+- SiS_SetCH700x(SiS_Pr,0x7109); /* TW: Black level for NTSC (113)*/
++ SiS_SetCH700x(SiS_Pr,0x0304); /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
++ SiS_SetCH700x(SiS_Pr,0x7109); /* Black level for NTSC (113)*/
+ }
+
+ temp = CHTVRegData[resindex].Reg[0];
+- tempbx=((temp&0x00FF)<<8)|0x00; /* TW: Mode register */
++ tempbx=((temp&0x00FF)<<8)|0x00; /* Mode register */
+ SiS_SetCH700x(SiS_Pr,tempbx);
+ temp = CHTVRegData[resindex].Reg[1];
+- tempbx=((temp&0x00FF)<<8)|0x07; /* TW: Start active video register */
++ tempbx=((temp&0x00FF)<<8)|0x07; /* Start active video register */
+ SiS_SetCH700x(SiS_Pr,tempbx);
+ temp = CHTVRegData[resindex].Reg[2];
+- tempbx=((temp&0x00FF)<<8)|0x08; /* TW: Position overflow register */
++ tempbx=((temp&0x00FF)<<8)|0x08; /* Position overflow register */
+ SiS_SetCH700x(SiS_Pr,tempbx);
+ temp = CHTVRegData[resindex].Reg[3];
+- tempbx=((temp&0x00FF)<<8)|0x0A; /* TW: Horiz Position register */
++ tempbx=((temp&0x00FF)<<8)|0x0A; /* Horiz Position register */
+ SiS_SetCH700x(SiS_Pr,tempbx);
+ temp = CHTVRegData[resindex].Reg[4];
+- tempbx=((temp&0x00FF)<<8)|0x0B; /* TW: Vertical Position register */
++ tempbx=((temp&0x00FF)<<8)|0x0B; /* Vertical Position register */
+ SiS_SetCH700x(SiS_Pr,tempbx);
+
+- /* TW: Set minimum flicker filter for Luma channel (SR1-0=00),
++ /* Set minimum flicker filter for Luma channel (SR1-0=00),
+ minimum text enhancement (S3-2=10),
+ maximum flicker filter for Chroma channel (S5-4=10)
+ =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
+ */
+ SiS_SetCH700x(SiS_Pr,0x2801);
+
+- /* TW: Set video bandwidth
++ /* Set video bandwidth
+ High bandwith Luma composite video filter(S0=1)
+ low bandwith Luma S-video filter (S2-1=00)
+ disable peak filter in S-video channel (S3=0)
+@@ -8936,22 +9261,24 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHA
+ */
+ SiS_SetCH700x(SiS_Pr,0xb103); /* old: 3103 */
+
+- /* TW: Register 0x3D does not exist in non-macrovision register map
++ /* Register 0x3D does not exist in non-macrovision register map
+ (Maybe this is a macrovision register?)
+ */
+- /* SiS_SetCH70xx(SiS_Pr,0x003D); */
++#ifndef SIS_CP
++ SiS_SetCH70xx(SiS_Pr,0x003D);
++#endif
+
+- /* TW: Register 0x10 only contains 1 writable bit (S0) for sensing,
++ /* Register 0x10 only contains 1 writable bit (S0) for sensing,
+ all other bits a read-only. Macrovision?
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
+
+- /* TW: Register 0x11 only contains 3 writable bits (S0-S2) for
++ /* Register 0x11 only contains 3 writable bits (S0-S2) for
+ contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
+
+- /* TW: Clear DSEN
++ /* Clear DSEN
+ */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
+
+@@ -8994,7 +9321,7 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHA
+ }
+ }
+ } else { /* ---- PAL ---- */
+- /* TW: We don't play around with FSCI in PAL mode */
++ /* We don't play around with FSCI in PAL mode */
+ if (resindex == 0x04) {
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF); /* loop filter off */
+ SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE); /* ACIV on */
+@@ -9012,7 +9339,7 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHA
+
+ #ifdef SIS315H
+
+- /* TW: We don't support modes >1024x768 */
++ /* We don't support modes >1024x768 */
+ if (resindex > 6) return;
+
+ temp = CHTVRegData[resindex].Reg[0];
+@@ -9082,26 +9409,29 @@ SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHA
+ #endif /* 315 */
+
+ }
++
++#ifdef SIS_CP
++ SIS_CP_INIT301_CP3
++#endif
++
+ }
+
+-/* TW: Chrontel 701x functions ================================= */
++/* Chrontel 701x functions ================================= */
+
+ void
+-SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr)
++SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+-#ifndef NEWCH701x
+ USHORT temp;
+-#endif
+
+- /* TW: Enable Chrontel 7019 LCD panel backlight */
++ /* Enable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+-#ifdef NEWCH701x
++ if(HwDeviceExtension->jChipType == SIS_740) {
+ SiS_SetCH701x(SiS_Pr,0x6566);
+-#else
++ } else {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp |= 0x20;
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+-#endif
++ }
+ }
+ }
+
+@@ -9110,7 +9440,7 @@ SiS_Chrontel701xBLOff(SiS_Private *SiS_P
+ {
+ USHORT temp;
+
+- /* TW: Disable Chrontel 7019 LCD panel backlight */
++ /* Disable Chrontel 7019 LCD panel backlight */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+ temp = SiS_GetCH701x(SiS_Pr,0x66);
+ temp &= 0xDF;
+@@ -9118,47 +9448,54 @@ SiS_Chrontel701xBLOff(SiS_Private *SiS_P
+ }
+ }
+
+-#ifdef SIS315H /* -------- 310/325 series only --------- */
++#ifdef SIS315H /* ----------- 315 series only ---------- */
+
+ void
+ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
+ {
+-#ifdef NEWCH701x
+- UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+- 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
+- UCHAR table1024[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+- 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
+- UCHAR table1280[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
+- UCHAR table1400[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
+- UCHAR table1600[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
+-#else
+- UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+- 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d };
+- UCHAR table1024[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+- 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
+- UCHAR table1280[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+- 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
+- UCHAR table1400[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
+- 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
+- UCHAR table1600[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+- 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
+-#endif
++ UCHAR regtable[] = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
++ 0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
++ UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
++ 0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
++ UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
++ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
++ UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
++ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
++ UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
++ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
++ UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
++ 0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
++ UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
++ 0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
++ UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
++ 0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
++ UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
++ 0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
+ UCHAR *tableptr = NULL;
+ USHORT tempbh;
+ int i;
+
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- tableptr = table1024;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+- tableptr = table1280;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+- tableptr = table1400;
+- } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
+- tableptr = table1600;
+- } else return;
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ tableptr = table1024_740;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ tableptr = table1280_740;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
++ tableptr = table1400_740;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
++ tableptr = table1600_740;
++ } else return;
++ } else {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ tableptr = table1024_650;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ tableptr = table1280_650;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
++ tableptr = table1400_650;
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
++ tableptr = table1600_650;
++ } else return;
++ }
+
+ tempbh = SiS_GetCH701x(SiS_Pr,0x74);
+ if((tempbh == 0xf6) || (tempbh == 0xc7)) {
+@@ -9172,54 +9509,64 @@ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr,
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) return;
+ }
+ }
+-#ifdef NEWCH701x /* New from 740/LVDS: */
+- for(i=0; i<0x0d; i++) {
+-#else
+- for(i=0; i<0x0c; i++) {
+-#endif
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ tempbh = 0x0d;
++ } else {
++ tempbh = 0x0c;
++ }
++ for(i = 0; i < tempbh; i++) {
+ SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+ }
+- SiS_ChrontelPowerSequencing(SiS_Pr);
++ SiS_ChrontelPowerSequencing(SiS_Pr,HwDeviceExtension);
+ tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
+ tempbh |= 0xc0;
+ SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
+-
+-#ifdef NEWCH701x /* 740/LVDS: */
+- tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
+- tempbh &= 0xfb;
+- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port, 0x2d, 0x03);
+- tempbh = SiS_GetCH701x(SiS_Pr,0x64);
+- tempbh |= 0x40;
+- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
+- tempbh = SiS_GetCH701x(SiS_Pr,0x03);
+- tempbh &= 0x3f;
+- SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
+-#endif /* End 740/LVDS */
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
++ tempbh &= 0xfb;
++ SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x03);
++ tempbh = SiS_GetCH701x(SiS_Pr,0x64);
++ tempbh |= 0x40;
++ SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
++ tempbh = SiS_GetCH701x(SiS_Pr,0x03);
++ tempbh &= 0x3f;
++ SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
++ }
+ }
+
+ void
+-SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr)
+-{
+- UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
+-#ifdef NEWCH701x
+- UCHAR table1024[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
+- UCHAR table1400[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
+-#else
+- UCHAR table1024[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+- UCHAR table1400[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+-#endif
++SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
++{
++ UCHAR regtable[] = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
++ UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
++ UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
++ UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
++ UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+ UCHAR *tableptr = NULL;
+ int i;
+
+ /* Set up Power up/down timing */
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- tableptr = table1024;
+- } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
+- (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
+- (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+- tableptr = table1400;
+- } else return;
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ tableptr = table1024_740;
++ } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
++ tableptr = table1400_740;
++ } else return;
++ } else {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ tableptr = table1024_650;
++ } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
++ (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
++ tableptr = table1400_650;
++ } else return;
++ }
+
+ for(i=0; i<5; i++) {
+ SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+@@ -9232,66 +9579,72 @@ SiS_Chrontel701xOn(SiS_Private *SiS_Pr,
+ USHORT temp;
+
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+-#ifdef NEWCH701x
+- temp = SiS_GetCH701x(SiS_Pr,0x1c);
+- temp |= 0x04;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+-#endif
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ temp = SiS_GetCH701x(SiS_Pr,0x1c);
++ temp |= 0x04;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
++ }
+ if(SiS_IsYPbPr(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ temp = SiS_GetCH701x(SiS_Pr,0x01);
+ temp &= 0x3f;
+- temp |= 0x80; /* TW: Enable YPrPb (HDTV) */
++ temp |= 0x80; /* Enable YPrPb (HDTV) */
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ }
+ if(SiS_IsChScart(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+ temp = SiS_GetCH701x(SiS_Pr,0x01);
+ temp &= 0x3f;
+- temp |= 0xc0; /* TW: Enable SCART + CVBS */
++ temp |= 0xc0; /* Enable SCART + CVBS */
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+ }
+-#ifdef NEWCH701x
+- SiS_ChrontelDoSomething5(SiS_Pr);
+- SiS_SetCH701x(SiS_Pr,0x2049); /* TW: Enable TV path */
+-#else
+- SiS_SetCH701x(SiS_Pr,0x2049); /* TW: Enable TV path */
+- temp = SiS_GetCH701x(SiS_Pr,0x49);
+- if(SiS_IsYPbPr(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- temp = SiS_GetCH701x(SiS_Pr,0x73);
+- temp |= 0x60;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_ChrontelDoSomething5(SiS_Pr);
++ SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
++ } else {
++ SiS_SetCH701x(SiS_Pr,0x2049); /* Enable TV path */
++ temp = SiS_GetCH701x(SiS_Pr,0x49);
++ if(SiS_IsYPbPr(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ temp = SiS_GetCH701x(SiS_Pr,0x73);
++ temp |= 0x60;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
++ }
++ temp = SiS_GetCH701x(SiS_Pr,0x47);
++ temp &= 0x7f;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
++ SiS_LongDelay(SiS_Pr,2);
++ temp = SiS_GetCH701x(SiS_Pr,0x47);
++ temp |= 0x80;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+ }
+- temp = SiS_GetCH701x(SiS_Pr,0x47);
+- temp &= 0x7f;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+- SiS_LongDelay(SiS_Pr,2);
+- temp = SiS_GetCH701x(SiS_Pr,0x47);
+- temp |= 0x80;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+-#endif
+ }
+ }
+
+ void
+-SiS_Chrontel701xOff(SiS_Private *SiS_Pr)
++SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+ USHORT temp;
+
++ /* Complete power down of LVDS */
+ if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_LongDelay(SiS_Pr,1);
++ SiS_GenericDelay(SiS_Pr,0x16ff);
++ SiS_SetCH701x(SiS_Pr,0xac76);
++ SiS_SetCH701x(SiS_Pr,0x0066);
++ } else {
+ SiS_LongDelay(SiS_Pr,2);
+- /* TW: Complete power down of LVDS */
+ temp = SiS_GetCH701x(SiS_Pr,0x76);
+ temp &= 0xfc;
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+ SiS_SetCH701x(SiS_Pr,0x0066);
++ }
+ }
+ }
+
+-#ifdef NEWCH701x
+ void
+ SiS_ChrontelDoSomething5(SiS_Private *SiS_Pr)
+ {
+ unsigned char temp, temp1;
+-
++
+ temp1 = SiS_GetCH701x(SiS_Pr,0x49);
+ SiS_SetCH701x(SiS_Pr,0x3e49);
+ temp = SiS_GetCH701x(SiS_Pr,0x47);
+@@ -9303,130 +9656,134 @@ SiS_ChrontelDoSomething5(SiS_Private *Si
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+ SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
+ }
+-#endif
+
+ void
+ SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+ {
+-#ifdef NEWCH701x
+ USHORT temp;
+-
+- /* 740/LVDS: */
+- temp = SiS_GetCH701x(SiS_Pr,0x4a);
+- temp &= 0x01;
+- if(!(temp)) {
+-
+- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- temp = SiS_GetCH701x(SiS_Pr,0x49);
+- SiS_SetCH701x(SiS_Pr,0x3e49);
+- }
+- /* TW: Reset Chrontel 7019 datapath */
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ temp = SiS_GetCH701x(SiS_Pr,0x4a);
++ temp &= 0x01;
++ if(!(temp)) {
++
++ if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ temp = SiS_GetCH701x(SiS_Pr,0x49);
++ SiS_SetCH701x(SiS_Pr,0x3e49);
++ }
++ /* Reset Chrontel 7019 datapath */
++ SiS_SetCH701x(SiS_Pr,0x1048);
++ SiS_LongDelay(SiS_Pr,1);
++ SiS_SetCH701x(SiS_Pr,0x1848);
++
++ if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_ChrontelDoSomething5(SiS_Pr);
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
++ }
++
++ } else {
++
++ temp = SiS_GetCH701x(SiS_Pr,0x5c);
++ temp &= 0xef;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
++ temp = SiS_GetCH701x(SiS_Pr,0x5c);
++ temp |= 0x10;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
++ temp = SiS_GetCH701x(SiS_Pr,0x5c);
++ temp &= 0xef;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
++ temp = SiS_GetCH701x(SiS_Pr,0x61);
++ if(!temp) {
++ SiS_SetCH701xForLCD(SiS_Pr,HwDeviceExtension,BaseAddr);
++ }
++ }
++ } else { /* 650 */
++ /* Reset Chrontel 7019 datapath */
+ SiS_SetCH701x(SiS_Pr,0x1048);
+ SiS_LongDelay(SiS_Pr,1);
+ SiS_SetCH701x(SiS_Pr,0x1848);
+-
+- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_ChrontelDoSomething5(SiS_Pr);
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
+- }
+- } else {
+-
+- temp = SiS_GetCH701x(SiS_Pr,0x5c);
+- temp &= 0xef;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+- temp = SiS_GetCH701x(SiS_Pr,0x5c);
+- temp |= 0x10;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+- temp = SiS_GetCH701x(SiS_Pr,0x5c);
+- temp &= 0xef;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+- temp = SiS_GetCH701x(SiS_Pr,0x61);
+- if(!temp) {
+- SiS_SetCH701xForLCD(SiS_Pr,HwDeviceExtension,BaseAddr);
+- }
+- }
+-#else /* pre 740/LVDS code */
+- /* TW: Reset Chrontel 7019 datapath */
+- SiS_SetCH701x(SiS_Pr,0x1048);
+- SiS_LongDelay(SiS_Pr,1);
+- SiS_SetCH701x(SiS_Pr,0x1848);
+-#endif
++ }
+ }
+
+ void
+ SiS_ChrontelDoSomething4(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+ {
+-#ifdef NEWCH701x
+- if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr))) {
+- SiS_ChrontelDoSomething5(SiS_Pr);
+- }
+-#else
+ USHORT temp;
+
+- SiS_SetCH701x(SiS_Pr,0xaf76); /* Power up LVDS block */
+- temp = SiS_GetCH701x(SiS_Pr,0x49);
+- temp &= 1;
+- if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
+- temp = SiS_GetCH701x(SiS_Pr,0x47);
+- temp &= 0x70;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* enable VSYNC */
+- SiS_LongDelay(SiS_Pr,3);
+- temp = SiS_GetCH701x(SiS_Pr,0x47);
+- temp |= 0x80;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* disable VSYNC */
++ if(HwDeviceExtension->jChipType == SIS_740) {
++
++ if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_ChrontelDoSomething5(SiS_Pr);
++ }
++
++ } else {
++
++ SiS_SetCH701x(SiS_Pr,0xaf76); /* Power up LVDS block */
++ temp = SiS_GetCH701x(SiS_Pr,0x49);
++ temp &= 1;
++ if(temp != 1) { /* TV block powered? (0 = yes, 1 = no) */
++ temp = SiS_GetCH701x(SiS_Pr,0x47);
++ temp &= 0x70;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* enable VSYNC */
++ SiS_LongDelay(SiS_Pr,3);
++ temp = SiS_GetCH701x(SiS_Pr,0x47);
++ temp |= 0x80;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47); /* disable VSYNC */
++ }
++
+ }
+-#endif
+ }
+
+ void
+ SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT BaseAddr)
+ {
+-#ifdef NEWCH701x
+- USHORT temp;
+-
+- temp = SiS_GetCH701x(SiS_Pr,0x61);
+- if(temp < 1) {
+- temp++;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+- }
+- SiS_SetCH701x(SiS_Pr,0x4566);
+- SiS_SetCH701x(SiS_Pr,0xaf76);
+- SiS_LongDelay(SiS_Pr,1);
+- SiS_GenericDelay(SiS_Pr,0x16ff);
+-
+-#else
+ USHORT temp,temp1;
+-
+- temp1 = 0;
+- temp = SiS_GetCH701x(SiS_Pr,0x61);
+- if(temp < 2) {
+- temp++;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+- temp1 = 1;
+- }
+- SiS_SetCH701x(SiS_Pr,0xac76);
+- temp = SiS_GetCH701x(SiS_Pr,0x66);
+- temp |= 0x5f;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+- if(ModeNo > 0x13) {
+- if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- SiS_GenericDelay(SiS_Pr,0x3ff);
+- } else {
+- SiS_GenericDelay(SiS_Pr,0x2ff);
+- }
+- } else {
+- if(!temp1)
+- SiS_GenericDelay(SiS_Pr,0x2ff);
++
++ if(HwDeviceExtension->jChipType == SIS_740) {
++
++ temp = SiS_GetCH701x(SiS_Pr,0x61);
++ if(temp < 1) {
++ temp++;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
++ }
++ SiS_SetCH701x(SiS_Pr,0x4566);
++ SiS_SetCH701x(SiS_Pr,0xaf76);
++ SiS_LongDelay(SiS_Pr,1);
++ SiS_GenericDelay(SiS_Pr,0x16ff);
++
++ } else { /* 650 */
++
++ temp1 = 0;
++ temp = SiS_GetCH701x(SiS_Pr,0x61);
++ if(temp < 2) {
++ temp++;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
++ temp1 = 1;
++ }
++ SiS_SetCH701x(SiS_Pr,0xac76);
++ temp = SiS_GetCH701x(SiS_Pr,0x66);
++ temp |= 0x5f;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
++ if(ModeNo > 0x13) {
++ if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ SiS_GenericDelay(SiS_Pr,0x3ff);
++ } else {
++ SiS_GenericDelay(SiS_Pr,0x2ff);
++ }
++ } else {
++ if(!temp1)
++ SiS_GenericDelay(SiS_Pr,0x2ff);
++ }
++ temp = SiS_GetCH701x(SiS_Pr,0x76);
++ temp |= 0x03;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
++ temp = SiS_GetCH701x(SiS_Pr,0x66);
++ temp &= 0x7f;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
++ SiS_LongDelay(SiS_Pr,1);
++
+ }
+- temp = SiS_GetCH701x(SiS_Pr,0x76);
+- temp |= 0x03;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+- temp = SiS_GetCH701x(SiS_Pr,0x66);
+- temp &= 0x7f;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+- SiS_LongDelay(SiS_Pr,1);
+-#endif
+ }
+
+ void
+@@ -9443,9 +9800,9 @@ SiS_ChrontelDoSomething2(SiS_Private *Si
+ temp &= 0x04;
+ if(temp == 0x04) break;
+
+-#ifdef NEWCH701x
+- SiS_SetCH701x(SiS_Pr,0xac76); /* 740/LVDS */
+-#endif
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_SetCH701x(SiS_Pr,0xac76);
++ }
+
+ SiS_SetCH701xForLCD(SiS_Pr,HwDeviceExtension,BaseAddr);
+
+@@ -9463,11 +9820,11 @@ SiS_ChrontelDoSomething2(SiS_Private *Si
+ temp = SiS_GetCH701x(SiS_Pr,0x76);
+ temp |= 0x04;
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+-#ifdef NEWCH701x
+- SiS_SetCH701x(SiS_Pr,0xe078);
+-#else
+- SiS_SetCH701x(SiS_Pr,0x6078);
+-#endif
++ if(HwDeviceExtension->jChipType == SIS_740) {
++ SiS_SetCH701x(SiS_Pr,0xe078);
++ } else {
++ SiS_SetCH701x(SiS_Pr,0x6078);
++ }
+ SiS_LongDelay(SiS_Pr,2);
+ } while(0);
+
+@@ -9485,51 +9842,52 @@ SiS_ChrontelDoSomething1(SiS_Private *Si
+ temp &= 0xbf; /* Set datapath 2 to LVDS */
+ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+
+-#ifdef NEWCH701x /* 740/LVDS: */
++ if(HwDeviceExtension->jChipType == SIS_740) {
++
++ temp = SiS_GetCH701x(SiS_Pr,0x1c);
++ temp &= 0xfb;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
++
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x03);
++
++ temp = SiS_GetCH701x(SiS_Pr,0x64);
++ temp |= 0x40;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
++
++ temp = SiS_GetCH701x(SiS_Pr,0x03);
++ temp &= 0x3f;
++ SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
++
++ temp = SiS_GetCH701x(SiS_Pr,0x66);
++ if(temp != 0x45) {
++ SiS_ChrontelResetDB(SiS_Pr,HwDeviceExtension,BaseAddr);
++ SiS_ChrontelDoSomething2(SiS_Pr,HwDeviceExtension,BaseAddr);
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34);
++ SiS_ChrontelDoSomething3(SiS_Pr,temp,HwDeviceExtension,BaseAddr);
++ }
++
++ } else { /* 650 */
+
+- temp = SiS_GetCH701x(SiS_Pr,0x1c);
+- temp &= 0xfb;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+-
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2d,0x03);
+-
+- temp = SiS_GetCH701x(SiS_Pr,0x64);
+- temp |= 0x40;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
+-
+- temp = SiS_GetCH701x(SiS_Pr,0x03);
+- temp &= 0x3f;
+- SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+-
+- temp = SiS_GetCH701x(SiS_Pr,0x66);
+- if(temp != 0x45) {
+ SiS_ChrontelResetDB(SiS_Pr,HwDeviceExtension,BaseAddr);
+- SiS_ChrontelDoSomething2(SiS_Pr,HwDeviceExtension,BaseAddr);
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34);
+- SiS_ChrontelDoSomething3(SiS_Pr,temp,HwDeviceExtension,BaseAddr);
+- }
+
+-#else /* pre-740/LVDS: */
++ SiS_ChrontelDoSomething2(SiS_Pr,HwDeviceExtension,BaseAddr);
+
+- SiS_ChrontelResetDB(SiS_Pr);
++ temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34);
++ SiS_ChrontelDoSomething3(SiS_Pr,temp,HwDeviceExtension,BaseAddr);
+
+- SiS_ChrontelDoSomething2(SiS_Pr,HwDeviceExtension,BaseAddr);
++ SiS_SetCH701x(SiS_Pr,0xaf76);
+
+- temp = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x34);
+- SiS_ChrontelDoSomething3(SiS_Pr,temp,HwDeviceExtension,BaseAddr);
++ }
+
+- SiS_SetCH701x(SiS_Pr,0xaf76);
+-
+-#endif /* End of pre-740/LVDS */
+ }
+
+-#endif /* 310/325 series --------------------------------- */
++#endif /* 315 series ------------------------------------ */
+
+-/* TW: End of Chrontel 701x functions ==================================== */
++/* End of Chrontel 701x functions ==================================== */
+
+-/* TW: Generic Read/write routines for Chrontel ========================== */
++/* Generic Read/write routines for Chrontel ========================== */
+
+-/* TW: The Chrontel is connected to the 630/730 via
++/* The Chrontel is connected to the 630/730 via
+ * the 630/730's DDC/I2C port.
+ *
+ * On 630(S)T chipset, the index changed from 0x11 to 0x0a,
+@@ -9539,13 +9897,13 @@ SiS_ChrontelDoSomething1(SiS_Private *Si
+ void
+ SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+ {
+- if (SiS_Pr->SiS_IF_DEF_CH70xx == 1)
++ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+ SiS_SetCH700x(SiS_Pr,tempbx);
+ else
+ SiS_SetCH701x(SiS_Pr,tempbx);
+ }
+
+-/* TW: Write to Chrontel 700x */
++/* Write to Chrontel 700x */
+ /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
+ void
+ SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+@@ -9553,100 +9911,100 @@ SiS_SetCH700x(SiS_Private *SiS_Pr, USHOR
+ USHORT tempah,temp,i;
+
+ if(!(SiS_Pr->SiS_ChrontelInit)) {
+- SiS_Pr->SiS_DDC_Index = 0x11; /* TW: Bit 0 = SC; Bit 1 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+ }
+
+- for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */
++ for(i=0;i<10;i++) { /* Do only 10 attempts to write */
+ /* SiS_SetSwitchDDC2(SiS_Pr); */
+- if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = tempbx & 0x00FF; /* TW: Write RAB */
+- tempah |= 0x80; /* TW: (set bit 7, see datasheet) */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = tempbx & 0x00FF; /* Write RAB */
++ tempah |= 0x80; /* (set bit 7, see datasheet) */
+ temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
+- if(temp) continue; /* TW: (ERROR: no ack) */
++ if(temp) continue; /* (ERROR: no ack) */
+ tempah = (tempbx & 0xFF00) >> 8;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */
++ if(temp) continue; /* (ERROR: no ack) */
++ if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
+ SiS_Pr->SiS_ChrontelInit = 1;
+ return;
+ }
+
+- /* TW: For 630ST */
++ /* For 630ST */
+ if(!(SiS_Pr->SiS_ChrontelInit)) {
+- SiS_Pr->SiS_DDC_Index = 0x0a; /* TW: Bit 7 = SC; Bit 6 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x0a; /* Bit 7 = SC; Bit 6 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+
+- for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */
++ for(i=0;i<10;i++) { /* Do only 10 attempts to write */
+ /* SiS_SetSwitchDDC2(SiS_Pr); */
+- if (SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ if (SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = tempbx & 0x00FF; /* TW: Write RAB */
+- tempah |= 0x80; /* TW: (set bit 7, see datasheet) */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = tempbx & 0x00FF; /* Write RAB */
++ tempah |= 0x80; /* (set bit 7, see datasheet) */
+ temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
+- if(temp) continue; /* TW: (ERROR: no ack) */
++ if(temp) continue; /* (ERROR: no ack) */
+ tempah = (tempbx & 0xFF00) >> 8;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */
++ if(temp) continue; /* (ERROR: no ack) */
++ if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
+ SiS_Pr->SiS_ChrontelInit = 1;
+ return;
+ }
+ }
+ }
+
+-/* TW: Write to Chrontel 701x */
++/* Write to Chrontel 701x */
+ /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
+ void
+ SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+ {
+ USHORT tempah,temp,i;
+
+- SiS_Pr->SiS_DDC_Index = 0x11; /* TW: Bit 0 = SC; Bit 1 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+
+- for(i=0;i<10;i++) { /* TW: Do only 10 attempts to write */
+- if (SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ for(i=0;i<10;i++) { /* Do only 10 attempts to write */
++ if (SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
+ tempah = tempbx & 0x00FF;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write RAB */
+- if(temp) continue; /* TW: (ERROR: no ack) */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write RAB */
++ if(temp) continue; /* (ERROR: no ack) */
+ tempah = (tempbx & 0xFF00) >> 8;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write data */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if(SiS_SetStop(SiS_Pr)) continue; /* TW: Set stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write data */
++ if(temp) continue; /* (ERROR: no ack) */
++ if(SiS_SetStop(SiS_Pr)) continue; /* Set stop condition */
+ return;
+ }
+ }
+
+-/* TW: Read from Chrontel 70xx */
++/* Read from Chrontel 70xx */
+ /* Parameter is [Register no (S7-S0)] */
+ USHORT
+ SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+ {
+- if (SiS_Pr->SiS_IF_DEF_CH70xx == 1)
++ if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+ return(SiS_GetCH700x(SiS_Pr,tempbx));
+ else
+ return(SiS_GetCH701x(SiS_Pr,tempbx));
+ }
+
+-/* TW: Read from Chrontel 700x */
++/* Read from Chrontel 700x */
+ /* Parameter is [Register no (S7-S0)] */
+ USHORT
+ SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+@@ -9654,57 +10012,57 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHOR
+ USHORT tempah,temp,i;
+
+ if(!(SiS_Pr->SiS_ChrontelInit)) {
+- SiS_Pr->SiS_DDC_Index = 0x11; /* TW: Bit 0 = SC; Bit 1 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x02; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x01; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
+ }
+
+ SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+
+- for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */
++ for(i=0;i<20;i++) { /* Do only 20 attempts to read */
+ /* SiS_SetSwitchDDC2(SiS_Pr); */
+- if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* TW: Write RAB | 0x80 */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* Write RAB | 0x80 */
+ temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */
++ if(temp) continue; /* (ERROR: no ack) */
++ if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */
+- if (SiS_SetStop(SiS_Pr)) continue; /* TW: Stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
++ if (SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
+ SiS_Pr->SiS_ChrontelInit = 1;
+ return(tempah);
+ }
+
+- /* TW: For 630ST */
++ /* For 630ST */
+ if(!SiS_Pr->SiS_ChrontelInit) {
+- SiS_Pr->SiS_DDC_Index = 0x0a; /* TW: Bit 0 = SC; Bit 1 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x0a; /* Bit 0 = SC; Bit 1 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x80; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x40; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB (Device Address Byte) */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB (Device Address Byte) */
+
+- for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */
++ for(i=0;i<20;i++) { /* Do only 20 attempts to read */
+ /* SiS_SetSwitchDDC2(SiS_Pr); */
+- if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* TW: Write RAB | 0x80 */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_Pr->SiS_DDC_ReadAddr | 0x80; /* Write RAB | 0x80 */
+ temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */
++ if(temp) continue; /* (ERROR: no ack) */
++ if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */
+- if (SiS_SetStop(SiS_Pr)) continue; /* TW: Stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
++ if (SiS_SetStop(SiS_Pr)) continue; /* Stop condition */
+ SiS_Pr->SiS_ChrontelInit = 1;
+ return(tempah);
+ }
+@@ -9712,52 +10070,51 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHOR
+ return(0xFFFF);
+ }
+
+-/* TW: Read from Chrontel 701x */
++/* Read from Chrontel 701x */
+ /* Parameter is [Register no (S7-S0)] */
+ USHORT
+ SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+ {
+ USHORT tempah,temp,i;
+
+- SiS_Pr->SiS_DDC_Index = 0x11; /* TW: Bit 0 = SC; Bit 1 = SD */
++ SiS_Pr->SiS_DDC_Index = 0x11; /* Bit 0 = SC; Bit 1 = SD */
+ SiS_Pr->SiS_DDC_Data = 0x08; /* Bitmask in IndexReg for Data */
+ SiS_Pr->SiS_DDC_Clk = 0x04; /* Bitmask in IndexReg for Clk */
+ SiS_Pr->SiS_DDC_DataShift = 0x00;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* TW: DAB */
++ SiS_Pr->SiS_DDC_DeviceAddr = 0xEA; /* DAB */
+ SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+
+- for(i=0;i<20;i++) { /* TW: Do only 20 attempts to read */
+- if(SiS_SetStart(SiS_Pr)) continue; /* TW: Set start condition */
++ for(i=0;i<20;i++) { /* Do only 20 attempts to read */
++ if(SiS_SetStart(SiS_Pr)) continue; /* Set start condition */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: Write DAB (S0=0=write) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_Pr->SiS_DDC_ReadAddr; /* TW: Write RAB */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* Write DAB (S0=0=write) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_Pr->SiS_DDC_ReadAddr; /* Write RAB */
+ temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- if (SiS_SetStart(SiS_Pr)) continue; /* TW: Re-start */
++ if(temp) continue; /* (ERROR: no ack) */
++ if (SiS_SetStart(SiS_Pr)) continue; /* Re-start */
+ tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01; /* DAB | 0x01 = Read */
+- temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* TW: DAB (S0=1=read) */
+- if(temp) continue; /* TW: (ERROR: no ack) */
+- tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* TW: Read byte */
+- SiS_SetStop(SiS_Pr); /* TW: Stop condition */
++ temp = SiS_WriteDDC2Data(SiS_Pr,tempah); /* DAB (S0=1=read) */
++ if(temp) continue; /* (ERROR: no ack) */
++ tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
++ SiS_SetStop(SiS_Pr); /* Stop condition */
+ return(tempah);
+ }
+ return 0xFFFF;
+ }
+
+-#ifdef LINUX_XF86
+-/* TW: Our own DDC functions */
++/* Our own DDC functions */
+ USHORT
+-SiS_InitDDCRegs(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, USHORT DDCdatatype,
+- BOOLEAN checkcr32)
++SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
++ USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
+ {
+ unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
+ unsigned char flag, cr32;
+ USHORT temp = 0, myadaptnum = adaptnum;
+
+ if(adaptnum != 0) {
+- if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_302B))) return 0xFFFF;
+- if((pSiS->VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
++ if(!(VBFlags & (VB_301|VB_301B|VB_302B))) return 0xFFFF;
++ if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
+ }
+
+ /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
+@@ -9771,8 +10128,9 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+ flag = 0xff;
+
+ cr32 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x32);
+-
+- if(pSiS->VBFlags & VB_SISBRIDGE) {
++
++#if 0
++ if(VBFlags & VB_SISBRIDGE) {
+ if(myadaptnum == 0) {
+ if(!(cr32 & 0x20)) {
+ myadaptnum = 2;
+@@ -9785,18 +10143,19 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+ }
+ }
+ }
++#endif
+
+- if(pSiS->VGAEngine == SIS_300_VGA) { /* 300 series */
++ if(VGAEngine == SIS_300_VGA) { /* 300 series */
+
+ if(myadaptnum != 0) {
+ flag = 0;
+- if(pSiS->VBFlags & VB_SISBRIDGE) {
++ if(VBFlags & VB_SISBRIDGE) {
+ SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
+ SiS_Pr->SiS_DDC_Index = 0x0f;
+ }
+ }
+
+- if(!(pSiS->VBFlags & VB_301)) {
++ if(!(VBFlags & VB_301)) {
+ if((cr32 & 0x80) && (checkcr32)) {
+ if(myadaptnum >= 1) {
+ if(!(cr32 & 0x08)) {
+@@ -9810,11 +10169,11 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+ temp = 4 - (myadaptnum * 2);
+ if(flag) temp = 0;
+
+- } else { /* 310/325/330 series */
++ } else { /* 315/330 series */
+
+ /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
+
+- if(pSiS->VBFlags & VB_SISBRIDGE) {
++ if(VBFlags & VB_SISBRIDGE) {
+ if(myadaptnum == 2) {
+ myadaptnum = 1;
+ }
+@@ -9822,7 +10181,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+
+ if(myadaptnum == 1) {
+ flag = 0;
+- if(pSiS->VBFlags & VB_SISBRIDGE) {
++ if(VBFlags & VB_SISBRIDGE) {
+ SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
+ SiS_Pr->SiS_DDC_Index = 0x0f;
+ }
+@@ -9840,7 +10199,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+ temp = myadaptnum;
+ if(myadaptnum == 1) {
+ temp = 0;
+- if(pSiS->VBFlags & VB_LVDS) flag = 0xff;
++ if(VBFlags & VB_LVDS) flag = 0xff;
+ }
+
+ if(flag) temp = 0;
+@@ -9852,7 +10211,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, SIS
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
+ SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
+-#endif
++#endif
+
+ return 0;
+ }
+@@ -9862,15 +10221,9 @@ SiS_WriteDABDDC(SiS_Private *SiS_Pr)
+ {
+ if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
+ if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "WriteDAB 1 failed\n");
+-#endif
+ return 0xFFFF;
+ }
+ if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "WriteDAB 2 failed\n");
+-#endif
+ return 0xFFFF;
+ }
+ return(0);
+@@ -9881,9 +10234,6 @@ SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
+ {
+ if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
+ if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "PrepareReadDDC 1 failed\n");
+-#endif
+ return 0xFFFF;
+ }
+ return(0);
+@@ -9921,9 +10271,6 @@ SiS_DoProbeDDC(SiS_Private *SiS_Pr)
+ SiS_SetSwitchDDC2(SiS_Pr);
+ if(SiS_PrepareDDC(SiS_Pr)) {
+ SiS_SetStop(SiS_Pr);
+-#ifdef TWDEBUG
+- xf86DrvMsg(0, X_INFO, "DoProbeDDC 1 failed at PrepareDDC\n");
+-#endif
+ return(0xFFFF);
+ }
+ mask = 0xf0;
+@@ -9972,7 +10319,7 @@ SiS_ProbeDDC(SiS_Private *SiS_Pr)
+ }
+
+ USHORT
+-SiS_ReadDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT DDCdatatype, unsigned char *buffer)
++SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
+ {
+ USHORT flag, length, i;
+ unsigned char chksum,gotcha;
+@@ -10004,28 +10351,7 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, SISPtr
+ return(flag);
+ }
+
+-USHORT
+-SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHORT length, unsigned char *buffer)
+-{
+- USHORT i=0, flag=0;
+-
+- length--;
+-
+- SiS_SetSwitchDDC2(SiS_Pr);
+- if(!(SiS_PrepareDDC(SiS_Pr))) {
+- for(i=0; i<length; i++) {
+- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+- SiS_SendACK(SiS_Pr, 0);
+- }
+- buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+- SiS_SendACK(SiS_Pr, 1);
+- } else flag = 0xFFFF;
+-
+- SiS_SetStop(SiS_Pr);
+- return(0);
+-}
+-
+-/* TW: Our private DDC function
++/* Our private DDC functions
+
+ It complies somewhat with the corresponding VESA function
+ in arguments and return values.
+@@ -10036,7 +10362,7 @@ SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHO
+
+ Arguments:
+ adaptnum: 0=CRT1, 1=LCD, 2=VGA2
+- CRT2 DDC is only supported on SiS301, 301B (non-DH version), 302B.
++ CRT2 DDC is only supported on SiS301, 301B, 302B.
+ DDCdatatype: 0=Probe, 1=EDID, 2=EDID+VDIF, 3=EDID V2 (P&D), 4=EDID V2 (FPDI-2)
+ buffer: ptr to 256 data bytes which will be filled with read data.
+
+@@ -10046,43 +10372,48 @@ SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHO
+
+ */
+ USHORT
+-SiS_HandleDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum,
+- USHORT DDCdatatype, unsigned char *buffer)
++SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
++ USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
+ {
+ if(adaptnum > 2) return 0xFFFF;
+ if(DDCdatatype > 4) return 0xFFFF;
+- if((!(pSiS->VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
+- if(SiS_InitDDCRegs(SiS_Pr, pSiS, adaptnum, DDCdatatype, TRUE) == 0xFFFF) return 0xFFFF;
++ if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
++ if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, TRUE) == 0xFFFF) return 0xFFFF;
+ if(DDCdatatype == 0) {
+ return(SiS_ProbeDDC(SiS_Pr));
+ } else {
+- return(SiS_ReadDDC(SiS_Pr, pSiS, DDCdatatype, buffer));
++ return(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer));
+ }
+ }
+
++#ifdef LINUX_XF86
+ /* Sense the LCD parameters (CR36, CR37) via DDC */
+ /* SiS30x(B) only */
+ USHORT
+ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
+ {
+- USHORT DDCdatatype, paneltype, flag, xres, yres;
++ USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
+ USHORT index, myindex, lumsize, numcodes;
+ unsigned char cr37=0, seekcode;
+ BOOLEAN checkexpand = FALSE;
+ int retry, i;
+ unsigned char buffer[256];
+-
++
++ for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
++ SiS_Pr->CP_HaveCustomData = FALSE;
++ SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
++
+ if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_302B))) return 0;
+ if(pSiS->VBFlags & VB_30xBDH) return 0;
+
+- if(SiS_InitDDCRegs(SiS_Pr, pSiS, 1, 0, FALSE) == 0xFFFF) return 0;
++ if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
+
+ SiS_Pr->SiS_DDC_SecAddr = 0x00;
+
+ /* Probe supported DA's */
+ flag = SiS_ProbeDDC(SiS_Pr);
+ #ifdef TWDEBUG
+- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
+ "CRT2 DDC capabilities 0x%x\n", flag);
+ #endif
+ if(flag & 0x10) {
+@@ -10099,7 +10430,7 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ /* Read the entire EDID */
+ retry = 2;
+ do {
+- if(SiS_ReadDDC(SiS_Pr, pSiS, DDCdatatype, buffer)) {
++ if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
+ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
+ "CRT2: DDC read failed (attempt %d), %s\n",
+ (3-retry), (retry == 1) ? "giving up" : "retrying");
+@@ -10132,7 +10463,7 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ }
+
+ if((buffer[0x18] & 0x18) != 0x08) {
+- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
+ "CRT2: Attached display is not of RGB but of %s type (0x%02x)\n",
+ ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
+ ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
+@@ -10140,103 +10471,226 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ buffer[0x18]);
+ return 0;
+ }
+-
+- /* Now analyze the first Detailed Timing Block and hope
+- * that the preferred timing mode is stored there.
+- */
+- xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
+- yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
++
++ /* Now analyze the first Detailed Timing Block and see
++ * if the preferred timing mode is stored there. If so,
++ * check if this is a standard panel for which we already
++ * know the timing.
++ */
++
++ paneltype = Panel_Custom;
+ checkexpand = FALSE;
+- switch(xres) {
+- case 800:
+- if(yres == 600) {
+- paneltype = Panel310_800x600;
+- checkexpand = TRUE;
+- }
+- break;
+- case 1024:
+- if(yres == 768) {
+- paneltype = Panel310_1024x768;
+- checkexpand = FALSE; /* expand causes error at 640x480, should otherwise be TRUE; */
+- }
+- break;
+- case 1280:
+- if(yres == 960) {
+- if(pSiS->VGAEngine == SIS_300_VGA) {
+- paneltype = Panel300_1280x960;
+- } else {
+- paneltype = Panel310_1280x960;
+- }
+- } else if(yres == 1024) {
+- paneltype = Panel310_1280x1024;
+- checkexpand = TRUE;
+- } else if(pSiS->VGAEngine == SIS_315_VGA) {
++
++ if(buffer[0x18] & 0x02) {
++
++ xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
++ yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
++
++ SiS_Pr->CP_PreferredX = xres;
++ SiS_Pr->CP_PreferredY = yres;
++
++ switch(xres) {
++ case 800:
++ if(yres == 600) {
++ paneltype = Panel_800x600;
++ checkexpand = TRUE;
++ }
++ break;
++ case 1024:
+ if(yres == 768) {
+- paneltype = Panel310_1280x768; /* Panel size 1280x768 not supported yet */
+- checkexpand = TRUE;
+- }
+- }
+- break;
+- case 1400:
+- if(pSiS->VGAEngine == SIS_315_VGA) {
+- if(yres == 1050) {
+- paneltype = Panel310_1400x1050;
+- checkexpand = TRUE;
+- }
+- }
+- break;
+- case 1600:
+- if(pSiS->VGAEngine == SIS_315_VGA) {
+- if(yres == 1200) {
+- paneltype = Panel310_1600x1200;
++ paneltype = Panel_1024x768;
++ checkexpand = TRUE;
++ }
++ break;
++ case 1280:
++ if(yres == 1024) {
++ paneltype = Panel_1280x1024;
+ checkexpand = TRUE;
+- }
+- }
+- break;
++ } else if(yres == 960) {
++ if(pSiS->VGAEngine == SIS_300_VGA) {
++ paneltype = Panel300_1280x960;
++ } else {
++ paneltype = Panel310_1280x960;
++ }
++ } else if(yres == 768) {
++ paneltype = Panel_1280x768;
++ checkexpand = FALSE;
++ cr37 |= 0x10;
++ }
++ break;
++ case 1400:
++ if(pSiS->VGAEngine == SIS_315_VGA) {
++ if(yres == 1050) {
++ paneltype = Panel310_1400x1050;
++ checkexpand = TRUE;
++ }
++ }
++ break;
++#if 0 /* Treat this as custom, as we have no valid timing data yet */
++ case 1600:
++ if(pSiS->VGAEngine == SIS_315_VGA) {
++ if(yres == 1200) {
++ paneltype = Panel310_1600x1200;
++ checkexpand = TRUE;
++ }
++ }
++ break;
++#endif
++ }
++
++ if(paneltype != Panel_Custom) {
++ if((buffer[0x47] & 0x18) == 0x18) {
++ cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
++ } else {
++ /* What now? There is no digital separate output timing... */
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
++ "CRT2: Unable to retrieve Sync polarity information\n");
++ }
++ }
++
+ }
+
+- if(buffer[0x18] & 0x02) {
+- /* If the preferred timing mode is stored in the first
+- * detailed timing block, we now can extract the sync
+- * polarisation information as well. This only works
+- * if the Flags indicate a digital separate output.
+- */
+- if((buffer[0x47] & 0x18) == 0x18) {
+- cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
+- } else {
+- /* What now? There is no digital separate output timing... */
+- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
+- "CRT2: Unable to retrieve Sync polarity information\n");
+- }
+-
+- } else {
+- /* If the preferred timing mode is *not* stored in the first
+- * detailed timing block, we need to guess the resolution
+- * from the supported Established Timings and assume the
+- * default sync polarity
+- */
++ /* If we still don't know what panel this is, we take it
++ * as a custom panel and derive the timing data from the
++ * detailed timing blocks
++ */
++ if(paneltype == Panel_Custom) {
++
++ BOOLEAN havesync = FALSE;
++ int i, temp, base = 0x36;
++ unsigned long estpack;
++ unsigned short estx[] = {
++ 720, 720, 640, 640, 640, 640, 800, 800,
++ 800, 800, 832,1024,1024,1024,1024,1280,
++ 1152
++ };
++ unsigned short esty[] = {
++ 400, 400, 480, 480, 480, 480, 600, 600,
++ 600, 600, 624, 768, 768, 768, 768,1024,
++ 870
++ };
++
+ paneltype = 0;
+- if(buffer[0x24] & 0x01) {
+- paneltype = Panel310_1280x1024;
+- checkexpand = TRUE;
+- cr37 |= 0x20;
+- } else if(buffer[0x24] & 0x0e) {
+- paneltype = Panel310_1024x768;
+- cr37 |= 0xe0;
+- checkexpand = FALSE; /* Bug at 640x480 */
+- } else if(buffer[0x23] & 0x01) {
+- paneltype = Panel310_800x600;
+- cr37 |= 0xe0;
+- checkexpand = TRUE;
+- }
++
++ /* Find the maximum resolution */
++
++ /* 1. From Established timings */
++ estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
++ for(i=16; i>=0; i--) {
++ if(estpack & (1 << i)) {
++ if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
++ if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
++ }
++ }
++
++ /* 2. From Standard Timings */
++ for(i=0x26; i < 0x36; i+=2) {
++ if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
++ temp = (buffer[i] + 31) * 8;
++ if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
++ switch((buffer[i+1] & 0xc0) >> 6) {
++ case 0x03: temp = temp * 9 / 16; break;
++ case 0x02: temp = temp * 4 / 5; break;
++ case 0x01: temp = temp * 3 / 4; break;
++ }
++ if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
++ }
++ }
++
++ /* Now extract the Detailed Timings and convert them into modes */
++
++ for(i = 0; i < 4; i++, base += 18) {
++
++ /* Is this a detailed timing block or a monitor descriptor? */
++ if(buffer[base] || buffer[base+1] || buffer[base+2]) {
++
++ xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
++ yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
++
++ SiS_Pr->CP_HDisplay[i] = xres;
++ SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
++ SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
++ SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
++ SiS_Pr->CP_HBlankStart[i] = xres + 1;
++ SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
++
++ SiS_Pr->CP_VDisplay[i] = yres;
++ SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
++ SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
++ SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
++ SiS_Pr->CP_VBlankStart[i] = yres + 1;
++ SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
++
++ SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
++
++ SiS_Pr->CP_DataValid[i] = TRUE;
++
++ /* Sort out invalid timings, interlace and too high clocks */
++ if((SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
++ (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
++ (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
++ (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
++ (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
++ (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
++ (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_Clock[i] > 108000) ||
++ (buffer[base+17] & 0x80)) {
++
++ SiS_Pr->CP_DataValid[i] = FALSE;
++
++ } else {
++
++ paneltype = Panel_Custom;
++
++ SiS_Pr->CP_HaveCustomData = TRUE;
++
++ if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
++ if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
++ if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
++
++ SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
++ SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
++
++ /* We must assume the panel can scale, since we have
++ * no scaling data
++ */
++ checkexpand = FALSE;
++ cr37 |= 0x10;
++
++ /* Extract the sync polarisation information. This only works
++ * if the Flags indicate a digital separate output.
++ */
++ if((buffer[base+17] & 0x18) == 0x18) {
++ SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
++ SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
++ SiS_Pr->CP_SyncValid[i] = TRUE;
++ if(!havesync) {
++ cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
++ havesync = TRUE;
++ }
++ } else {
++ SiS_Pr->CP_SyncValid[i] = FALSE;
++ }
++ }
++ }
++ }
++ if(!havesync) {
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
++ "CRT2: Unable to retrieve Sync polarity information\n");
++ }
+ }
+-
+- if(checkexpand) {
+- /* If any of the Established low-res modes is supported, the
++
++ if(paneltype && checkexpand) {
++ /* If any of the Established low-res modes is supported, the
+ * panel can scale automatically. For 800x600 panels, we only
+ * check the even lower ones.
+ */
+- if(paneltype == Panel310_800x600) {
++ if(paneltype == Panel_800x600) {
+ if(buffer[0x23] & 0xfc) cr37 |= 0x10;
+ } else {
+ if(buffer[0x23]) cr37 |= 0x10;
+@@ -10262,20 +10716,31 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ buffer[0x41]);
+ return 0;
+ }
+-
+- xres = buffer[0x76] | (buffer[0x77] << 8);
+- yres = buffer[0x78] | (buffer[0x79] << 8);
++
++ paneltype = Panel_Custom;
++ SiS_Pr->CP_MaxX = xres = buffer[0x76] | (buffer[0x77] << 8);
++ SiS_Pr->CP_MaxY = yres = buffer[0x78] | (buffer[0x79] << 8);
+ switch(xres) {
+ case 800:
+ if(yres == 600) {
+- paneltype = Panel310_800x600;
++ paneltype = Panel_800x600;
+ checkexpand = TRUE;
+ }
+ break;
+ case 1024:
+ if(yres == 768) {
+- paneltype = Panel310_1024x768;
+- checkexpand = FALSE; /* Bug at 640x480; we do the scaling ourselves */
++ paneltype = Panel_1024x768;
++ checkexpand = TRUE;
++ }
++ break;
++ case 1152:
++ if(yres == 768) {
++ if(pSiS->VGAEngine == SIS_300_VGA) {
++ paneltype = Panel300_1152x768;
++ } else {
++ paneltype = Panel310_1152x768;
++ }
++ checkexpand = TRUE;
+ }
+ break;
+ case 1280:
+@@ -10286,45 +10751,46 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ paneltype = Panel300_1280x960;
+ }
+ } else if(yres == 1024) {
+- paneltype = Panel310_1280x1024;
++ paneltype = Panel_1280x1024;
+ checkexpand = TRUE;
+- } else if(pSiS->VGAEngine == SIS_315_VGA) {
+- if(yres == 768) {
+- paneltype = Panel310_1280x768; /* Panel size 1280x768 not supported yet */
+- checkexpand = TRUE;
+- }
+- }
++ } else if(yres == 768) {
++ paneltype = Panel_1280x768;
++ checkexpand = FALSE;
++ cr37 |= 0x10;
++ }
+ break;
+ case 1400:
+ if(pSiS->VGAEngine == SIS_315_VGA) {
+ if(yres == 1050) {
+ paneltype = Panel310_1400x1050;
+ checkexpand = TRUE;
+- }
++ }
+ }
+ break;
++#if 0 /* Treat this one as custom since we have no timing data yet */
+ case 1600:
+ if(pSiS->VGAEngine == SIS_315_VGA) {
+ if(yres == 1200) {
+ paneltype = Panel310_1600x1200;
+ checkexpand = TRUE;
+- }
++ }
+ }
+ break;
++#endif
+ }
+-
++
+ /* Determine if RGB18 or RGB24 */
+ if(index) {
+ if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
+ cr37 |= 0x01;
+ }
+ }
+-
++
+ if(checkexpand) {
+ /* TODO - for now, we let the panel scale */
+ cr37 |= 0x10;
+ }
+-
++
+ /* Now seek 4-Byte Timing codes and extract sync pol info */
+ index = 0x80;
+ if(buffer[0x7e] & 0x20) { /* skip Luminance Table (if provided) */
+@@ -10346,28 +10812,117 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
+ if(buffer[myindex] == seekcode) {
+ cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
+ } else {
+- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
+- "CRT2: Unable to retrieve Sync polarity information\n");
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
++ "CRT2: Unable to retrieve Sync polarity information\n");
+ }
+ } else {
+- xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
+- "CRT2: Unable to retrieve Sync polarity information\n");
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
++ "CRT2: Unable to retrieve Sync polarity information\n");
++ }
++
++ /* Now seek the detailed timing descriptions for custom panels */
++ if(paneltype == Panel_Custom) {
++ index += (numcodes * 4);
++ numcodes = buffer[0x7f] & 0x07;
++ for(i=0; i<numcodes; i++) {
++ xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
++ yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
++
++ SiS_Pr->CP_HDisplay[i] = xres;
++ SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
++ SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
++ SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
++ SiS_Pr->CP_HBlankStart[i] = xres + 1;
++ SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
++
++ SiS_Pr->CP_VDisplay[i] = yres;
++ SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
++ SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
++ SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
++ SiS_Pr->CP_VBlankStart[i] = yres + 1;
++ SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
++
++ SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
++
++ SiS_Pr->CP_DataValid[i] = TRUE;
++
++ if((SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i]) ||
++ (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
++ (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i]) ||
++ (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i]) ||
++ (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i]) ||
++ (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i]) ||
++ (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i]) ||
++ (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i]) ||
++ (SiS_Pr->CP_Clock[i] > 108000) ||
++ (buffer[index + 17] & 0x80)) {
++
++ SiS_Pr->CP_DataValid[i] = FALSE;
++
++ } else {
++
++ SiS_Pr->CP_HaveCustomData = TRUE;
++
++ if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
++
++ SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
++ SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
++ SiS_Pr->CP_SyncValid[i] = TRUE;
++
++ SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
++ SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
++
++ /* We must assume the panel can scale, since we have
++ * no scaling data
++ */
++ cr37 |= 0x10;
++
++ }
++ }
++
+ }
+
+ break;
+-
++
+ }
+-
++
+ /* 1280x960 panels are always RGB24, unable to scale and use
+ * high active sync polarity
+ */
+ if(pSiS->VGAEngine == SIS_315_VGA) {
+- if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
++ if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
+ } else {
+- if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
++ if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
+ }
+-
++
++ for(i = 0; i < 7; i++) {
++ if(SiS_Pr->CP_DataValid[i]) {
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
++ "Non-standard LCD timing data no. %d:\n", i);
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
++ " HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
++ SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
++ SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
++ " VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
++ SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
++ SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
++ " Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
++ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
++ " To use this, add \"%dx%d\" to the list of Modes in the Display section\n",
++ SiS_Pr->CP_HDisplay[i],
++ SiS_Pr->CP_VDisplay[i]);
++ }
++ }
++
+ if(paneltype) {
++ if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
++ if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
+ cr37 &= 0xf1;
+ cr37 |= 0x02; /* SiS301 */
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
+@@ -10392,7 +10947,7 @@ SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SI
+ if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_302B))) return 0;
+ /* if(pSiS->VBFlags & VB_30xBDH) return 0; */
+
+- if(SiS_InitDDCRegs(SiS_Pr, pSiS, 2, 0, FALSE) == 0xFFFF) return 0;
++ if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
+
+ SiS_Pr->SiS_DDC_SecAddr = 0x00;
+
+@@ -10416,7 +10971,7 @@ SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SI
+ /* Read the entire EDID */
+ retry = 2;
+ do {
+- if(SiS_ReadDDC(SiS_Pr, pSiS, DDCdatatype, buffer)) {
++ if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
+ xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
+ "CRT2: DDC read failed (attempt %d), %s\n",
+ (3-retry), (retry == 1) ? "giving up" : "retrying");
+@@ -10435,6 +10990,8 @@ SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SI
+ "CRT2: Attached display expects digital input\n");
+ return 0;
+ }
++ SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
++ SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
+ foundcrt = TRUE;
+ break;
+ case 3:
+@@ -10448,198 +11005,19 @@ SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SI
+ buffer[0x41]);
+ return 0;
+ }
++ SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
++ SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
+ foundcrt = TRUE;
+- break;
++ break;
+ }
+-
++
+ if(foundcrt) {
+ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
+ }
+ return(0);
+ }
+
+-#if 0
+- /* ----- */
+-USHORT
+-SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
+-{
+- USHORT DDCdatatype, paneltype, flag;
+- unsigned char cr36=0, cr37=0;
+- unsigned char tempal, tempah, tempbl, tempbh;
+- USHORT tempax, tempbx, tempcx, push1, push2, push3;
+- unsigned char addresstable[] = { 0x00, 0x22, 0x30, 0x40 };
+- int i;
+- unsigned char buffer[256];
+-
+- if(pSiS->VGAEngine != SIS_315_VGA) return 0xFFFF;
+- if(!(pSiS->VBFlags & (VB_301B|VB_302B))) return 0xFFFF;
+-
+- if(SiS_InitDDCRegs(SiS_Pr, pSiS, 1, 0, FALSE) == 0xFFFF) return 0xFFFF;
+-
+- flag = SiS_ProbeDDC(SiS_Pr);
+- if(flag & 0x02) {
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0; /* EDID V1 */
+- DDCdatatype = 1;
+- SiS_Pr->SiS_DDC_SecAddr = 0x3a;
+- } else if(flag & 0x08) {
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa2; /* EDID V2 (P&D-D Monitor) */
+- DDCdatatype = 3;
+- SiS_Pr->SiS_DDC_SecAddr = 0x76;
+- } else if(flag & 0x10) {
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa6; /* EDID V2 (FP) */
+- DDCdatatype = 4;
+- SiS_Pr->SiS_DDC_SecAddr = 0x76;
+- } else return 0xFFFF;
+-
+-
+- SiS_ReadLCDDDC(SiS_Pr, 4, buffer);
+- tempbl = buffer[0]; /* 3a - 76 */
+- tempbh = buffer[1]; /* 3b - 77 */
+-
+- if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
+-
+- /* Read and analyze EDID V1 (res) */
+-
+- tempah = 0x02; /* 1024x768 by default */
+- tempbl &= 0xf0;
+- if(tempbl != 0x40) {
+- tempah = 0x03; /* 1280x1024 by default */
+- if(tempbl == 0x50) {
+- if(!tempbh) {
+- tempbh = buffer[3] & 0xf0;
+- if(tempbh == 0x30) {
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
+- SiS_Pr->SiS_DDC_SecAddr = 0x23;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempbl = buffer[0]; /* 0x23 */
+- tempbh = buffer[1]; /* 0x24 */
+- if(tempbl) cr37 |= 0x10;
+- tempah = 0x0a; /* 1280x768 */
+- }
+- if(tempbh == 0x40) {
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
+- SiS_Pr->SiS_DDC_SecAddr = 0x23;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempbl = buffer[0]; /* 0x23 */
+- tempbh = buffer[1]; /* 0x24 */
+- if(tempbl) cr37 |= 0x10;
+- tempah = 0x03; /* 1280x1024 */
+- }
+- tempbh = 0x00;
+- }
+- }
+- if(tempbh == 0x00) goto cr36ready;
+- tempah = 0x07; /* 1280x960 */
+- if(tempbh == 0xc0) goto cr36ready;
+- }
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
+- SiS_Pr->SiS_DDC_SecAddr = 0x18; /* feature support */
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempbl = buffer[0];
+- tempbh = buffer[1];
+- if(tempbl & 0x02) goto cr36ready;
+- SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
+- SiS_Pr->SiS_DDC_SecAddr = 0x23; /* Established Timings */
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempbl = buffer[0];
+- tempbh = buffer[1];
+- tempah = 0x03;
+- if(!(tempbh & 0x01)) tempah = 0x02;
+- if(!tempbl) cr37 |= 0x10;
+-
+- } else {
+-
+- /* Read and analyze EDID V2 (res) */
+-
+- tempah = 0x02;
+- tempbx = tempbl | (tempbh << 8);
+- if(tempbx != 1024) tempah = 0x03;
+-
+- }
+-
+-cr36ready:
+- cr36 = tempah;
+-
+- if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
+-
+- /* Read and analyze EDID V1 (pol) */
+-
+- SiS_Pr->SiS_DDC_SecAddr = 0x47;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempah = buffer[0];
+- tempah &= 0x06;
+- tempah ^= 0x06;
+- tempah <<= 5;
+- tempah |= 0x20;
+- cr37 &= 0x1f;
+- cr37 |= tempah;
+- if((cr36 & 0x07) == 0x07) cr37 &= 0x0e;
+-
+- } else {
+-
+- /* Read and analyze EDID V2 (depth, pol) */
+-
+- push1 = tempah;
+- SiS_Pr->SiS_DDC_SecAddr = 0x45;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempah = 0x01;
+- if((buffer[0] != 0x20) && (buffer[0] != 0x34)) { /* RGB18 or 24? */
+- tempah = 0x00;
+- }
+- cr37 &= 0xfe;
+- cr37 |= tempah;
+-
+- SiS_Pr->SiS_DDC_SecAddr = 0x7e;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempax = (USHORT)(buffer[0] | (buffer[1] << 8));
+- push2 = tempax;
+- tempax &= 0x0003;
+- tempax *= 0x1b;
+- push3 = tempax;
+- tempax = (USHORT)buffer[0];
+- tempax &= 0x001c;
+- tempax >>= 2;
+- tempax *= 8;
+- tempbx = push3;
+- tempbx += tempax;
+- if(buffer[0] & 0x20) { /* Luminance table provided? */
+- SiS_Pr->SiS_DDC_SecAddr = 0x80;
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempax = buffer[0] | (buffer[1] << 8);
+- tempax &= 0x1f;
+- if(buffer[0] & 0x70) tempax <<= 1;
+- tempax++;
+- tempbx += tempax; /* yes -> skip it */
+- }
+- tempcx = push2;
+- tempax = push1 << 8;
+- tempbx = (tempbx & 0xff00) | (((tempbx & 0x00ff) + 0x80) & 0x00ff);
+- if(tempcx & 0xf800) {
+- tempal = addresstable[((tempax & 0xff00) >> 8)];
+- tempcx &= 0xf8ff;
+- tempcx >>= 11;
+- for(i=0; i<tempcx; i++) {
+- SiS_Pr->SiS_DDC_SecAddr = (tempbx & 0x00ff);
+- SiS_ReadLCDDDC(SiS_Pr, 2, buffer);
+- tempbx += 0x04;
+- if(buffer[0] == tempal) break;
+- }
+- tempah = buffer[1];
+- tempah &= 0x0c;
+- tempah ^= 0x0c;
+- tempah <<= 4;
+- tempah |= 0x20;
+- cr37 &= 0x1f;
+- cr37 |= tempah;
+- if((cr36 & 0x07) == 0x07) cr37 &= 0x0e;
+- }
+- }
+- xf86DrvMsg(0, X_INFO, "DDC: cr36 = 0x%02x, cr37 = 0x%02x\n", cr36, cr37);
+- return 0;
+-}
+-#endif
+-
+-/* TW: Generic I2C functions (compliant to i2c library) */
++/* Generic I2C functions (compliant to i2c library) */
+
+ #if 0
+ USHORT
+@@ -10675,16 +11053,14 @@ SiS_I2C_Stop(SiS_Private *SiS_Pr)
+ void
+ SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
+ {
+- USHORT tempal,tempah,tempbl;
++ USHORT tempbl;
+
+- tempal = tempax & 0x00FF;
+- tempah =(tempax >> 8) & 0x00FF;
+- tempbl = SiS_GetCH70xx(SiS_Pr,tempal);
+- tempbl = (((tempbl & tempbh) | tempah) << 8 | tempal);
++ tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
++ tempbl = (((tempbl & tempbh) << 8) | tempax);
+ SiS_SetCH70xx(SiS_Pr,tempbl);
+ }
+
+-/* TW: Generic I2C functions for Chrontel --------- */
++/* Generic I2C functions for Chrontel --------- */
+
+ void
+ SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
+@@ -10698,37 +11074,37 @@ SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
+ SiS_WaitRetraceDDC(SiS_Pr);
+ }
+
+-/* TW: Set I2C start condition */
+-/* TW: This is done by a SD high-to-low transition while SC is high */
++/* Set I2C start condition */
++/* This is done by a SD high-to-low transition while SC is high */
+ USHORT
+ SiS_SetStart(SiS_Private *SiS_Pr)
+ {
+- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */
++ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: SD->high */
+- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: SC->high */
++ ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* SD->high */
++ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: SD->low = start condition */
+- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */
++ ~SiS_Pr->SiS_DDC_Data,0x00); /* SD->low = start condition */
++ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ return 0;
+ }
+
+-/* TW: Set I2C stop condition */
+-/* TW: This is done by a SD low-to-high transition while SC is high */
++/* Set I2C stop condition */
++/* This is done by a SD low-to-high transition while SC is high */
+ USHORT
+ SiS_SetStop(SiS_Private *SiS_Pr)
+ {
+- if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* TW: (SC->low) */
++ if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF; /* (SC->low) */
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: SD->low */
+- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: SC->high */
++ ~SiS_Pr->SiS_DDC_Data,0x00); /* SD->low */
++ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* SC->high */
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: SD->high = stop condition */
+- if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* TW: (SC->high) */
++ ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* SD->high = stop condition */
++ if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF; /* (SC->high) */
+ return 0;
+ }
+
+-/* TW: Write 8 bits of data */
++/* Write 8 bits of data */
+ USHORT
+ SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+ {
+@@ -10736,18 +11112,18 @@ SiS_WriteDDC2Data(SiS_Private *SiS_Pr, U
+
+ flag=0x80;
+ for(i=0;i<8;i++) {
+- SiS_SetSCLKLow(SiS_Pr); /* TW: SC->low */
++ SiS_SetSCLKLow(SiS_Pr); /* SC->low */
+ if(tempax & flag) {
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: Write bit (1) to SD */
++ ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* Write bit (1) to SD */
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,0x00); /* TW: Write bit (0) to SD */
++ ~SiS_Pr->SiS_DDC_Data,0x00); /* Write bit (0) to SD */
+ }
+- SiS_SetSCLKHigh(SiS_Pr); /* TW: SC->high */
++ SiS_SetSCLKHigh(SiS_Pr); /* SC->high */
+ flag >>= 1;
+ }
+- temp = SiS_CheckACK(SiS_Pr); /* TW: Check acknowledge */
++ temp = SiS_CheckACK(SiS_Pr); /* Check acknowledge */
+ return(temp);
+ }
+
+@@ -10808,27 +11184,27 @@ SiS_DDC2Delay(SiS_Private *SiS_Pr, USHOR
+ }
+ }
+
+-/* TW: Check I2C acknowledge */
++/* Check I2C acknowledge */
+ /* Returns 0 if ack ok, non-0 if ack not ok */
+ USHORT
+ SiS_CheckACK(SiS_Private *SiS_Pr)
+ {
+ USHORT tempah;
+
+- SiS_SetSCLKLow(SiS_Pr); /* TW: (SC->low) */
++ SiS_SetSCLKLow(SiS_Pr); /* (SC->low) */
+ SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
+- ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* TW: (SD->high) */
+- SiS_SetSCLKHigh(SiS_Pr); /* TW: SC->high = clock impulse for ack */
+- tempah = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);/* TW: Read SD */
+- SiS_SetSCLKLow(SiS_Pr); /* TW: SC->low = end of clock impulse */
+- if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* TW: Ack OK if bit = 0 */
++ ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data); /* (SD->high) */
++ SiS_SetSCLKHigh(SiS_Pr); /* SC->high = clock impulse for ack */
++ tempah = SiS_GetReg1(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);/* Read SD */
++ SiS_SetSCLKLow(SiS_Pr); /* SC->low = end of clock impulse */
++ if(tempah & SiS_Pr->SiS_DDC_Data) return(1); /* Ack OK if bit = 0 */
+ else return(0);
+ }
+
+-/* TW: End of I2C functions ----------------------- */
++/* End of I2C functions ----------------------- */
+
+
+-/* =============== SiS 310/325/330 O.E.M. ================= */
++/* =============== SiS 315/330 O.E.M. ================= */
+
+ #ifdef SIS315H
+
+@@ -10838,11 +11214,11 @@ GetRAMDACromptr(SiS_Private *SiS_Pr, PSI
+ USHORT romptr;
+
+ if(HwDeviceExtension->jChipType < SIS_330) {
+- romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8);
++ romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8);
+ if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ romptr = ROMAddr[0x12a] | (ROMAddr[0x12b] << 8);
+ } else {
+- romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8);
++ romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8);
+ if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+ romptr = ROMAddr[0x1aa] | (ROMAddr[0x1ab] << 8);
+ }
+@@ -10855,11 +11231,11 @@ GetLCDromptr(SiS_Private *SiS_Pr, PSIS_H
+ USHORT romptr;
+
+ if(HwDeviceExtension->jChipType < SIS_330) {
+- romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
++ romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+ } else {
+- romptr = ROMAddr[0x1a0] | (ROMAddr[0x1a1] << 8);
++ romptr = ROMAddr[0x1a0] | (ROMAddr[0x1a1] << 8);
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+ romptr = ROMAddr[0x1a2] | (ROMAddr[0x1a3] << 8);
+ }
+@@ -10884,10 +11260,22 @@ GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW
+ }
+
+ static USHORT
+-GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr)
++GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr)
+ {
+ USHORT index;
+-
++
++ if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
++ if(!(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr))) {
++ if((index = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
++ index >>= 4;
++ index *= 3;
++ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
++ else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
++ return index;
++ }
++ }
++ }
++
+ index = SiS_Pr->SiS_LCDResInfo & 0x0F;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) index -= 5;
+ else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) index -= 6;
+@@ -10895,7 +11283,6 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr)
+ index *= 3;
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+ else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
+-
+ return index;
+ }
+
+@@ -10945,8 +11332,9 @@ static void
+ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+ UCHAR *ROMAddr, USHORT ModeNo)
+ {
+- USHORT delay,index,myindex,temp,romptr=0;
+-
++ USHORT delay=0,index,myindex,temp,romptr=0;
++ BOOLEAN dochiptest = TRUE;
++
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) { /* VGA */
+
+ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+@@ -10969,61 +11357,81 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1)
+ delay = 0x00;
+ }
+-
++
+ } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) { /* LCD */
+-
+- index = GetLCDPtrIndexBIOS(SiS_Pr);
+- myindex = GetLCDPtrIndex(SiS_Pr);
+-
+- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { /* 650+30xLV */
+- if(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+- if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+-#if 0 /* Always use the second pointer on 650; some BIOSes */
+- /* still carry old 301 data at the first location */
+- romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
+- if(SiS_Pr->SiS_VBType & VB_SIS302LV)
+-#endif
+- romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+- if(!romptr) return;
+- delay = ROMAddr[(romptr + index)];
+- } else {
+- delay = SiS310_LCDDelayCompensation_650301B[myindex];
+-#if 0
++
++ BOOLEAN gotitfrompci = FALSE;
++
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
++
++ /* This is a piece of typical SiS crap: They code the OEM LCD
++ * delay into the code, at none defined place in the BIOS.
++ * We now have to start doing a PCI subsystem check here.
++ */
++
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
++ gotitfrompci = TRUE;
++ dochiptest = FALSE;
++ delay = 0x03;
++ }
++ }
++
++ if(!gotitfrompci) {
++
++ index = GetLCDPtrIndexBIOS(SiS_Pr, HwDeviceExtension, BaseAddr);
++ myindex = GetLCDPtrIndex(SiS_Pr);
++
++ if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) { /* 650+30xLV */
++ if(SiS_IsNotM650or651(SiS_Pr,HwDeviceExtension, BaseAddr)) {
++ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
++#if 0 /* Always use the second pointer on 650; some BIOSes */
++ /* still carry old 301 data at the first location */
++ romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
++ if(SiS_Pr->SiS_VBType & VB_SIS302LV)
++#endif
++ romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
++ if(!romptr) return;
++ delay = ROMAddr[(romptr + index)];
++ } else {
++ delay = SiS310_LCDDelayCompensation_650301B[myindex];
++#if 0
++ if(SiS_Pr->SiS_VBType & VB_SIS302LV)
++ delay = SiS310_LCDDelayCompensation_650301B[myindex];
++#endif
++ }
++ } else {
++ delay = SiS310_LCDDelayCompensation_651301LV[myindex];
+ if(SiS_Pr->SiS_VBType & VB_SIS302LV)
+- delay = SiS310_LCDDelayCompensation_650301B[myindex];
+-#endif
+- }
+- } else {
+- delay = SiS310_LCDDelayCompensation_651301LV[myindex];
+- if(SiS_Pr->SiS_VBType & VB_SIS302LV)
+- delay = SiS310_LCDDelayCompensation_651302LV[myindex];
+- }
+- } else {
+- if((ROMAddr) && SiS_Pr->SiS_UseROM && /* 315, 330, 740, 650+301B */
+- (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) {
+- romptr = GetLCDromptr(SiS_Pr, HwDeviceExtension, ROMAddr);
+- if(!romptr) return;
+- delay = ROMAddr[(romptr + index)];
++ delay = SiS310_LCDDelayCompensation_651302LV[myindex];
++ }
+ } else {
+- delay = SiS310_LCDDelayCompensation_301[myindex];
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+-#if 0 /* This data is (like the one in the BIOS) wrong. */
+- if(IS_SIS650740) { /* V */
+- delay = SiS310_LCDDelayCompensation_650301B[myindex];
+- } else {
+-#endif
+- delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
+-#if 0
++ if((ROMAddr) && SiS_Pr->SiS_UseROM && /* 315, 330, 740, 650+301B */
++ (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) {
++ romptr = GetLCDromptr(SiS_Pr, HwDeviceExtension, ROMAddr);
++ if(!romptr) return;
++ delay = ROMAddr[(romptr + index)];
++ } else {
++ delay = SiS310_LCDDelayCompensation_301[myindex];
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++#if 0 /* This data is (like the one in the BIOS) wrong. */
++ if(IS_SIS550650740660) {
++ delay = SiS310_LCDDelayCompensation_650301B[myindex];
++ } else {
++#endif
++ delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
++#if 0
++ }
++#endif
+ }
+-#endif
+- }
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(IS_SIS650) {
+- delay = SiS310_LCDDelayCompensation_LVDS650[myindex];
+- } else {
+- delay = SiS310_LCDDelayCompensation_LVDS740[myindex];
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
++ if(IS_SIS650) {
++ delay = SiS310_LCDDelayCompensation_LVDS650[myindex];
++ } else {
++ delay = SiS310_LCDDelayCompensation_LVDS740[myindex];
++ }
+ }
+- }
++ }
+ }
+ }
+
+@@ -11086,16 +11494,18 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
+ }
+ }
+ } else {
+- if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
++ if(dochiptest && IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+ temp = (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
+- if(temp == 8) {
++ if(temp == 8) { /* 1400x1050 BIOS */
+ delay &= 0x0f;
+ delay |= 0xb0;
+ } else if(temp == 6) {
+ delay &= 0x0f;
+ delay |= 0xc0;
++ } else if(temp > 7) { /* 1280x1024 BIOS */
++ delay = 0x35;
+ }
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2D,delay); /* index 2D D[3:0] */
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2D,delay);
+ } else {
+ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0xF0,delay);
+ }
+@@ -11118,7 +11528,7 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS
+
+ if(ROMAddr && SiS_Pr->SiS_UseROM) {
+ romptr = ROMAddr[0x112] | (ROMAddr[0x113] << 8);
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ romptr = ROMAddr[0x192] | (ROMAddr[0x193] << 8);
+ }
+ }
+@@ -11150,7 +11560,7 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS
+
+ if(ROMAddr && SiS_Pr->SiS_UseROM) {
+ romptr = ROMAddr[0x124] | (ROMAddr[0x125] << 8);
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ romptr = ROMAddr[0x1a4] | (ROMAddr[0x1a5] << 8);
+ }
+ }
+@@ -11198,7 +11608,7 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_
+
+ if(ROMAddr && SiS_Pr->SiS_UseROM) {
+ OutputSelect = ROMAddr[0xf3];
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ OutputSelect = ROMAddr[0x11b];
+ }
+ }
+@@ -11220,6 +11630,7 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+ }
+ }
++ /* PALN : Is this data correct? */
+ if(temp == EnablePALN) {
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ for(i=0x35, j=0; i<=0x38; i++, j++) {
+@@ -11247,13 +11658,13 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
+ if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+
+ temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x38); /* if PALM/N not set */
+- temp1 &= (EnablePALM | EnablePALN);
++ temp1 &= (EnablePALM | EnablePALN);
+ if(temp1) return;
+
+- if (ModeNo<=0x13) {
+- resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
++ if(ModeNo<=0x13) {
++ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ } else {
+- resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
++ resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+ }
+
+ temp = GetTVPtrIndex(SiS_Pr);
+@@ -11262,17 +11673,17 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
+ */
+ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+ romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+ }
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ romptr = ROMAddr[0x11c] | (ROMAddr[0x11d] << 8);
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ romptr = ROMAddr[0x19c] | (ROMAddr[0x19d] << 8);
+ }
+ if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_SetFlag & TVSimuMode))) {
+ romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+ }
+ }
+@@ -11296,19 +11707,19 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_H
+ }
+ }
+
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* TW: 650/301LV: (VB_SIS301LV | VB_SIS302LV)) */
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) { /* 650/301LV: (VB_SIS301LV | VB_SIS302LV)) */
+ if((!(SiS_Pr->SiS_VBInfo & SetPALTV)) && (ModeNo > 0x13)) {
+- if(resinfo == 6) {
++ if(resinfo == SIS_RI_640x480) {
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x21);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0xf0);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xf5);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x34,0x7f);
+- } else if (resinfo == 7) {
++ } else if (resinfo == SIS_RI_800x600) {
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x21);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0xf0);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xf5);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x34,0x7f);
+- } else if (resinfo == 8) {
++ } else if (resinfo == SIS_RI_1024x768) {
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x31,0x1e);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x32,0x8b);
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x33,0xfb);
+@@ -11323,7 +11734,9 @@ SiS_OEM310Setting(SiS_Private *SiS_Pr, P
+ UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex)
+ {
+ SetDelayComp(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo);
+- /* TW: The TV functions are not for LVDS */
++
++ if(SiS_Pr->UseCustomMode) return;
++
+ if( (SiS_Pr->SiS_IF_DEF_LVDS == 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
+ SetAntiFlicker(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+ SetPhaseIncr(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+@@ -11335,7 +11748,7 @@ SiS_OEM310Setting(SiS_Private *SiS_Pr, P
+ }
+
+ /* FinalizeLCD
+- * This finalizes some Part1 registers for the very panel used.
++ * This finalizes some CRT2 registers for the very panel used.
+ * If we have a backup if these registers, we use it; otherwise
+ * we set the register according to most BIOSes. However, this
+ * function looks quite different in every BIOS, so you better
+@@ -11350,6 +11763,11 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
+
+ if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
+
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
++ if(SiS_Pr->UseCustomMode) return;
++
++ if(SiS_Pr->SiS_CustomT == CUT_COMPAQ12802) return;
++
+ if(ModeNo <= 0x13) {
+ resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+@@ -11358,20 +11776,34 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
+ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+ }
+
++ if(IS_SIS650) {
++ if((SiS_GetReg1(SiS_Pr->SiS_P3d4, 0x5f) & 0xf0)) {
++ SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
++ }
++ }
++
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x30,0x00);
+ SiS_SetReg1(SiS_Pr->SiS_Part4Port,0x34,0x10);
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) { /* For all panels? */
++ /* Maybe ACER only? */
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
+ }
+ tempch = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36);
+ tempch &= 0xf0;
+ tempch >>= 4;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
++ if(tempch == 0x03) {
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x02);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1b,0x25);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1c,0x00);
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
++ }
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x1f,0x76);
+- }
+- if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
++ } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
+@@ -11387,14 +11819,14 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,0x90);
+ if(ModeNo <= 0x13) {
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x11);
+- if((resinfo == 0) && (resinfo == 2)) return;
++ if((resinfo == 0) || (resinfo == 2)) return;
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x18);
+- if((resinfo == 1) && (resinfo == 3)) return;
++ if((resinfo == 1) || (resinfo == 3)) return;
+ }
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x02);
+- if((ModeNo > 0x13) && (resinfo == 8)) {
++ if((ModeNo > 0x13) && (resinfo == SIS_RI_1024x768)) {
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,0x02); /* 1.10.7u */
+-#if 0
++#if 0
+ tempbx = 806; /* 0x326 */ /* other older BIOSes */
+ tempbx--;
+ temp = tempbx & 0xff;
+@@ -11449,7 +11881,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
+ tempbl = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x04);
+ tempbx = (tempbh << 8) | tempbl;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+- if((resinfo == 8) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
++ if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
+ if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+ tempbx = 770;
+ } else {
+@@ -11477,67 +11909,56 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USH
+ }
+ }
+
+-#if 0
+-/* TW: New and checked from 650/301LV BIOS */
+-/* This might clash with newer "FinalizeLCD()" function */
++#endif
++
++
++/* ================= SiS 300 O.E.M. ================== */
++
++#ifdef SIS300
++
+ void
+-SiS_OEMLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+- UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex)
++SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
++ UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
+ {
+- USHORT tempbx,tempah,tempbl,tempbh,tempcl;
+-
+- if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
++ USHORT crt2crtc=0, modeflag, myindex=0;
++ UCHAR temp;
++ int i;
+
+- if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+- SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr);
+- tempbh = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x1a);
+- tempbh &= 0x38;
+- tempbh >>= 3;
+- tempbl = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x18);
+- tempbx = (tempbh << 8) | tempbl;
+- if(SiS_Pr->SiS_LCDTypeInfo == 1) tempbx -= 0x12;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,tempbx & 0x00ff);
+- tempah = (tempbx & 0xff00) >> 8;
+- tempah &= 0x07;
+- tempah <<= 3;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0xc7,tempah);
+- tempah = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x19);
+- tempah &= 0x0f;
+- if(SiS_Pr->SiS_LCDTypeInfo == 1) tempah -= 2;
+- tempah &= 0x0f;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,tempah);
+- tempah = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x14);
+- if(SiS_Pr->SiS_LCDTypeInfo == 1) tempah++;
+- tempah -= 8;
+- SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x14,tempah);
+- } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- tempcl = tempbh = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x01);
+- tempbh &= 0x70;
+- tempbh >>= 4;
+- tempbl = SiS_GetReg1(SiS_Pr->SiS_Part2Port,0x04);
+- tempbx = (tempbh << 8) | tempbl;
+- if(SiS_Pr->SiS_LCDTypeInfo == 1) {
+- tempbx -= 0x1e;
+- tempcl &= 0x0f;
+- tempcl -= 4;
+- tempcl &= 0x0f;
+- }
+- tempbl = tempbx & 0x00ff;
+- tempbh = (tempbx >> 8) & 0x00ff;
+- SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x04,tempbl);
+- tempbh <<= 4;
+- tempbh |= tempcl;
+- SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,tempbh);
+- }
+-}
+-#endif
++ if(ModeNo <= 0x13) {
++ modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
++ crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
++ } else {
++ modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
++ crt2crtc = SiS_Pr->SiS_RefIndex[RefTabIndex].Ext_CRT2CRTC;
++ }
+
+-#endif
++ crt2crtc &= 0x3f;
+
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
++ SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xdf);
++ }
+
+-/* ================= SiS 300 O.E.M. ================== */
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
++ if(modeflag & HalfDCLK) myindex = 1;
+
+-#ifdef SIS300
++ if(SiS_LowModeStuff(SiS_Pr,ModeNo,HwDeviceExtension)) {
++ for(i=0; i<7; i++) {
++ if(barco_p1[myindex][crt2crtc][i][0]) {
++ SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,
++ barco_p1[myindex][crt2crtc][i][0],
++ barco_p1[myindex][crt2crtc][i][2],
++ barco_p1[myindex][crt2crtc][i][1]);
++ }
++ }
++ }
++ temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00);
++ if(temp & 0x80) {
++ temp = SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x18);
++ temp++;
++ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x18,temp);
++ }
++ }
++}
+
+ #if 0 /* Not used */
+ static USHORT
+@@ -11582,7 +12003,7 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_H
+
+ if(HwDeviceExtension->jChipType == SIS_300) {
+
+- tempbx = SiS_Pr->SiS_LCDResInfo - 2;
++ tempbx = (SiS_GetReg1(SiS_Pr->SiS_P3d4,0x36) & 0x0f) - 2;
+ if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
+ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
+@@ -11636,24 +12057,29 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
+ {
+ USHORT index,temp,romptr=0;
+
++ if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
++
+ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+ if(!(ROMAddr[0x237] & 0x01)) return;
+ if(!(ROMAddr[0x237] & 0x02)) return;
+ romptr = ROMAddr[0x24b] | (ROMAddr[0x24c] << 8);
+ }
+
+- /* TW: The Panel Compensation Delay should be set according to tables
+- * here. Unfortunately, various BIOS versions don't case about
+- * a uniform way using eg. ROM byte 0x220, but use different
+- * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
+- * Thus we don't set this if the user select a custom pdc or if
+- * we otherwise detected a valid pdc.
++ /* The Panel Compensation Delay should be set according to tables
++ * here. Unfortunately, various BIOS versions don't case about
++ * a uniform way using eg. ROM byte 0x220, but use different
++ * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
++ * Thus we don't set this if the user select a custom pdc or if
++ * we otherwise detected a valid pdc.
+ */
+ if(HwDeviceExtension->pdc) return;
+
+ temp = GetOEMLCDPtr(SiS_Pr,HwDeviceExtension, ROMAddr, 0);
+
+- index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
++ if(SiS_Pr->UseCustomMode)
++ index = 0;
++ else
++ index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
+
+ if(HwDeviceExtension->jChipType != SIS_300) {
+ if(romptr) {
+@@ -11700,9 +12126,9 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS
+
+ static void
+ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+- UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex)
++ UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex)
+ {
+-#if 0 /* TW: Unfinished; VData table missing */
++#if 0 /* Unfinished; Data table missing */
+ USHORT index,temp;
+
+ if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+@@ -11899,25 +12325,29 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_
+
+ void
+ SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+- USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo)
++ USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
++ USHORT RefTableIndex)
+ {
+- USHORT ModeIdIndex;
++ USHORT OEMModeIdIndex=0;
+
+- ModeIdIndex = SiS_SearchVBModeID(SiS_Pr,ROMAddr,&ModeNo);
+- if(!(ModeIdIndex)) return;
++ if(!SiS_Pr->UseCustomMode) {
++ OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,ROMAddr,&ModeNo);
++ if(!(OEMModeIdIndex)) return;
++ }
+
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+- SetOEMLCDDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
++ SetOEMLCDDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- SetOEMLCDData(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
++ SetOEMLCDData(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
+ }
+ }
++ if(SiS_Pr->UseCustomMode) return;
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+- SetOEMTVDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
++ SetOEMTVDelay(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 0) {
+- SetOEMAntiFlicker(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+- SetOEMPhaseIncr(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
+- SetOEMYFilter(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,ModeIdIndex);
++ SetOEMAntiFlicker(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
++ SetOEMPhaseIncr(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
++ SetOEMYFilter(SiS_Pr,HwDeviceExtension,BaseAddr,ROMAddr,ModeNo,OEMModeIdIndex);
+ }
+ }
+ }
+--- linux-2.6.0-test6/drivers/video/sis/init301.h 2003-06-14 12:18:21.000000000 -0700
++++ 25/drivers/video/sis/init301.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,20 +1,47 @@
+-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init301.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
++/* $XFree86$ */
++/*
++ * Data and prototypes for init301.c
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
++
+ #ifndef _INIT301_
+ #define _INIT301_
+
+ #include "osdef.h"
++
+ #include "initdef.h"
+ #include "vgatypes.h"
+ #include "vstruct.h"
+
+-#ifdef TC
+-#include <stdio.h>
+-#include <string.h>
+-#include <conio.h>
+-#include <dos.h>
+-#include <stdlib.h>
+-#endif
+-
+ #ifdef LINUX_XF86
+ #include "xf86.h"
+ #include "xf86Pci.h"
+@@ -24,6 +51,9 @@
+ #endif
+
+ #ifdef LINUX_KERNEL
++#ifdef SIS_CP
++#undef SIS_CP
++#endif
+ #include <linux/config.h>
+ #include <linux/version.h>
+ #include <asm/io.h>
+@@ -35,24 +65,60 @@
+ #endif
+ #endif
+
+-#ifdef WIN2000
+-#include <stdio.h>
+-#include <string.h>
+-#include <miniport.h>
+-#include "dderror.h"
+-#include "devioctl.h"
+-#include "miniport.h"
+-#include "ntddvdeo.h"
+-#include "video.h"
+-#include "sisv.h"
+-#endif
++const UCHAR SiS_HiVisionTable[3][64] = {
++ {
++ 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c,
++ 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a,
++ 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b,
++ 0x0c, 0x50, 0x00, 0x97, 0x00, 0xd4, 0x4a, 0x17,
++ 0x7d, 0x05, 0x4b, 0x00, 0x00, 0xe2, 0x00, 0x02,
++ 0x03, 0x0a, 0x65, 0x9d, 0x08, 0x92, 0x8f, 0x40,
++ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x53,
++ 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00
++ },
++ {
++ 0x1d, 0x1d, 0x06, 0x09, 0x0b, 0x0c, 0x0c, 0x0c,
++ 0x98, 0x0a, 0x01, 0x0d, 0x06, 0x0d, 0x04, 0x0a,
++ 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
++ 0x0c, 0x50, 0xb2, 0x2e, 0x16, 0xb5, 0xf4, 0x03,
++ 0x7d, 0x11, 0x7d, 0xea, 0x30, 0x36, 0x18, 0x96,
++ 0x21, 0x0a, 0x58, 0xee, 0x42, 0x92, 0x0f, 0x40,
++ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x04, 0xf3,
++ 0x00, 0x40, 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00
++ },
++ {
++ 0x13, 0x1d, 0xe8, 0x09, 0x09, 0xed, 0x0c, 0x0c,
++ 0x98, 0x0a, 0x01, 0x0c, 0x06, 0x0d, 0x04, 0x0a,
++ 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
++ 0xed, 0x50, 0x70, 0x9f, 0x16, 0x59, 0x2b, 0x13,
++ 0x27, 0x0b, 0x27, 0xfc, 0x30, 0x27, 0x1c, 0xb0,
++ 0x4b, 0x4b, 0x6f, 0x2f, 0x63, 0x92, 0x0f, 0x40,
++ 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x2a,
++ 0x00, 0x40, 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00
++ }
++};
+
+-#if 0
+-extern const USHORT SiS_MDA_DAC[];
+-extern const USHORT SiS_CGA_DAC[];
+-extern const USHORT SiS_EGA_DAC[];
+-extern const USHORT SiS_VGA_DAC[];
+-#endif
++const UCHAR SiS_HiTVGroup3_1[] = {
++ 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
++ 0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
++ 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
++ 0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
++ 0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
++ 0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
++ 0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
++ 0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
++};
++
++const UCHAR SiS_HiTVGroup3_2[] = {
++ 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
++ 0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
++ 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
++ 0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
++ 0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
++ 0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
++ 0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
++ 0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
++};
+
+ extern BOOLEAN SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *RomAddr, USHORT *);
+
+@@ -77,7 +143,8 @@ void SiS_GetCRT2PtrA(SiS_Private *Si
+ USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex);
+ #endif
+ void SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+- USHORT RefreshRateTableIndex,USHORT *CRT2Index, USHORT *ResIndex);
++ USHORT RefreshRateTableIndex,USHORT *CRT2Index, USHORT *ResIndex,
++ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_GetCRT2Data301(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ USHORT SiS_GetResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex);
+@@ -129,7 +196,6 @@ void SiS_GetVBInfo(SiS_Private *SiS_
+ BOOLEAN SiS_BridgeIsOn(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO);
+ BOOLEAN SiS_BridgeIsEnable(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO);
+ BOOLEAN SiS_BridgeInSlave(SiS_Private *SiS_Pr);
+-void SiS_PresetScratchregister(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SetTVSystem(SiS_Private *SiS_Pr);
+ void SiS_LongWait(SiS_Private *SiS_Pr);
+ USHORT SiS_GetQueueConfig(SiS_Private *SiS_Pr);
+@@ -149,7 +215,7 @@ void SiS_GetLVDSDesPtrA(SiS_Private
+ USHORT RefreshRateTableIndex,USHORT *PanelIndex,USHORT *ResIndex);
+ #endif
+ void SiS_SetTPData(SiS_Private *SiS_Pr);
+-void SiS_WhatIsThis(SiS_Private *SiS_Pr, USHORT myvbinfo);
++void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
+ void SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SetCHTVReg(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+@@ -178,30 +244,28 @@ USHORT SiS_SetSCLKHigh(SiS_Private *Si
+ USHORT SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+ USHORT SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+ USHORT SiS_CheckACK(SiS_Private *SiS_Pr);
+-USHORT SiS_ReadLCDDDC(SiS_Private *SiS_Pr, USHORT length, unsigned char *buffer);
+-#ifdef LINUX_XF86
+-USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+-USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+-#endif
++
+ #ifdef SIS315H
+ void SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+ UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex);
+ void SiS_OEMLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+- UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex);
++ UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex);
+ #endif
+ #ifdef SIS300
+ void SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
+- UCHAR *ROMAddr,USHORT ModeNo);
++ UCHAR *ROMAddr,USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
++void SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr,
++ UCHAR *ROMAddr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+ #endif
+ BOOLEAN SiS_LowModeStuff(SiS_Private *SiS_Pr, USHORT ModeNo,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+
+-BOOLEAN SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, USHORT ModeIdIndex,
++void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo, USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ /* void SiS_CHACRT1CRTC(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex); */
+
+-BOOLEAN SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+- PSIS_HW_DEVICE_INFO HwDeviceExtension);
++BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
++ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT RefreshRateTableIndex);
+ void SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+@@ -237,19 +301,19 @@ void SiS_VBWait(SiS_Private *SiS_Pr)
+ void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+
+-void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr);
++void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
+ #ifdef SIS315H
+ void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT BaseAddr);
+-void SiS_Chrontel701xOff(SiS_Private *SiS_Pr);
++void SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ void SiS_ChrontelDoSomething4(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ void SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ void SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ void SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ BOOLEAN SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+-void SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr);
++void SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+ #ifdef NEWCH701x
+ void SiS_ChrontelDoSomething5(SiS_Private *SiS_Pr);
+@@ -289,73 +353,21 @@ extern void SiS_LoadDAC(SiS_Privat
+ extern UCHAR SiS_Get310DRAMType(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ #endif
+
+-#ifdef LINUX_XF86
+ /* DDC functions */
+-USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
++USHORT SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
++ USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
+ USHORT SiS_WriteDABDDC(SiS_Private *SiS_Pr);
+ USHORT SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
+ USHORT SiS_PrepareDDC(SiS_Private *SiS_Pr);
+ void SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
+ USHORT SiS_DoProbeDDC(SiS_Private *SiS_Pr);
+ USHORT SiS_ProbeDDC(SiS_Private *SiS_Pr);
+-USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT DDCdatatype, unsigned char *buffer);
+-USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, SISPtr pSiS, USHORT adaptnum,
+- USHORT DDCdatatype, unsigned char *buffer);
++USHORT SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer);
++USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
++ USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
++#ifdef LINUX_XF86
++USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
++USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+ #endif
+
+-const UCHAR SiS_HiVisionTable[3][64] = {
+- {
+- 0x17, 0x1d, 0x03, 0x09, 0x05, 0x06, 0x0c, 0x0c,
+- 0x94, 0x49, 0x01, 0x0a, 0x06, 0x0d, 0x04, 0x0a,
+- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x1b,
+- 0x0c, 0x50, 0x00, 0x97, 0x00, 0xd4, 0x4a, 0x17,
+- 0x7d, 0x05, 0x4b, 0x00, 0x00, 0xe2, 0x00, 0x02,
+- 0x03, 0x0a, 0x65, 0x9d, 0x08, 0x92, 0x8f, 0x40,
+- 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x53,
+- 0x00, 0x40, 0x44, 0x00, 0xdb, 0x02, 0x3b, 0x00
+- },
+- {
+- 0x1d, 0x1d, 0x06, 0x09, 0x0b, 0x0c, 0x0c, 0x0c,
+- 0x98, 0x0a, 0x01, 0x0d, 0x06, 0x0d, 0x04, 0x0a,
+- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
+- 0x0c, 0x50, 0xb2, 0x2e, 0x16, 0xb5, 0xf4, 0x03,
+- 0x7d, 0x11, 0x7d, 0xea, 0x30, 0x36, 0x18, 0x96,
+- 0x21, 0x0a, 0x58, 0xee, 0x42, 0x92, 0x0f, 0x40,
+- 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x04, 0xf3,
+- 0x00, 0x40, 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00
+- },
+- {
+- 0x13, 0x1d, 0xe8, 0x09, 0x09, 0xed, 0x0c, 0x0c,
+- 0x98, 0x0a, 0x01, 0x0c, 0x06, 0x0d, 0x04, 0x0a,
+- 0x06, 0x14, 0x0d, 0x04, 0x0a, 0x00, 0x85, 0x3f,
+- 0xed, 0x50, 0x70, 0x9f, 0x16, 0x59, 0x2b, 0x13,
+- 0x27, 0x0b, 0x27, 0xfc, 0x30, 0x27, 0x1c, 0xb0,
+- 0x4b, 0x4b, 0x6f, 0x2f, 0x63, 0x92, 0x0f, 0x40,
+- 0x60, 0x80, 0x14, 0x90, 0x8c, 0x60, 0x14, 0x2a,
+- 0x00, 0x40, 0x11, 0x00, 0xfc, 0xff, 0x32, 0x00
+- }
+-};
+-
+-const UCHAR SiS_HiTVGroup3_1[] = {
+- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
+- 0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
+- 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+- 0xac, 0xda, 0x60, 0xfe, 0x6a, 0x9a, 0x06, 0x10,
+- 0xd1, 0x04, 0x18, 0x0a, 0xff, 0x80, 0x00, 0x80,
+- 0x3b, 0x77, 0x00, 0xef, 0xe0, 0x10, 0xb0, 0xe0,
+- 0x10, 0x4f, 0x0f, 0x0f, 0x05, 0x0f, 0x08, 0x6e,
+- 0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
+-};
+-
+-const UCHAR SiS_HiTVGroup3_2[] = {
+- 0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
+- 0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
+- 0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
+- 0xac, 0x6a, 0x60, 0x2b, 0x52, 0xcd, 0x61, 0x10,
+- 0x51, 0x04, 0x18, 0x0a, 0x1f, 0x80, 0x00, 0x80,
+- 0xff, 0xa4, 0x04, 0x2b, 0x94, 0x21, 0x72, 0x94,
+- 0x26, 0x05, 0x01, 0x0f, 0xed, 0x0f, 0x0a, 0x64,
+- 0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
+-};
+-
+ #endif
+--- linux-2.6.0-test6/drivers/video/sis/init.c 2003-06-14 12:18:05.000000000 -0700
++++ 25/drivers/video/sis/init.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,24 +1,17 @@
+ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/init.c,v 1.3 2002/24/04 01:16:16 dawes Exp $ */
+ /*
+- * Mode switching code (CRT1 section) for SiS 300/540/630/730/315/550/650/740/330
++ * Mode switching code (CRT1 section) for
++ * SiS 300/540/630/730/315/550/650/M650/651/M652/740/330/660/M660/760
+ * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ *
+ * Assembler-To-C translation
+- * Copyright 2002 by Thomas Winischhofer <thomas@winischhofer.net>
+- * Minor parts Copyright SiS, Inc.
++ * Copyright 2002, 2003 by Thomas Winischhofer <thomas@winischhofer.net>
++ * Formerly based on non-functional code-fragements by SiS, Inc.
+ *
+- * Based on BIOS
+- * 1.10.07, 1.10a for 650/CH7019
+- * 1.11.21a for 740/CH7019
+- * 1.11.05 for 650/LVDS (w/o Chrontel)
+- * 1.07.1b, 1.11.6s, 1.11.6w, 1.11.7w, 1.11.8r for 650/301(B/LV)
+- * 2.04.50 (I) and 2.04.5c (II) for 630/301(B)
+- * 2.06.50 for 630/301B (dual VGA)
+- * 2.02.3b, 2.03.02, 2.04.5c, 2.07a and 2.08.b3 for 630/LVDS/LVDS+CH7005
+- * 2.04.5c, 2.04.6c for 730+LVDS+CH7005
+- * 1.09b for 315/301(B)
+- * 1.16.51 for 300+301LV (ECS A907)
+- * 1.01.03 for 330 (Xabre 400)
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+@@ -61,12 +54,12 @@
+ #ifdef LINUX_XF86
+ BOOLEAN SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
+-DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn);
+-#ifdef SISDUALHEAD /* TW: For dual head */
++DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi);
++#ifdef SISDUALHEAD
+ BOOLEAN SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
+ BOOLEAN SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+- ScrnInfoPtr pScrn, DisplayModePtr mode);
++ ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN IsCustom);
+ #endif /* dual head */
+ #endif /* linux_xf86 */
+
+@@ -90,49 +83,201 @@ BOOLEAN SiSSetMode(SiS_Private *SiS_Pr,
+ static ULONG GetDRAMSize(SiS_Private *SiS_Pr,
+ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+
+-static void DelaySeconds(int seconds);
+-void SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code);
+-
+ static void
+-DelaySeconds(int seconds)
+-{
+- int i;
+-#ifdef WIN2000
+- int j;
+-#endif
+-
+- for (i=0;i<seconds;i++) {
+-#ifdef TC
+- delay(1000);
+-#endif
+-
+-#ifdef WIN2000
+- for (j=0;j<20000;j++)
+- VideoPortStallExecution(50);
+-#endif
+-
+-#ifdef WINCE_HEADER
+-#endif
+-
+-#ifdef LINUX_KERNEL
+-#endif
+- }
+-}
+-
+-void
+-SiS_DebugCode(SiS_Private *SiS_Pr, UCHAR code)
++InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
+- OutPortByte(0x80, code);
+- DelaySeconds(0x3);
++ SiS_Pr->SiS_StResInfo = SiS_StResInfo;
++ SiS_Pr->SiS_ModeResInfo = SiS_ModeResInfo;
++ SiS_Pr->SiS_StandTable = SiS_StandTable;
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++ SiS_StandTable[0x04].CRTC[4] = 0x2b;
++ SiS_StandTable[0x05].CRTC[4] = 0x2b;
++ SiS_StandTable[0x06].CRTC[4] = 0x54;
++ SiS_StandTable[0x06].CRTC[5] = 0x80;
++ SiS_StandTable[0x0d].CRTC[4] = 0x2b;
++ SiS_StandTable[0x0e].CRTC[4] = 0x54;
++ SiS_StandTable[0x0e].CRTC[5] = 0x80;
++ SiS_StandTable[0x11].CRTC[4] = 0x54;
++ SiS_StandTable[0x11].CRTC[5] = 0x80;
++ SiS_StandTable[0x11].CRTC[16] = 0x83;
++ SiS_StandTable[0x11].CRTC[17] = 0x85;
++ SiS_StandTable[0x12].CRTC[4] = 0x54;
++ SiS_StandTable[0x12].CRTC[5] = 0x80;
++ SiS_StandTable[0x12].CRTC[16] = 0x83;
++ SiS_StandTable[0x12].CRTC[17] = 0x85;
++ SiS_StandTable[0x13].CRTC[5] = 0xa0;
++ SiS_StandTable[0x17].CRTC[5] = 0xa0;
++ SiS_StandTable[0x1a].CRTC[4] = 0x54;
++ SiS_StandTable[0x1a].CRTC[5] = 0x80;
++ SiS_StandTable[0x1a].CRTC[16] = 0xea;
++ SiS_StandTable[0x1a].CRTC[17] = 0x8c;
++ SiS_StandTable[0x1b].CRTC[4] = 0x54;
++ SiS_StandTable[0x1b].CRTC[5] = 0x80;
++ SiS_StandTable[0x1b].CRTC[16] = 0xea;
++ SiS_StandTable[0x1b].CRTC[17] = 0x8c;
++ SiS_StandTable[0x1c].CRTC[4] = 0x54;
++ SiS_StandTable[0x1c].CRTC[5] = 0x80;
++ } else {
++ SiS_StandTable[0x04].CRTC[4] = 0x2c;
++ SiS_StandTable[0x05].CRTC[4] = 0x2c;
++ SiS_StandTable[0x06].CRTC[4] = 0x55;
++ SiS_StandTable[0x06].CRTC[5] = 0x81;
++ SiS_StandTable[0x0d].CRTC[4] = 0x2c;
++ SiS_StandTable[0x0e].CRTC[4] = 0x55;
++ SiS_StandTable[0x0e].CRTC[5] = 0x81;
++ SiS_StandTable[0x11].CRTC[4] = 0x55;
++ SiS_StandTable[0x11].CRTC[5] = 0x81;
++ SiS_StandTable[0x11].CRTC[16] = 0x82;
++ SiS_StandTable[0x11].CRTC[17] = 0x84;
++ SiS_StandTable[0x12].CRTC[4] = 0x55;
++ SiS_StandTable[0x12].CRTC[5] = 0x81;
++ SiS_StandTable[0x12].CRTC[16] = 0x82;
++ SiS_StandTable[0x12].CRTC[17] = 0x84;
++ SiS_StandTable[0x13].CRTC[5] = 0xb1;
++ SiS_StandTable[0x17].CRTC[5] = 0xb1;
++ SiS_StandTable[0x1a].CRTC[4] = 0x55;
++ SiS_StandTable[0x1a].CRTC[5] = 0x81;
++ SiS_StandTable[0x1a].CRTC[16] = 0xe9;
++ SiS_StandTable[0x1a].CRTC[17] = 0x8b;
++ SiS_StandTable[0x1b].CRTC[4] = 0x55;
++ SiS_StandTable[0x1b].CRTC[5] = 0x81;
++ SiS_StandTable[0x1b].CRTC[16] = 0xe9;
++ SiS_StandTable[0x1b].CRTC[17] = 0x8b;
++ SiS_StandTable[0x1c].CRTC[4] = 0x55;
++ SiS_StandTable[0x1c].CRTC[5] = 0x81;
++ }
++
++ SiS_Pr->SiS_NTSCPhase = SiS_NTSCPhase;
++ SiS_Pr->SiS_PALPhase = SiS_PALPhase;
++ SiS_Pr->SiS_NTSCPhase2 = SiS_NTSCPhase2;
++ SiS_Pr->SiS_PALPhase2 = SiS_PALPhase2;
++ SiS_Pr->SiS_PALMPhase = SiS_PALMPhase;
++ SiS_Pr->SiS_PALNPhase = SiS_PALNPhase;
++ SiS_Pr->SiS_PALMPhase2 = SiS_PALMPhase2;
++ SiS_Pr->SiS_PALNPhase2 = SiS_PALNPhase2;
++ SiS_Pr->SiS_SpecialPhase = SiS_SpecialPhase;
++
++ SiS_Pr->SiS_NTSCTiming = SiS_NTSCTiming;
++ SiS_Pr->SiS_PALTiming = SiS_PALTiming;
++ SiS_Pr->SiS_HiTVSt1Timing = SiS_HiTVSt1Timing;
++ SiS_Pr->SiS_HiTVSt2Timing = SiS_HiTVSt2Timing;
++ SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
++ SiS_Pr->SiS_HiTVExtTiming = SiS_HiTVExtTiming;
++ SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
++ SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
++ SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
++
++ SiS_Pr->SiS_StPALData = SiS_StPALData;
++ SiS_Pr->SiS_ExtPALData = SiS_ExtPALData;
++ SiS_Pr->SiS_StNTSCData = SiS_StNTSCData;
++ SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
++/* SiS_Pr->SiS_St1HiTVData = SiS_St1HiTVData; */
++ SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
++ SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
++
++ SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
++ SiS_Pr->pSiS_SoftSetting = &SiS_SoftSetting;
++
++ SiS_Pr->SiS_LCD1280x960Data = SiS_LCD1280x960Data;
++ SiS_Pr->SiS_ExtLCD1400x1050Data = SiS_ExtLCD1400x1050Data;
++ SiS_Pr->SiS_ExtLCD1600x1200Data = SiS_ExtLCD1600x1200Data;
++ SiS_Pr->SiS_StLCD1400x1050Data = SiS_StLCD1400x1050Data;
++ SiS_Pr->SiS_StLCD1600x1200Data = SiS_StLCD1600x1200Data;
++ SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050;
++ SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200;
++ SiS_Pr->SiS_ExtLCD1280x768Data = SiS_ExtLCD1280x768Data;
++ SiS_Pr->SiS_StLCD1280x768Data = SiS_StLCD1280x768Data;
++ SiS_Pr->SiS_NoScaleData1280x768 = SiS_NoScaleData1280x768;
++ SiS_Pr->SiS_NoScaleData = SiS_NoScaleData;
++
++ SiS_Pr->SiS_LVDS320x480Data_1 = SiS_LVDS320x480Data_1;
++ SiS_Pr->SiS_LVDS800x600Data_1 = SiS_LVDS800x600Data_1;
++ SiS_Pr->SiS_LVDS800x600Data_2 = SiS_LVDS800x600Data_2;
++ SiS_Pr->SiS_LVDS1024x768Data_1 = SiS_LVDS1024x768Data_1;
++ SiS_Pr->SiS_LVDS1024x768Data_2 = SiS_LVDS1024x768Data_2;
++ SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1;
++ SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2;
++ SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1;
++ SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2;
++ SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1;
++ SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2;
++ SiS_Pr->SiS_LVDS1280x768Data_1 = SiS_LVDS1280x768Data_1;
++ SiS_Pr->SiS_LVDS1280x768Data_2 = SiS_LVDS1280x768Data_2;
++ SiS_Pr->SiS_LVDS1024x600Data_1 = SiS_LVDS1024x600Data_1;
++ SiS_Pr->SiS_LVDS1024x600Data_2 = SiS_LVDS1024x600Data_2;
++ SiS_Pr->SiS_LVDS1152x768Data_1 = SiS_LVDS1152x768Data_1;
++ SiS_Pr->SiS_LVDS1152x768Data_2 = SiS_LVDS1152x768Data_2;
++ SiS_Pr->SiS_LVDSXXXxXXXData_1 = SiS_LVDSXXXxXXXData_1;
++ SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x960Data_1;
++ SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x960Data_2;
++ SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
++ SiS_Pr->SiS_LVDS1280x960Data_1 = SiS_LVDS1280x1024Data_1;
++ SiS_Pr->SiS_LVDS1280x960Data_2 = SiS_LVDS1280x1024Data_2;
++ SiS_Pr->SiS_LVDS640x480Data_1 = SiS_LVDS640x480Data_1;
++ SiS_Pr->SiS_LVDS640x480Data_2 = SiS_LVDS640x480Data_2;
++
++ SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
++ SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
++ SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
++ SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
++ SiS_Pr->SiS_LVDS848x480Data_1 = SiS_LVDS848x480Data_1;
++ SiS_Pr->SiS_LVDS848x480Data_2 = SiS_LVDS848x480Data_2;
++
++ SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1;
++ SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2;
++ SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1;
++ SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2;
++ SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
++ SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
++
++ SiS_Pr->LVDS1024x768Des_1 = SiS_PanelType1076_1;
++ SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1;
++ SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1;
++ SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1;
++ SiS_Pr->LVDS1024x768Des_2 = SiS_PanelType1076_2;
++ SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2;
++ SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2;
++ SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2;
++
++ SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1;
++ SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2;
++
++ SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
++ SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
++ SiS_Pr->SiS_CHTVUPALDesData = SiS_CHTVUPALDesData;
++ SiS_Pr->SiS_CHTVOPALDesData = SiS_CHTVOPALDesData;
++
++ SiS_Pr->SiS_LVDSCRT11280x768_1 = SiS_LVDSCRT11280x768_1;
++ SiS_Pr->SiS_LVDSCRT11024x600_1 = SiS_LVDSCRT11024x600_1;
++ SiS_Pr->SiS_LVDSCRT11152x768_1 = SiS_LVDSCRT11152x768_1;
++ SiS_Pr->SiS_LVDSCRT11280x768_1_H = SiS_LVDSCRT11280x768_1_H;
++ SiS_Pr->SiS_LVDSCRT11024x600_1_H = SiS_LVDSCRT11024x600_1_H;
++ SiS_Pr->SiS_LVDSCRT11152x768_1_H = SiS_LVDSCRT11152x768_1_H;
++ SiS_Pr->SiS_LVDSCRT11280x768_2 = SiS_LVDSCRT11280x768_2;
++ SiS_Pr->SiS_LVDSCRT11024x600_2 = SiS_LVDSCRT11024x600_2;
++ SiS_Pr->SiS_LVDSCRT11152x768_2 = SiS_LVDSCRT11152x768_2;
++ SiS_Pr->SiS_LVDSCRT11280x768_2_H = SiS_LVDSCRT11280x768_2_H;
++ SiS_Pr->SiS_LVDSCRT11024x600_2_H = SiS_LVDSCRT11024x600_2_H;
++ SiS_Pr->SiS_LVDSCRT11152x768_2_H = SiS_LVDSCRT11152x768_2_H;
++ SiS_Pr->SiS_LVDSCRT1320x480_1 = SiS_LVDSCRT1320x480_1;
++ SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = SiS_LVDSCRT1XXXxXXX_1;
++ SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = SiS_LVDSCRT1XXXxXXX_1_H;
++ SiS_Pr->SiS_LVDSCRT1640x480_1 = SiS_LVDSCRT1640x480_1;
++ SiS_Pr->SiS_LVDSCRT1640x480_1_H = SiS_LVDSCRT1640x480_1_H;
++ SiS_Pr->SiS_LVDSCRT1640x480_2 = SiS_LVDSCRT1640x480_2;
++ SiS_Pr->SiS_LVDSCRT1640x480_2_H = SiS_LVDSCRT1640x480_2_H;
++ SiS_Pr->SiS_LVDSCRT1640x480_3 = SiS_LVDSCRT1640x480_3;
++ SiS_Pr->SiS_LVDSCRT1640x480_3_H = SiS_LVDSCRT1640x480_3_H;
+ }
+
+ #ifdef SIS300
+ static void
+ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
++ InitCommonPointer(SiS_Pr, HwDeviceExtension);
++
+ SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS300_SModeIDTable;
+ SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable;
+- SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS300_StandTable;
+ SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS300_EModeIDTable;
+ SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS300_RefIndex;
+ SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS300_CRT1Table;
+@@ -141,15 +286,12 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ } else {
+ SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */
+ }
++#ifdef LINUXBIOS
+ SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS300_ECLKData;
++#endif
+ SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS300_VCLKData;
+ SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
+ SiS_Pr->SiS_ScreenOffset = SiS300_ScreenOffset;
+- SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS300_StResInfo;
+- SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS300_ModeResInfo;
+-
+- SiS_Pr->pSiS_OutputSelect = &SiS300_OutputSelect;
+- SiS_Pr->pSiS_SoftSetting = &SiS300_SoftSetting;
+
+ SiS_Pr->SiS_SR15 = SiS300_SR15;
+
+@@ -178,15 +320,6 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->pSiS_YCSenseData2 = &SiS300_YCSenseData2;
+ #endif
+
+- SiS_Pr->SiS_NTSCPhase = SiS300_NTSCPhase;
+- SiS_Pr->SiS_PALPhase = SiS300_PALPhase;
+- SiS_Pr->SiS_NTSCPhase2 = SiS300_NTSCPhase2;
+- SiS_Pr->SiS_PALPhase2 = SiS300_PALPhase2;
+- SiS_Pr->SiS_PALMPhase = SiS300_PALMPhase;
+- SiS_Pr->SiS_PALNPhase = SiS300_PALNPhase;
+- SiS_Pr->SiS_PALMPhase2 = SiS300_PALMPhase2;
+- SiS_Pr->SiS_PALNPhase2 = SiS300_PALNPhase2;
+-
+ SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data;
+ SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data;
+ SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data;
+@@ -195,68 +328,18 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data;
+ SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768;
+ SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024;
+- SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS300_LCD1280x960Data;
+- SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1400x1050Data;
+- SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_ExtLCD1600x1200Data;
+- SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS300_StLCD1400x1050Data;
+- SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS300_StLCD1600x1200Data;
+- SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS300_NoScaleData1400x1050;
+- SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS300_NoScaleData1600x1200;
+-
+- SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS300_StPALData;
+- SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS300_ExtPALData;
+- SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS300_StNTSCData;
+- SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS300_ExtNTSCData;
+-/* SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS300_St1HiTVData; */
+- SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS300_St2HiTVData;
+- SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS300_ExtHiTVData;
+-
+- SiS_Pr->SiS_NTSCTiming = SiS300_NTSCTiming;
+- SiS_Pr->SiS_PALTiming = SiS300_PALTiming;
+- SiS_Pr->SiS_HiTVSt1Timing = SiS300_HiTVSt1Timing;
+- SiS_Pr->SiS_HiTVSt2Timing = SiS300_HiTVSt2Timing;
+- SiS_Pr->SiS_HiTVTextTiming = SiS300_HiTVTextTiming;
+- SiS_Pr->SiS_HiTVGroup3Data = SiS300_HiTVGroup3Data;
+- SiS_Pr->SiS_HiTVGroup3Simu = SiS300_HiTVGroup3Simu;
+- SiS_Pr->SiS_HiTVGroup3Text = SiS300_HiTVGroup3Text;
+
+ SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
+ SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS;
+
+- SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_1;
+- SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS800x600Data_2;
+- SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_1;
+- SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x768Data_2;
+- SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1;
+- SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2;
+- SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_1;
+- SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x1024Data_2;
+- SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_1;
+- SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1400x1050Data_2;
+- SiS_Pr->SiS_LVDS1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1600x1200Data_1;
+- SiS_Pr->SiS_LVDS1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1600x1200Data_2;
+- SiS_Pr->SiS_LVDS1280x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_1;
+- SiS_Pr->SiS_LVDS1280x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1280x768Data_2;
+- SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_1;
+- SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1024x600Data_2;
+- SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_1;
+- SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS300_LVDS1152x768Data_2;
+- SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS300_LVDSXXXxXXXData_1;
+- SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS320x480Data_1;
+- SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS300_LVDS640x480Data_1;
+- SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_1;
+- SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1400x1050Data_2;
+- SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_1;
+- SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS300_LCDA1600x1200Data_2;
+- SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData;
+- SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData;
+ SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;
+ SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;
+- SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVUNTSCData; /* not supported on 300 series */
+- SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS300_CHTVONTSCData; /* not supported on 300 series */
++ SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; /* not supported on 300 series */
++ SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; /* not supported on 300 series */
+ SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData; /* not supported on 300 series */
+ SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData; /* not supported on 300 series */
+ SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData;
++
+ SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1;
+ SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1;
+ SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1;
+@@ -289,32 +372,28 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2;
+ SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2;
+ SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2;
+- SiS_Pr->SiS_PanelTypeNS_1 = (SiS_LVDSDesStruct *)SiS300_PanelTypeNS_1;
+- SiS_Pr->SiS_PanelTypeNS_2 = (SiS_LVDSDesStruct *)SiS300_PanelTypeNS_2;
+- SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUNTSCDesData;
+- SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS300_CHTVONTSCDesData;
+- SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVUPALDesData;
+- SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS300_CHTVOPALDesData;
++
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
++ SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a;
++ SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a;
++ }
++ if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
++ SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b;
++ SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b;
++ }
++
+ SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1;
+ SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1;
+ SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1;
+- SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1;
+- SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1;
+ SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H;
+ SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H;
+ SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H;
+- SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_1_H;
+- SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_1_H;
+ SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2;
+ SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2;
+ SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2;
+- SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2;
+- SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2;
+ SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H;
+ SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H;
+ SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H;
+- SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x600_2_H;
+- SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11152x768_2_H;
+ SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC;
+ SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC;
+ SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL;
+@@ -339,7 +418,6 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL; /* not supported on 300 series */
+ SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
+
+- /* TW: New from 300/301LV BIOS */
+ SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1;
+ SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1;
+ SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1;
+@@ -353,7 +431,7 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3;
+ SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3;
+
+- /* TW: LCDResInfo will on 300 series be translated to 310/325 series definitions */
++ /* TW: LCDResInfo will on 300 series be translated to 315 series definitions */
+ SiS_Pr->SiS_Panel320x480 = Panel_320x480;
+ SiS_Pr->SiS_Panel640x480 = Panel_640x480;
+ SiS_Pr->SiS_Panel800x600 = Panel_800x600;
+@@ -362,13 +440,17 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_Panel1280x960 = Panel_1280x960;
+ SiS_Pr->SiS_Panel1024x600 = Panel_1024x600;
+ SiS_Pr->SiS_Panel1152x768 = Panel_1152x768;
+- SiS_Pr->SiS_Panel1600x1200 = 16; /* TW: Something illegal */
+- SiS_Pr->SiS_Panel1400x1050 = 16; /* TW: Something illegal */
+- SiS_Pr->SiS_Panel1152x864 = 16; /* TW: Something illegal */
+- SiS_Pr->SiS_Panel1280x768 = 16; /* TW: Something illegal */
++ SiS_Pr->SiS_Panel1280x768 = Panel_1280x768;
++ SiS_Pr->SiS_Panel1600x1200 = 255; /* TW: Something illegal */
++ SiS_Pr->SiS_Panel1400x1050 = 255; /* TW: Something illegal */
++ SiS_Pr->SiS_Panel640x480_2 = 255; /* TW: Something illegal */
++ SiS_Pr->SiS_Panel640x480_3 = 255; /* TW: Something illegal */
++ SiS_Pr->SiS_Panel1152x864 = 255; /* TW: Something illegal */
+ SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */
+ SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: Lowest value LVDS */
+ SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */
++ SiS_Pr->SiS_PanelCustom = Panel_Custom;
++ SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366;
+ }
+ #endif
+
+@@ -376,29 +458,33 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PS
+ static void
+ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
+ {
++ InitCommonPointer(SiS_Pr, HwDeviceExtension);
++
+ SiS_Pr->SiS_SModeIDTable = (SiS_StStruct *)SiS310_SModeIDTable;
+- SiS_Pr->SiS_StandTable = (SiS_StandTableStruct *)SiS310_StandTable;
+ SiS_Pr->SiS_EModeIDTable = (SiS_ExtStruct *)SiS310_EModeIDTable;
+ SiS_Pr->SiS_RefIndex = (SiS_Ext2Struct *)SiS310_RefIndex;
+ SiS_Pr->SiS_CRT1Table = (SiS_CRT1TableStruct *)SiS310_CRT1Table;
+ /* TW: MCLK is different */
+- if(HwDeviceExtension->jChipType == SIS_330) {
++#ifdef LINUXBIOS
++ if(HwDeviceExtension->jChipType >= SIS_660) {
++ SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660; /* 660/760 */
++ } else if(HwDeviceExtension->jChipType == SIS_330) {
++#endif
+ SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330; /* 330 */
++#ifdef LINUXBIOS
+ } else if(HwDeviceExtension->jChipType > SIS_315PRO) {
+ SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650; /* 550, 650, 740 */
+ } else {
+ SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315; /* 315 */
+ }
++#endif
+ SiS_Pr->SiS_MCLKData_1 = (SiS_MCLKDataStruct *)SiS310_MCLKData_1;
++#ifdef LINUXBIOS
+ SiS_Pr->SiS_ECLKData = (SiS_ECLKDataStruct *)SiS310_ECLKData;
++#endif
+ SiS_Pr->SiS_VCLKData = (SiS_VCLKDataStruct *)SiS310_VCLKData;
+ SiS_Pr->SiS_VBVCLKData = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData;
+ SiS_Pr->SiS_ScreenOffset = SiS310_ScreenOffset;
+- SiS_Pr->SiS_StResInfo = (SiS_StResInfoStruct *)SiS310_StResInfo;
+- SiS_Pr->SiS_ModeResInfo = (SiS_ModeResInfoStruct *)SiS310_ModeResInfo;
+-
+- SiS_Pr->pSiS_OutputSelect = &SiS310_OutputSelect;
+- SiS_Pr->pSiS_SoftSetting = &SiS310_SoftSetting;
+
+ SiS_Pr->SiS_SR15 = SiS310_SR15;
+
+@@ -427,16 +513,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->pSiS_YCSenseData2 = &SiS310_YCSenseData2;
+ #endif
+
+- SiS_Pr->SiS_NTSCPhase = SiS310_NTSCPhase;
+- SiS_Pr->SiS_PALPhase = SiS310_PALPhase;
+- SiS_Pr->SiS_NTSCPhase2 = SiS310_NTSCPhase2;
+- SiS_Pr->SiS_PALPhase2 = SiS310_PALPhase2;
+- SiS_Pr->SiS_PALMPhase = SiS310_PALMPhase;
+- SiS_Pr->SiS_PALNPhase = SiS310_PALNPhase;
+- SiS_Pr->SiS_PALMPhase2 = SiS310_PALMPhase2;
+- SiS_Pr->SiS_PALNPhase2 = SiS310_PALNPhase2;
+- SiS_Pr->SiS_SpecialPhase = SiS310_SpecialPhase;
+-
+ SiS_Pr->SiS_StLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data;
+ SiS_Pr->SiS_ExtLCD1024x768Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data;
+ SiS_Pr->SiS_St2LCD1024x768Data = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data;
+@@ -445,62 +521,10 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_St2LCD1280x1024Data = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data;
+ SiS_Pr->SiS_NoScaleData1024x768 = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768;
+ SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024;
+- SiS_Pr->SiS_LCD1280x960Data = (SiS_LCDDataStruct *)SiS310_LCD1280x960Data;
+- SiS_Pr->SiS_ExtLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1400x1050Data;
+- SiS_Pr->SiS_ExtLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_ExtLCD1600x1200Data;
+- SiS_Pr->SiS_StLCD1400x1050Data = (SiS_LCDDataStruct *)SiS310_StLCD1400x1050Data;
+- SiS_Pr->SiS_StLCD1600x1200Data = (SiS_LCDDataStruct *)SiS310_StLCD1600x1200Data;
+- SiS_Pr->SiS_NoScaleData1400x1050 = (SiS_LCDDataStruct *)SiS310_NoScaleData1400x1050;
+- SiS_Pr->SiS_NoScaleData1600x1200 = (SiS_LCDDataStruct *)SiS310_NoScaleData1600x1200;
+-
+- SiS_Pr->SiS_StPALData = (SiS_TVDataStruct *)SiS310_StPALData;
+- SiS_Pr->SiS_ExtPALData = (SiS_TVDataStruct *)SiS310_ExtPALData;
+- SiS_Pr->SiS_StNTSCData = (SiS_TVDataStruct *)SiS310_StNTSCData;
+- SiS_Pr->SiS_ExtNTSCData = (SiS_TVDataStruct *)SiS310_ExtNTSCData;
+-/* SiS_Pr->SiS_St1HiTVData = (SiS_TVDataStruct *)SiS310_St1HiTVData; */
+- SiS_Pr->SiS_St2HiTVData = (SiS_TVDataStruct *)SiS310_St2HiTVData;
+- SiS_Pr->SiS_ExtHiTVData = (SiS_TVDataStruct *)SiS310_ExtHiTVData;
+-
+- SiS_Pr->SiS_NTSCTiming = SiS310_NTSCTiming;
+- SiS_Pr->SiS_PALTiming = SiS310_PALTiming;
+- SiS_Pr->SiS_HiTVSt1Timing = SiS310_HiTVSt1Timing;
+- SiS_Pr->SiS_HiTVSt2Timing = SiS310_HiTVSt2Timing;
+- SiS_Pr->SiS_HiTVTextTiming = SiS310_HiTVTextTiming;
+- SiS_Pr->SiS_HiTVExtTiming = SiS310_HiTVExtTiming;
+- SiS_Pr->SiS_HiTVGroup3Data = SiS310_HiTVGroup3Data;
+- SiS_Pr->SiS_HiTVGroup3Simu = SiS310_HiTVGroup3Simu;
+- SiS_Pr->SiS_HiTVGroup3Text = SiS310_HiTVGroup3Text;
+
+- SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
++ SiS_Pr->SiS_PanelDelayTbl = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
+ SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS;
+
+- SiS_Pr->SiS_LVDS800x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_1;
+- SiS_Pr->SiS_LVDS800x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS800x600Data_2;
+- SiS_Pr->SiS_LVDS1024x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_1;
+- SiS_Pr->SiS_LVDS1024x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x768Data_2;
+- SiS_Pr->SiS_LVDS1280x1024Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_1;
+- SiS_Pr->SiS_LVDS1280x1024Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x1024Data_2;
+- SiS_Pr->SiS_LVDS1280x960Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_1;
+- SiS_Pr->SiS_LVDS1280x960Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x960Data_2;
+- SiS_Pr->SiS_LVDS1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_1;
+- SiS_Pr->SiS_LVDS1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1400x1050Data_2;
+- SiS_Pr->SiS_LVDS1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1600x1200Data_1;
+- SiS_Pr->SiS_LVDS1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1600x1200Data_2;
+- SiS_Pr->SiS_LVDS1280x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_1;
+- SiS_Pr->SiS_LVDS1280x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1280x768Data_2;
+- SiS_Pr->SiS_LVDS1024x600Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_1;
+- SiS_Pr->SiS_LVDS1024x600Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1024x600Data_2;
+- SiS_Pr->SiS_LVDS1152x768Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_1;
+- SiS_Pr->SiS_LVDS1152x768Data_2 = (SiS_LVDSDataStruct *)SiS310_LVDS1152x768Data_2;
+- SiS_Pr->SiS_LVDSXXXxXXXData_1 = (SiS_LVDSDataStruct *)SiS310_LVDSXXXxXXXData_1;
+- SiS_Pr->SiS_LVDS320x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS320x480Data_1;
+- SiS_Pr->SiS_LVDS640x480Data_1 = (SiS_LVDSDataStruct *)SiS310_LVDS640x480Data_1;
+- SiS_Pr->SiS_LCDA1400x1050Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_1;
+- SiS_Pr->SiS_LCDA1400x1050Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1400x1050Data_2;
+- SiS_Pr->SiS_LCDA1600x1200Data_1 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_1;
+- SiS_Pr->SiS_LCDA1600x1200Data_2 = (SiS_LVDSDataStruct *)SiS310_LCDA1600x1200Data_2;
+- SiS_Pr->SiS_CHTVUNTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVUNTSCData;
+- SiS_Pr->SiS_CHTVONTSCData = (SiS_LVDSDataStruct *)SiS310_CHTVONTSCData;
+ SiS_Pr->SiS_CHTVUPALData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData;
+ SiS_Pr->SiS_CHTVOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData;
+ SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData;
+@@ -508,6 +532,7 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData;
+ SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData;
+ SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData;
++
+ SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1;
+ SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1;
+ SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1;
+@@ -540,19 +565,7 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2;
+ SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2;
+ SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2;
+- SiS_Pr->SiS_PanelTypeNS_1 = (SiS_LVDSDesStruct *)SiS310_PanelTypeNS_1;
+- SiS_Pr->SiS_PanelTypeNS_2 = (SiS_LVDSDesStruct *)SiS310_PanelTypeNS_2;
+
+- SiS_Pr->LVDS1024x768Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_1;
+- SiS_Pr->LVDS1280x1024Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_1;
+- SiS_Pr->LVDS1400x1050Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_1 ;
+- SiS_Pr->LVDS1600x1200Des_1 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_1 ;
+- SiS_Pr->LVDS1024x768Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1076_2;
+- SiS_Pr->LVDS1280x1024Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1210_2;
+- SiS_Pr->LVDS1400x1050Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1296_2;
+- SiS_Pr->LVDS1600x1200Des_2 = (SiS_LVDSDesStruct *)SiS310_PanelType1600_2 ;
+-
+- /* TW: New from 650/301LV BIOS */
+ SiS_Pr->SiS_CRT2Part2_1024x768_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1;
+ SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1;
+ SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1;
+@@ -566,51 +579,32 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3;
+ SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3;
+
+- SiS_Pr->SiS_CHTVUNTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUNTSCDesData;
+- SiS_Pr->SiS_CHTVONTSCDesData = (SiS_LVDSDesStruct *)SiS310_CHTVONTSCDesData;
+- SiS_Pr->SiS_CHTVUPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVUPALDesData;
+- SiS_Pr->SiS_CHTVOPALDesData = (SiS_LVDSDesStruct *)SiS310_CHTVOPALDesData;
+-
+ SiS_Pr->SiS_LVDSCRT1800x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1;
+ SiS_Pr->SiS_LVDSCRT11024x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1;
+ SiS_Pr->SiS_LVDSCRT11280x1024_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1;
+ SiS_Pr->SiS_LVDSCRT11400x1050_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1;
+- SiS_Pr->SiS_LVDSCRT11280x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1;
+- SiS_Pr->SiS_LVDSCRT11024x600_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1;
+- SiS_Pr->SiS_LVDSCRT11152x768_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1;
+ SiS_Pr->SiS_LVDSCRT11600x1200_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1;
+ SiS_Pr->SiS_LVDSCRT1800x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H;
+ SiS_Pr->SiS_LVDSCRT11024x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H;
+ SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H;
+ SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H;
+- SiS_Pr->SiS_LVDSCRT11280x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_1_H;
+- SiS_Pr->SiS_LVDSCRT11024x600_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_1_H;
+- SiS_Pr->SiS_LVDSCRT11152x768_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_1_H;
+ SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H;
+ SiS_Pr->SiS_LVDSCRT1800x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2;
+ SiS_Pr->SiS_LVDSCRT11024x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2;
+ SiS_Pr->SiS_LVDSCRT11280x1024_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2;
+ SiS_Pr->SiS_LVDSCRT11400x1050_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2;
+- SiS_Pr->SiS_LVDSCRT11280x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2;
+- SiS_Pr->SiS_LVDSCRT11024x600_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2;
+- SiS_Pr->SiS_LVDSCRT11152x768_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2;
+ SiS_Pr->SiS_LVDSCRT11600x1200_2 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2;
+ SiS_Pr->SiS_LVDSCRT1800x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H;
+ SiS_Pr->SiS_LVDSCRT11024x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H;
+ SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H;
+ SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H;
+- SiS_Pr->SiS_LVDSCRT11280x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x768_2_H;
+- SiS_Pr->SiS_LVDSCRT11024x600_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x600_2_H;
+- SiS_Pr->SiS_LVDSCRT11152x768_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11152x768_2_H;
+ SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H;
+- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1;
+- SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1XXXxXXX_1_H;
+- SiS_Pr->SiS_LVDSCRT1320x480_1 = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1320x480_1;
+- SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
+- SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
+- SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
+- SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
+- SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1SOPAL;
++ SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
++ SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
++ SiS_Pr->SiS_CHTVCRT1UPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
++ SiS_Pr->SiS_CHTVCRT1OPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
++ SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1SOPAL;
++
+ SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC;
+ SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC;
+ SiS_Pr->SiS_CHTVReg_UPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL;
+@@ -620,6 +614,7 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN;
+ SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN;
+ SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_SOPAL;
++
+ SiS_Pr->SiS_LCDACRT1800x600_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT1800x600_1;
+ SiS_Pr->SiS_LCDACRT11024x768_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1;
+ SiS_Pr->SiS_LCDACRT11280x1024_1 = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1;
+@@ -640,6 +635,7 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H;
+ SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H;
+ SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H;
++
+ SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
+ SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
+ SiS_Pr->SiS_CHTVVCLKUPAL = SiS310_CHTVVCLKUPAL;
+@@ -662,9 +658,13 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PS
+ SiS_Pr->SiS_Panel1152x864 = Panel_1152x864;
+ SiS_Pr->SiS_Panel1280x768 = Panel_1280x768;
+ SiS_Pr->SiS_Panel1024x600 = Panel_1024x600;
++ SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2;
++ SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3;
+ SiS_Pr->SiS_PanelMax = Panel_320x480; /* TW: highest value */
+ SiS_Pr->SiS_PanelMinLVDS = Panel_800x600; /* TW: lowest value LVDS/LCDA */
+ SiS_Pr->SiS_PanelMin301 = Panel_1024x768; /* TW: lowest value 301 */
++ SiS_Pr->SiS_PanelCustom = Panel_Custom;
++ SiS_Pr->SiS_PanelBarco1366 = 255;
+ }
+ #endif
+
+@@ -727,7 +727,9 @@ SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEV
+ (HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330))
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760))
+ InitTo310Pointer(SiS_Pr, HwDeviceExtension);
+ #endif
+
+@@ -896,7 +898,9 @@ SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEV
+ (HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330)) {
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760)) {
+ for(i=0x12; i<=0x1B; i++) SiS_SetReg1(SiS_Pr->SiS_P3c4,i,0);
+ for(i=0x79; i<=0x7C; i++) SiS_SetReg1(SiS_Pr->SiS_P3d4,i,0);
+ }
+@@ -953,14 +957,16 @@ SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEV
+ if((HwDeviceExtension->jChipType == SIS_315H) ||
+ (HwDeviceExtension->jChipType == SIS_315) ||
+ (HwDeviceExtension->jChipType == SIS_315PRO) ||
+- (HwDeviceExtension->jChipType == SIS_330) ) {
++ (HwDeviceExtension->jChipType == SIS_330)) {
+ if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) {
+ temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3A) & 0x03;
+ }
+ }
+ if((HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_650)) {
++ (HwDeviceExtension->jChipType == SIS_650) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760)) {
+ if((*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) == 0) {
+ temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+ }
+@@ -977,7 +983,7 @@ SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEV
+ if((HwDeviceExtension->jChipType != SIS_540) &&
+ (HwDeviceExtension->jChipType != SIS_630) &&
+ (HwDeviceExtension->jChipType != SIS_730)){
+- for(i=0x15;i<0x1C;i++) {
++ for(i=0x15; i<0x1C; i++) {
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,i,SiS_Pr->SiS_SR15[i-0x15][SiS_Pr->SiS_RAMType]);
+ }
+ }
+@@ -1023,7 +1029,9 @@ SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEV
+ (HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330))
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760))
+ SiS_SetReg1(SiS_Pr->SiS_Part1Port,0x2E,0x08); /* use VB */
+ #endif
+
+@@ -1180,7 +1188,9 @@ SiS_Set_LVDS_TRUMPION(SiS_Private *SiS_P
+ #ifdef SIS315H
+ if((HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330)) {
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760)) {
+ #if 0 /* TW: This is not required */
+ /* TW: Read POWER_ON_TRAP and copy to CR37 */
+ temp = (UCHAR)SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1A);
+@@ -1299,7 +1309,7 @@ SiS_ChkBUSWidth_300(SiS_Private *SiS_Pr,
+ #endif
+ /* =============== SiS 300 dram sizing end =============== */
+
+-/* ============ SiS 310/325 dram sizing begin ============== */
++/* ============ SiS 315 dram sizing begin ============== */
+ #ifdef SIS315H
+
+ /* TW: Moved Get310DRAMType further down */
+@@ -1893,8 +1903,7 @@ SiS_Get310DRAMType(SiS_Private *SiS_Pr,
+ if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
+ data = *SiS_Pr->pSiS_SoftSetting & 0x03;
+ } else {
+- if((HwDeviceExtension->jChipType > SIS_315PRO) &&
+- (HwDeviceExtension->jChipType < SIS_330)) {
++ if(IS_SIS550650740660) {
+ data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+ } else { /* TW: 315, 330 */
+ data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
+@@ -1934,13 +1943,17 @@ void SiSRegInit(SiS_Private *SiS_Pr, USH
+ SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
+ SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
+ SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
+- SiS_Pr->SiS_P3da = BaseAddr + 0x2A;
+- SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */
+- SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */
+- SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */
+- SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
+- SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14+2; /* 301 palette address port registers */
+- SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */
++ SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
++ SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
++ SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
++ SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04; /* Digital video interface registers (LCD) */
++ SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10; /* 301 TV Encoder registers */
++ SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12; /* 301 Macrovision registers */
++ SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */
++ SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */
++ SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14; /* DDC Port ( = P3C4, SR11/0A) */
++ SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
++ SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
+ }
+
+ void
+@@ -1965,7 +1978,9 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_
+ (HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330)) {
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760)) {
+ /* TW: This seems to be done the same way on these chipsets */
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x20,0xa1);
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0xFF,0x5A);
+@@ -1987,10 +2002,14 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_
+
+ SiS_Pr->SiS_ChrontelInit = 0;
+
+- if((ModeNo == 0x5a) || (ModeNo == 0x5b)) {
+- SiS_Pr->SiS_IF_DEF_DSTN = 1; /* for 550 dstn */
+- SiS_Pr->SiS_IF_DEF_FSTN = 1; /* for fstn */
++#if 0
++ if(HwDeviceExtension->jChipType >= SIS_315H) {
++ if((ModeNo == 0x5a) || (ModeNo == 0x5b)) {
++ SiS_Pr->SiS_IF_DEF_DSTN = 1; /* for 550 dstn */
++ SiS_Pr->SiS_IF_DEF_FSTN = 1; /* for fstn */
++ }
+ }
++#endif
+
+ #ifdef SIS300
+ if((HwDeviceExtension->jChipType == SIS_540) ||
+@@ -2015,11 +2034,15 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_
+ if((HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330))
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760))
+ {
+- /* TW: CR37 is different on 310/325 series */
++ /* TW: CR37 is different on 315 series */
++#if 0
+ if(SiS_Pr->SiS_IF_DEF_FSTN) /* fstn: set CR37=0x04 */
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x37,0x04); /* (fake LVDS bridge) */
++#endif
+
+ temp=SiS_GetReg1(SiS_Pr->SiS_P3d4,0x37);
+ temp = (temp & 0x0E) >> 1;
+@@ -2044,7 +2067,9 @@ SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_
+ (HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_650) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_330))
++ (HwDeviceExtension->jChipType == SIS_330) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760))
+ InitTo310Pointer(SiS_Pr, HwDeviceExtension);
+ #endif
+
+@@ -2073,14 +2098,21 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr
+ SiS_Pr->SiS_UseROM = TRUE;
+ else SiS_Pr->SiS_UseROM = FALSE;
+ } else if(HwDeviceExtension->jChipType < SIS_315H) {
++#if 0
+ /* TW: Rest of 300 series: We don't use the ROM image if
+ * the BIOS version < 2.0.0 as such old BIOSes don't
+ * have the needed data at the expected locations.
+ */
+ if(ROMAddr[0x06] < '2') SiS_Pr->SiS_UseROM = FALSE;
+ else SiS_Pr->SiS_UseROM = TRUE;
++#else
++ /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
++ * the others do as well
++ */
++ SiS_Pr->SiS_UseROM = TRUE;
++#endif
+ } else {
+- /* TW: 310/325/330 series stick to the standard */
++ /* TW: 315/330 series stick to the standard */
+ SiS_Pr->SiS_UseROM = TRUE;
+ }
+ } else SiS_Pr->SiS_UseROM = FALSE;
+@@ -2104,24 +2136,27 @@ SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS
+ SiS_Pr->UseCustomMode = FALSE;
+
+ if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
+-
+- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
+- SiS_Pr->CHDisplay, SiS_Pr->CVDisplay);
+-
++
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
++ SiS_Pr->CHDisplay,
++ (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
++ (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
++ SiS_Pr->CVDisplay)));
++
+ return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE));
+-
++
+ }
+-
+- ModeNo = SiS_CalcModeIndex(pScrn, mode);
++
++ ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->HaveCustomModes);
+ if(!ModeNo) return FALSE;
+
+- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting mode 0x%x\n", ModeNo);
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
+
+- return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE));
++ return(SiSSetMode(SiS_Pr, HwDeviceExtension, pScrn, ModeNo, TRUE));
+ }
+
+ #ifdef SISDUALHEAD
+-/* TW: Set CRT1 mode (used for dual head) */
++/* TW: Set CRT1 mode (used for dual head and MergedFB) */
+ BOOLEAN
+ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn,
+ DisplayModePtr mode, BOOLEAN IsCustom)
+@@ -2134,31 +2169,37 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr,
+ SISEntPtr pSiSEnt = pSiS->entityPrivate;
+ unsigned char backupreg=0;
+ BOOLEAN backupcustom;
+-
+ UShort ModeNo=0;
+
+ SiS_Pr->UseCustomMode = FALSE;
+-
++
+ if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
+-
++
++ USHORT temptemp = SiS_Pr->CVDisplay;
++
++ if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
++ else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
++
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+- "Setting custom mode %dx%d in CRT1\n",
+- SiS_Pr->CHDisplay, SiS_Pr->CVDisplay);
++ "Setting custom mode %dx%d on CRT1\n",
++ SiS_Pr->CHDisplay, temptemp);
+ ModeNo = 0xfe;
+-
++
+ } else {
+
+- ModeNo = SiS_CalcModeIndex(pScrn, mode);
++ ModeNo = SiS_CalcModeIndex(pScrn, mode, pSiS->HaveCustomModes);
+ if(!ModeNo) return FALSE;
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+- "Setting mode 0x%x on CRT1\n", ModeNo);
++ "Setting standard mode 0x%x on CRT1\n", ModeNo);
+ }
+
+ SiSInitPtr(SiS_Pr, HwDeviceExtension);
+
+ SiSRegInit(SiS_Pr, BaseAddr);
+
++ SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
++
+ SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+
+ SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
+@@ -2167,7 +2208,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr,
+
+ SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr);
+
+- /* TW: We don't clear the buffer under X */
++ /* We don't clear the buffer under X */
+ SiS_Pr->SiS_flag_clearbuffer = 0;
+
+ /* 1.Openkey */
+@@ -2175,8 +2216,8 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr,
+
+ SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
+
++ /* 2.Get ModeID Table */
+ if(!SiS_Pr->UseCustomMode) {
+- /* 2.Get ModeID Table */
+ temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
+ if(temp == 0) return(0);
+ } else {
+@@ -2201,53 +2242,65 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr,
+ SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= SetDOSMode;
++ } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
++ SiS_Pr->SiS_SetFlag |= SetDOSMode;
+ }
+ }
+
+- /* TW: New from 650/LV 1.10.6x */
+ if(IS_SIS650) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
++ if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
++ }
+ }
+ }
+
+- /* TW: Set mode on CRT1 */
++ /* Set mode on CRT1 */
+ SiS_SetCRT1Group(SiS_Pr, ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr);
+
+- pSiSEnt->CRT1ModeNo = ModeNo;
+- pSiSEnt->CRT1DMode = mode;
+-
+- /* TW: SetPitch: Adapt to virtual size & position */
++ /* SetPitch: Adapt to virtual size & position */
+ SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr);
+
++ if(pSiS->DualHeadMode) {
++ pSiSEnt->CRT1ModeNo = ModeNo;
++ pSiSEnt->CRT1DMode = mode;
++ }
++
++ if(SiS_Pr->UseCustomMode) {
++ SiS_Pr->CRT1UsesCustomMode = TRUE;
++ SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
++ SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
++ } else {
++ SiS_Pr->CRT1UsesCustomMode = FALSE;
++ }
++
+ /* We have to reset CRT2 if changing mode on CRT1 */
+- if(pSiSEnt->CRT2ModeNo != -1) {
+- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+- "(Re-)Setting mode 0x%x on CRT2\n",
+- pSiSEnt->CRT2ModeNo);
+- backupcustom = SiS_Pr->UseCustomMode;
+- if(SiS_Pr->UseCustomMode) {
+- SiS_Pr->CRT1UsesCustomMode = TRUE;
+- } else {
+- SiS_Pr->CRT1UsesCustomMode = FALSE;
+- }
+- SiSBIOSSetModeCRT2(SiS_Pr, HwDeviceExtension, pSiSEnt->pScrn_1,
+- pSiSEnt->CRT2DMode);
+- SiS_Pr->UseCustomMode = backupcustom;
+- SiS_Pr->CRT1UsesCustomMode = FALSE;
++ if(pSiS->DualHeadMode) {
++ if(pSiSEnt->CRT2ModeNo != -1) {
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
++ "(Re-)Setting mode for CRT2\n");
++ backupcustom = SiS_Pr->UseCustomMode;
++ SiSBIOSSetModeCRT2(SiS_Pr, HwDeviceExtension, pSiSEnt->pScrn_1,
++ pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
++ SiS_Pr->UseCustomMode = backupcustom;
++ }
+ }
+-
++
++ /* Warning: From here, the custom mode entries in SiS_Pr are
++ * possibly overwritten
++ */
++
+ SiS_HandleCRT1(SiS_Pr);
+
++ SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
++
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
+
+- /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630/301B 2.06.50 */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x38,backupreg);
+@@ -2266,7 +2319,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr,
+ /* TW: Set CRT2 mode (used for dual head) */
+ BOOLEAN
+ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, ScrnInfoPtr pScrn,
+- DisplayModePtr mode)
++ DisplayModePtr mode, BOOLEAN IsCustom)
+ {
+ ULONG temp;
+ USHORT ModeIdIndex;
+@@ -2276,16 +2329,52 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ SISPtr pSiS = SISPTR(pScrn);
+ SISEntPtr pSiSEnt = pSiS->entityPrivate;
+ unsigned char tempr1, tempr2, backupreg=0;
+-
++
+ SiS_Pr->UseCustomMode = FALSE;
+-
+- ModeNo = SiS_CalcModeIndex(pScrn, mode);
+- if(!ModeNo) return FALSE;
++
++ /* Remember: Custom modes for CRT2 are ONLY supported
++ * -) on 315/330 series,
++ * -) on the 301 and 30xB, and
++ * -) if CRT2 is LCD or VGA
++ */
++
++ if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
++
++ ModeNo = 0xfe;
++
++ } else {
++
++ BOOLEAN havecustommodes = pSiS->HaveCustomModes;
++
++#ifdef SISMERGED
++ if(pSiS->MergedFB) havecustommodes = pSiS->HaveCustomModes2;
++#endif
++
++ ModeNo = SiS_CalcModeIndex(pScrn, mode, havecustommodes);
++ if(!ModeNo) return FALSE;
++
++ }
++
++ /* Save mode info so we can set it from within SetMode for CRT1 */
++ if(pSiS->DualHeadMode) {
++ pSiSEnt->CRT2ModeNo = ModeNo;
++ pSiSEnt->CRT2DMode = mode;
++ pSiSEnt->CRT2IsCustom = IsCustom;
++
++ /* We can't set CRT2 mode before CRT1 mode is set */
++ if(pSiSEnt->CRT1ModeNo == -1) {
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
++ "Setting CRT2 mode delayed until after setting CRT1 mode\n");
++ return TRUE;
++ }
++ }
+
+ SiSInitPtr(SiS_Pr, HwDeviceExtension);
+
+ SiSRegInit(SiS_Pr, BaseAddr);
+
++ SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
++
+ SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+
+ SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
+@@ -2294,22 +2383,26 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+
+ SiSDetermineROMUsage(SiS_Pr, HwDeviceExtension, ROMAddr);
+
+- /* TW: We don't clear the buffer under X */
++ /* We don't clear the buffer under X */
+ SiS_Pr->SiS_flag_clearbuffer=0;
+
+- /* TW: Save ModeNo so we can set it from within SetMode for CRT1 */
+- pSiSEnt->CRT2ModeNo = ModeNo;
+- pSiSEnt->CRT2DMode = mode;
+-
+- /* TW: We can't set CRT2 mode before CRT1 mode is set */
+- if(pSiSEnt->CRT1ModeNo == -1) {
+- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+- "Setting CRT2 mode delayed until after setting CRT1 mode\n");
+- return TRUE;
+- }
++ if(SiS_Pr->UseCustomMode) {
++
++ USHORT temptemp = SiS_Pr->CVDisplay;
++
++ if(SiS_Pr->CModeFlag & DoubleScanMode) temptemp >>= 1;
++ else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
++
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
++ "Setting custom mode %dx%d on CRT2\n",
++ SiS_Pr->CHDisplay, temptemp);
+
+- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+- "Setting mode 0x%x on CRT2\n", ModeNo);
++ } else {
++
++ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
++ "Setting standard mode 0x%x on CRT2\n", ModeNo);
++
++ }
+
+ /* 1.Openkey */
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86);
+@@ -2317,10 +2410,14 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
+
+ /* 2.Get ModeID */
+- temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
+- if(temp == 0) return(0);
++ if(!SiS_Pr->UseCustomMode) {
++ temp = SiS_SearchModeID(SiS_Pr, ROMAddr,&ModeNo,&ModeIdIndex);
++ if(temp == 0) return(0);
++ } else {
++ ModeIdIndex = 0;
++ }
+
+- /* TW: Determine VBType (301,301B,301LV,302B,302LV) */
++ /* Determine VBType (301,301B,301LV,302B,302LV) */
+ SiS_GetVBType(SiS_Pr, BaseAddr,HwDeviceExtension);
+
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+@@ -2343,15 +2440,22 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ }
+ }
+
+- /* TW: Get VB information (connectors, connected devices) */
+- SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
++ /* Get VB information (connectors, connected devices) */
++ if(!SiS_Pr->UseCustomMode) {
++ SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
++ } else {
++ /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
++ SiS_GetVBInfo(SiS_Pr, BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,0);
++ }
+ SiS_SetHiVision(SiS_Pr, BaseAddr,HwDeviceExtension);
+ SiS_GetLCDResInfo(SiS_Pr, ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= SetDOSMode;
++ } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
++ SiS_Pr->SiS_SetFlag |= SetDOSMode;
+ }
+ }
+ }
+@@ -2364,17 +2468,19 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ case VB_CHIP_302:
+ case VB_CHIP_302B:
+ case VB_CHIP_302LV:
+- SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
++ SiS_SetCRT2Group(SiS_Pr, BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+ break;
+ case VB_CHIP_UNKNOWN:
+- if (SiS_Pr->SiS_IF_DEF_LVDS == 1 ||
+- SiS_Pr->SiS_IF_DEF_CH70xx != 0 ||
+- SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
+- SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1 ||
++ SiS_Pr->SiS_IF_DEF_CH70xx != 0 ||
++ SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
++ SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+ }
+ break;
+ }
+
++ SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
++
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
+
+@@ -2386,7 +2492,6 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ }
+ }
+
+- /* TW: New from 650/LV 1.10.6x and 1.10.7w, 630 2.06.50 */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+@@ -2412,7 +2517,7 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr,
+ }
+ }
+
+- /* TW: SetPitch: Adapt to virtual size & position */
++ /* SetPitch: Adapt to virtual size & position */
+ SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr);
+
+ return TRUE;
+@@ -2442,12 +2547,14 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+
+ if(SiS_Pr->UseCustomMode) {
+ ModeNo = 0xfe;
+- }
+-
++ }
++
+ SiSInitPtr(SiS_Pr, HwDeviceExtension);
+
+ SiSRegInit(SiS_Pr, BaseAddr);
+
++ SiS_GetSysFlags(SiS_Pr, HwDeviceExtension);
++
+ #ifdef LINUX_XF86
+ if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
+ else
+@@ -2458,7 +2565,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "VGAInfo 0x%02x\n", SiS_Pr->SiS_VGAINFO);
+ #endif
+-#endif
++#endif
+
+ SiSInitPCIetc(SiS_Pr, HwDeviceExtension);
+
+@@ -2469,10 +2576,10 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ if(!SiS_Pr->UseCustomMode) {
+ /* TW: Shift the clear-buffer-bit away */
+ ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f);
+- }
++ }
+
+ #ifdef LINUX_XF86
+- /* TW: We never clear the buffer in X */
++ /* We never clear the buffer in X */
+ ModeNo |= 0x8000;
+ #endif
+
+@@ -2490,21 +2597,21 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ SiS_UnLockCRT2(SiS_Pr, HwDeviceExtension, BaseAddr);
+
+ if(!SiS_Pr->UseCustomMode) {
+-
++
+ /* 2.Get ModeID Table */
+ temp = SiS_SearchModeID(SiS_Pr,ROMAddr,&ModeNo,&ModeIdIndex);
+ if(temp == 0) return(0);
+-
++
+ } else {
+-
++
+ ModeIdIndex = 0;
+-
++
+ }
+-
+- /* TW: Determine VBType (301,301B,301LV,302B,302LV) */
++
++ /* Determine VBType (301,301B,301LV,302B,302LV) */
+ SiS_GetVBType(SiS_Pr,BaseAddr,HwDeviceExtension);
+
+- /* TW: Init/restore some VB registers */
++ /* Init/restore some VB registers */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ SiS_UnLockCRT2(SiS_Pr,HwDeviceExtension,BaseAddr);
+@@ -2525,8 +2632,12 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+ }
+
+- /* TW: Get VB information (connectors, connected devices) */
+- SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
++ /* Get VB information (connectors, connected devices) */
++ if(SiS_Pr->UseCustomMode) {
++ SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,0);
++ } else {
++ SiS_GetVBInfo(SiS_Pr,BaseAddr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension,1);
++ }
+ SiS_SetHiVision(SiS_Pr,BaseAddr,HwDeviceExtension);
+ SiS_GetLCDResInfo(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,HwDeviceExtension);
+
+@@ -2535,22 +2646,32 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ if(!temp) return(0);
+
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+- if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x17) & 0x08) {
++ if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+ if(ModeNo != 0x10) SiS_Pr->SiS_SetFlag |= SetDOSMode;
++ } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
++ SiS_Pr->SiS_SetFlag |= SetDOSMode;
+ }
+ }
+
+- /* TW: New from 650/LV 1.10.6x; not in any BIOS for other chipsets */
+ if(IS_SIS650) {
+- if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+- SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+- }
++ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
++ if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
++ }
+ }
+ }
+
+- /* TW: Set mode on CRT1 */
++ if(SiS_Pr->UseCustomMode) {
++ SiS_Pr->CRT1UsesCustomMode = TRUE;
++ SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
++ SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
++ } else {
++ SiS_Pr->CRT1UsesCustomMode = FALSE;
++ }
++
++ /* Set mode on CRT1 */
+ if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
+ SiS_SetCRT1Group(SiS_Pr,ROMAddr,HwDeviceExtension,ModeNo,ModeIdIndex,BaseAddr);
+ } else {
+@@ -2559,7 +2680,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+ }
+
+- /* TW: Set mode on CRT2 */
++ /* Set mode on CRT2 */
+ if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchToCRT2 | SetCRT2ToLCDA)) {
+ switch (HwDeviceExtension->ujVBChipID) {
+ case VB_CHIP_301:
+@@ -2568,18 +2689,20 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ case VB_CHIP_302:
+ case VB_CHIP_302B:
+ case VB_CHIP_302LV:
+- SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
++ SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+ break;
+ case VB_CHIP_UNKNOWN:
+ if(SiS_Pr->SiS_IF_DEF_LVDS == 1 ||
+ SiS_Pr->SiS_IF_DEF_CH70xx != 0 ||
+ SiS_Pr->SiS_IF_DEF_TRUMPION != 0)
+- SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
++ SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,ModeNo,HwDeviceExtension);
+ break;
+ }
+ }
+
+ SiS_HandleCRT1(SiS_Pr);
++
++ SiS_StrangeStuff(SiS_Pr, HwDeviceExtension);
+
+ SiS_DisplayOn(SiS_Pr);
+ SiS_SetReg3(SiS_Pr->SiS_P3c6,0xFF);
+@@ -2592,7 +2715,6 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+ }
+
+- /* TW: New from 650/LV 1.10.6x and 1.10.7w */
+ if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ if(SiS_IsVAMode(SiS_Pr,HwDeviceExtension, BaseAddr)) {
+@@ -2627,7 +2749,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+
+ #ifdef LINUX_XF86
+ if(pScrn) {
+- /* TW: SetPitch: Adapt to virtual size & position */
++ /* SetPitch: Adapt to virtual size & position */
+ if((ModeNo > 0x13) && (dosetpitch)) {
+ SiS_SetPitch(SiS_Pr, pScrn, BaseAddr);
+ }
+@@ -2637,7 +2759,7 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+ #endif
+
+-#ifndef LINUX_XF86 /* TW: We never lock registers in XF86 */
++#ifndef LINUX_XF86 /* We never lock registers in XF86 */
+ if(KeepLockReg == 0xA1) SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x86);
+ else SiS_SetReg1(SiS_Pr->SiS_P3c4,0x05,0x00);
+ #endif
+@@ -2646,10 +2768,15 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_
+ }
+
+ void
+-SiS_SetEnableDstn(SiS_Private *SiS_Pr) /* TW: Called from sis_main.c */
++SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable)
++{
++ SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
++}
++
++void
++SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable)
+ {
+- /* For 550 dstn */
+- SiS_Pr->SiS_IF_DEF_DSTN = 1;
++ SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
+ }
+
+ void
+@@ -2663,13 +2790,73 @@ SiS_HandleCRT1(SiS_Private *SiS_Pr)
+ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf);
+
+ #if 0
+- if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01))
+- SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
++ if(!(SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
++ if((SiS_GetReg1(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
++ (SiS_GetReg1(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
++ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
++ }
+ }
+ #endif
+ }
+
+ void
++SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
++{
++ unsigned char cr5f, temp1, temp2;
++
++ /* You should use the macros, not these flags directly */
++
++ SiS_Pr->SiS_SysFlags = 0;
++ if(HwDeviceExtension->jChipType == SIS_650) {
++ cr5f = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
++ SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
++ temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
++ SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
++ temp2 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
++ if((!temp1) || (temp2)) {
++ switch(cr5f) {
++ case 0x80:
++ case 0x90:
++ case 0xc0:
++ SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
++ case 0xa0:
++ case 0xb0:
++ case 0xe0:
++ SiS_Pr->SiS_SysFlags |= SF_Is651; break;
++ }
++ } else {
++ switch(cr5f) {
++ case 0x90:
++ temp1 = SiS_GetReg1(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
++ switch(temp1) {
++ case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
++ case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
++ default: SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
++ }
++ break;
++ case 0xb0:
++ SiS_Pr->SiS_SysFlags |= SF_Is652; break;
++ default:
++ SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
++ }
++ }
++ }
++}
++
++void
++SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension)
++{
++ if((IS_SIS651) || (IS_SISM650)) {
++ SiS_SetReg1(SiS_Pr->SiS_VidCapt, 0x3f, 0x00); /* Fiddle with capture regs */
++ SiS_SetReg1(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
++ SiS_SetReg1(SiS_Pr->SiS_VidPlay, 0x00, 0x86); /* (BIOS does NOT unlock) */
++ SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x30, 0xfe); /* Fiddle with video regs */
++ SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
++ }
++ /* !!! This does not support modes < 0x13 !!! */
++}
++
++void
+ SiS_SetCRT1Group(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo,USHORT ModeIdIndex,USHORT BaseAddr)
+ {
+@@ -2683,6 +2870,9 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, UC
+ }
+ }
+
++ /* 550, 651 */
++ SiS_WhatTheHellIsThis(SiS_Pr,HwDeviceExtension,BaseAddr);
++
+ SiS_SetSeqRegs(SiS_Pr,ROMAddr,StandTableIndex);
+ SiS_SetMiscRegs(SiS_Pr,ROMAddr,StandTableIndex);
+ SiS_SetCRTCRegs(SiS_Pr,ROMAddr,HwDeviceExtension,StandTableIndex);
+@@ -2759,15 +2949,20 @@ void
+ SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr)
+ {
+ SISPtr pSiS = SISPTR(pScrn);
++ BOOLEAN isslavemode = FALSE;
++
++ if( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
++ ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
++ ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
++ isslavemode = TRUE;
++ }
+
+- /* TW: We need to set pitch for CRT1 if bridge is in SlaveMode, too */
+- if( (pSiS->VBFlags & DISPTYPE_DISP1) ||
+- ( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
+- ( ((pSiS->VGAEngine == SIS_300_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
+- ((pSiS->VGAEngine == SIS_315_VGA) && (SiS_GetReg1(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) ) {
++ /* We need to set pitch for CRT1 if bridge is in slave mode, too */
++ if( (pSiS->VBFlags & DISPTYPE_DISP1) || (isslavemode) ) {
+ SiS_SetPitchCRT1(SiS_Pr, pScrn, BaseAddr);
+ }
+- if (pSiS->VBFlags & DISPTYPE_DISP2) {
++ /* We must not set the pitch for CRT2 if bridge is in slave mode */
++ if( (pSiS->VBFlags & DISPTYPE_DISP2) && (!isslavemode) ) {
+ SiS_SetPitchCRT2(SiS_Pr, pScrn, BaseAddr);
+ }
+ }
+@@ -2790,7 +2985,7 @@ SiS_SetPitchCRT2(SiS_Private *SiS_Pr, Sc
+ SISPtr pSiS = SISPTR(pScrn);
+ ULong HDisplay,temp;
+
+- HDisplay = pSiS->scrnPitch / 8;
++ HDisplay = pSiS->scrnPitch2 / 8;
+
+ /* Unlock CRT2 */
+ if (pSiS->VGAEngine == SIS_315_VGA)
+@@ -2880,7 +3075,6 @@ SiS_SearchModeID(SiS_Private *SiS_Pr, UC
+ return TRUE;
+ }
+
+-/* For SiS 300 oem util: Search VBModeID */
+ BOOLEAN
+ SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo)
+ {
+@@ -2946,6 +3140,81 @@ SiS_GetModePtr(SiS_Private *SiS_Pr, UCHA
+ return index;
+ }
+
++static void
++SiS_WhatIsThis1a(SiS_Private *SiS_Pr, USHORT somevalue)
++{
++ USHORT temp, tempbl, tempbh;
++
++ tempbl = tempbh = somevalue;
++ temp = SiS_GetReg2(SiS_Pr->SiS_P3cb);
++ temp &= 0xf0;
++ tempbl >>= 4;
++ temp |= tempbl;
++ SiS_SetReg3(SiS_Pr->SiS_P3cb, temp);
++ temp = SiS_GetReg2(SiS_Pr->SiS_P3cd);
++ temp &= 0xf0;
++ tempbh &= 0x0f;
++ temp |= tempbh;
++ SiS_SetReg3(SiS_Pr->SiS_P3cd, temp);
++}
++
++static void
++SiS_WhatIsThis1b(SiS_Private *SiS_Pr, USHORT somevalue)
++{
++ USHORT temp, tempbl, tempbh;
++
++ tempbl = tempbh = somevalue;
++ temp = SiS_GetReg2(SiS_Pr->SiS_P3cb);
++ temp &= 0x0f;
++ tempbl &= 0xf0;
++ temp |= tempbl;
++ SiS_SetReg3(SiS_Pr->SiS_P3cb, temp);
++ temp = SiS_GetReg2(SiS_Pr->SiS_P3cd);
++ temp &= 0x0f;
++ tempbh <<= 4;
++ temp |= tempbh;
++ SiS_SetReg3(SiS_Pr->SiS_P3cd, temp);
++}
++
++static void
++SiS_WhatIsThis2b(SiS_Private *SiS_Pr, USHORT somevalue)
++{
++ SiS_WhatIsThis1a(SiS_Pr, somevalue);
++ SiS_WhatIsThis1b(SiS_Pr, somevalue);
++}
++
++static void
++SiS_WhatIsThis1(SiS_Private *SiS_Pr)
++{
++ SiS_WhatIsThis2b(SiS_Pr, 0);
++}
++
++static void
++SiS_WhatIsThis2a(SiS_Private *SiS_Pr, USHORT somevalue)
++{
++ USHORT temp = somevalue >> 8;
++
++ temp &= 0x07;
++ temp |= (temp << 4);
++ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1d,temp);
++ SiS_WhatIsThis2b(SiS_Pr, somevalue);
++}
++
++static void
++SiS_WhatIsThis2(SiS_Private *SiS_Pr)
++{
++ SiS_WhatIsThis2a(SiS_Pr, 0);
++}
++
++void
++SiS_WhatTheHellIsThis(SiS_Private *SiS_Pr,PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr)
++{
++ if(IS_SIS65x) {
++ SiS_WhatIsThis1(SiS_Pr);
++ SiS_WhatIsThis2(SiS_Pr);
++ }
++}
++
+ void
+ SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex)
+ {
+@@ -3027,7 +3296,7 @@ SiS_SetCRTCRegs(SiS_Private *SiS_Pr, UCH
+ (HwDeviceExtension->jChipRevision >= 0x30) ) { /* for 630S0 */
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+ if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+- SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE);
++ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x18,0xFE);
+ }
+ }
+ }
+@@ -3065,7 +3334,7 @@ SiS_SetATTRegs(SiS_Private *SiS_Pr, UCHA
+ }
+ if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+- if(IS_SIS650740 || IS_SIS550) {
++ if(IS_SIS550650740660) {
+ /* 315, 330 don't do this */
+ if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+ if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+@@ -3148,7 +3417,7 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCH
+ USHORT tempah,i,modeflag,j;
+ #ifdef SIS315H
+ USHORT temp;
+- USHORT ResInfo,DisplayType;
++ USHORT ResIndex,DisplayType;
+ const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
+ #endif
+
+@@ -3171,7 +3440,7 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCH
+ /* LCDA */
+
+ temp = SiS_GetLCDACRT1Ptr(SiS_Pr,ROMAddr,ModeNo,ModeIdIndex,
+- RefreshRateTableIndex,&ResInfo,&DisplayType);
++ RefreshRateTableIndex,&ResIndex,&DisplayType);
+
+ switch(DisplayType) {
+ case Panel_800x600 : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT1800x600_1; break;
+@@ -3197,30 +3466,30 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCH
+ default: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1; break;
+ }
+
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[0];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[0];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,0x00,tempah);
+ for(i=0x01,j=1;i<=0x07;i++,j++){
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x10,j=8;i<=0x12;i++,j++){
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x15,j=11;i<=0x16;i++,j++){
+- tempah =(LCDACRT1Ptr+ResInfo)->CR[j];
++ tempah =(LCDACRT1Ptr+ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3d4,i,tempah);
+ }
+ for(i=0x0A,j=13;i<=0x0C;i++,j++){
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[j];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[j];
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,i,tempah);
+ }
+
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[16];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[16];
+ tempah &= 0x0E0;
+ SiS_SetReg1(SiS_Pr->SiS_P3c4,0x0E,tempah);
+
+- tempah = (LCDACRT1Ptr+ResInfo)->CR[16];
++ tempah = (LCDACRT1Ptr+ResIndex)->CR[16];
+ tempah &= 0x01;
+ tempah <<= 5;
+ if(modeflag & DoubleScanMode) tempah |= 0x080;
+@@ -3301,7 +3570,7 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, UCH
+
+ BOOLEAN
+ SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+- USHORT RefreshRateTableIndex,USHORT *ResInfo,
++ USHORT RefreshRateTableIndex,USHORT *ResIndex,
+ USHORT *DisplayType)
+ {
+ USHORT tempbx=0,modeflag=0;
+@@ -3320,7 +3589,7 @@ SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr,
+ if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 32;
+ if(modeflag & HalfDCLK) tempbx += 16;
+
+- *ResInfo = CRT2CRTC & 0x3F;
++ *ResIndex = CRT2CRTC & 0x3F;
+ *DisplayType = tempbx;
+
+ return 1;
+@@ -3470,6 +3739,9 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
+ USHORT data,data2,data3;
+ USHORT infoflag=0,modeflag;
+ USHORT resindex,xres;
++#ifdef SIS315H
++ ULONG longdata;
++#endif
+
+ if(SiS_Pr->UseCustomMode) {
+ modeflag = SiS_Pr->CModeFlag;
+@@ -3490,11 +3762,11 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
+
+ data2 = 0;
+ if(ModeNo > 0x13) {
+- if(SiS_Pr->SiS_ModeType > 0x02) {
+- data2 |= 0x02;
+- data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2;
+- data2 |= data3;
+- }
++ if(SiS_Pr->SiS_ModeType > 0x02) {
++ data2 |= 0x02;
++ data3 = (SiS_Pr->SiS_ModeType - ModeVGA) << 2;
++ data2 |= data3;
++ }
+ }
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n",
+@@ -3517,7 +3789,8 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
+ if(HwDeviceExtension->jChipType != SIS_300) {
+ data = 0x0000;
+ if(infoflag & InterlaceMode) {
+- if(xres == 1024) data = 0x0035;
++ if(xres <= 800) data = 0x0020;
++ else if(xres <= 1024) data = 0x0035;
+ else data = 0x0048;
+ }
+ data2 = data & 0x00FF;
+@@ -3549,6 +3822,7 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
+ } else {
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7);
+ }
++ /* 651 BIOS does something for mode 0x12 here */
+ }
+
+ if(HwDeviceExtension->jChipType != SIS_300) {
+@@ -3604,9 +3878,9 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
+ data2 *= data3;
+
+ data3 = SiS_GetMCLK(SiS_Pr,ROMAddr, HwDeviceExtension);
+- data3 *= 1024;
++ longdata = data3 * 1024;
+
+- data2 = data3 / data2;
++ data2 = longdata / data2;
+
+ if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+ if(data2 >= 0x19c) data = 0xba;
+@@ -3679,7 +3953,7 @@ SiS_SetVCLKState(SiS_Private *SiS_Pr, UC
+ if(VCLK >= 150) data2 |= 0x08; /* VCLK > 150 */
+ SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2);
+
+- } else { /* 310/325 series */
++ } else { /* 315 series */
+
+ data = 0;
+ if(VCLK >= 166) data |= 0x0c; /* TW: Was 200; is 166 in 650, 315 and 330 BIOSes */
+@@ -3688,12 +3962,6 @@ SiS_SetVCLKState(SiS_Private *SiS_Pr, UC
+ if(VCLK >= 166) { /* TW: Was 200, is 166 in 650, 315 and 330 BIOSes */
+ SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
+ }
+-#if 0 /* Not done in 315 and 650/301LV/LVDS BIOSes: */
+- data = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x1F); /* DAC pedestal */
+- data &= 0xE7;
+- if(VCLK<200) data |= 0x10;
+- SiS_SetReg1(SiS_Pr->SiS_P3c4,0x1F,data); /* DAC pedestal */
+-#endif
+ }
+
+ data2 = 0x03;
+@@ -3918,7 +4186,9 @@ GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW
+
+ } else if((HwDeviceExtension->jChipType == SIS_550) ||
+ (HwDeviceExtension->jChipType == SIS_740) ||
+- (HwDeviceExtension->jChipType == SIS_650)) {
++ (HwDeviceExtension->jChipType == SIS_650) ||
++ (HwDeviceExtension->jChipType == SIS_660) ||
++ (HwDeviceExtension->jChipType == SIS_760)) {
+
+ counter = SiS_GetReg1(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
+ counter++;
+@@ -4728,7 +4998,7 @@ SiS_GetSenseStatus(SiS_Private *SiS_Pr,
+ SiS_Pr->SiS_SetFlag = 0x00;
+ SiS_Pr->SiS_ModeType = ModeVGA;
+ SiS_Pr->SiS_VBInfo = SetCRT2ToRAMDAC |LoadDACFlag |SetInSlaveMode;
+- SiS_SetCRT2Group301(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
++ SiS_SetCRT2Group(SiS_Pr, BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
+ for(i=0;i<20;i++) {
+ SiS_LongWait(SiS_Pr);
+ }
+@@ -4766,7 +5036,7 @@ SiS_GetSenseStatus(SiS_Private *SiS_Pr,
+ #ifdef SIS315H
+ if(HwDeviceExtension->jChipType >= SIS_315H) {
+ OutputSelect = ROMAddr[0xf3];
+- if(HwDeviceExtension->jChipType == SIS_330) {
++ if(HwDeviceExtension->jChipType >= SIS_330) {
+ OutputSelect = ROMAddr[0x11b];
+ }
+ }
+@@ -4814,7 +5084,7 @@ SiS_GetSenseStatus(SiS_Private *SiS_Pr,
+ SiS_SetReg1(SiS_Pr->SiS_Part2Port,0x00,P2reg0);
+ if(!(P2reg0 & 0x20)) {
+ SiS_Pr->SiS_VBInfo = DisableCRT2Display;
+- SiS_SetCRT2Group301(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
++ SiS_SetCRT2Group(SiS_Pr,BaseAddr,ROMAddr,SenseModeNo,HwDeviceExtension);
+ }
+ }
+ }
+@@ -4884,111 +5154,6 @@ SiS_SenseCHTV(SiS_Private *SiS_Pr)
+ }
+ #endif /* LINUXBIOS */
+
+-/* ================ for TC only ================= */
+-
+-#ifdef TC
+-
+-int
+-INT1AReturnCode(union REGS regs)
+-{
+- if (regs.x.cflag)
+- {
+- /*printf("Error to find pci device!\n"); */
+- return 1;
+- }
+-
+- switch(regs.h.ah)
+- {
+- case 0: return 0;
+- break;
+- case 0x81: printf("Function not support\n");
+- break;
+- case 0x83: printf("bad vendor id\n");
+- break;
+- case 0x86: printf("device not found\n");
+- break;
+- case 0x87: printf("bad register number\n");
+- break;
+- case 0x88: printf("set failed\n");
+- break;
+- case 0x89: printf("buffer too small");
+- break;
+- }
+- return 1;
+-}
+-
+-unsigned
+-FindPCIIOBase(unsigned index,unsigned deviceid)
+-{
+- union REGS regs;
+-
+- regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */
+- regs.h.al = 0x02; /*FIND_PCI_DEVICE */
+- regs.x.cx = deviceid;
+- regs.x.dx = 0x1039;
+- regs.x.si = index; /* find n-th device */
+-
+- int86(0x1A, ®s, ®s);
+-
+- if (INT1AReturnCode(regs)!=0)
+- return 0;
+-
+- /* regs.h.bh *//* bus number */
+- /* regs.h.bl *//* device number */
+- regs.h.ah = 0xb1; /*PCI_FUNCTION_ID */
+- regs.h.al = 0x09; /*READ_CONFIG_WORD */
+- regs.x.cx = deviceid;
+- regs.x.dx = 0x1039;
+- regs.x.di = 0x18; /* register number */
+- int86(0x1A, ®s, ®s);
+-
+- if (INT1AReturnCode(regs)!=0)
+- return 0;
+- return regs.x.cx;
+-}
+-
+-
+-void
+-main(int argc, char *argv[])
+-{
+- SIS_HW_DEVICE_INFO HwDeviceExtension;
+- USHORT temp;
+- USHORT ModeNo;
+-
+- /*HwDeviceExtension.pjVirtualRomBase =(PUCHAR) MK_FP(0xC000,0); */
+- /*HwDeviceExtension.pjVideoMemoryAddress = (PUCHAR)MK_FP(0xA000,0);*/
+-
+-#ifdef SIS300
+- HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x6300)&0xFF80) + 0x30;
+- HwDeviceExtension.jChipType = SIS_630;
+-#endif
+-
+-#ifdef SIS315H
+-// HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x5315)&0xFF80) + 0x30;
+-// HwDeviceExtension.jChipType = SIS_550;
+- HwDeviceExtension.ulIOAddress = (FindPCIIOBase(0,0x325)&0xFF80) + 0x30;
+- HwDeviceExtension.jChipType = SIS_315H;
+-#endif
+-
+- HwDeviceExtension.ujVBChipID = VB_CHIP_301;
+- strcpy(HwDeviceExtension.szVBIOSVer,"0.84");
+- HwDeviceExtension.bSkipDramSizing = FALSE;
+- HwDeviceExtension.ulVideoMemorySize = 0;
+- if(argc==2) {
+- ModeNo=atoi(argv[1]);
+- }
+- else {
+- ModeNo=0x2e;
+- /*ModeNo=0x37; */ /* 1024x768x 4bpp */
+- /*ModeNo=0x38; *//* 1024x768x 8bpp */
+- /*ModeNo=0x4A; *//* 1024x768x 16bpp */
+- /*ModeNo=0x47;*/ /* 800x600x 16bpp */
+- }
+- /* SiSInit(SiS_Pr, &HwDeviceExtension);*/
+- SiSSetMode(SiS_Pr, &HwDeviceExtension, ModeNo);
+-}
+-#endif /* TC END */
+-
+ /* ================ XFREE86 ================= */
+
+ /* Helper functions */
+@@ -5000,44 +5165,78 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
+ SISPtr pSiS = SISPTR(pScrn);
+ int out_n, out_dn, out_div, out_sbit, out_scale;
+ int depth = pSiS->CurrentLayout.bitsPerPixel;
+-
+-#ifdef SISDUALHEAD
+- if( ((!pSiS->DualHeadMode) && (VBFlags & DISPTYPE_DISP2)) ||
+- ((pSiS->DualHeadMode) && (!pSiS->SecondHead)) ) return 0;
+-#else
+- if(VBFlags & DISPTYPE_DISP2) return 0;
+-#endif
++ unsigned int vclk[5];
++
++#define Midx 0
++#define Nidx 1
++#define VLDidx 2
++#define Pidx 3
++#define PSNidx 4
++
++ pSiS->SiS_Pr->CModeFlag = 0;
+
+ pSiS->SiS_Pr->CDClock = mode->Clock;
+-
++
+ pSiS->SiS_Pr->CHDisplay = mode->HDisplay;
+ pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart;
+ pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd;
+ pSiS->SiS_Pr->CHTotal = mode->HTotal;
+- pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
+- pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
+-
++
+ pSiS->SiS_Pr->CVDisplay = mode->VDisplay;
+ pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart;
+ pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd;
+ pSiS->SiS_Pr->CVTotal = mode->VTotal;
++
++ pSiS->SiS_Pr->CFlags = mode->Flags;
++
++ if(pSiS->SiS_Pr->CFlags & V_INTERLACE) {
++ pSiS->SiS_Pr->CVDisplay >>= 1;
++ pSiS->SiS_Pr->CVSyncStart >>= 1;
++ pSiS->SiS_Pr->CVSyncEnd >>= 1;
++ pSiS->SiS_Pr->CVTotal >>= 1;
++ }
++ if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) {
++ /* pSiS->SiS_Pr->CDClock <<= 1; */
++ pSiS->SiS_Pr->CVDisplay <<= 1;
++ pSiS->SiS_Pr->CVSyncStart <<= 1;
++ pSiS->SiS_Pr->CVSyncEnd <<= 1;
++ pSiS->SiS_Pr->CVTotal <<= 1;
++ }
++
++ pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
++ pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
+ pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1;
+ pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal;
+-
+- pSiS->SiS_Pr->CFlags = mode->Flags;
+
+- SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale);
+-
++ if(SiS_compute_vclk(pSiS->SiS_Pr->CDClock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) {
++ pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00;
++ pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f);
++ pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f;
++ pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5);
++ pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7);
+ #ifdef TWDEBUG
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
+- pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale);
+-#endif
+-
+- pSiS->SiS_Pr->CSR2B = (out_div == 2) ? 0x80 : 0x00;
+- pSiS->SiS_Pr->CSR2B |= ((out_n - 1) & 0x7f);
+- pSiS->SiS_Pr->CSR2C = (out_dn - 1) & 0x1f;
+- pSiS->SiS_Pr->CSR2C |= (((out_scale - 1) & 3) << 5);
+- pSiS->SiS_Pr->CSR2C |= ((out_sbit & 0x01) << 7);
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
++ pSiS->SiS_Pr->CDClock, out_n, out_dn, out_div, out_sbit, out_scale);
++#endif
++ } else {
++ SiSCalcClock(pScrn, pSiS->SiS_Pr->CDClock, 2, vclk);
++ pSiS->SiS_Pr->CSR2B = (vclk[VLDidx] == 2) ? 0x80 : 0x00;
++ pSiS->SiS_Pr->CSR2B |= (vclk[Midx] - 1) & 0x7f;
++ pSiS->SiS_Pr->CSR2C = (vclk[Nidx] - 1) & 0x1f;
++ if(vclk[Pidx] <= 4) {
++ /* postscale 1,2,3,4 */
++ pSiS->SiS_Pr->CSR2C |= ((vclk[Pidx] - 1) & 3) << 5;
++ } else {
++ /* postscale 6,8 */
++ pSiS->SiS_Pr->CSR2C |= (((vclk[Pidx] / 2) - 1) & 3) << 5;
++ pSiS->SiS_Pr->CSR2C |= 0x80;
++ }
++#ifdef TWDEBUG
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n",
++ pSiS->SiS_Pr->CDClock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]);
++#endif
++ }
++
+ pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
+
+ pSiS->SiS_Pr->CCRT1CRTC[0] = ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff;
+@@ -5045,9 +5244,9 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
+ pSiS->SiS_Pr->CCRT1CRTC[2] = (pSiS->SiS_Pr->CHBlankStart >> 3) - 1;
+ pSiS->SiS_Pr->CCRT1CRTC[3] = (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
+ pSiS->SiS_Pr->CCRT1CRTC[4] = (pSiS->SiS_Pr->CHSyncStart >> 3) + 3;
+- pSiS->SiS_Pr->CCRT1CRTC[5] = ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
++ pSiS->SiS_Pr->CCRT1CRTC[5] = ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
+ (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+-
++
+ pSiS->SiS_Pr->CCRT1CRTC[6] = (pSiS->SiS_Pr->CVTotal - 2) & 0xFF;
+ pSiS->SiS_Pr->CCRT1CRTC[7] = (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8)
+ | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+@@ -5057,50 +5256,50 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
+ | (((pSiS->SiS_Pr->CVTotal - 2) & 0x200) >> 4)
+ | (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+ | ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2);
+-
++
+ pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); /* cr9 */
+-
+-#if 0
++
++#if 0
+ if (mode->VScan >= 32)
+ regp->CRTC[9] |= 0x1F;
+ else if (mode->VScan > 1)
+ regp->CRTC[9] |= mode->VScan - 1;
+-#endif
++#endif
+
+- pSiS->SiS_Pr->CCRT1CRTC[8] = (pSiS->SiS_Pr->CVSyncStart - 1) & 0xFF; /* cr10 */
+- pSiS->SiS_Pr->CCRT1CRTC[9] = ((pSiS->SiS_Pr->CVSyncEnd - 1) & 0x0F) | 0x80; /* cr11 */
+- pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay - 1) & 0xFF; /* cr12 */
+- pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF; /* cr15 */
+- pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd - 1) & 0xFF; /* cr16 */
+-
+- pSiS->SiS_Pr->CCRT1CRTC[13] =
++ pSiS->SiS_Pr->CCRT1CRTC[8] = (pSiS->SiS_Pr->CVSyncStart ) & 0xFF; /* cr10 */
++ pSiS->SiS_Pr->CCRT1CRTC[9] = ((pSiS->SiS_Pr->CVSyncEnd ) & 0x0F) | 0x80; /* cr11 */
++ pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay - 1) & 0xFF; /* cr12 */
++ pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF; /* cr15 */
++ pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd - 1) & 0xFF; /* cr16 */
++
++ pSiS->SiS_Pr->CCRT1CRTC[13] =
+ GETBITSTR((pSiS->SiS_Pr->CVTotal -2), 10:10, 0:0) |
+ GETBITSTR((pSiS->SiS_Pr->CVDisplay -1), 10:10, 1:1) |
+ GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+ GETBITSTR((pSiS->SiS_Pr->CVSyncStart ), 10:10, 3:3) |
+ GETBITSTR((pSiS->SiS_Pr->CVBlankEnd -1), 8:8, 4:4) |
+- GETBITSTR((pSiS->SiS_Pr->CVSyncEnd -1), 4:4, 5:5) ;
++ GETBITSTR((pSiS->SiS_Pr->CVSyncEnd ), 4:4, 5:5) ;
+
+- pSiS->SiS_Pr->CCRT1CRTC[14] =
++ pSiS->SiS_Pr->CCRT1CRTC[14] =
+ GETBITSTR((pSiS->SiS_Pr->CHTotal >> 3) - 5, 9:8, 1:0) |
+ GETBITSTR((pSiS->SiS_Pr->CHDisplay >> 3) - 1, 9:8, 3:2) |
+ GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+ GETBITSTR((pSiS->SiS_Pr->CHSyncStart >> 3) + 3, 9:8, 7:6) ;
+
+-
++
+ pSiS->SiS_Pr->CCRT1CRTC[15] =
+ GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+- GETBITSTR((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
+-
++ GETBITSTR((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3, 5:5, 2:2) ;
++
+ switch(depth) {
+- case 8:
+- pSiS->SiS_Pr->CModeFlag = 0x223b;
++ case 8:
++ pSiS->SiS_Pr->CModeFlag |= 0x223b;
+ break;
+- case 16:
+- pSiS->SiS_Pr->CModeFlag = 0x227d;
++ case 16:
++ pSiS->SiS_Pr->CModeFlag |= 0x227d;
+ break;
+- case 32:
+- pSiS->SiS_Pr->CModeFlag = 0x22ff;
++ case 32:
++ pSiS->SiS_Pr->CModeFlag |= 0x22ff;
+ break;
+ default:
+ return 0;
+@@ -5114,9 +5313,9 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
+ pSiS->SiS_Pr->CModeFlag |= LineCompareOff;
+ if(pSiS->SiS_Pr->CFlags & V_CLKDIV2)
+ pSiS->SiS_Pr->CModeFlag |= HalfDCLK;
+-
++
+ pSiS->SiS_Pr->CInfoFlag = 0x0007;
+- if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
++ if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
+ pSiS->SiS_Pr->CInfoFlag |= 0x4000;
+ if(pSiS->SiS_Pr->CFlags & V_NVSYNC)
+ pSiS->SiS_Pr->CInfoFlag |= 0x8000;
+@@ -5152,13 +5351,13 @@ SiS_CheckBuildCustomMode(ScrnInfoPtr pSc
+ pSiS->SiS_Pr->CSR2B,
+ pSiS->SiS_Pr->CSR2C,
+ pSiS->SiS_Pr->CSRClock);
+-#endif
++#endif
+ return 1;
+ }
+
+ /* TW: Build a list of supported modes */
+ DisplayModePtr
+-SiSBuildBuiltInModeList(ScrnInfoPtr pScrn)
++SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi)
+ {
+ SISPtr pSiS = SISPTR(pScrn);
+ unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+@@ -5166,11 +5365,16 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ unsigned char sr_data, cr_data, cr_data2, cr_data3;
+ unsigned char sr2b, sr2c;
+ float num, denum, postscalar, divider;
+- int A, B, C, D, E, F, temp, i, j, index, vclkindex;
+- DisplayModePtr new = NULL, current = NULL, first = NULL, backup = NULL;
++ int A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex;
++ DisplayModePtr new = NULL, current = NULL, first = NULL;
++ BOOLEAN done = FALSE;
++#if 0
++ DisplayModePtr backup = NULL;
++#endif
+
+ pSiS->backupmodelist = NULL;
+-
++ pSiS->AddedPlasmaModes = FALSE;
++
+ /* Initialize our pointers */
+ if(pSiS->VGAEngine == SIS_300_VGA) {
+ #ifdef SIS300
+@@ -5194,15 +5398,20 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ if(pSiS->VGAEngine == SIS_300_VGA) index &= 0x3F;
+ #endif
+
+- if(((pSiS->SiS_Pr->SiS_RefIndex[i].XRes < 512) && (!pSiS->DSTN)) ||
+- ((pSiS->DSTN) &&
+- (pSiS->SiS_Pr->SiS_RefIndex[i].XRes < 512) &&
+- (pSiS->SiS_Pr->SiS_RefIndex[i].XRes != 320) &&
+- (pSiS->SiS_Pr->SiS_RefIndex[i].YRes != 480))) {
++ /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */
++ if((!pSiS->FSTN) &&
++ (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a)) {
+ i++;
+ continue;
+ }
+-
++ if((pSiS->FSTN) &&
++ (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
++ (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) &&
++ (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) {
++ i++;
++ continue;
++ }
++
+ if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
+ memset(new, 0, sizeof(DisplayModeRec));
+ if(!(new->name = xalloc(10))) {
+@@ -5216,13 +5425,13 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ }
+
+ current = new;
+-
++
+ sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes,
+ pSiS->SiS_Pr->SiS_RefIndex[i].YRes);
+
+ current->status = MODE_OK;
+
+- current->type = M_T_DEFAULT;
++ current->type = M_T_DEFAULT;
+
+ vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK;
+ if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F;
+@@ -5235,7 +5444,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0);
+ num = (sr2b & 0x7f) + 1.0;
+ denum = (sr2c & 0x1f) + 1.0;
+-
++
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "------------\n");
+ xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n",
+@@ -5303,10 +5512,29 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+
+ D = B - F - C;
+
+- current->HDisplay = (E * 8);
+- current->HSyncStart = (E * 8) + (F * 8);
+- current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
+- current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
++ if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
++ ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) ||
++ (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) {
++
++ /* Terrible hack, but correct CRTC data for
++ * these modes only produces a black screen...
++ * (HRE is 0, leading into a too large C and
++ * a negative D. The CRT controller does not
++ * seem to like correcting HRE to 50
++ */
++ current->HDisplay = 320;
++ current->HSyncStart = 328;
++ current->HSyncEnd = 376;
++ current->HTotal = 400;
++
++ } else {
++
++ current->HDisplay = (E * 8);
++ current->HSyncStart = (E * 8) + (F * 8);
++ current->HSyncEnd = (E * 8) + (F * 8) + (C * 8);
++ current->HTotal = (E * 8) + (F * 8) + (C * 8) + (D * 8);
++
++ }
+
+ #ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO,
+@@ -5430,7 +5658,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ current->VSyncStart <<= 1;
+ current->VSyncEnd <<= 1;
+ current->VTotal <<= 1;
+- current->VTotal |= 1;
++ current->VTotal |= 1;
+ }
+ if(current->Flags & V_DBLSCAN) {
+ current->Clock >>= 1;
+@@ -5440,6 +5668,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ current->VTotal >>= 1;
+ }
+
++#if 0
+ if((backup = xalloc(sizeof(DisplayModeRec)))) {
+ if(!pSiS->backupmodelist) pSiS->backupmodelist = backup;
+ else {
+@@ -5458,6 +5687,7 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ backup->Flags = current->Flags;
+ backup->Clock = current->Clock;
+ }
++#endif
+
+ #ifdef TWDEBUG
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+@@ -5470,6 +5700,187 @@ SiSBuildBuiltInModeList(ScrnInfoPtr pScr
+ i++;
+ }
+
++ /* Add non-standard LCD modes for panel's detailed timings */
++
++ if(!includelcdmodes) return first;
++
++ xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n",
++ pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product);
++
++ i = 0;
++ while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) {
++
++ if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) {
++
++ for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
++
++ if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) {
++
++ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "Identified %s panel, adding specific modes\n",
++ SiS_PlasmaTable[i].plasmaname);
++
++ for(k=0; k<SiS_PlasmaTable[i].modenum; k++) {
++
++ if(isfordvi) {
++ if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue;
++ } else {
++ if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue;
++ }
++
++ if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
++
++ memset(new, 0, sizeof(DisplayModeRec));
++ if(!(new->name = xalloc(10))) {
++ xfree(new);
++ return first;
++ }
++ if(!first) first = new;
++ if(current) {
++ current->next = new;
++ new->prev = current;
++ }
++
++ current = new;
++
++ pSiS->AddedPlasmaModes = TRUE;
++
++ l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f;
++
++ sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay,
++ SiS_PlasmaMode[l].VDisplay);
++
++ current->status = MODE_OK;
++
++ current->type = M_T_BUILTIN;
++
++ current->Clock = SiS_PlasmaMode[l].clock;
++ current->SynthClock = current->Clock;
++
++ current->HDisplay = SiS_PlasmaMode[l].HDisplay;
++ current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch;
++ current->HSyncEnd = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth;
++ current->HTotal = SiS_PlasmaMode[l].HTotal;
++
++ current->VDisplay = SiS_PlasmaMode[l].VDisplay;
++ current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch;
++ current->VSyncEnd = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth;
++ current->VTotal = SiS_PlasmaMode[l].VTotal;
++
++ current->CrtcHDisplay = current->HDisplay;
++ current->CrtcHBlankStart = current->HSyncStart;
++ current->CrtcHSyncStart = current->HSyncStart;
++ current->CrtcHSyncEnd = current->HSyncEnd;
++ current->CrtcHBlankEnd = current->HSyncEnd;
++ current->CrtcHTotal = current->HTotal;
++
++ current->CrtcVDisplay = current->VDisplay;
++ current->CrtcVBlankStart = current->VSyncStart;
++ current->CrtcVSyncStart = current->VSyncStart;
++ current->CrtcVSyncEnd = current->VSyncEnd;
++ current->CrtcVBlankEnd = current->VSyncEnd;
++ current->CrtcVTotal = current->VTotal;
++
++ if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP)
++ current->Flags |= V_PHSYNC;
++ else
++ current->Flags |= V_NHSYNC;
++
++ if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP)
++ current->Flags |= V_PVSYNC;
++ else
++ current->Flags |= V_NVSYNC;
++
++ if(current->HDisplay > pSiS->LCDwidth)
++ pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay;
++ if(current->VDisplay > pSiS->LCDheight)
++ pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay;
++
++ }
++ done = TRUE;
++ break;
++ }
++ }
++ }
++
++ i++;
++
++ }
++
++ if(pSiS->SiS_Pr->CP_HaveCustomData) {
++
++ for(i=0; i<7; i++) {
++
++ if(pSiS->SiS_Pr->CP_DataValid[i]) {
++
++ if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
++
++ memset(new, 0, sizeof(DisplayModeRec));
++ if(!(new->name = xalloc(10))) {
++ xfree(new);
++ return first;
++ }
++ if(!first) first = new;
++ if(current) {
++ current->next = new;
++ new->prev = current;
++ }
++
++ current = new;
++
++ sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i],
++ pSiS->SiS_Pr->CP_VDisplay[i]);
++
++ current->status = MODE_OK;
++
++ current->type = M_T_BUILTIN;
++
++ current->Clock = pSiS->SiS_Pr->CP_Clock[i];
++ current->SynthClock = current->Clock;
++
++ current->HDisplay = pSiS->SiS_Pr->CP_HDisplay[i];
++ current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i];
++ current->HSyncEnd = pSiS->SiS_Pr->CP_HSyncEnd[i];
++ current->HTotal = pSiS->SiS_Pr->CP_HTotal[i];
++
++ current->VDisplay = pSiS->SiS_Pr->CP_VDisplay[i];
++ current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i];
++ current->VSyncEnd = pSiS->SiS_Pr->CP_VSyncEnd[i];
++ current->VTotal = pSiS->SiS_Pr->CP_VTotal[i];
++
++ current->CrtcHDisplay = current->HDisplay;
++ current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i];
++ current->CrtcHSyncStart = current->HSyncStart;
++ current->CrtcHSyncEnd = current->HSyncEnd;
++ current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i];
++ current->CrtcHTotal = current->HTotal;
++
++ current->CrtcVDisplay = current->VDisplay;
++ current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i];
++ current->CrtcVSyncStart = current->VSyncStart;
++ current->CrtcVSyncEnd = current->VSyncEnd;
++ current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i];
++ current->CrtcVTotal = current->VTotal;
++
++ if(pSiS->SiS_Pr->CP_SyncValid[i]) {
++ if(pSiS->SiS_Pr->CP_HSync_P[i])
++ current->Flags |= V_PHSYNC;
++ else
++ current->Flags |= V_NHSYNC;
++
++ if(pSiS->SiS_Pr->CP_VSync_P[i])
++ current->Flags |= V_PVSYNC;
++ else
++ current->Flags |= V_NVSYNC;
++ } else {
++ /* No sync data? Use positive sync... */
++ current->Flags |= V_PHSYNC;
++ current->Flags |= V_PVSYNC;
++ }
++ }
++ }
++ }
++
+ return first;
+
+ }
+@@ -5486,25 +5897,25 @@ sisfb_mode_rate_to_dclock(SiS_Private *S
+ UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+ ULONG temp = 0;
+ int Clock;
+-
++
+ if(HwDeviceExtension->jChipType < SIS_315H) {
+ #ifdef SIS300
+ InitTo300Pointer(SiS_Pr, HwDeviceExtension);
+ #else
+- return 65;
++ return 65 * 1000 * 1000;
+ #endif
+ } else {
+ #ifdef SIS315H
+ InitTo310Pointer(SiS_Pr, HwDeviceExtension);
+ #else
+- return 65;
++ return 65 * 1000 * 1000;
+ #endif
+ }
+-
++
+ temp = SiS_SearchModeID(SiS_Pr, ROMAddr, &ModeNo, &ModeIdIndex);
+ if(!temp) {
+ printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+- return 65;
++ return 65 * 1000 * 1000;
+ }
+
+ RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+@@ -5518,6 +5929,56 @@ sisfb_mode_rate_to_dclock(SiS_Private *S
+ return(Clock);
+ }
+
++BOOLEAN
++sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
++ unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex)
++{
++ USHORT ModeNo = modeno;
++ USHORT ModeIdIndex = 0, CRT1Index = 0;
++ USHORT RefreshRateTableIndex = 0;
++ UCHAR *ROMAddr = HwDeviceExtension->pjVirtualRomBase;
++ ULONG temp = 0;
++ unsigned char sr_data, cr_data, cr_data2;
++
++ if(HwDeviceExtension->jChipType < SIS_315H) {
++#ifdef SIS300
++ InitTo300Pointer(SiS_Pr, HwDeviceExtension);
++#else
++ return FALSE;
++#endif
++ } else {
++#ifdef SIS315H
++ InitTo310Pointer(SiS_Pr, HwDeviceExtension);
++#else
++ return FALSE;
++#endif
++ }
++
++ temp = SiS_SearchModeID(SiS_Pr, ROMAddr, &ModeNo, &ModeIdIndex);
++ if(!temp) return FALSE;
++
++ RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
++ RefreshRateTableIndex += (rateindex - 1);
++ CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
++
++ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
++ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
++ *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
++
++ sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
++ cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
++ cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
++ *vtotal = ((cr_data & 0xFF) |
++ ((unsigned short)(cr_data2 & 0x01) << 8) |
++ ((unsigned short)(cr_data2 & 0x20) << 4) |
++ ((unsigned short)(sr_data & 0x01) << 10)) + 2;
++
++ if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode)
++ *vtotal *= 2;
++
++ return TRUE;
++}
++
+ int
+ sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex,
+@@ -5606,17 +6067,32 @@ sisfb_mode_rate_to_ddata(SiS_Private *Si
+ C = (temp > 0) ? temp : (temp + 64);
+
+ D = B - F - C;
+-
+- *left_margin = D * 8;
+- *right_margin = F * 8;
+- *hsync_len = C * 8;
++
++ if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) &&
++ ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) ||
++ (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) {
++
++ /* Terrible hack, but the correct CRTC data for
++ * these modes only produces a black screen...
++ */
++ *left_margin = (400 - 376);
++ *right_margin = (328 - 320);
++ *hsync_len = (376 - 328);
++
++ } else {
++
++ *left_margin = D * 8;
++ *right_margin = F * 8;
++ *hsync_len = C * 8;
++
++ }
+
+ sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13];
+
+ cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6];
+-
++
+ cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7];
+-
++
+ /* Vertical total */
+ VT = (cr_data & 0xFF) |
+ ((unsigned short) (cr_data2 & 0x01) << 8) |
+@@ -5699,19 +6175,19 @@ sisfb_mode_rate_to_ddata(SiS_Private *Si
+ j++;
+ }
+ }
+-
+-#if 0 /* That's bullshit, only the resolution needs to be shifted */
++
+ if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
++#if 0 /* Do this? */
+ *upper_margin <<= 1;
+ *lower_margin <<= 1;
+ *vsync_len <<= 1;
++#endif
+ } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ *upper_margin >>= 1;
+ *lower_margin >>= 1;
+ *vsync_len >>= 1;
+- }
+-#endif
+-
++ }
++
+ return 1;
+ }
+
+--- linux-2.6.0-test6/drivers/video/sis/initdef.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/drivers/video/sis/initdef.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,5 +1,37 @@
+ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/initdef.h,v 1.4 2000/12/02 01:16:17 dawes Exp $ */
+-
++/*
++ * Global definitions for init.c and init301.c
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
+
+ #ifndef _INITDEF_
+ #define _INITDEF_
+@@ -22,12 +54,19 @@
+ #define VB_SIS301B302B (VB_SIS301B|VB_SIS302B)
+ #define VB_SIS301LV302LV (VB_SIS301LV|VB_SIS302LV)
+
+-#define IS_SIS650740 ((HwDeviceExtension->jChipType >= SIS_650) && (HwDeviceExtension->jChipType < SIS_330))
+-
+ #define IS_SIS650 (HwDeviceExtension->jChipType == SIS_650)
+ #define IS_SIS740 (HwDeviceExtension->jChipType == SIS_740)
+ #define IS_SIS330 (HwDeviceExtension->jChipType == SIS_330)
+ #define IS_SIS550 (HwDeviceExtension->jChipType == SIS_550)
++#define IS_SIS651 (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
++#define IS_SISM650 (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
++#define IS_SIS65x (IS_SIS651 || IS_SISM650)
++#define IS_SIS660 (HwDeviceExtension->jChipType == SIS_660)
++#define IS_SIS760 (HwDeviceExtension->jChipType == SIS_760)
++#define IS_SIS650660 (IS_SIS650 || IS_SIS660)
++#define IS_SIS650740 ((HwDeviceExtension->jChipType >= SIS_650) && (HwDeviceExtension->jChipType < SIS_330))
++#define IS_SIS650740660 (IS_SIS650 || IS_SIS660 || IS_SIS740 || IS_SIS760)
++#define IS_SIS550650740660 (IS_SIS550 || IS_SIS650 || IS_SIS660 || IS_SIS740 || IS_SIS760)
+
+ #define CRT1Len 17
+ #define LVDSCRT1Len 15
+@@ -63,7 +102,7 @@
+ #define SupportTV 0x0008
+ #define SupportHiVisionTV 0x0010
+ #define SupportLCD 0x0020
+-#define SupportRAMDAC2 0x0040
++#define SupportRAMDAC2 0x0040
+ #define NoSupportTV 0x0070
+ #define NoSupportHiVisionTV 0x0060
+ #define NoSupportLCD 0x0058
+@@ -105,6 +144,24 @@
+ #define HotKeySwitch 0x8000 /* TW: ? */
+ #define SetCRT2ToLCDA 0x8000
+
++/* SetFlag */
++#define ProgrammingCRT2 0x01
++#define TVSimuMode 0x02
++#define RPLLDIV2XO 0x04
++#define LCDVESATiming 0x08
++#define EnableLVDSDDA 0x10
++#define SetDispDevSwitchFlag 0x20
++#define CheckWinDos 0x40
++#define SetDOSMode 0x80
++
++/* SysFlags */
++#define SF_Is651 0x0001
++#define SF_IsM650 0x0002
++#define SF_Is652 0x0004
++#define SF_IsM652 0x0008
++#define SF_IsM653 0x0010
++#define SF_Is660 0x8000
++
+ #define PanelRGB18Bit 0x0100
+ #define PanelRGB24Bit 0x0000
+
+@@ -112,7 +169,7 @@
+ #define TVOverScanShift 4
+ #define ClearBufferFlag 0x20
+
+-/* CR32 (Newer 630, and 310/325 series)
++/* CR32 (Newer 630, and 315 series)
+
+ [0] VB connected with CVBS
+ [1] VB connected with SVHS
+@@ -134,7 +191,7 @@
+ 011 LVDS + Tumpion Zurac
+ 100 LVDS + Chrontel 7005
+ 110 Chrontel 7005
+- 310/325 series
++ 315 series
+ 001 SiS30x (never seen)
+ 010 LVDS
+ 011 LVDS + Chrontel 7019
+@@ -163,14 +220,15 @@
+ #define LCDSyncBit 0x00e0
+ #define LCDSyncShift 6
+
+-/* CR38 (310/325 series) */
++/* CR38 (315 series) */
+ #define EnableDualEdge 0x01
+ #define SetToLCDA 0x02 /* LCD channel A (302B/LV and 650+LVDS only) */
+ #define EnableSiSHiVision 0x04 /* HiVision (HDTV) on SiS bridge */
+ #define EnableLVDSScart 0x04 /* Scart on Ch7019 (unofficial definition - TW) */
+ #define EnableLVDSHiVision 0x08 /* YPbPr color format (480i HDTV); only on 650/Ch7019 systems */
+-#define SiSHiVision1 0x10 /* See SetHiVision() */
+-#define SiSHiVision2 0x20
++#define EnableHiVision750 0x08 /* Enable 750P HiVision mode (30xLV only) */
++#define EnableHiVision525 0x10 /* Enable 525P HiVision mode (30xLV only) */
++#define SiSHiVision2 0x20 /* ? - | --- mask 0x38 combinations have different meaning! */
+ #define EnablePALM 0x40 /* 1 = Set PALM */
+ #define EnablePALN 0x80 /* 1 = Set PALN */
+
+@@ -184,7 +242,7 @@
+ #define Enable302LV_DualLink 0x04 /* 30xNEW (302LV) only; set by mode switching function */
+
+
+-/* CR79 (310/325 series only)
++/* CR79 (315 series only)
+ [3-0] Notify driver
+ 0001 Mode Switch event (set by BIOS)
+ 0010 Epansion On/Off event
+@@ -202,16 +260,6 @@
+ [7] TV UnderScan/OverScan (set by BIOS)
+ */
+
+-/* SetFlag */
+-#define ProgrammingCRT2 0x01
+-#define TVSimuMode 0x02
+-#define RPLLDIV2XO 0x04
+-#define LCDVESATiming 0x08
+-#define EnableLVDSDDA 0x10
+-#define SetDispDevSwitchFlag 0x20
+-#define CheckWinDos 0x40
+-#define SetDOSMode 0x80
+-
+ /* LCDResInfo */
+ #define Panel300_800x600 0x01 /* CR36 */
+ #define Panel300_1024x768 0x02
+@@ -220,7 +268,10 @@
+ #define Panel300_640x480 0x05
+ #define Panel300_1024x600 0x06
+ #define Panel300_1152x768 0x07
+-#define Panel300_320x480 0x08 /* fstn - TW: This is fake, can be any */
++#define Panel300_1280x768 0x0a
++#define Panel300_320x480 0x0e /* fstn - TW: This is fake, can be any */
++#define Panel300_Custom 0x0f
++#define Panel300_Barco1366 0x10
+
+ #define Panel310_800x600 0x01
+ #define Panel310_1024x768 0x02
+@@ -231,9 +282,12 @@
+ #define Panel310_1280x960 0x07
+ #define Panel310_1152x768 0x08 /* LVDS only */
+ #define Panel310_1400x1050 0x09
+-#define Panel310_1280x768 0x0a /* LVDS only */
++#define Panel310_1280x768 0x0a
+ #define Panel310_1600x1200 0x0b
+-#define Panel310_320x480 0x0c /* fstn - TW: This is fake, can be any */
++#define Panel310_640x480_2 0x0c
++#define Panel310_640x480_3 0x0d
++#define Panel310_320x480 0x0e /* fstn - TW: This is fake, can be any */
++#define Panel310_Custom 0x0f
+
+ #define Panel_800x600 0x01 /* Unified values */
+ #define Panel_1024x768 0x02
+@@ -246,7 +300,43 @@
+ #define Panel_1400x1050 0x09
+ #define Panel_1280x768 0x0a /* LVDS only */
+ #define Panel_1600x1200 0x0b
+-#define Panel_320x480 0x0c /* fstn - TW: This is fake, can be any */
++#define Panel_640x480_2 0x0c
++#define Panel_640x480_3 0x0d
++#define Panel_320x480 0x0e /* fstn - TW: This is fake, can be any */
++#define Panel_Custom 0x0f
++#define Panel_Barco1366 0x10
++#define Panel_848x480 0x11
++
++/* Index in ModeResInfo table */
++#define SIS_RI_320x200 0
++#define SIS_RI_320x240 1
++#define SIS_RI_320x400 2
++#define SIS_RI_400x300 3
++#define SIS_RI_512x384 4
++#define SIS_RI_640x400 5
++#define SIS_RI_640x480 6
++#define SIS_RI_800x600 7
++#define SIS_RI_1024x768 8
++#define SIS_RI_1280x1024 9
++#define SIS_RI_1600x1200 10
++#define SIS_RI_1920x1440 11
++#define SIS_RI_2048x1536 12
++#define SIS_RI_720x480 13
++#define SIS_RI_720x576 14
++#define SIS_RI_1280x960 15
++#define SIS_RI_800x480 16
++#define SIS_RI_1024x576 17
++#define SIS_RI_1280x720 18
++#define SIS_RI_856x480 19
++#define SIS_RI_1280x768 20
++#define SIS_RI_1400x1050 21
++#define SIS_RI_1152x864 22
++#define SIS_RI_848x480 23
++#define SIS_RI_1360x768 24
++#define SIS_RI_1024x600 25
++#define SIS_RI_1152x768 26
++#define SIS_RI_768x576 27
++#define SIS_RI_1360x1024 28
+
+ #define ExtChipType 0x0e
+ #define ExtChip301 0x02
+@@ -278,15 +368,34 @@
+ #define VCLKStartFreq 25
+ #define SoftDramType 0x80
+
+-#define VCLK40 0x04 /* Index in VCLKData array */
+-#define VCLK65 0x09 /* Index in VCLKData array */
+-#define VCLK108_2 0x14 /* Index in VCLKData array */
+-#define TVVCLKDIV2 0x21 /* Indices in (VB)VCLKData arrays */
+-#define TVVCLK 0x22
+-#define HiTVVCLKDIV2 0x23
+-#define HiTVVCLK 0x24
+-#define HiTVSimuVCLK 0x25
+-#define HiTVTextVCLK 0x26
++/* Indices in (VB)VCLKData tables */
++
++#define VCLK28 0x00 /* Index in VCLKData table (300 and 315) */
++#define VCLK40 0x04 /* Index in VCLKData table (300 and 315) */
++#define VCLK65_300 0x09 /* Index in VCLKData table (300) */
++#define VCLK108_2_300 0x14 /* Index in VCLKData table (300) */
++#define VCLK81_300 0x3f /* Index in VCLKData table (300) */
++#define VCLK108_3_300 0x42 /* Index in VCLKData table (300) */
++#define VCLK100_300 0x43 /* Index in VCLKData table (300) */
++#define VCLK34_300 0x3d /* Index in VCLKData table (300) */
++#define VCLK65_315 0x0b /* Index in (VB)VCLKData table (315) */
++#define VCLK108_2_315 0x19 /* Index in (VB)VCLKData table (315) */
++#define VCLK81_315 0x5b /* Index in (VB)VCLKData table (315) */
++#define VCLK162_315 0x21 /* Index in (VB)VCLKData table (315) */
++#define VCLK108_3_315 0x45 /* Index in VBVCLKData table (315) */
++#define VCLK100_315 0x46 /* Index in VBVCLKData table (315) */
++#define VCLK34_315 0x55 /* Index in VBVCLKData table (315) */
++
++#define TVCLKBASE_300 0x21 /* Indices on TV clocks in VCLKData table (300) */
++#define TVCLKBASE_315 0x3a /* Indices on TV clocks in (VB)VCLKData table (315) */
++#define TVVCLKDIV2 0x00 /* Index relative to TVCLKBASE */
++#define TVVCLK 0x01 /* Index relative to TVCLKBASE */
++#define HiTVVCLKDIV2 0x02 /* Index relative to TVCLKBASE */
++#define HiTVVCLK 0x03 /* Index relative to TVCLKBASE */
++#define HiTVSimuVCLK 0x04 /* Index relative to TVCLKBASE */
++#define HiTVTextVCLK 0x05 /* Index relative to TVCLKBASE */
++
++/* ------------------------------ */
+
+ #define LoadDACFlag 0x1000
+ #define AfterLockCRT2 0x4000
+@@ -306,6 +415,8 @@
+ #define HotPlugFunction 0x08
+ #define StStructSize 0x06
+
++#define SIS_VIDEO_CAPTURE 0x00 - 0x30
++#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
+ #define SIS_CRT2_PORT_04 0x04 - 0x30
+ #define SIS_CRT2_PORT_10 0x10 - 0x30
+ #define SIS_CRT2_PORT_12 0x12 - 0x30
+@@ -393,7 +504,7 @@
+
+ /*
+ =============================================================
+- for 310/325 series
++ for 315 series
+ =============================================================
+ */
+ #define SoftDRAMType 0x80
+--- linux-2.6.0-test6/drivers/video/sis/init.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/drivers/video/sis/init.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,19 +1,47 @@
++/* $XFree86$ */
++/*
++ * Data and prototypes for init.c
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
++
+ #ifndef _INIT_
+ #define _INIT_
+
+ #include "osdef.h"
++
+ #include "initdef.h"
+ #include "vgatypes.h"
+ #include "vstruct.h"
+
+-#ifdef TC
+-#include <stdio.h>
+-#include <string.h>
+-#include <conio.h>
+-#include <dos.h>
+-#include <stdlib.h>
+-#endif
+-
+ #ifdef LINUX_XF86
+ #include "xf86.h"
+ #include "xf86Pci.h"
+@@ -24,6 +52,9 @@
+ #endif
+
+ #ifdef LINUX_KERNEL
++#ifdef SIS_CP
++#undef SIS_CP
++#endif
+ #include <linux/config.h>
+ #include <linux/version.h>
+ #include <linux/types.h>
+@@ -36,19 +67,6 @@
+ #endif
+ #endif
+
+-#ifdef WIN2000
+-#include <stdio.h>
+-#include <string.h>
+-#include <miniport.h>
+-#include "dderror.h"
+-#include "devioctl.h"
+-#include "miniport.h"
+-#include "ntddvdeo.h"
+-#include "video.h"
+-#include "sisv.h"
+-#include "tools.h"
+-#endif
+-
+ const USHORT SiS_DRAMType[17][5]={
+ {0x0C,0x0A,0x02,0x40,0x39},
+ {0x0D,0x0A,0x01,0x40,0x48},
+@@ -144,6 +162,2227 @@ const USHORT SiS_VGA_DAC[] =
+ 0x0B,0x0C,0x0D,0x0F,0x10
+ };
+
++static const SiS_StResInfoStruct SiS_StResInfo[]=
++{
++ { 640,400},
++ { 640,350},
++ { 720,400},
++ { 720,350},
++ { 640,480}
++};
++
++static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
++{
++ { 320, 200, 8, 8}, /* 0x00 */
++ { 320, 240, 8, 8}, /* 0x01 */
++ { 320, 400, 8, 8}, /* 0x02 */
++ { 400, 300, 8, 8}, /* 0x03 */
++ { 512, 384, 8, 8}, /* 0x04 */
++ { 640, 400, 8,16}, /* 0x05 */
++ { 640, 480, 8,16}, /* 0x06 */
++ { 800, 600, 8,16}, /* 0x07 */
++ { 1024, 768, 8,16}, /* 0x08 */
++ { 1280,1024, 8,16}, /* 0x09 */
++ { 1600,1200, 8,16}, /* 0x0a */
++ { 1920,1440, 8,16}, /* 0x0b */
++ { 2048,1536, 8,16}, /* 0x0c */
++ { 720, 480, 8,16}, /* 0x0d */
++ { 720, 576, 8,16}, /* 0x0e */
++ { 1280, 960, 8,16}, /* 0x0f */
++ { 800, 480, 8,16}, /* 0x10 */
++ { 1024, 576, 8,16}, /* 0x11 */
++ { 1280, 720, 8,16}, /* 0x12 */
++ { 856, 480, 8,16}, /* 0x13 */
++ { 1280, 768, 8,16}, /* 0x14 */
++ { 1400,1050, 8,16}, /* 0x15 */
++ { 1152, 864, 8,16}, /* 0x16 */
++ { 848, 480, 8,16}, /* 0x17 */
++ { 1360, 768, 8,16}, /* 0x18 */
++ { 1024, 600, 8,16}, /* 0x19 */
++ { 1152, 768, 8,16}, /* 0x1a */
++ { 768, 576, 8,16}, /* 0x1b */
++ { 1360,1024, 8,16} /* 0x1c */
++};
++
++static SiS_StandTableStruct SiS_StandTable[]=
++{
++/* 0x00: MD_0_200 */
++ {
++ 0x28,0x18,0x08,0x0800,
++ {0x09,0x03,0x00,0x02},
++ 0x63,
++ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x01: MD_1_200 */
++ {
++ 0x28,0x18,0x08,0x0800,
++ {0x09,0x03,0x00,0x02},
++ 0x63,
++ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x02: MD_2_200 */
++ {
++ 0x50,0x18,0x08,0x1000,
++ {0x01,0x03,0x00,0x02},
++ 0x63,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x03: MD_3_200 - mode 0x03 - 0 */
++ {
++ 0x50,0x18,0x08,0x1000,
++ {0x01,0x03,0x00,0x02},
++ 0x63,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0xc7,0x06,0x07,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x04: MD_4 */
++ {
++ 0x28,0x18,0x08,0x4000,
++ {0x09,0x03,0x00,0x02},
++ 0x63,
++ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x2c is 2b for 300 */
++ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
++ 0xff},
++ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x01,0x00,0x03,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
++ 0xff}
++ },
++/* 0x05: MD_5 */
++ {
++ 0x28,0x18,0x08,0x4000,
++ {0x09,0x03,0x00,0x02},
++ 0x63,
++ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 0x2c is 2b for 300 */
++ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,
++ 0xff},
++ {0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x01,0x00,0x03,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x00,
++ 0xff}
++ },
++/* 0x06: MD_6 */
++ {
++ 0x50,0x18,0x08,0x4000,
++ {0x01,0x01,0x00,0x06},
++ 0x63,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 for 300 */
++ 0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,
++ 0xff},
++ {0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
++ 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
++ 0x01,0x00,0x01,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,
++ 0xff}
++ },
++/* 0x07: MD_7 */
++ {
++ 0x50,0x18,0x0e,0x1000,
++ {0x00,0x03,0x00,0x03},
++ 0xa6,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
++ 0x83,0x85,0x5d,0x28,0x0d,0x63,0xba,0xa3,
++ 0xff},
++ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
++ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
++ 0x0e,0x00,0x0f,0x08},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
++ 0xff}
++ },
++/* 0x08: MDA_DAC */
++ {
++ 0x00,0x00,0x00,0x0000,
++ {0x00,0x00,0x00,0x15},
++ 0x15,
++ {0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
++ 0x15,0x15,0x15,0x15,0x15,0x15,0x3f,0x3f,
++ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0x00,
++ 0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x15,
++ 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
++ 0x15,0x15,0x15,0x15},
++ {0x15,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
++ 0x3f}
++ },
++/* 0x09: CGA_DAC */
++ {
++ 0x00,0x10,0x04,0x0114,
++ {0x11,0x09,0x15,0x00},
++ 0x10,
++ {0x04,0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,
++ 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x2a,0x3a,
++ 0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x10,
++ 0x04},
++ {0x14,0x01,0x11,0x09,0x15,0x00,0x10,0x04,
++ 0x14,0x01,0x11,0x09,0x15,0x2a,0x3a,0x2e,
++ 0x3e,0x2b,0x3b,0x2f},
++ {0x3f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
++ 0x3f}
++ },
++/* 0x0a: EGA_DAC */
++ {
++ 0x00,0x10,0x04,0x0114,
++ {0x11,0x05,0x15,0x20},
++ 0x30,
++ {0x24,0x34,0x21,0x31,0x25,0x35,0x08,0x18,
++ 0x0c,0x1c,0x09,0x19,0x0d,0x1d,0x28,0x38,
++ 0x2c,0x3c,0x29,0x39,0x2d,0x3d,0x02,0x12,
++ 0x06},
++ {0x16,0x03,0x13,0x07,0x17,0x22,0x32,0x26,
++ 0x36,0x23,0x33,0x27,0x37,0x0a,0x1a,0x0e,
++ 0x1e,0x0b,0x1b,0x0f},
++ {0x1f,0x2a,0x3a,0x2e,0x3e,0x2b,0x3b,0x2f,
++ 0x3f}
++ },
++/* 0x0b: VGA_DAC */
++ {
++ 0x00,0x10,0x04,0x0114,
++ {0x11,0x09,0x15,0x2a},
++ 0x3a,
++ {0x2e,0x3e,0x2b,0x3b,0x2f,0x3f,0x00,0x05,
++ 0x08,0x0b,0x0e,0x11,0x14,0x18,0x1c,0x20,
++ 0x24,0x28,0x2d,0x32,0x38,0x3f,0x00,0x10,
++ 0x1f},
++ {0x2f,0x3f,0x1f,0x27,0x2f,0x37,0x3f,0x2d,
++ 0x31,0x36,0x3a,0x3f,0x00,0x07,0x0e,0x15,
++ 0x1c,0x0e,0x11,0x15},
++ {0x18,0x1c,0x14,0x16,0x18,0x1a,0x1c,0x00,
++ 0x04}
++ },
++/* 0x0c */
++ {
++ 0x08,0x0c,0x10,0x0a08,
++ {0x0c,0x0e,0x10,0x0b},
++ 0x0c,
++ {0x0d,0x0f,0x10,0x10,0x01,0x08,0x00,0x00,
++ 0x00,0x00,0x01,0x00,0x02,0x02,0x01,0x00,
++ 0x04,0x04,0x01,0x00,0x05,0x02,0x05,0x00,
++ 0x06},
++ {0x01,0x06,0x05,0x06,0x00,0x08,0x01,0x08,
++ 0x00,0x07,0x02,0x07,0x06,0x07,0x00,0x00,
++ 0x00,0x00,0x00,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x00}
++ },
++/* 0x0d: MD_D */
++ {
++ 0x28,0x18,0x08,0x2000,
++ {0x09,0x0f,0x00,0x06},
++ 0x63,
++ {0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f, /* 2c is 2b for 300 */
++ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x01,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++ 0xff}
++ },
++/* 0x0e: MD_E */
++ {
++ 0x50,0x18,0x08,0x4000,
++ {0x01,0x0f,0x00,0x06},
++ 0x63,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 for 300 */
++ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
++ 0x01,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++ 0xff}
++ },
++/* 0x0f: ExtVGATable - modes > 0x13 */
++ {
++ 0x00,0x00,0x00,0x0000,
++ {0x01,0x0f,0x00,0x0e},
++ 0x23,
++ {0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
++ 0x01,0x00,0x00,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
++ 0xff}
++ },
++/* 0x10: ROM_SAVEPTR - totally different for 300 */
++ {
++ 0x9f,0x3b,0x00,0x00c0,
++ {0x00,0x00,0x00,0x00},
++ 0x00,
++ {0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x3f,
++ 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x00,0x00,0x1a,0x00,0xac,0x3e,0x00,0xc0,
++ 0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x00,0x00,0x00,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x00}
++ },
++/* 0x11: MD_F */
++ {
++ 0x50,0x18,0x0e,0x8000,
++ {0x01,0x0f,0x00,0x06},
++ 0xa2,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */
++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, /* 82,84 is 83,85 on 300 */
++ 0xff},
++ {0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,
++ 0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,
++ 0x0b,0x00,0x05,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,
++ 0xff}
++ },
++/* 0x12: MD_10 */
++ {
++ 0x50,0x18,0x0e,0x8000,
++ {0x01,0x0f,0x00,0x06},
++ 0xa3,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */
++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x82,0x84,0x5d,0x28,0x0f,0x63,0xba,0xe3, /* 82,84 is 83,85 on 300 */
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x01,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++ 0xff}
++ },
++/* 0x13: MD_0_350 */
++ {
++ 0x28,0x18,0x0e,0x0800,
++ {0x09,0x03,0x00,0x02},
++ 0xa3,
++ {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, /* b1 is a0 on 300 */
++ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
++ 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x14: MD_1_350 */
++ {
++ 0x28,0x18,0x0e,0x0800,
++ {0x09,0x03,0x00,0x02},
++ 0xa3,
++ {0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
++ 0x83,0x85,0x5d,0x14,0x1f,0x63,0xba,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x15: MD_2_350 */
++ {
++ 0x50,0x18,0x0e,0x1000,
++ {0x01,0x03,0x00,0x02},
++ 0xa3,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
++ 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x16: MD_3_350 - mode 0x03 - 1 */
++ {
++ 0x50,0x18,0x0e,0x1000,
++ {0x01,0x03,0x00,0x02},
++ 0xa3,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0x4d,0x0b,0x0c,0x00,0x00,0x00,0x00,
++ 0x83,0x85,0x5d,0x28,0x1f,0x63,0xba,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x08,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x17: MD_0_1_400 */
++ {
++ 0x28,0x18,0x10,0x0800,
++ {0x08,0x03,0x00,0x02},
++ 0x67,
++ {0x2d,0x27,0x28,0x90,0x2b,0xb1,0xbf,0x1f, /* b1 is a0 on 300 */
++ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x0c,0x00,0x0f,0x08},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x18: MD_2_3_400 - mode 0x03 - 2 */
++ {
++ 0x50,0x18,0x10,0x1000,
++ {0x00,0x03,0x00,0x02},
++ 0x67,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x0c,0x00,0x0f,0x08},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,
++ 0xff}
++ },
++/* 0x19: MD_7_400 */
++ {
++ 0x50,0x18,0x10,0x1000,
++ {0x00,0x03,0x00,0x02},
++ 0x66,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
++ 0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
++ 0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
++ 0x0e,0x00,0x0f,0x08},
++ {0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x00,
++ 0xff}
++ },
++/* 0x1a: MD_11 */
++ {
++ 0x50,0x1d,0x10,0xa000,
++ {0x01,0x0f,0x00,0x06},
++ 0xe3,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 55,81 is 54,80 on 300 */
++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xc3, /* e9,8b is ea,8c on 300 */
++ 0xff},
++ {0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
++ 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,
++ 0x01,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,
++ 0xff}
++ },
++/* 0x1b: ExtEGATable - Modes <= 0x02 */
++ {
++ 0x50,0x1d,0x10,0xa000,
++ {0x01,0x0f,0x00,0x06},
++ 0xe3,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e, /* 55,81 is 54,80 on 300 */
++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0xe9,0x8b,0xdf,0x28,0x00,0xe7,0x04,0xe3, /* e9,8b is ea,8c on 300 */
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
++ 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
++ 0x01,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,
++ 0xff}
++ },
++/* 0x1c: MD_13 */
++ {
++ 0x28,0x18,0x08,0x2000,
++ {0x01,0x0f,0x00,0x0e},
++ 0x63,
++ {0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f, /* 55,81 is 54,80 on 300 */
++ 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
++ 0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,
++ 0xff},
++ {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
++ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
++ 0x41,0x00,0x0f,0x00},
++ {0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
++ 0xff}
++ }
++};
++
++static const UCHAR SiS_NTSCTiming[] = {
++ 0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
++ 0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
++ 0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
++ 0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
++ 0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
++ 0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50,
++ 0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
++};
++
++static const UCHAR SiS_PALTiming[] = {
++ 0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
++ 0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
++ 0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
++ 0x70,0x50,0x00,0x9b,0x00,0xd9,0x5d,0x17,
++ 0x7d,0x05,0x45,0x00,0x00,0xe8,0x00,0x02,
++ 0x0d,0x00,0x68,0xb0,0x0b,0x92,0x8f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x63,
++ 0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
++};
++
++static const UCHAR SiS_HiTVExtTiming[] = {
++ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
++ 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
++ 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
++ 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
++ 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
++ 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
++ 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
++};
++
++static const UCHAR SiS_HiTVSt1Timing[] = {
++ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
++ 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
++ 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
++ 0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
++ 0x11,0x15,0x11,0xcf,0x10,0x11,0xcf,0x10,
++ 0x35,0x35,0x3b,0x69,0x1d,0x92,0x0f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x86,
++ 0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
++};
++
++static const UCHAR SiS_HiTVSt2Timing[] = {
++ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
++ 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
++ 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
++ 0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
++ 0x2a,0xde,0x2a,0x44,0x40,0x2a,0x44,0x40,
++ 0x8e,0x8e,0x82,0x07,0x0b,0x92,0x0f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x3d,
++ 0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
++};
++
++static const UCHAR SiS_HiTVTextTiming[] = {
++ 0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
++ 0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
++ 0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
++ 0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
++ 0x14,0x78,0x14,0x08,0x20,0x14,0x08,0x20,
++ 0xc8,0xc8,0x3b,0xd2,0x26,0x92,0x0f,0x40,
++ 0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
++ 0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
++};
++
++static const UCHAR SiS_HiTVGroup3Data[] = {
++ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
++ 0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
++ 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
++ 0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
++ 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
++ 0x4f,0x7f,0x03,0xa8,0x7d,0x20,0x1a,0xa9,
++ 0x14,0x05,0x03,0x7e,0x64,0x31,0x14,0x75,
++ 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
++};
++
++static const UCHAR SiS_HiTVGroup3Simu[] = {
++ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
++ 0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
++ 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
++ 0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
++ 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
++ 0x67,0x36,0x01,0x47,0x0e,0x10,0xbe,0xb4,
++ 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
++ 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
++};
++
++static const UCHAR SiS_HiTVGroup3Text[] = {
++ 0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
++ 0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
++ 0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
++ 0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
++ 0x56,0x36,0x4f,0x6e,0x3f,0x80,0x00,0x80,
++ 0x93,0x3c,0x01,0x50,0x2f,0x10,0xf4,0xca,
++ 0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
++ 0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
++};
++
++static const UCHAR SiS_NTSCPhase[] = {0x21,0xed,0xba,0x08}; /* Was {0x21,0xed,0x8a,0x08}; */
++static const UCHAR SiS_PALPhase[] = {0x2a,0x05,0xe3,0x00}; /* Was {0x2a,0x05,0xd3,0x00}; */
++static const UCHAR SiS_PALMPhase[] = {0x21,0xE4,0x2E,0x9B};
++static const UCHAR SiS_PALNPhase[] = {0x21,0xF4,0x3E,0xBA};
++static const UCHAR SiS_NTSCPhase2[] = {0x21,0xF0,0x7B,0xD6};
++static const UCHAR SiS_PALPhase2[] = {0x2a,0x09,0x86,0xe9};
++static const UCHAR SiS_PALMPhase2[] = {0x21,0xE6,0xEF,0xA4};
++static const UCHAR SiS_PALNPhase2[] = {0x21,0xF6,0x94,0x46};
++static const UCHAR SiS_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a};
++
++static const SiS_TVDataStruct SiS_StPALData[]=
++{
++ { 1, 1, 864, 525,1270, 400, 100, 0, 760,0xf4,0xff,0x1c,0x22},
++ { 1, 1, 864, 525,1270, 350, 100, 0, 760,0xf4,0xff,0x1c,0x22},
++ { 1, 1, 864, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
++ { 1, 1, 864, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
++ { 1, 1, 864, 525,1270, 480, 50, 0, 760,0xf4,0xff,0x1c,0x22},
++ { 1, 1, 864, 525,1270, 600, 50, 0, 0,0xf4,0xff,0x1c,0x22}
++};
++
++static const SiS_TVDataStruct SiS_ExtPALData[] =
++{
++ { 27, 10, 848, 448,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22}, /* 640x400, 320x200 */
++ { 108, 35, 848, 398,1270, 530, 50, 0, 50,0xf4,0xff,0x1c,0x22},
++ { 12, 5, 954, 448,1270, 530, 50, 0, 50,0xf1,0x04,0x1f,0x18},
++ { 9, 4, 960, 463,1644, 438, 50, 0, 50,0xf4,0x0b,0x1c,0x0a},
++ { 9, 4, 848, 528,1270, 530, 0, 0, 50,0xf5,0xfb,0x1b,0x2a}, /* 640x480, 320x240 */
++ { 36, 25,1060, 648,1316, 530, 438, 0, 438,0xeb,0x05,0x25,0x16}, /* 800x600, 400x300 */
++ { 3, 2,1080, 619,1270, 540, 438, 0, 438,0xf3,0x00,0x1d,0x20}, /* 720x576 */
++ { 1, 1,1170, 821,1270, 520, 686, 0, 686,0xF3,0x00,0x1D,0x20} /* 1024x768 */
++};
++
++static const SiS_TVDataStruct SiS_StNTSCData[]=
++{
++ { 1, 1, 858, 525,1270, 400, 50, 0, 760,0xf1,0x04,0x1f,0x18},
++ { 1, 1, 858, 525,1270, 350, 50, 0, 640,0xf1,0x04,0x1f,0x18},
++ { 1, 1, 858, 525,1270, 400, 0, 0, 720,0xf1,0x04,0x1f,0x18},
++ { 1, 1, 858, 525,1270, 350, 0, 0, 720,0xf4,0x0b,0x1c,0x0a},
++ { 1, 1, 858, 525,1270, 480, 0, 0, 760,0xf1,0x04,0x1f,0x18}
++};
++
++static const SiS_TVDataStruct SiS_ExtNTSCData[]=
++{
++ { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18}, /* 640x400, 320x200 */
++ { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
++ { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
++ { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
++ { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16}, /* 640x480, 320x240 */
++ { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00}, /* 800x600, 400x300 */
++ { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08}, /* 720x480 - BETTER (from 300 series) */
++/*{ 2, 1, 858, 503,1270, 480, 0, 128, 0,0xee,0x0c,0x22,0x08},*/ /* 720x480 (old, from 650) */
++ { 1, 1,1100, 811,1412, 440, 0, 128, 0,0xee,0x0c,0x22,0x08} /* 1024x768 CORRECTED */
++/*{ 65, 64,1056, 791,1270, 480, 638, 0, 0,0xEE,0x0C,0x22,0x08} */ /* 1024x768 */
++#if 0 /* 300 series was: */
++ { 143, 65, 858, 443,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
++ { 88, 35, 858, 393,1270, 440, 171, 0, 171,0xf1,0x04,0x1f,0x18},
++ { 143, 70, 924, 443,1270, 440, 92, 0, 92,0xf1,0x04,0x1f,0x18},
++ { 143, 70, 924, 393,1270, 440, 92, 0, 92,0xf4,0x0b,0x1c,0x0a},
++ { 143, 76, 836, 523,1270, 440, 224, 0, 0,0xf1,0x05,0x1f,0x16},
++ { 143, 120,1056, 643,1270, 440, 0, 128, 0,0xf4,0x10,0x1c,0x00},
++ { 143, 76, 836, 523,1270, 440, 0, 128, 0,0xee,0x0c,0x22,0x08},
++ { 65, 64,1056, 791,1270, 480, 638, 0, 0,0xf1,0x04,0x1f,0x18}
++#endif
++};
++
++
++static const SiS_TVDataStruct SiS_St2HiTVData[]=
++{
++ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
++ { 1, 1, 0x37c,0x233,0x2b2,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 3, 1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00},
++ { 1, 1, 0x3e8,0x233,0x311,0x2bc, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 5, 2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
++ { 8, 5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
++};
++
++static const SiS_TVDataStruct SiS_ExtHiTVData[]=
++{
++ { 6, 1, 0x348,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 3, 1, 0x348,0x1e3,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 3, 1, 0x3c0,0x233,0x660,0x3c0, 0, 0, 0, 0x00,0x00,0x00,0x00},
++ { 5, 1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00}, /* 640x480 */
++ { 16, 5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x600 */
++ { 25, 12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x768 */
++ { 5, 4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00}, /* 1280x1024 */
++ { 4, 1, 0x41a,0x233,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00}, /* 800x480 */
++ { 5, 2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0x00,0x00,0x00,0x00}, /* 1024x576 */
++ { 8, 5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0x00,0x00,0x00,0x00} /* 1280x720 */
++};
++
++static const UCHAR SiS_OutputSelect = 0x40;
++
++static const UCHAR SiS_SoftSetting = 0x30; /* RAM setting */
++
++static const SiS_LCDDataStruct SiS_LCD1280x960Data[] =
++{
++ { 9, 2, 800, 500,1800,1000},
++ { 9, 2, 800, 500,1800,1000},
++ { 4, 1, 900, 500,1800,1000},
++ { 4, 1, 900, 500,1800,1000},
++ { 9, 2, 800, 500,1800,1000},
++ { 30, 11,1056, 625,1800,1000},
++ { 5, 3,1350, 800,1800,1000},
++ { 1, 1,1576,1050,1576,1050},
++ { 1, 1,1800,1000,1800,1000}
++};
++
++static const SiS_LCDDataStruct SiS_StLCD1280x768Data[] =
++{
++ { 211, 100, 2100, 408, 1688, 802 }, /* These values are *wrong* */
++ { 211, 64, 1536, 358, 1688, 802 }, /* (which is why they aren't used yet) */
++ { 211, 100, 2100, 408, 1688, 802 },
++ { 211, 64, 1536, 358, 1688, 802 },
++ { 211, 48, 840, 488, 1688, 802 },
++ { 211, 72, 1008, 609, 1688, 802 },
++ { 211, 128, 1400, 776, 1688, 802 },
++ { 211, 205, 1680, 1041, 1688, 802 },
++ { 1, 1, 1688, 802, 1688, 802 } /* That's the only one that *might* be correct */
++};
++
++static const SiS_LCDDataStruct SiS_ExtLCD1280x768Data[] =
++{
++ { 211, 100, 2100, 408, 1688, 802 }, /* These values are *wrong* */
++ { 211, 64, 1536, 358, 1688, 802 }, /* (which is why they aren't used yet) */
++ { 211, 100, 2100, 408, 1688, 802 },
++ { 211, 64, 1536, 358, 1688, 802 },
++ { 211, 48, 840, 488, 1688, 802 },
++ { 211, 72, 1008, 609, 1688, 802 },
++ { 211, 128, 1400, 776, 1688, 802 },
++ { 211, 205, 1680, 1041, 1688, 802 },
++ { 1, 1, 1688, 802, 1688, 802 } /* That's the only one that *might* be correct */
++};
++
++static const SiS_LCDDataStruct SiS_NoScaleData1280x768[] =
++{ /* All values guessed */
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802},
++ { 1, 1, 1688, 802, 1688, 802}
++};
++
++static const SiS_LCDDataStruct SiS_StLCD1400x1050Data[] =
++{
++ { 211, 100, 2100, 408, 1688, 1066 },
++ { 211, 64, 1536, 358, 1688, 1066 },
++ { 211, 100, 2100, 408, 1688, 1066 },
++ { 211, 64, 1536, 358, 1688, 1066 },
++ { 211, 48, 840, 488, 1688, 1066 },
++ { 211, 72, 1008, 609, 1688, 1066 },
++ { 211, 128, 1400, 776, 1688, 1066 },
++ { 211, 205, 1680, 1041, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 }
++};
++
++static const SiS_LCDDataStruct SiS_ExtLCD1400x1050Data[] =
++{
++ { 211, 100, 2100, 408, 1688, 1066 },
++ { 211, 64, 1536, 358, 1688, 1066 },
++ { 211, 100, 2100, 408, 1688, 1066 },
++ { 211, 64, 1536, 358, 1688, 1066 },
++ { 211, 48, 840, 488, 1688, 1066 },
++ { 211, 72, 1008, 609, 1688, 1066 },
++ { 211, 128, 1400, 776, 1688, 1066 },
++ { 211, 205, 1680, 1041, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 }
++};
++
++static const SiS_LCDDataStruct SiS_NoScaleData1400x1050[] =
++{
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 },
++ { 1, 1, 1688, 1066, 1688, 1066 }
++};
++
++static const SiS_LCDDataStruct SiS_StLCD1600x1200Data[] =
++{
++ {27, 4, 800, 500, 2160, 1250 },
++ {27, 4, 800, 500, 2160, 1250 },
++ { 6, 1, 900, 500, 2160, 1250 },
++ { 6, 1, 900, 500, 2160, 1250 },
++ {27, 1, 800, 500, 2160, 1250 },
++ { 4, 1,1080, 625, 2160, 1250 },
++ { 5, 2,1350, 800, 2160, 1250 },
++ {135,88,1600,1100, 2160, 1250 },
++ {135,88,1600,1100, 2160, 1250 },
++ { 1, 1,2160,1250, 2160, 1250 }
++};
++
++static const SiS_LCDDataStruct SiS_ExtLCD1600x1200Data[] =
++{
++ {27, 4, 800, 500, 2160, 1250 },
++ {27, 4, 800, 500, 2160, 1250 },
++ { 6, 1, 900, 500, 2160, 1250 },
++ { 6, 1, 900, 500, 2160, 1250 },
++ {27, 1, 800, 500, 2160, 1250 },
++ { 4, 1,1080, 625, 2160, 1250 },
++ { 5, 2,1350, 800, 2160, 1250 },
++ {27,16,1500,1064, 2160, 1250 },
++ {27,16,1500,1064, 2160, 1250 },
++ { 1, 1,2160,1250, 2160, 1250 }
++};
++
++static const SiS_LCDDataStruct SiS_NoScaleData1600x1200[] =
++{
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++ {1, 1, 2160, 1250, 2048, 1250},
++};
++
++static const SiS_LCDDataStruct SiS_NoScaleData[] =
++{
++ { 1, 1, 800, 449, 800, 449 },
++ { 1, 1, 800, 449, 800, 449 },
++ { 1, 1, 900, 449, 900, 449 },
++ { 1, 1, 900, 449, 900, 449 },
++ { 1, 1, 800, 525, 800, 525 },
++ { 1, 1,1056, 628,1056, 628 },
++ { 1, 1,1344, 806,1344, 806 },
++ { 1, 1,1688,1066,1688,1066 },
++ { 1, 1,1688, 802,1688, 802 }, /* 1280x768: 802 was 806 in both cases */
++ { 1, 1,2160,1250,2160,1250 }, /* 1600x1200 */
++ { 1, 1,1800,1000,1800,1000 } /* 1280x960 */
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS320x480Data_1[]=
++{
++ { 848, 433, 400, 525},
++ { 848, 389, 400, 525},
++ { 848, 433, 400, 525},
++ { 848, 389, 400, 525},
++ { 848, 518, 400, 525},
++ {1056, 628, 400, 525},
++ { 400, 525, 400, 525},
++ { 800, 449,1000, 644},
++ { 800, 525,1000, 635}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS800x600Data_1[]=
++{
++ { 848, 433,1060, 629},
++ { 848, 389,1060, 629},
++ { 848, 433,1060, 629},
++ { 848, 389,1060, 629},
++ { 848, 518,1060, 629},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ { 800, 449,1000, 644},
++ { 800, 525,1000, 635}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS800x600Data_2[]=
++{
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ {1056, 628,1056, 628},
++ { 800, 449,1000, 644},
++ { 800, 525,1000, 635}
++};
++
++
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_1[]=
++{
++ {1048, 442,1688,1066},
++ {1048, 392,1688,1066},
++ {1048, 442,1688,1066},
++ {1048, 392,1688,1066},
++ {1048, 522,1688,1066},
++ {1208, 642,1688,1066},
++ {1432, 810,1688,1066},
++ {1688,1066,1688,1066}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x1024Data_2[]=
++{
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_1[]=
++{
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 518,1344, 806}, /* 640x480 */
++ {1050, 638,1344, 806}, /* 800x600 */
++ {1344, 806,1344, 806}, /* 1024x768 */
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1024x768Data_2[]=
++{
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++/* Custom data for Barco iQ R300 */
++static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_1[]=
++{
++ { 832, 438,1331, 806},
++ { 832, 388,1331, 806},
++ { 832, 438,1331, 806},
++ { 832, 388,1331, 806},
++ { 832, 518,1331, 806},
++ {1050, 638,1344, 806},
++ {1344, 806,1344, 806},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066} /* 1360x1024 */
++};
++
++/* Custom data for Barco iQ R300 */
++static const SiS_LVDSDataStruct SiS_LVDSBARCO1366Data_2[]=
++{
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1688,1066,1688,1066},
++ {1688,1066,1688,1066} /* 1360x1024 */
++};
++
++static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_1[]=
++{
++ { 832, 438,1331, 806},
++ { 832, 409,1331, 806},
++ { 832, 438,1331, 806},
++ { 832, 409,1331, 806},
++ { 832, 518,1331, 806}, /* 640x480 */
++ {1050, 638,1344, 806}, /* 800x600 */
++ {1344, 806,1344, 806}, /* 1024x768 */
++};
++
++static const SiS_LVDSDataStruct SiS_LVDSBARCO1024Data_2[]=
++{
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_1[]=
++{
++ { 928, 416, 1688,1066},
++ { 928, 366, 1688,1066},
++ { 928, 416, 1688,1066},
++ { 928, 366, 1688,1066},
++ { 928, 496, 1688,1066},
++ {1088, 616, 1688,1066},
++ {1312, 784, 1688,1066},
++ {1568,1040, 1688,1066},
++ {1688,1066, 1688,1066}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1400x1050Data_2[]=
++{
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++ {1688,1066, 1688,1066},
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_1[]=
++{
++ {1088, 450, 2048,1250},
++ {1088, 400, 2048,1250},
++ {1088, 450, 2048,1250},
++ {1088, 400, 2048,1250},
++ {1088, 530, 2048,1250},
++ {1248, 650, 2048,1250},
++ {1472, 818, 2048,1250},
++ {1728,1066, 2048,1250},
++ {1848,1066, 2048,1250},
++ {2048,1250, 2048,1250}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1600x1200Data_2[]=
++{
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250},
++ {2048,1250, 2048,1250}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_1[]=
++{
++ { 768, 438, 1408, 806},
++ { 768, 388, 1408, 806},
++ { 768, 438, 1408, 806},
++ { 768, 388, 1408, 806},
++ { 768, 518, 1408, 806},
++ { 928, 638, 1408, 806},
++ {1152, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x768Data_2[]=
++{
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806},
++ {1408, 806, 1408, 806}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_1[] =
++{
++ {840, 604,1344, 800},
++ {840, 560,1344, 800},
++ {840, 604,1344, 800},
++ {840, 560,1344, 800},
++ {840, 689,1344, 800},
++ {1050, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {800, 449,1280, 789},
++ {800, 525,1280, 785}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1024x600Data_2[] =
++{
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ {1344, 800,1344, 800},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_1[] =
++{
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 518,1344, 806},
++ {1050, 638,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1152x768Data_2[] =
++{
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++/* TW: Pass 1:1 data */
++static const SiS_LVDSDataStruct SiS_LVDSXXXxXXXData_1[]=
++{
++ { 800, 449, 800, 449},
++ { 800, 449, 800, 449},
++ { 900, 449, 900, 449},
++ { 900, 449, 900, 449},
++ { 800, 525, 800, 525}, /* 640x480 */
++ {1056, 628, 1056, 628}, /* 800x600 */
++ {1344, 806, 1344, 806}, /* 1024x768 */
++ {1344,1066, 1344,1066}, /* 1280x1024 */ /* INSERTED ! */
++ {1688, 806, 1688, 806}, /* 1280x768 */
++ /* No other panels ! */
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS640x480Data_1[]=
++{
++ { 800, 445, 800, 525}, /* 800, 449, 800, 449 */
++ { 800, 395, 800, 525},
++ { 800, 445, 800, 525},
++ { 800, 395, 800, 525},
++ { 800, 525, 800, 525},
++ { 800, 525, 800, 525}, /* pseudo */
++ { 800, 525, 800, 525} /* pseudo */
++};
++
++/* FSTN 320x240 */
++static const SiS_LVDSDataStruct SiS_LVDS640x480Data_2[]=
++{
++ { 800, 445, 800, 525},
++ { 800, 395, 800, 525},
++ { 800, 445, 800, 525},
++ { 800, 395, 800, 525},
++ { 800, 525, 800, 525},
++ { 800, 525, 800, 525}, /* pseudo */
++ { 800, 525, 800, 525} /* pseudo */
++};
++
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_1[]=
++{
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 438,1344, 806},
++ { 840, 409,1344, 806},
++ { 840, 518,1344, 806},
++ {1050, 638,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS1280x960Data_2[]=
++{
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS848x480Data_1[]=
++{
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ {1088, 525,1088, 525}, /* 640x480 TODO */
++ {1088, 525,1088, 525}, /* 800x600 TODO */
++ {1088, 525,1088, 525}, /* 1024x768 TODO */
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ {1088, 525,1088, 525}, /* 848x480 */
++ {1088, 525,1088, 525} /* 1360x768 TODO */
++};
++
++static const SiS_LVDSDataStruct SiS_LVDS848x480Data_2[]=
++{
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ {1088, 525,1088, 525}, /* 640x480 */
++ {1088, 525,1088, 525}, /* 800x600 */
++ {1088, 525,1088, 525}, /* 1024x768 */
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ { 0, 0, 0, 0},
++ {1088, 525,1088, 525}, /* 848x480 */
++ {1088, 525,1088, 525} /* 1360x768 TODO */
++};
++
++/* LCDA */
++
++static const SiS_LVDSDataStruct SiS_LCDA1400x1050Data_1[]=
++{ /* TW: Might be temporary (invalid) data */
++ { 928, 416, 1688,1066},
++ { 928, 366, 1688,1066},
++ {1008, 416, 1688,1066},
++ {1008, 366, 1688,1066},
++ {1200, 530, 1688,1066},
++ {1088, 616, 1688,1066},
++ {1312, 784, 1688,1066},
++ {1568,1040, 1688,1066},
++ {1688,1066, 1688,1066}
++};
++
++static const SiS_LVDSDataStruct SiS_LCDA1400x1050Data_2[]=
++{ /* TW: Temporary data. Not valid */
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LCDA1600x1200Data_1[]=
++{ /* TW: Temporary data. Not valid */
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ {1344, 806,1344, 806},
++ { 800, 449,1280, 801},
++ { 800, 525,1280, 813}
++};
++
++static const SiS_LVDSDataStruct SiS_LCDA1600x1200Data_2[]=
++{ /* TW: Temporary data. Not valid */
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0},
++ {0, 0, 0, 0}
++};
++
++static const SiS_LVDSDataStruct SiS_CHTVUNTSCData[]=
++{
++ { 840, 600, 840, 600},
++ { 840, 600, 840, 600},
++ { 840, 600, 840, 600},
++ { 840, 600, 840, 600},
++ { 784, 600, 784, 600},
++ {1064, 750,1064, 750},
++ {1160, 945,1160, 945}
++};
++
++static const SiS_LVDSDataStruct SiS_CHTVONTSCData[]=
++{
++ { 840, 525, 840, 525},
++ { 840, 525, 840, 525},
++ { 840, 525, 840, 525},
++ { 840, 525, 840, 525},
++ { 784, 525, 784, 525},
++ {1040, 700,1040, 700},
++ {1160, 840,1160, 840}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1076_1[]=
++{ /* 1024x768 */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1076_2[]=
++{ /* 1024x768 */
++ { 1184, 622 },
++ { 1184, 597 },
++ { 1184, 622 },
++ { 1184, 597 },
++ { 1152, 622 },
++ { 1232, 722 },
++ { 0, 0 },
++ { 0, 794 },
++ { 0, 0 }
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1210_1[]=
++{ /* 1280x1024 */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1210_2[]=
++{ /* 1280x1024 */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1296_1[]=
++{ /* 1400x1050 */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1296_2[]=
++{ /* 1400x1050 - looks heavily invalid */
++ { 808 , 740},
++ { 0 , 715},
++ { 632 , 740},
++ { 632 , 715},
++ { 1307, 780},
++ { 1387,1157},
++ { 1499, 924},
++ { 1627,1052},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1600_1[]=
++{ /* 1600x1200 */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelType1600_2[]=
++{ /* 1600x1200 - BIOS looks heavily invalid, not copied */
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_PanelTypeNS_1[]=
++{
++ { 8, 0},
++ { 8, 0},
++ { 8, 0},
++ { 8, 0},
++ { 8, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 806},
++ { 0, 0 }
++};
++
++static const SiS_LVDSDesStruct SiS_PanelTypeNS_2[] =
++{
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0},
++ { 0 , 0}
++};
++
++static const SiS_LVDSDesStruct SiS_CHTVUNTSCDesData[]=
++{
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0}
++};
++
++static const SiS_LVDSDesStruct SiS_CHTVONTSCDesData[]=
++{
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0}
++};
++
++static const SiS_LVDSDesStruct SiS_CHTVUPALDesData[]=
++{
++ {256, 0},
++ {256, 0},
++ {256, 0},
++ {256, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0}
++};
++
++static const SiS_LVDSDesStruct SiS_CHTVOPALDesData[]=
++{
++ {256, 0},
++ {256, 0},
++ {256, 0},
++ {256, 0},
++ { 0, 0},
++ { 0, 0},
++ { 0, 0}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1320x480_1[] =
++{
++ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
++ 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
++ 0x00 }},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00 }},
++ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00 }},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00 }},
++ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
++ 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
++ 0x00 }},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01 }},
++ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00 }}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1[] =
++{
++ {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
++ 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
++ 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
++ 0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
++ 0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
++ 0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
++ 0x00}},
++ {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
++ 0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
++ 0x01}},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
++ 0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_1_H[] =
++{
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
++ 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
++ 0x00}},
++ {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
++ 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
++ 0x01}},
++ {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2[] =
++{
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
++ 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
++ 0x01}},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11024x600_2_H[] =
++{
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
++ 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
++ 0x01}},
++ {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1[] =
++{
++ {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
++ 0x00}},
++ {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
++ 0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
++ 0x00}},
++ {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
++ 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
++ 0x01}},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_1_H[] =
++{
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
++ 0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
++ 0x00}},
++ {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
++ 0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
++ 0x00}},
++ {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
++ 0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
++ 0x01}},
++ {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2[] =
++{
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
++ 0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
++ 0x00}},
++ {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
++ 0xae,0x84,0x57,0x25,0x30,0x00,0x02,
++ 0x01}},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11152x768_2_H[] =
++{
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
++ 0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
++ 0x00}},
++ {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
++ 0xae,0x84,0x57,0x25,0x30,0x00,0x01,
++ 0x01}},
++ {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1[] =
++{
++ {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
++ 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
++ 0x00}},
++ {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
++ 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
++ 0x00}},
++ {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
++ 0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
++ 0x00}},
++ {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
++ 0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
++ 0x00}},
++ {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e,
++ 0xec,0x8e,0xdf,0x05,0x20,0x00,0x01,
++ 0x00}},
++ {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0,
++ 0x64,0x86,0x57,0x7d,0x20,0x00,0x05,
++ 0x01}},
++ {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5,
++ 0x0c,0x8e,0xff,0x25,0x30,0x00,0x02,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
++ 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
++ 0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_1_H[] =
++{
++ {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
++ 0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
++ 0x00}},
++ {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
++ 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
++ 0x00}},
++ {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
++ 0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
++ 0x00}},
++ {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
++ 0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
++ 0x00}},
++ {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
++ 0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
++ 0x00}},
++ {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
++ 0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
++ 0x01}},
++ {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
++ 0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
++ 0x01}},
++ {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
++ 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
++ 0x01}},
++ {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
++ 0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2[] =
++{
++ {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
++ 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
++ 0x00}},
++ {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
++ 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
++ 0x00}},
++ {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
++ 0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
++ 0x00}},
++ {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
++ 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
++ 0x00}},
++ {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3,
++ 0x7c,0x8e,0x03,0x02,0x10,0x00,0x02,
++ 0x01}},
++ {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1,
++ 0xb6,0x88,0x57,0x25,0x10,0x00,0x02,
++ 0x01}},
++ {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x02,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT11280x768_2_H[] =
++{
++ {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
++ 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
++ 0x00}},
++ {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
++ 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
++ 0x00}},
++ {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
++ 0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
++ 0x00}},
++ {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
++ 0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
++ 0x00}},
++ {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3,
++ 0x7c,0x8e,0x03,0x02,0x10,0x00,0x01,
++ 0x01}},
++ {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1,
++ 0xb6,0x88,0x57,0x25,0x10,0x00,0x01,
++ 0x01}},
++ {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x01,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
++ 0x01}},
++ {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
++ 0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1XXXxXXX_1[] =
++{
++ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}},
++ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x02,
++ 0x01}},
++ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
++ 0x00,0x84,0xff,0x29,0x09,0x00,0x07,
++ 0x01}},
++ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x07,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1XXXxXXX_1_H[] =
++{
++ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
++ 0x00}},
++ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
++ 0x00}},
++ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
++ 0x00}},
++ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
++ 0x00}},
++ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}},
++ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
++ 0x01}},
++ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
++ 0x02,0x88,0xff,0x25,0x10,0x00,0x01,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1[] =
++{
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_1_H[] =
++{
++ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
++ 0x00}},
++ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
++ 0x00}},
++ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
++ 0x00}},
++ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
++ 0x83,0x85,0x63,0xba,0x00,0x00,0x00,
++ 0x00}},
++ {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2[] =
++{
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}},
++ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_2_H[] =
++{
++ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
++ 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
++ 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}},
++ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3[] =
++{
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
++ 0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}},
++ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}}
++};
++
++static const SiS_LVDSCRT1DataStruct SiS_LVDSCRT1640x480_3_H[] =
++{
++ {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
++ 0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x54,0x9f,0xc4,0x1f,
++ 0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
++ 0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
++ 0x00}},
++ {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
++ 0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
++ 0x00}},
++ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
++ 0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
++ 0x01}},
++ {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
++ 0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
++ 0x00}}
++};
++
++#define SIS_PL_HSYNCP 0x01
++#define SIS_PL_HSYNCN 0x02
++#define SIS_PL_VSYNCP 0x04
++#define SIS_PL_VSYNCN 0x08
++#define SIS_PL_DVI 0x80
++
++typedef struct _SiS_PlasmaModes
++{
++ const char *name;
++ ULONG clock;
++ USHORT HDisplay, HTotal, HFrontPorch, HSyncWidth;
++ USHORT VDisplay, VTotal, VFrontPorch, VSyncWidth;
++ UCHAR SyncFlags;
++} SiS_PlasmaModes;
++
++
++typedef struct _SiS_PlasmaTables
++{
++ USHORT vendor;
++ UCHAR productnum;
++ USHORT product[5];
++ const char *plasmaname;
++ UCHAR modenum;
++ UCHAR plasmamodes[20]; /* | 0x80 = DVI-capable, | 0x40 = analog */
++} SiS_PlasmaTables;
++
++static const SiS_PlasmaModes SiS_PlasmaMode[] = {
++ { "640x400", /* 00: IBM 400@70 */
++ 25175,
++ 640, 800, 17, 64,
++ 400, 449, 13, 2,
++ SIS_PL_HSYNCN | SIS_PL_VSYNCN },
++ { "640x480", /* 01: VESA 480@72 */
++ 31500,
++ 640, 832, 24, 40,
++ 480, 520, 9, 3,
++ SIS_PL_HSYNCN | SIS_PL_VSYNCN },
++ { "800x600", /* 02: VESA 600@72 */
++ 50000,
++ 800, 1040, 56, 120,
++ 600, 666, 37, 6,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "864x480", /* 03: Cereb wide 1 */
++ 42526,
++ 864, 1134, 22, 86,
++ 480, 500, 1, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCN },
++ { "848x480", /* 04: VESA wide (NEC1) */
++ 33750,
++ 848, 1088, 16, 112,
++ 480, 517, 6, 8,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1024x576", /* 05: VESA wide (NEC2) */
++ 47250,
++ 1024, 1320, 16, 144,
++ 576, 596, 2, 4,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1280x720", /* 06: VESA wide (NEC3) */
++ 76500,
++ 1280, 1696, 48, 176,
++ 720, 750, 4, 8,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1360x765", /* 07: VESA wide (NEC4) */
++ 85500,
++ 1360, 1792, 64, 176,
++ 765, 795, 4, 8,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1024x600", /* 08: CEREB wide 2 */
++ 51200,
++ 1024, 1352, 51, 164,
++ 600, 628, 1, 4,
++ SIS_PL_HSYNCN | SIS_PL_VSYNCP },
++ { "1024x768", /* 09: VESA 768@75 */
++ 78750,
++ 1024, 1312, 16, 96,
++ 768, 800, 1, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1152x864", /* 10: VESA 1152x864@75 */
++ 108000,
++ 1152, 1600, 64, 128,
++ 864, 900, 1, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1280x1024", /* 11: VESA 1024@60 */
++ 108000,
++ 1280, 1688, 48, 112,
++ 1024, 1066, 1, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1280x768", /* 12: W_XGA */
++ 81000,
++ 1280, 1688, 48, 112,
++ 768, 802, 3, 6,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCN },
++ { "1280x768", /* 13: I/O Data W_XGA@56Hz */
++ 76064,
++ 1280, 1688, 48, 112,
++ 768, 802, 2, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1376x768", /* 14: I/O Wide XGA */
++ 87340,
++ 1376, 1808, 32, 128,
++ 768, 806, 3, 6,
++ SIS_PL_HSYNCN | SIS_PL_VSYNCP },
++ { "1280x960", /* 15: VESA 960@60 */
++ 108000,
++ 1280, 1800, 96, 112,
++ 960, 1000, 1, 3,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "1400x1050", /* 16: VESA 1050@60Hz */
++ 108000,
++ 1400, 1688, 48, 112,
++ 1050, 1066, 1, 3,
++ SIS_PL_HSYNCN | SIS_PL_VSYNCN },
++ { "1360x768", /* 17: VESA wide (NEC4/2) */
++ 85500,
++ 1360, 1792, 64, 112,
++ 765, 795, 3, 6,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP },
++ { "800x600", /* 18: VESA 600@56 */
++ 36000,
++ 800, 1024, 24, 2,
++ 600, 625, 1, 2,
++ SIS_PL_HSYNCP | SIS_PL_VSYNCP }
++};
++
++static const SiS_PlasmaTables SiS_PlasmaTable[] = {
++#if 0 /* Product IDs missing */
++ { 0x38a3, 4,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42VP4/42VP4D/42VP4G/42VP4DG",
++ 14, /* All DVI, except 0, 7, 13; 3, 15, 16 unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,12|0xc0,
++ 13|0x40,14|0xc0,15|0xc0,16|0xc0, 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 3,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42PD1/50PD1/50PD2",
++ 5, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0, 0 , 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42PD3",
++ 10, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 7|0x40, 8|0xc0, 9|0xc0,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 2,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42VM3/61XM1",
++ 11, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 8|0xc0, 9|0xc0,11|0xc0,
++ 17|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 2,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42MP1/42MP2",
++ 6, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 50MP1",
++ 10, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++#endif
++ { 0x38a3, 4,
++ { 0xa482, 0xa483, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 42MP3/42MP4/50MP2/61MP1",
++ 11, /* All DVI except 0, 7, 13, 17 */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
++ 17|0x40, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++#if 0 /* Product IDs missing */
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 3300W",
++ 3,
++ { 0|0x40, 1|0xc0,18|0xc0, 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 4200W",
++ 4, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 0 , 0 , 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 4210W",
++ 6, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x38a3, 1,
++ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "NEC PlasmaSync 5000W",
++ 7, /* DVI entirely unknown */
++ { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,11|0xc0, 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++#endif
++ { 0x412f, 2,
++ { 0x000c, 0x000b, 0x0000, 0x0000, 0x0000 },
++ "Pioneer 503CMX/PDA-5002",
++ 6, /* DVI unknown */
++ { 1|0xc0, 2|0xc0, 9|0xc0,11|0xc0,12|0xc0,15|0xc0, 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x34a9, 1,
++ { 0xa00e, 0x0000, 0x0000, 0x0000, 0x0000 },
++ "Panasonic TH-42",
++ 5, /* No DVI output */
++ { 1|0x40, 2|0x40, 4|0x40, 9|0x40,15|0x40, 0 , 0 , 0 , 0 , 0 ,
++ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }
++ },
++ { 0x0000 }
++};
++
+ void SiS_SetReg1(USHORT, USHORT, USHORT);
+ void SiS_SetReg2(SiS_Private *, USHORT, USHORT, USHORT);
+ void SiS_SetReg3(USHORT, USHORT);
+@@ -158,6 +2397,7 @@ void SiS_SetMemoryClock(SiS_Private
+ void SiS_SetDRAMModeRegister(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ BOOLEAN SiS_SearchVBModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo);
+ void SiS_IsLowResolution(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex);
++void SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+
+ #ifdef SIS300
+ void SiS_SetDRAMSize_300(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+@@ -192,12 +2432,15 @@ void SiS_VerifyMclk(SiS_Private *SiS
+
+ void SiS_HandleCRT1(SiS_Private *SiS_Pr);
+ void SiS_Handle301B_1400x1050(SiS_Private *SiS_Pr, USHORT ModeNo);
+-void SiS_SetEnableDstn(SiS_Private *SiS_Pr);
++void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
++void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
+ void SiS_Delay15us(SiS_Private *SiS_Pr);
+ BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT *ModeNo,USHORT *ModeIdIndex);
+ BOOLEAN SiS_CheckMemorySize(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ USHORT ModeNo,USHORT ModeIdIndex);
+ UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex);
++void SiS_WhatTheHellIsThis(SiS_Private *SiS_Pr,PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr);
++void SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ void SiS_SetSeqRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex);
+ void SiS_SetMiscRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT StandTableIndex);
+ void SiS_SetCRTCRegs(SiS_Private *SiS_Pr, UCHAR *ROMAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension,
+@@ -267,26 +2510,26 @@ void SiS_SetPitchCRT1(SiS_Private *S
+ void SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, UShort BaseAddr);
+ extern int SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div,
+ int *out_sbit, int *out_scale);
++extern void SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk);
++
+ extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value);
+ extern unsigned char SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
+-extern USHORT SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode);
++extern USHORT SiS_CalcModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode, BOOLEAN hcm);
+ #endif
+
+ extern USHORT SiS_GetOffset(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex,
+ USHORT RefreshRateTableIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ extern USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,USHORT ModeIdIndex);
+ extern void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT BaseAddr);
+-extern BOOLEAN SiS_SetCRT2Group301(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+- PSIS_HW_DEVICE_INFO HwDeviceExtension);
+-extern void SiS_PresetScratchregister(SiS_Private *SiS_Pr, USHORT SiS_P3d4,
+- PSIS_HW_DEVICE_INFO HwDeviceExtension);
++extern BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
++ PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr);
+ extern void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,USHORT BaseAddr);
+ extern BOOLEAN SiS_BridgeIsOn(SiS_Private *SiS_Pr, USHORT BaseAddr);
+ extern BOOLEAN SiS_BridgeIsEnable(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO );
+ extern void SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT BaseAddr,UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex,PSIS_HW_DEVICE_INFO HwDeviceExtension, int chkcrt2mode);
+-extern BOOLEAN SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,
++extern void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, UCHAR *ROMAddr,USHORT ModeNo,
+ USHORT ModeIdIndex, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ extern void SiS_SetHiVision(SiS_Private *SiS_Pr, USHORT BaseAddr,PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ extern USHORT SiS_GetRatePtrCRT2(SiS_Private *SiS_Pr, UCHAR *ROMAddr, USHORT ModeNo,USHORT ModeIdIndex,
+@@ -321,10 +2564,12 @@ int sisfb_mode_rate_to_dclock(SiS_Pri
+ unsigned char modeno, unsigned char rateindex);
+ int sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
+ unsigned char modeno, unsigned char rateindex,
+- ULONG *left_margin, ULONG *right_margin,
++ ULONG *left_margin, ULONG *right_margin,
+ ULONG *upper_margin, ULONG *lower_margin,
+ ULONG *hsync_len, ULONG *vsync_len,
+ ULONG *sync, ULONG *vmode);
++BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
++ unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+ #endif
+
+ #endif
+--- linux-2.6.0-test6/drivers/video/sis/oem300.h 2003-06-14 12:18:05.000000000 -0700
++++ 25/drivers/video/sis/oem300.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,5 +1,37 @@
+-
+-/* OEM Data for 300 series */
++/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/oem300.h.c,v 1.0 2001/11/30 12:12:01 eich Exp $ */
++/*
++ * OEM Data for 300 series
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
+
+ const UCHAR SiS300_OEMTVDelay301[8][4] =
+ {
+@@ -680,325 +712,147 @@ const UCHAR SiS300_Filter2[10][9][7] =
+ }
+ };
+
+-const UCHAR SiS300_LCDHData[24][11][5] = {
++/* Custom data for Barco iQ Pro R300 */
++const UCHAR barco_p1[2][9][7][3] = {
+ {
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x8a,0x14,0x00,0x80,0x00},
+- {0x8a,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9a,0x56,0x00},
+- {0x67,0x11,0x9a,0x56,0x00},
+- {0x8a,0x14,0x00,0x80,0x00},
+- {0x8a,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x8a,0x14,0x00,0x80,0x00},
+- {0x8a,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x8e,0x18,0x28,0x78,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x4e,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9a,0x56,0x00},
+- {0x67,0x11,0x9a,0x56,0x00},
+- {0x8a,0x14,0x00,0x80,0x00},
+- {0x8a,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x67,0x91,0x84,0x5e,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x65,0xef,0x83,0x5c,0x00},
+- {0x8a,0x14,0x00,0x80,0x00},
+- {0x8a,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x67,0x91,0x84,0x5E,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x65,0xEF,0x83,0x5C,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
+- },
+- {
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x8E,0x18,0x28,0x78,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x4E,0x18,0x90,0x38,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x67,0x11,0x9A,0x56,0x00},
+- {0x8A,0x14,0x00,0x80,0x00},
+- {0x8A,0x14,0x00,0x80,0x00}
++ { { 0x16, 0xcf, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x19, 0x00 }
++ },
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x1e, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x16, 0x00 }
++ },
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x19, 0x00 },
++ { 0, 0, 0 }
++ },
++ {
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x1e, 0x00 },
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0xd1, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x11, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x26, 0x00 }
++ },
++ {
++ { 0x16, 0xd1, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x30, 0x00 },
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0x00, 0x00 },
++ { 0x17, 0xa0, 0x00 },
++ { 0x1a, 0xa0, 0x00 },
++ { 0x1b, 0x2a, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0x00, 0x00 },
++ { 0x17, 0xaa, 0x00 },
++ { 0x1a, 0xa0, 0x00 },
++ { 0x1b, 0x2a, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0, 0, 0 }
++ }
++ },
++ {
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x19, 0x00 }
++ },
++ {
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x19, 0x00 },
++ },
++ {
++ { 0, 0, 0 }
++ },
++ {
++ { 0x16, 0xcf, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe7, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x1e, 0x00 }
++ },
++ {
++ { 0x16, 0xd1, 0x00 },
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe6, 0x00 },
++ { 0x1b, 0x11, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x26, 0x00 }
++ },
++ {
++ { 0x18, 0x00, 0x00 },
++ { 0x1a, 0xe0, 0x00 },
++ { 0x1b, 0x26, 0x00 },
++ { 0x1c, 0xff, 0x00 },
++ { 0x1d, 0x1c, 0x00 },
++ { 0x1e, 0x30, 0x00 },
++ { 0, 0, 0 }
++ },
++ {
++ { 0, 0, 0 }
++ },
++ {
++ { 0, 0, 0 }
++ }
+ }
+ };
+
+-#if 0
+-const UCHAR SiS300_LCDVData[24][11][6] = {
+- {
+- {
+- },
+-};
+-#endif
++
++
++
++
++
+--- linux-2.6.0-test6/drivers/video/sis/oem310.h 2003-06-14 12:17:55.000000000 -0700
++++ 25/drivers/video/sis/oem310.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,5 +1,37 @@
+-
+-/* OEM Data for 310/325/330 series */
++/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/oem300.h.c,v 1.0 2001/11/30 12:12:01 eich Exp $ */
++/*
++ * OEM Data for 315/330 series
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Based on code by Silicon Intergrated Systems
++ *
++ */
+
+ const UCHAR SiS310_LCDDelayCompensation_301[] = /* 301 */
+ {
+@@ -100,7 +132,7 @@ const UCHAR SiS310_LCDDelayCompensation_
+
+ const UCHAR SiS310_LCDDelayCompensation_651301LV[] = /* M650/651 301LV */
+ {
+- 0x33,0x33,0x33, /* 800x600 (guessed) */
++ 0x33,0x33,0x33, /* 800x600 (guessed) - new: PanelType, not PanelRes ! */
+ 0x33,0x33,0x33, /* 1024x768 */
+ 0x33,0x33,0x33, /* 1280x1024 */
+ 0x33,0x33,0x33, /* 640x480 (unknown) */
+@@ -361,5 +393,55 @@ const UCHAR SiS310_TVPhaseIncr2[3][2][4]
+ }
+ };
+
++/* OEM data for Compaq Presario 3045US */
++static const SiS_LCDDataStruct SiS310_ExtCompaq1280x1024Data[] =
++{
++ { 211, 60,1024, 501,1688,1066},
++ { 211, 60,1024, 508,1688,1066},
++ { 211, 60,1024, 501,1688,1066},
++ { 211, 60,1024, 508,1688,1066},
++ { 32, 15,1696, 501,1696,1066},
++ { 212, 75,1024, 621,1696,1066},
++ { 4, 3,1696, 810,1696,1066},
++ { 1, 1,1696,1066,1696,1066}
++};
++
++static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_1[] =
++{
++ {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x35,0x1B,0xA0,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x45,0x1C,0x20,0x3F,0xFF,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
++ {{0x49,0x1C,0x40,0x7F,0xFF,0xAD,0x23,0x0A,0x07,0xF3,0x8A,0x12}},
++ {{0x4C,0x1C,0x18,0x2F,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
++};
++
++static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_2[] =
++{
++ {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
++ {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
++ {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
++ {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
++ {{0x33,0x13,0x01,0x0D,0xFD,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
++ {{0x3F,0x1B,0x3D,0x49,0x39,0x54,0x23,0xC0,0x27,0x66,0x30,0x42}},
++ {{0x33,0x1B,0x91,0x9D,0x8D,0x8C,0x23,0xF8,0x27,0x9E,0x68,0x42}},
++ {{0x43,0x24,0x11,0x1D,0x0D,0xCC,0x23,0x38,0x37,0xDE,0xA8,0x42}},
++ {{0x43,0x24,0x21,0x29,0x19,0xEA,0x23,0x0A,0x07,0x32,0xC6,0x42}}
++};
++
++static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_3[] =
++{
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
++ {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}}
++};
++
+
+
+--- linux-2.6.0-test6/drivers/video/sis/osdef.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/drivers/video/sis/osdef.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,79 +1,43 @@
+-/* #define WINCE_HEADER */
+-/* #define WIN2000 */
+-/* #define TC */
++
++/* OS depending defines */
++
++/* The choices are: */
++
+ #define LINUX_KERNEL /* Kernel framebuffer */
+ /* #define LINUX_XF86 */ /* XFree86 */
+
+ /**********************************************************************/
+-#ifdef LINUX_KERNEL
+- #include <linux/config.h>
+- #include <linux/version.h>
+- #ifdef CONFIG_FB_SIS_300
+- #define SIS300
+- #endif
+-
+- #ifdef CONFIG_FB_SIS_315
+- #define SIS315H
+- #endif
+- #if 1
+- #define SISFBACCEL /* Include 2D acceleration */
+- #endif
+- #if 1
+- #define SISFB_PAN /* Include Y-Panning code */
+- #endif
+-#else
+-/* #define SIS300*/
+- #define SIS315H
+-#endif
+-#ifdef LINUX_XF86
+- #define SIS300
+- /* #define SIS315H */ /* TW: done above */
+-#endif
++#ifdef LINUX_KERNEL /* -------------------------- */
++#include <linux/config.h>
++#include <linux/version.h>
+
+-/**********************************************************************/
+-#ifdef TC
+-#endif
+-#ifdef WIN2000
+-#endif
+-#ifdef WINCE_HEADER
+-#endif
+-#ifdef LINUX_XF86
++#ifdef CONFIG_FB_SIS_300
++#define SIS300
+ #endif
+-#ifdef LINUX_KERNEL
+-#endif
+-/**********************************************************************/
+-#ifdef TC
+-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
+-#endif
+-#ifdef WIN2000
+-#define SiS_SetMemory(MemoryAddress,MemorySize,value) MemFill((PVOID) MemoryAddress,(ULONG) MemorySize,(UCHAR) value);
++
++#ifdef CONFIG_FB_SIS_315
++#define SIS315H
+ #endif
+-#ifdef WINCE_HEADER
+-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize);
++
++#if 1
++#define SISFBACCEL /* Include 2D acceleration */
+ #endif
+-#ifdef LINUX_XF86
+-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
++
+ #endif
+-#ifdef LINUX_KERNEL
+-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
++
++#ifdef LINUX_XF86 /* ----------------------------- */
++#define SIS300
++#define SIS315H
+ #endif
+-/**********************************************************************/
+
+ /**********************************************************************/
+-
+-#ifdef TC
+-#define SiS_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+-#endif
+-#ifdef WIN2000
+-#define SiS_MemoryCopy(Destination,Soruce,Length) /*VideoPortMoveMemory((PUCHAR)Destination , Soruce,length);*/
+-#endif
+-#ifdef WINCE_HEADER
+-#define SiS_MemoryCopy(Destination,Soruce,Length) memmove(Destination, Soruce, Length);
+-#endif
+ #ifdef LINUX_XF86
++#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+ #define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+ #endif
++
+ #ifdef LINUX_KERNEL
++#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
+ #define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
+ #endif
+
+@@ -104,19 +68,6 @@
+ #endif /* InPortLong */
+
+ /**********************************************************************/
+-/* TC */
+-/**********************************************************************/
+-
+-#ifdef TC
+-#define OutPortByte(p,v) outp((unsigned short)(p),(unsigned char)(v))
+-#define OutPortWord(p,v) outp((unsigned short)(p),(unsigned short)(v))
+-#define OutPortLong(p,v) outp((unsigned short)(p),(unsigned long)(v))
+-#define InPortByte(p) inp((unsigned short)(p))
+-#define InPortWord(p) inp((unsigned short)(p))
+-#define InPortLong(p) ((inp((unsigned short)(p+2))<<16) | inp((unsigned short)(p)))
+-#endif
+-
+-/**********************************************************************/
+ /* LINUX XF86 */
+ /**********************************************************************/
+
+@@ -142,29 +93,4 @@
+ #define InPortLong(p) inl((u16)(p))
+ #endif
+
+-/**********************************************************************/
+-/* WIN 2000 */
+-/**********************************************************************/
+-
+-#ifdef WIN2000
+-#define OutPortByte(p,v) VideoPortWritePortUchar ((PUCHAR) (p), (UCHAR) (v))
+-#define OutPortWord(p,v) VideoPortWritePortUshort((PUSHORT) (p), (USHORT) (v))
+-#define OutPortLong(p,v) VideoPortWritePortUlong ((PULONG) (p), (ULONG) (v))
+-#define InPortByte(p) VideoPortReadPortUchar ((PUCHAR) (p))
+-#define InPortWord(p) VideoPortReadPortUshort ((PUSHORT) (p))
+-#define InPortLong(p) VideoPortReadPortUlong ((PULONG) (p))
+-#endif
+
+-
+-/**********************************************************************/
+-/* WIN CE */
+-/**********************************************************************/
+-
+-#ifdef WINCE_HEADER
+-#define OutPortByte(p,v) WRITE_PORT_UCHAR ((PUCHAR) (p), (UCHAR) (v))
+-#define OutPortWord(p,v) WRITE_PORT_USHORT((PUSHORT) (p), (USHORT) (v))
+-#define OutPortLong(p,v) WRITE_PORT_ULONG ((PULONG) (p), (ULONG) (v))
+-#define InPortByte(p) READ_PORT_UCHAR ((PUCHAR) (p))
+-#define InPortWord(p) READ_PORT_USHORT ((PUSHORT) (p))
+-#define InPortLong(p) READ_PORT_ULONG ((PULONG) (p))
+-#endif
+--- linux-2.6.0-test6/drivers/video/sis/sis_accel.c 2003-06-14 12:18:52.000000000 -0700
++++ 25/drivers/video/sis/sis_accel.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,5 +1,5 @@
+ /*
+- * SiS 300/630/730/540/315/550/650/740 frame buffer driver
++ * SiS 300/630/730/540/315/550/650/740/330/660 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+ * 2D acceleration part
+@@ -211,7 +211,7 @@ SiS300SubsequentSolidFillRect(int x, int
+ SiS300DoCMD
+ }
+
+-/* 310/325 series ------------------------------------------------ */
++/* 315 series ---------------------------------------------------- */
+
+ static void
+ SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
+@@ -230,7 +230,7 @@ SiS310SetupForScreenToScreenCopy(int xdi
+ /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
+ }
+ SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth)
+- /* TW: The 310/325 series is smart enough to know the direction */
++ /* The 315 series is smart enough to know the direction */
+ }
+
+ static void
+@@ -328,11 +328,13 @@ void sisfb_syncaccel(void)
+ }
+ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* --- KERNEL 2.5.34 and later --- */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* --------------- 2.5 --------------- */
+
+ int fbcon_sis_sync(struct fb_info *info)
+ {
+- if(!sisfb_accel) return 0;
++ if(!ivideo.accel)
++ return 0;
++
+ CRITFLAGS
+ if(sisvga_engine == SIS_300_VGA) {
+ SiS300Sync();
+@@ -352,7 +354,7 @@ void fbcon_sis_fillrect(struct fb_info *
+ if(!rect->width || !rect->height)
+ return;
+
+- if(!sisfb_accel) {
++ if(!ivideo.accel) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+@@ -388,7 +390,7 @@ void fbcon_sis_copyarea(struct fb_info *
+ CRITFLAGS
+
+ TWDEBUG("Inside sis_copyarea");
+- if(!sisfb_accel) {
++ if(!ivideo.accel) {
+ cfb_copyarea(info, area);
+ return;
+ }
+@@ -418,7 +420,7 @@ void fbcon_sis_copyarea(struct fb_info *
+
+ #endif
+
+-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ------ KERNEL <2.5.34 ------ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* -------------- 2.4 --------------- */
+
+ void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
+ int dsty, int dstx, int height, int width)
+@@ -591,38 +593,38 @@ void fbcon_sis_revc(struct display *p, i
+
+ #ifdef FBCON_HAS_CFB8
+ struct display_switch fbcon_sis8 = {
+- setup: fbcon_cfb8_setup,
+- bmove: fbcon_sis_bmove,
+- clear: fbcon_sis_clear8,
+- putc: fbcon_cfb8_putc,
+- putcs: fbcon_cfb8_putcs,
+- revc: fbcon_cfb8_revc,
+- clear_margins: fbcon_cfb8_clear_margins,
+- fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
++ .setup = fbcon_cfb8_setup,
++ .bmove = fbcon_sis_bmove,
++ .clear = fbcon_sis_clear8,
++ .putc = fbcon_cfb8_putc,
++ .putcs = fbcon_cfb8_putcs,
++ .revc = fbcon_cfb8_revc,
++ .clear_margins = fbcon_cfb8_clear_margins,
++ .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+ };
+ #endif
+ #ifdef FBCON_HAS_CFB16
+ struct display_switch fbcon_sis16 = {
+- setup: fbcon_cfb16_setup,
+- bmove: fbcon_sis_bmove,
+- clear: fbcon_sis_clear16,
+- putc: fbcon_cfb16_putc,
+- putcs: fbcon_cfb16_putcs,
+- revc: fbcon_sis_revc,
+- clear_margins: fbcon_cfb16_clear_margins,
+- fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
++ .setup = fbcon_cfb16_setup,
++ .bmove = fbcon_sis_bmove,
++ .clear = fbcon_sis_clear16,
++ .putc = fbcon_cfb16_putc,
++ .putcs = fbcon_cfb16_putcs,
++ .revc = fbcon_sis_revc,
++ .clear_margins = fbcon_cfb16_clear_margins,
++ .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+ };
+ #endif
+ #ifdef FBCON_HAS_CFB32
+ struct display_switch fbcon_sis32 = {
+- setup: fbcon_cfb32_setup,
+- bmove: fbcon_sis_bmove,
+- clear: fbcon_sis_clear32,
+- putc: fbcon_cfb32_putc,
+- putcs: fbcon_cfb32_putcs,
+- revc: fbcon_sis_revc,
+- clear_margins: fbcon_cfb32_clear_margins,
+- fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
++ .setup = fbcon_cfb32_setup,
++ .bmove = fbcon_sis_bmove,
++ .clear = fbcon_sis_clear32,
++ .putc = fbcon_cfb32_putc,
++ .putcs = fbcon_cfb32_putcs,
++ .revc = fbcon_sis_revc,
++ .clear_margins = fbcon_cfb32_clear_margins,
++ .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+ };
+ #endif
+
+--- linux-2.6.0-test6/drivers/video/sis/sis_accel.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/drivers/video/sis/sis_accel.h 2003-10-05 00:34:22.000000000 -0700
+@@ -47,7 +47,7 @@
+ #define TRAPAZOID_FILL 0x00000005 /* Fill trapezoid */
+ #define TRANSPARENT_BITBLT 0x00000006 /* Transparent Blit */
+
+-/* Additional engine commands for 310/325 */
++/* Additional engine commands for 315 */
+ #define ALPHA_BLEND 0x00000007 /* Alpha blend ? */
+ #define A3D_FUNCTION 0x00000008 /* 3D command ? */
+ #define CLEAR_Z_BUFFER 0x00000009 /* ? */
+@@ -90,11 +90,11 @@
+ #define NO_RESET_COUNTER 0x00400000
+ #define NO_LAST_PIXEL 0x00200000
+
+-/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */
++/* Subfunctions for Color/Enhanced Color Expansion (315 only) */
+ #define COLOR_TO_MONO 0x00100000
+ #define AA_TEXT 0x00200000
+
+-/* Some general registers for 310/325 series */
++/* Some general registers for 315 series */
+ #define SRC_ADDR 0x8200
+ #define SRC_PITCH 0x8204
+ #define AGP_BASE 0x8206 /* color-depth dependent value */
+@@ -326,7 +326,7 @@ int CmdQueLen;
+
+
+
+-/* ----------- SiS 310/325 series --------------- */
++/* -------------- SiS 315 series --------------- */
+
+ /* Q_STATUS:
+ bit 31 = 1: All engines idle and all queues empty
+@@ -342,16 +342,27 @@ int CmdQueLen;
+ bits 7:0: 2D counter 1
+
+ Where is the command queue length (current amount of commands the queue
+- can accept) on the 310/325 series? (The current implementation is taken
+- from 300 series and certainly wrong...)
++ can accept) on the 315 series?
+ */
+
+ /* TW: FIXME: CmdQueLen is... where....? */
++/* We assume a length of 4 bytes per command; since 512K of
++ * of RAM are allocated, the number of commands is easily
++ * calculated (assuming that there is no 3D support yet)
++ * We calculate it very cautiously (128K only) and let the
++ * rest to the (never?)-to-come (?) 3D engine. (The 3D engine
++ * can use a similar technique, using the remaining 384K,
++ * hence a queue overflow is avoided)
++ * UPDATE: This technique causes a terrible system latency
++ * on integrated chipsets. Disable the queue handling for
++ * now.
++ */
+ #define SiS310Idle \
+ { \
+ while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+ while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+- CmdQueLen=MMIO_IN16(ivideo.mmio_vbase, Q_STATUS); \
++ CmdQueLen = 0; \
++ /*CmdQueLen = ((128 * 1024) / 4) - 64; */ \
+ }
+
+ #define SiS310SetupSRCBase(base) \
+--- linux-2.6.0-test6/drivers/video/sis/sis_main.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/video/sis/sis_main.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,25 +1,20 @@
+ /*
+- * SiS 300/630/730/540/315/550/650/740 frame buffer device
++ * SiS 300/630/730/540/315/550/650/740/330/660/760 frame buffer driver
+ * for Linux kernels 2.4.x and 2.5.x
+ *
+- * Partly based on the VBE 2.0 compliant graphic boards framebuffer driver,
++ * (C) 1999 Silicon Integrated Systems, Inc.
++ * (C) 2001-2003 Thomas Winischhofer, Vienna, Austria.
++ *
++ * Author: Thomas Winischhofer <thomas@winischhofer.net>
++ *
++ * Author of code base:
++ * SiS (www.sis.com.tw)
++ *
++ * See http://www.winischhofer.net/ for more information and updates
++ *
++ * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
+ * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+- * Authors: SiS (www.sis.com.tw)
+- * (Various others)
+- * Thomas Winischhofer <thomas@winischhofer.net>:
+- * - SiS Xabre (330) support
+- * - many fixes and enhancements for all chipset series,
+- * - extended bridge handling, TV output for Chrontel 7005
+- * - 650/LVDS support (for LCD panels up to 1600x1200)
+- * - 650/740/Chrontel 7019 support
+- * - 30xB/30xLV LCD, TV and VGA2 support
+- * - memory queue handling enhancements,
+- * - 2D acceleration and y-panning,
+- * - portation to 2.5 API
+- * - etc.
+- * (see http://www.winischhofer.net/
+- * for more information and updates)
+ */
+
+ #include <linux/config.h>
+@@ -43,6 +38,8 @@
+ #include <linux/fs.h>
+ #include <linux/agp_backend.h>
+ #include <linux/types.h>
++#include <linux/vmalloc.h>
++#include <asm/uaccess.h>
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ #include <linux/spinlock.h>
+@@ -79,6 +76,12 @@
+ #endif
+ #endif
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)
++#error "This version of sisfb requires at least 2.5.69"
++#endif
++#endif
++
+ /* -------------------- Macro definitions ---------------------------- */
+
+ #undef SISFBDEBUG /* TW: no debugging */
+@@ -134,9 +137,19 @@ sisfb_query_VGA_config_space(PSIS_HW_DEV
+
+ if (!init) {
+ init = TRUE;
+- pdev = pci_find_device(PCI_VENDOR_ID_SI, ivideo.chip_id, pdev);
+- if (pdev)
+- valid_pdev = TRUE;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
++ DPRINTK("sisfb: Current: 0x%x, target: 0x%x\n",
++ pdev->device, ivideo.chip_id);
++ if ((pdev->vendor == PCI_VENDOR_ID_SI)
++ && (pdev->device == ivideo.chip_id)) {
++ valid_pdev = TRUE;
++ break;
++ }
++ }
+ }
+
+ if (!valid_pdev) {
+@@ -163,6 +176,7 @@ BOOLEAN sisfb_query_north_bridge_space(P
+ if (!init) {
+ init = TRUE;
+ switch (ivideo.chip) {
++#ifdef CONFIG_FB_SIS_300
+ case SIS_540:
+ nbridge_id = PCI_DEVICE_ID_SI_540;
+ break;
+@@ -172,23 +186,42 @@ BOOLEAN sisfb_query_north_bridge_space(P
+ case SIS_730:
+ nbridge_id = PCI_DEVICE_ID_SI_730;
+ break;
++#endif
++#ifdef CONFIG_FB_SIS_315
+ case SIS_550:
+ nbridge_id = PCI_DEVICE_ID_SI_550;
+ break;
+ case SIS_650:
+ nbridge_id = PCI_DEVICE_ID_SI_650;
+ break;
+- case SIS_740:
++ case SIS_740:
+ nbridge_id = PCI_DEVICE_ID_SI_740;
+ break;
++ case SIS_660:
++ nbridge_id = PCI_DEVICE_ID_SI_660;
++ break;
++ case SIS_760:
++ nbridge_id = PCI_DEVICE_ID_SI_760;
++ break;
++#endif
+ default:
+ nbridge_id = 0;
+ break;
+ }
+
+- pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
+- if (pdev)
+- valid_pdev = TRUE;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
++ DPRINTK("Current: 0x%x, target: 0x%x\n",
++ pdev->device, ivideo.chip_id);
++ if ((pdev->vendor == PCI_VENDOR_ID_SI)
++ && (pdev->device == nbridge_id)) {
++ valid_pdev = TRUE;
++ break;
++ }
++ }
+ }
+
+ if (!valid_pdev) {
+@@ -207,66 +240,291 @@ BOOLEAN sisfb_query_north_bridge_space(P
+
+ /* ------------------ Internal helper routines ----------------- */
+
+-static void sisfb_search_mode(const char *name)
++static BOOLEAN sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
+ {
+- int i = 0, j = 0;
++ int htotal, vtotal;
++ unsigned int dclock, hsync;
+
+- if(name == NULL) {
+- printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+- sisfb_mode_idx = DEFAULT_MODE;
+- return;
++ if(!monitor->datavalid) return TRUE;
++
++ if(mode_idx < 0) return FALSE;
++
++ if(rate < (monitor->vmin - 1)) return FALSE;
++ if(rate > (monitor->vmax + 1)) return FALSE;
++
++ if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
++ &htotal, &vtotal, rate_idx)) {
++ dclock = (htotal * vtotal * rate) / 1000;
++ if(dclock > (monitor->dclockmax + 1000)) return FALSE;
++ hsync = dclock / htotal;
++ if(hsync < (monitor->hmin - 1)) return FALSE;
++ if(hsync > (monitor->hmax + 1)) return FALSE;
++ } else {
++ return FALSE;
+ }
+-
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+- if (!strcmp(name, sisbios_mode[MODE_INDEX_NONE].name)) {
+- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+- sisfb_mode_idx = DEFAULT_MODE;
+- return;
++ return TRUE;
++};
++
++static BOOLEAN sisfb_interpret_edid(struct sisfb_monitor *monitor, unsigned char *buffer)
++{
++ int i, j, xres, yres, refresh, index;
++ u32 emodes;
++
++ if(buffer[0] != 0x00 || buffer[1] != 0xff ||
++ buffer[2] != 0xff || buffer[3] != 0xff ||
++ buffer[4] != 0xff || buffer[5] != 0xff ||
++ buffer[6] != 0xff || buffer[7] != 0x00) {
++ printk(KERN_DEBUG "sisfb: Bad EDID header\n");
++ return FALSE;
+ }
+-#endif
+
+- while(sisbios_mode[i].mode_no != 0) {
+- if (!strcmp(name, sisbios_mode[i].name)) {
+- sisfb_mode_idx = i;
+- j = 1;
+- break;
+- }
+- i++;
++ if(buffer[0x12] != 0x01) {
++ printk(KERN_INFO "sisfb: EDID version %d not supported\n",
++ buffer[0x12]);
++ return FALSE;
++ }
++
++ monitor->feature = buffer[0x18];
++
++ if(!buffer[0x14] & 0x80) {
++ if(!(buffer[0x14] & 0x08)) {
++ printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n");
++ }
++ }
++
++ if(buffer[0x13] >= 0x01) {
++ /* EDID V1 rev 1 and 2: Search for monitor descriptor
++ * to extract ranges
++ */
++ j = 0x36;
++ for(i=0; i<4; i++) {
++ if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
++ buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
++ buffer[j + 4] == 0x00) {
++ monitor->hmin = buffer[j + 7];
++ monitor->hmax = buffer[j + 8];
++ monitor->vmin = buffer[j + 5];
++ monitor->vmax = buffer[j + 6];
++ monitor->dclockmax = buffer[j + 9] * 10 * 1000;
++ monitor->datavalid = TRUE;
++ break;
++ }
++ j += 18;
++ }
++ }
++
++ if(!monitor->datavalid) {
++ /* Otherwise: Get a range from the list of supported
++ * Estabished Timings. This is not entirely accurate,
++ * because fixed frequency monitors are not supported
++ * that way.
++ */
++ monitor->hmin = 65535; monitor->hmax = 0;
++ monitor->vmin = 65535; monitor->vmax = 0;
++ monitor->dclockmax = 0;
++ emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
++ for(i = 0; i < 13; i++) {
++ if(emodes & sisfb_ddcsmodes[i].mask) {
++ if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
++ if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
++ if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
++ if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
++ if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
++ }
++ }
++ index = 0x26;
++ for(i = 0; i < 8; i++) {
++ xres = (buffer[index] + 31) * 8;
++ switch(buffer[index + 1] & 0xc0) {
++ case 0xc0: yres = (xres * 9) / 16; break;
++ case 0x80: yres = (xres * 4) / 5; break;
++ case 0x40: yres = (xres * 3) / 4; break;
++ default: yres = xres; break;
++ }
++ refresh = (buffer[index + 1] & 0x3f) + 60;
++ if((xres >= 640) && (yres >= 480)) {
++ for(j = 0; j < 8; j++) {
++ if((xres == sisfb_ddcfmodes[j].x) &&
++ (yres == sisfb_ddcfmodes[j].y) &&
++ (refresh == sisfb_ddcfmodes[j].v)) {
++ if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
++ if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
++ if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
++ if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
++ if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
++ }
++ }
++ }
++ index += 2;
++ }
++ if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
++ monitor->datavalid = TRUE;
++ }
++ }
++
++ return(monitor->datavalid);
++}
++
++static void sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
++{
++ USHORT temp, i, realcrtno = crtno;
++ unsigned char buffer[256];
++
++ monitor->datavalid = FALSE;
++
++ if(crtno) {
++ if(ivideo.vbflags & CRT2_LCD) realcrtno = 1;
++ else if(ivideo.vbflags & CRT2_VGA) realcrtno = 2;
++ else return;
++ }
++
++ if((sisfb_crt1off) && (!crtno)) return;
++
++ temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, realcrtno, 0, &buffer[0]);
++ if((!temp) || (temp == 0xffff)) {
++ printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
++ return;
++ } else {
++ printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
++ printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
++ crtno + 1,
++ (temp & 0x1a) ? "" : "[none of the supported]",
++ (temp & 0x02) ? "2 " : "",
++ (temp & 0x08) ? "D&P" : "",
++ (temp & 0x10) ? "FPDI-2" : "");
++ if(temp & 0x02) {
++ i = 3; /* Number of retrys */
++ do {
++ temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine,
++ realcrtno, 1, &buffer[0]);
++ } while((temp) && i--);
++ if(!temp) {
++ if(sisfb_interpret_edid(monitor, &buffer[0])) {
++ printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
++ monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
++ monitor->dclockmax / 1000);
++ } else {
++ printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
++ }
++ } else {
++ printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
++ }
++ } else {
++ printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
++ }
+ }
+- if(!j) printk(KERN_INFO "sisfb: Invalid mode '%s'\n", name);
+ }
+
+-static void sisfb_search_vesamode(unsigned int vesamode)
++static void sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+ {
+ int i = 0, j = 0;
+
+ if(vesamode == 0) {
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ sisfb_mode_idx = MODE_INDEX_NONE;
+ #else
+- printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
++ if(!quiet)
++ printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+ sisfb_mode_idx = DEFAULT_MODE;
+-#endif
++#endif
+ return;
+ }
+
+ vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
+
++ while(sisbios_mode[i++].mode_no != 0) {
++ if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
++ (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
++ if(sisfb_fstn) {
++ if(sisbios_mode[i-1].mode_no == 0x50 ||
++ sisbios_mode[i-1].mode_no == 0x56 ||
++ sisbios_mode[i-1].mode_no == 0x53) continue;
++ } else {
++ if(sisbios_mode[i-1].mode_no == 0x5a ||
++ sisbios_mode[i-1].mode_no == 0x5b) continue;
++ }
++ sisfb_mode_idx = i - 1;
++ j = 1;
++ break;
++ }
++ }
++ if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
++}
++
++static void sisfb_search_mode(char *name, BOOLEAN quiet)
++{
++ int i = 0;
++ unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
++ char strbuf[16], strbuf1[20];
++ char *nameptr = name;
++
++ if(name == NULL) {
++ if(!quiet)
++ printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
++ sisfb_mode_idx = DEFAULT_MODE;
++ return;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ if (!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
++ if(!quiet)
++ printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
++ sisfb_mode_idx = DEFAULT_MODE;
++ return;
++ }
++#endif
++ if(strlen(name) <= 19) {
++ strcpy(strbuf1, name);
++ for(i=0; i<strlen(strbuf1); i++) {
++ if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
++ }
++
++ /* This does some fuzzy mode naming detection */
++ if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
++ if((rate <= 32) || (depth > 32)) {
++ j = rate; rate = depth; depth = j;
++ }
++ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
++ nameptr = strbuf;
++ ivideo.refresh_rate = sisfb_parm_rate = rate;
++ } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
++ sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
++ nameptr = strbuf;
++ } else {
++ xres = 0;
++ if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
++ sprintf(strbuf, "%ux%ux8", xres, yres);
++ nameptr = strbuf;
++ } else {
++ sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
++ return;
++ }
++ }
++ }
++
++ i = 0; j = 0;
+ while(sisbios_mode[i].mode_no != 0) {
+- if( (sisbios_mode[i].vesa_mode_no_1 == vesamode) ||
+- (sisbios_mode[i].vesa_mode_no_2 == vesamode) ) {
+- sisfb_mode_idx = i;
+- j = 1;
+- break;
++ if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
++ if(sisfb_fstn) {
++ if(sisbios_mode[i-1].mode_no == 0x50 ||
++ sisbios_mode[i-1].mode_no == 0x56 ||
++ sisbios_mode[i-1].mode_no == 0x53) continue;
++ } else {
++ if(sisbios_mode[i-1].mode_no == 0x5a ||
++ sisbios_mode[i-1].mode_no == 0x5b) continue;
++ }
++ sisfb_mode_idx = i - 1;
++ j = 1;
++ break;
+ }
+- i++;
+ }
+- if(!j) printk(KERN_INFO "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
++ if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
++
+ }
+
+-static int sisfb_validate_mode(int myindex)
++static int sisfb_validate_mode(int myindex, unsigned long vbflags)
+ {
+- u16 xres, yres;
++ u16 xres, yres, myres;
+
+ #ifdef CONFIG_FB_SIS_300
+ if(sisvga_engine == SIS_300_VGA) {
+@@ -283,8 +541,10 @@ static int sisfb_validate_mode(int myind
+ }
+ #endif
+
+- switch (ivideo.disp_state & DISPTYPE_DISP2) {
+- case DISPTYPE_LCD:
++ myres = sisbios_mode[myindex].yres;
++
++ switch (vbflags & VB_DISPTYPE_DISP2) {
++ case CRT2_LCD:
+ switch (sishw_ext.ulCRT2LCDType) {
+ case LCD_640x480:
+ xres = 640; yres = 480; break;
+@@ -306,140 +566,209 @@ static int sisfb_validate_mode(int myind
+ xres = 1400; yres = 1050; break;
+ case LCD_1600x1200:
+ xres = 1600; yres = 1200; break;
+- case LCD_320x480: /* TW: FSTN */
++ case LCD_320x480: /* FSTN (old) */
+ xres = 320; yres = 480; break;
++ case LCD_640x480_2: /* FSTN (new) */
++ case LCD_640x480_3:
++ xres = 640; yres = 480; break;
+ default:
+ xres = 0; yres = 0; break;
+ }
+- if(sisbios_mode[myindex].xres > xres) {
+- return(-1);
++
++ if(SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
++ xres = 1360; yres = 1024;
+ }
+- if(sisbios_mode[myindex].yres > yres) {
++
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
++ xres = 848; yres = 480;
++ } else {
++ if(sisbios_mode[myindex].xres > xres) {
++ return(-1);
++ }
++ if(myres > yres) {
+ return(-1);
++ }
+ }
+- if((sishw_ext.usExternalChip == 0x01) || /* LVDS */
+- (sishw_ext.usExternalChip == 0x05) || /* LVDS+Chrontel */
+- (sishw_ext.Is301BDH)) { /* 301B-DH */
++
++ if(vbflags & (VB_LVDS | VB_30xBDH)) {
+ switch (sisbios_mode[myindex].xres) {
++ case 320:
++ if((myres != 200) && (myres != 240))
++ return(-1);
++ if((myres == 240) || (myres == 480)) {
++ if(!sisfb_fstn) {
++ if(sisbios_mode[myindex].mode_no == 0x5a ||
++ sisbios_mode[myindex].mode_no == 0x5b)
++ return(-1);
++ } else {
++ if(sisbios_mode[myindex].mode_no == 0x50 ||
++ sisbios_mode[myindex].mode_no == 0x56 ||
++ sisbios_mode[myindex].mode_no == 0x53)
++ return(-1);
++ }
++ }
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
++ break;
++ case 400:
++ if(myres != 300) return(-1);
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
++ break;
+ case 512:
+- if(sisbios_mode[myindex].yres != 512) return -1;
+- if(sishw_ext.ulCRT2LCDType == LCD_1024x600) return -1;
++ if(myres != 384) return(-1);
++ if(sishw_ext.ulCRT2LCDType == LCD_1024x600) return(-1);
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
+ break;
+ case 640:
+- if((sisbios_mode[myindex].yres != 400) &&
+- (sisbios_mode[myindex].yres != 480))
++ if((myres != 400) && (myres != 480))
+ return -1;
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
++ if(myres == 400)
++ return(-1);
++ }
+ break;
+ case 800:
+- if(sisbios_mode[myindex].yres != 600) return -1;
++ if(myres != 600) return(-1);
++ break;
++ case 848:
++ if(SiS_Pr.SiS_CustomT != CUT_PANEL848) return(-1);
++ if(myres != 480) return(-1);
+ break;
+ case 1024:
+- if((sisbios_mode[myindex].yres != 600) &&
+- (sisbios_mode[myindex].yres != 768))
+- return -1;
+- if((sisbios_mode[myindex].yres == 600) &&
++ if((myres != 600) && (myres != 768))
++ return(-1);
++ if((myres == 600) &&
+ (sishw_ext.ulCRT2LCDType != LCD_1024x600))
+- return -1;
++ return(-1);
+ break;
+ case 1152:
+- if((sisbios_mode[myindex].yres) != 768) return -1;
+- if(sishw_ext.ulCRT2LCDType != LCD_1152x768) return -1;
++ if(myres != 768) return(-1);
++ if(sishw_ext.ulCRT2LCDType != LCD_1152x768) return(-1);
+ break;
+ case 1280:
+- if((sisbios_mode[myindex].yres != 768) &&
+- (sisbios_mode[myindex].yres != 1024))
+- return -1;
+- if((sisbios_mode[myindex].yres == 768) &&
++ if((myres != 768) && (myres != 1024))
++ return(-1);
++ if((myres == 768) &&
+ (sishw_ext.ulCRT2LCDType != LCD_1280x768))
+- return -1;
++ return(-1);
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
++ break;
++ case 1360:
++ if(SiS_Pr.SiS_CustomT != CUT_BARCO1366) return(-1);
++ if(myres != 1024) return(-1);
+ break;
+ case 1400:
+- if(sisbios_mode[myindex].yres != 1050) return -1;
++ if(myres != 1050) return(-1);
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
+ break;
+ case 1600:
+- if(sisbios_mode[myindex].yres != 1200) return -1;
++ if(myres != 1200) return(-1);
++ if(SiS_Pr.SiS_CustomT == CUT_PANEL848) return(-1);
+ break;
+ default:
+- return -1;
++ return(-1);
+ }
+ } else {
+ switch (sisbios_mode[myindex].xres) {
++ case 320:
++ if((myres != 200) && (myres != 240))
++ return -1;
++ break;
++ case 400:
++ if(myres != 300) return(-1);
++ break;
+ case 512:
+- if(sisbios_mode[myindex].yres != 512) return -1;
++ if(myres != 384) return(-1);
+ break;
+ case 640:
+- if((sisbios_mode[myindex].yres != 400) &&
+- (sisbios_mode[myindex].yres != 480))
+- return -1;
++ if((myres != 400) && (myres != 480))
++ return(-1);
+ break;
+ case 800:
+- if(sisbios_mode[myindex].yres != 600) return -1;
++ if(myres != 600) return(-1);
+ break;
+ case 1024:
+- if(sisbios_mode[myindex].yres != 768) return -1;
++ if(myres != 768) return(-1);
+ break;
+ case 1280:
+- if((sisbios_mode[myindex].yres != 960) &&
+- (sisbios_mode[myindex].yres != 1024))
+- return -1;
+- if(sisbios_mode[myindex].yres == 960) {
+- if(sishw_ext.ulCRT2LCDType == LCD_1400x1050)
+- return -1;
++ if((myres != 960) && (myres != 768) && (myres != 1024))
++ return(-1);
++ if((myres == 768) || (myres == 960)) {
++ if(sishw_ext.ulCRT2LCDType == LCD_1400x1050)
++ return(-1);
++ }
++ if(myres == 768) {
++ if(sishw_ext.ulCRT2LCDType == LCD_1280x960)
++ return(-1);
+ }
+ break;
+ case 1400:
+- if(sisbios_mode[myindex].yres != 1050) return -1;
++ if(myres != 1050) return(-1);
+ break;
+ case 1600:
+- if(sisbios_mode[myindex].yres != 1200) return -1;
++ if(myres != 1200) return(-1);
+ break;
+ default:
+- return -1;
++ return(-1);
+ }
+ }
+ break;
+- case DISPTYPE_TV:
++
++ case CRT2_TV:
+ switch (sisbios_mode[myindex].xres) {
++ case 320:
++ if(vbflags & VB_CHRONTEL) return(-1);
++ if((myres != 200) && (myres != 240))
++ return(-1);
++ break;
++ case 400:
++ if(vbflags & VB_CHRONTEL) return(-1);
++ if(myres != 300) return(-1);
++ break;
+ case 512:
++ if(vbflags & VB_CHRONTEL) return(-1);
++ if((vbflags & VB_SISBRIDGE) && (vbflags & TV_NTSC))
++ return(-1);
++ if(myres != 384) return(-1);
++ break;
+ case 640:
+- case 800:
++ if((myres != 400) && (myres != 480))
++ return(-1);
++ if((vbflags & VB_CHRONTEL) && (myres == 400))
++ return(-1);
+ break;
+ case 720:
+- if (ivideo.TV_type == TVMODE_NTSC) {
+- if (sisbios_mode[myindex].yres != 480) {
+- return(-1);
+- }
+- } else if (ivideo.TV_type == TVMODE_PAL) {
+- if (sisbios_mode[myindex].yres != 576) {
+- return(-1);
+- }
+- }
+- /* TW: LVDS/CHRONTEL does not support 720 */
+- if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||
+- ivideo.hasVB == HASVB_CHRONTEL) {
+- return(-1);
+- }
++ if(vbflags & VB_CHRONTEL) return(-1);
++ if((vbflags & TV_NTSC) && (myres != 480))
++ return(-1);
++ if((vbflags & TV_PAL) && (myres != 576))
++ return(-1);
++ break;
++ case 768:
++ if(vbflags & VB_CHRONTEL) return(-1);
++ if(!(vbflags & TV_PAL)) return(-1);
++ if(myres != 576) return(-1);
++ break;
++ case 800:
++ if(myres != 600) return(-1);
+ break;
+ case 1024:
+- if (ivideo.TV_type == TVMODE_NTSC) {
+- if(sisbios_mode[myindex].bpp == 32) {
+- return(-1);
+- }
+- }
+- /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)*/
+- if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||
+- ivideo.hasVB == HASVB_CHRONTEL) {
+- if(ivideo.chip < SIS_315H) {
++ if(vbflags & VB_301) return(-1);
++ if(vbflags & VB_CHRONTEL) {
++ if(ivideo.chip < SIS_315H) {
+ return(-1);
+- }
++ }
+ }
+ break;
+ default:
+ return(-1);
+ }
+ break;
+- case DISPTYPE_CRT2:
+- if(sisbios_mode[myindex].xres > 1280) return -1;
++
++ case CRT2_VGA:
++ if(sisbios_mode[myindex].xres > 1600) return(-1);
++ if(!(vbflags & (VB_301B|VB_302B))) {
++ if(sisbios_mode[myindex].xres > 1400) return(-1);
++ }
+ break;
+ }
+ return(myindex);
+@@ -453,15 +782,20 @@ static void sisfb_search_crt2type(const
+ return;
+
+ while(sis_crt2type[i].type_no != -1) {
+- if (!strcmp(name, sis_crt2type[i].name)) {
++ if (!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+ sisfb_crt2type = sis_crt2type[i].type_no;
+ sisfb_tvplug = sis_crt2type[i].tvplug_no;
++ sisfb_dstn = (sis_crt2type[i].flags & FL_550_DSTN) ? 1 : 0;
++ sisfb_fstn = (sis_crt2type[i].flags & FL_550_FSTN) ? 1 : 0;
+ break;
+ }
+ i++;
+ }
+ if(sisfb_crt2type < 0)
+- printk(KERN_INFO "sisfb: Invalid CRT2 type: %s\n", name);
++ printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
++ if(ivideo.chip != SIS_550) {
++ sisfb_dstn = sisfb_fstn = 0;
++ }
+ }
+
+ static void sisfb_search_queuemode(const char *name)
+@@ -472,23 +806,23 @@ static void sisfb_search_queuemode(const
+ return;
+
+ while (sis_queuemode[i].type_no != -1) {
+- if (!strcmp(name, sis_queuemode[i].name)) {
++ if (!strnicmp(name, sis_queuemode[i].name, strlen(sis_queuemode[i].name))) {
+ sisfb_queuemode = sis_queuemode[i].type_no;
+ break;
+ }
+ i++;
+ }
+ if (sisfb_queuemode < 0)
+- printk(KERN_INFO "sisfb: Invalid queuemode type: %s\n", name);
++ printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);
+ }
+
+-static u8 sisfb_search_refresh_rate(unsigned int rate)
++static u8 sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+ {
+ u16 xres, yres;
+ int i = 0;
+
+- xres = sisbios_mode[sisfb_mode_idx].xres;
+- yres = sisbios_mode[sisfb_mode_idx].yres;
++ xres = sisbios_mode[mode_idx].xres;
++ yres = sisbios_mode[mode_idx].yres;
+
+ sisfb_rate_idx = 0;
+ while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+@@ -536,23 +870,60 @@ static void sisfb_search_tvstd(const cha
+ return;
+
+ while (sis_tvtype[i].type_no != -1) {
+- if (!strcmp(name, sis_tvtype[i].name)) {
+- sisfb_tvmode = sis_tvtype[i].type_no;
++ if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
++ ivideo.vbflags |= sis_tvtype[i].type_no;
+ break;
+ }
+ i++;
+ }
+ }
+
++static void sisfb_search_specialtiming(const char *name)
++{
++ int i = 0;
++ BOOLEAN found = FALSE;
++
++ if(name == NULL)
++ return;
++
++ if(!strnicmp(name, "none", 4)) {
++ SiS_Pr.SiS_CustomT = CUT_FORCENONE;
++ printk(KERN_DEBUG "sisfb: Special timing disabled\n");
++ } else {
++ while(mycustomttable[i].chipID != 0) {
++ if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
++ SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
++ found = TRUE;
++ printk(KERN_INFO "sisfb: Special timing for %s %s forced\n",
++ mycustomttable[i].vendorName, mycustomttable[i].cardName);
++ break;
++ }
++ i++;
++ }
++ if(!found) {
++ printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
++ printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
++ i = 0;
++ while(mycustomttable[i].chipID != 0) {
++ printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
++ mycustomttable[i].optionName,
++ mycustomttable[i].vendorName,
++ mycustomttable[i].cardName);
++ i++;
++ }
++ }
++ }
++}
++
+ static BOOLEAN sisfb_bridgeisslave(void)
+ {
+- unsigned char usScratchP1_00;
++ unsigned char P1_00;
+
+- if(ivideo.hasVB == HASVB_NONE) return FALSE;
++ if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
+
+- inSISIDXREG(SISPART1,0x00,usScratchP1_00);
+- if( ((sisvga_engine == SIS_300_VGA) && (usScratchP1_00 & 0xa0) == 0x20) ||
+- ((sisvga_engine == SIS_315_VGA) && (usScratchP1_00 & 0x50) == 0x10) ) {
++ inSISIDXREG(SISPART1,0x00,P1_00);
++ if( ((sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
++ ((sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+ return TRUE;
+ } else {
+ return FALSE;
+@@ -597,7 +968,7 @@ static BOOLEAN sisfbcheckvretracecrt2(vo
+
+ static BOOLEAN sisfb_CheckVBRetrace(void)
+ {
+- if(ivideo.disp_state & DISPTYPE_DISP2) {
++ if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+ if(sisfb_bridgeisslave()) {
+ return(sisfbcheckvretracecrt1());
+ } else {
+@@ -607,60 +978,195 @@ static BOOLEAN sisfb_CheckVBRetrace(void
+ return(sisfbcheckvretracecrt1());
+ }
+
++static int sisfb_myblank(int blank)
++{
++ u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
++ BOOLEAN backlight = TRUE;
++
++ switch(blank) {
++ case 0: /* on */
++ sr01 = 0x00;
++ sr11 = 0x00;
++ sr1f = 0x00;
++ cr63 = 0x00;
++ p2_0 = 0x20;
++ p1_13 = 0x00;
++ backlight = TRUE;
++ break;
++ case 1: /* blank */
++ sr01 = 0x20;
++ sr11 = 0x00;
++ sr1f = 0x00;
++ cr63 = 0x00;
++ p2_0 = 0x20;
++ p1_13 = 0x00;
++ backlight = TRUE;
++ break;
++ case 2: /* no vsync */
++ sr01 = 0x20;
++ sr11 = 0x08;
++ sr1f = 0x80;
++ cr63 = 0x40;
++ p2_0 = 0x40;
++ p1_13 = 0x80;
++ backlight = FALSE;
++ break;
++ case 3: /* no hsync */
++ sr01 = 0x20;
++ sr11 = 0x08;
++ sr1f = 0x40;
++ cr63 = 0x40;
++ p2_0 = 0x80;
++ p1_13 = 0x40;
++ backlight = FALSE;
++ break;
++ case 4: /* off */
++ sr01 = 0x20;
++ sr11 = 0x08;
++ sr1f = 0xc0;
++ cr63 = 0x40;
++ p2_0 = 0xc0;
++ p1_13 = 0xc0;
++ backlight = FALSE;
++ break;
++ default:
++ return 1;
++ }
++
++ if(ivideo.currentvbflags & VB_DISPTYPE_CRT1) {
++
++ setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
++
++ if( (!sisfb_thismonitor.datavalid) ||
++ ((sisfb_thismonitor.datavalid) &&
++ (sisfb_thismonitor.feature & 0xe0))) {
++
++ if(sisvga_engine == SIS_315_VGA) {
++ setSISIDXREG(SISCR, 0x63, 0xbf, cr63);
++ }
++
++ setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
++ }
++
++ }
++
++ if(ivideo.currentvbflags & CRT2_LCD) {
++
++ if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
++ if(backlight) {
++ SiS_SiS30xBLOn(&SiS_Pr, &sishw_ext);
++ } else {
++ SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
++ }
++ } else if(sisvga_engine == SIS_315_VGA) {
++ if(ivideo.vbflags & VB_CHRONTEL) {
++ if(backlight) {
++ SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
++ } else {
++ SiS_Chrontel701xBLOff(&SiS_Pr);
++ }
++ }
++ }
++
++ if(((sisvga_engine == SIS_300_VGA) &&
++ (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
++ ((sisvga_engine == SIS_315_VGA) &&
++ ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
++ setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
++ }
++
++ if(sisvga_engine == SIS_300_VGA) {
++ if((ivideo.vbflags & (VB_301B|VB_302B)) &&
++ (!(ivideo.vbflags & VB_30xBDH))) {
++ setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
++ }
++ } else if(sisvga_engine == SIS_315_VGA) {
++ if((ivideo.vbflags & (VB_301B|VB_302B)) &&
++ (!(ivideo.vbflags & VB_30xBDH))) {
++ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
++ }
++ }
++
++ } else if(ivideo.currentvbflags & CRT2_VGA) {
++
++ if(ivideo.vbflags & (VB_301B|VB_302B)) {
++ setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
++ }
++
++ }
++
++ return(0);
++}
++
+ /* ----------- FBDev related routines for all series ----------- */
+
++static void sisfb_set_vparms(void)
++{
++ switch(ivideo.video_bpp) {
++ case 8:
++ ivideo.DstColor = 0x0000;
++ ivideo.SiS310_AccelDepth = 0x00000000;
++ ivideo.video_cmap_len = 256;
++ break;
++ case 16:
++ ivideo.DstColor = 0x8000;
++ ivideo.SiS310_AccelDepth = 0x00010000;
++ ivideo.video_cmap_len = 16;
++ break;
++ case 32:
++ ivideo.DstColor = 0xC000;
++ ivideo.SiS310_AccelDepth = 0x00020000;
++ ivideo.video_cmap_len = 16;
++ break;
++ default:
++ ivideo.video_cmap_len = 16;
++ printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);
++ ivideo.accel = 0;
++ break;
++ }
++}
++
+ static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info)
+ {
+- unsigned int htotal =
+- var->left_margin + var->xres + var->right_margin +
+- var->hsync_len;
+- unsigned int vtotal = 0;
++ unsigned int htotal = 0, vtotal = 0;
+ double drate = 0, hrate = 0;
+ int found_mode = 0;
+ int old_mode;
+- unsigned char reg;
++ u32 pixclock;
+
+- TWDEBUG("Inside do_set_var");
+-
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+- inSISIDXREG(SISCR,0x34,reg);
+- if(reg & 0x80) {
+- printk(KERN_INFO "sisfb: Cannot change display mode, X server is active\n");
+- return -EBUSY;
+- }
+-#endif
++ htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
++
++ vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
++
++ pixclock = var->pixclock;
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+- vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
+ vtotal <<= 1;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+- vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
+ vtotal <<= 2;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+- vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
+- var->vsync_len;
+- } else vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
++ vtotal <<= 1;
++ } else vtotal += var->yres;
+
+ if(!(htotal) || !(vtotal)) {
+ DPRINTK("sisfb: Invalid 'var' information\n");
+ return -EINVAL;
+ }
+
+- if(var->pixclock && htotal && vtotal) {
+- drate = 1E12 / var->pixclock;
++ if(pixclock && htotal && vtotal) {
++ drate = 1E12 / pixclock;
+ hrate = drate / htotal;
+ ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+ } else ivideo.refresh_rate = 60;
+
+- /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
+- if((var->xres == 1024) && (var->yres == 600)) ivideo.refresh_rate = 60;
+-
++#if 0
+ printk(KERN_DEBUG "sisfb: Change mode to %dx%dx%d-%dHz\n",
+ var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);
++#endif
+
+ old_mode = sisfb_mode_idx;
+ sisfb_mode_idx = 0;
+@@ -678,7 +1184,7 @@ static int sisfb_do_set_var(struct fb_va
+ }
+
+ if(found_mode)
+- sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx);
++ sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
+ else
+ sisfb_mode_idx = -1;
+
+@@ -689,12 +1195,21 @@ static int sisfb_do_set_var(struct fb_va
+ return -EINVAL;
+ }
+
+- if(sisfb_search_refresh_rate(ivideo.refresh_rate) == 0) {
++ if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+ ivideo.refresh_rate = 60;
+ }
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ if(sisfb_thismonitor.datavalid) {
++ if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
++ sisfb_rate_idx, ivideo.refresh_rate)) {
++ printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
++ }
++ }
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
+ #else
+ if(isactive) {
+@@ -708,14 +1223,6 @@ static int sisfb_do_set_var(struct fb_va
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+- sisfb_post_setmode();
+-
+- DPRINTK("sisfb: Set new mode: %dx%dx%d-%d \n",
+- sisbios_mode[sisfb_mode_idx].xres,
+- sisbios_mode[sisfb_mode_idx].yres,
+- sisbios_mode[sisfb_mode_idx].bpp,
+- ivideo.refresh_rate);
+-
+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
+ ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
+@@ -725,53 +1232,38 @@ static int sisfb_do_set_var(struct fb_va
+ if(sisfb_accel) {
+ ivideo.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
+ }
+- switch(ivideo.video_bpp) {
+- case 8:
+- ivideo.DstColor = 0x0000;
+- ivideo.SiS310_AccelDepth = 0x00000000;
+- ivideo.video_cmap_len = 256;
+- break;
+- case 16:
+- ivideo.DstColor = 0x8000;
+- ivideo.SiS310_AccelDepth = 0x00010000;
+- ivideo.video_cmap_len = 16;
+- break;
+- case 32:
+- ivideo.DstColor = 0xC000;
+- ivideo.SiS310_AccelDepth = 0x00020000;
+- ivideo.video_cmap_len = 16;
+- break;
+- default:
+- ivideo.video_cmap_len = 16;
+- printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);
+- ivideo.accel = 0;
+- break;
+- }
++
++ sisfb_set_vparms();
++
++ ivideo.current_width = ivideo.video_width;
++ ivideo.current_height = ivideo.video_height;
++ ivideo.current_bpp = ivideo.video_bpp;
++ ivideo.current_htotal = htotal;
++ ivideo.current_vtotal = vtotal;
++ ivideo.current_pixclock = var->pixclock;
++ ivideo.current_refresh_rate = ivideo.refresh_rate;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ sisfb_lastrates[sisfb_mode_no] = ivideo.refresh_rate;
++#endif
++
++ sisfb_post_setmode();
+
+ }
+- TWDEBUG("End of do_set_var");
+ return 0;
+ }
+
+-#ifdef SISFB_PAN
+ static int sisfb_pan_var(struct fb_var_screeninfo *var)
+ {
+ unsigned int base;
+
+- TWDEBUG("Inside pan_var");
+-
+ if (var->xoffset > (var->xres_virtual - var->xres)) {
+- printk(KERN_INFO "Pan: xo: %d xv %d xr %d\n",
+- var->xoffset, var->xres_virtual, var->xres);
+ return -EINVAL;
+ }
+ if(var->yoffset > (var->yres_virtual - var->yres)) {
+- printk(KERN_INFO "Pan: yo: %d yv %d yr %d\n",
+- var->yoffset, var->yres_virtual, var->yres);
+ return -EINVAL;
+ }
+
+- base = var->yoffset * var->xres_virtual + var->xoffset;
++ base = var->yoffset * var->xres_virtual + var->xoffset;
+
+ /* calculate base bpp dep. */
+ switch(var->bits_per_pixel) {
+@@ -794,7 +1286,7 @@ static int sisfb_pan_var(struct fb_var_s
+ if(sisvga_engine == SIS_315_VGA) {
+ setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
+ }
+- if(ivideo.disp_state & DISPTYPE_DISP2) {
++ if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+ orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+ outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
+ outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
+@@ -803,10 +1295,8 @@ static int sisfb_pan_var(struct fb_var_s
+ setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
+ }
+ }
+- TWDEBUG("End of pan_var");
+ return 0;
+ }
+-#endif
+
+ static void sisfb_bpp_to_var(struct fb_var_screeninfo *var)
+ {
+@@ -843,22 +1333,24 @@ static void sisfb_bpp_to_var(struct fb_v
+
+ void sis_dispinfo(struct ap_data *rec)
+ {
+- rec->minfo.bpp = ivideo.video_bpp;
+- rec->minfo.xres = ivideo.video_width;
+- rec->minfo.yres = ivideo.video_height;
+- rec->minfo.v_xres = ivideo.video_vwidth;
+- rec->minfo.v_yres = ivideo.video_vheight;
+- rec->minfo.org_x = ivideo.org_x;
+- rec->minfo.org_y = ivideo.org_y;
+- rec->minfo.vrate = ivideo.refresh_rate;
+- rec->iobase = ivideo.vga_base - 0x30;
+- rec->mem_size = ivideo.video_size;
+- rec->disp_state = ivideo.disp_state;
+- rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+- rec->hasVB = ivideo.hasVB;
+- rec->TV_type = ivideo.TV_type;
+- rec->TV_plug = ivideo.TV_plug;
+- rec->chip = ivideo.chip;
++ rec->minfo.bpp = ivideo.video_bpp;
++ rec->minfo.xres = ivideo.video_width;
++ rec->minfo.yres = ivideo.video_height;
++ rec->minfo.v_xres = ivideo.video_vwidth;
++ rec->minfo.v_yres = ivideo.video_vheight;
++ rec->minfo.org_x = ivideo.org_x;
++ rec->minfo.org_y = ivideo.org_y;
++ rec->minfo.vrate = ivideo.refresh_rate;
++ rec->iobase = ivideo.vga_base - 0x30;
++ rec->mem_size = ivideo.video_size;
++ rec->disp_state = ivideo.disp_state;
++ rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
++ rec->hasVB = ivideo.hasVB;
++ rec->TV_type = ivideo.TV_type;
++ rec->TV_plug = ivideo.TV_plug;
++ rec->chip = ivideo.chip;
++ rec->vbflags = ivideo.vbflags;
++ rec->currentvbflags = ivideo.currentvbflags;
+ }
+
+ /* ------------ FBDev related routines for 2.4 series ----------- */
+@@ -873,7 +1365,6 @@ static void sisfb_crtc_to_var(struct fb_
+ int A, B, C, D, E, F, temp;
+ double hrate, drate;
+
+- TWDEBUG("Inside crtc_to_var");
+ inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
+
+ if (sr_data & SIS_INTERLACED_MODE)
+@@ -921,6 +1412,8 @@ static void sisfb_crtc_to_var(struct fb_
+
+ inSISIDXREG(SISCR, 0x09, cr_data3);
+
++ if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
++
+ VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
+ ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+
+@@ -939,26 +1432,22 @@ static void sisfb_crtc_to_var(struct fb_
+ D = B - F - C;
+
+ var->yres = E;
+-#ifndef SISFB_PAN
+- var->yres_virtual = E;
+-#endif
+- /* TW: We have to report the physical dimension to the console! */
++ var->upper_margin = D;
++ var->lower_margin = F;
++ var->vsync_len = C;
++
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ var->yres <<= 1;
+-#ifndef SISFB_PAN
+- var->yres_virtual <<= 1;
+-#endif
++ var->upper_margin <<= 1;
++ var->lower_margin <<= 1;
++ var->vsync_len <<= 1;
+ } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+ var->yres >>= 1;
+-#ifndef SISFB_PAN
+- var->yres_virtual >>= 1;
+-#endif
++ var->upper_margin >>= 1;
++ var->lower_margin >>= 1;
++ var->vsync_len >>= 1;
+ }
+
+- var->upper_margin = D;
+- var->lower_margin = F;
+- var->vsync_len = C;
+-
+ inSISIDXREG(SISSR, 0x0b, sr_data);
+
+ inSISIDXREG(SISCR, 0x00, cr_data);
+@@ -999,10 +1488,20 @@ static void sisfb_crtc_to_var(struct fb_
+ D = B - F - C;
+
+ var->xres = var->xres_virtual = E * 8;
+- var->left_margin = D * 8;
+- var->right_margin = F * 8;
+- var->hsync_len = C * 8;
+
++ if((var->xres == 320) &&
++ (var->yres == 200 || var->yres == 240)) {
++ /* Terrible hack, but the correct CRTC data for
++ * these modes only produces a black screen...
++ */
++ var->left_margin = (400 - 376);
++ var->right_margin = (328 - 320);
++ var->hsync_len = (376 - 328);
++ } else {
++ var->left_margin = D * 8;
++ var->right_margin = F * 8;
++ var->hsync_len = C * 8;
++ }
+ var->activate = FB_ACTIVATE_NOW;
+
+ var->sync = 0;
+@@ -1022,21 +1521,21 @@ static void sisfb_crtc_to_var(struct fb_
+ VT <<= 1;
+ HT = (HT + 5) * 8;
+
++ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
++ VT <<= 1;
++ }
+ hrate = (double) ivideo.refresh_rate * (double) VT / 2;
+ drate = hrate * HT;
+ var->pixclock = (u32) (1E12 / drate);
+
+-#ifdef SISFB_PAN
+ if(sisfb_ypan) {
+ var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+ if(var->yres_virtual <= var->yres) {
+ var->yres_virtual = var->yres;
+ }
+ } else
+-#endif
+- var->yres_virtual = var->yres;
++ var->yres_virtual = var->yres;
+
+- TWDEBUG("end of crtc_to_var");
+ }
+
+ static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+@@ -1069,7 +1568,7 @@ static int sisfb_setcolreg(unsigned regn
+ outSISREG(SISDACD, (red >> 10));
+ outSISREG(SISDACD, (green >> 10));
+ outSISREG(SISDACD, (blue >> 10));
+- if (ivideo.disp_state & DISPTYPE_DISP2) {
++ if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+ outSISREG(SISDAC2A, regno);
+ outSISREG(SISDAC2D, (red >> 8));
+ outSISREG(SISDAC2D, (green >> 8));
+@@ -1118,7 +1617,7 @@ static void sisfb_set_disp(int con, stru
+ display->ywrapstep = fix.ywrapstep;
+ display->line_length = fix.line_length;
+ display->next_line = fix.line_length;
+- display->can_soft_blank = 0;
++ display->can_soft_blank = 1;
+ display->inverse = sisfb_inverse;
+ display->var = *var;
+
+@@ -1162,17 +1661,12 @@ static void sisfb_set_disp(int con, stru
+ display->dispsw = &sisfb_sw;
+ restore_flags(flags);
+
+-#ifdef SISFB_PAN
+- if((ivideo.accel) && (sisfb_ypan)) {
+- /* display->scrollmode = SCROLL_YPAN; - not defined */
++ if(sisfb_ypan) {
++ /* display->scrollmode = 0; */
+ } else {
+ display->scrollmode = SCROLL_YREDRAW;
+ sisfb_sw.bmove = fbcon_redraw_bmove;
+ }
+-#else
+- display->scrollmode = SCROLL_YREDRAW;
+- sisfb_sw.bmove = fbcon_redraw_bmove;
+-#endif
+ }
+
+ static void sisfb_do_install_cmap(int con, struct fb_info *info)
+@@ -1191,17 +1685,16 @@ static void sisfb_do_install_cmap(int co
+ static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+ {
+- TWDEBUG("inside get_var");
+ if(con == -1)
+ memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+ else
+ *var = fb_display[con].var;
+
+- /* For FSTN, DSTN */
+- if (var->xres == 320 && var->yres == 480)
++ if(sisfb_fstn) {
++ if (var->xres == 320 && var->yres == 480)
+ var->yres = 240;
+-
+- TWDEBUG("end of get_var");
++ }
++
+ return 0;
+ }
+
+@@ -1211,8 +1704,6 @@ static int sisfb_set_var(struct fb_var_s
+ int err;
+ unsigned int cols, rows;
+
+- TWDEBUG("inside set_var");
+-
+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
+ if(sisfb_do_set_var(var, con == currcon, info)) {
+ sisfb_crtc_to_var(var);
+@@ -1233,16 +1724,17 @@ static int sisfb_set_var(struct fb_var_s
+
+ cols = sisbios_mode[sisfb_mode_idx].cols;
+ rows = sisbios_mode[sisfb_mode_idx].rows;
+- vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
++#if 0
++ /* Why was this called here? */
++ vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
++#endif
+
+- TWDEBUG("end of set_var");
+ return 0;
+ }
+
+ static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+ {
+- TWDEBUG("inside get_cmap");
+ if (con == currcon)
+ return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
+
+@@ -1251,7 +1743,6 @@ static int sisfb_get_cmap(struct fb_cmap
+ else
+ fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);
+
+- TWDEBUG("end of get_cmap");
+ return 0;
+ }
+
+@@ -1260,7 +1751,6 @@ static int sisfb_set_cmap(struct fb_cmap
+ {
+ int err;
+
+- TWDEBUG("inside set_cmap");
+ if (!fb_display[con].cmap.len) {
+ err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
+ if (err)
+@@ -1272,17 +1762,15 @@ static int sisfb_set_cmap(struct fb_cmap
+
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+- TWDEBUG("end of set_cmap");
++
+ return 0;
+ }
+
+-#ifdef SISFB_PAN
+ static int sisfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info* info)
+ {
+ int err;
+-
+- TWDEBUG("inside pan_display");
++
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+ return -EINVAL;
+@@ -1303,10 +1791,8 @@ static int sisfb_pan_display(struct fb_v
+ else
+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+
+- TWDEBUG("end of pan_display");
+ return 0;
+ }
+-#endif
+
+ static int sisfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma)
+@@ -1316,7 +1802,6 @@ static int sisfb_mmap(struct fb_info *in
+ unsigned long off;
+ u32 len, mmio_off;
+
+- TWDEBUG("inside mmap");
+ if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+@@ -1351,11 +1836,11 @@ static int sisfb_mmap(struct fb_info *in
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+ #endif
++ /* RedHat requires vma as the first paramater to the following call */
+ if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+- TWDEBUG("end of mmap");
+ return 0;
+ }
+
+@@ -1368,7 +1853,6 @@ static void sis_get_glyph(struct fb_info
+ u8 *gbuf = gly->gmask;
+ int size;
+
+- TWDEBUG("Inside get_glyph");
+ gly->fontheight = fontheight(p);
+ gly->fontwidth = fontwidth(p);
+ widthb = (fontwidth(p) + 7) / 8;
+@@ -1382,16 +1866,11 @@ static void sis_get_glyph(struct fb_info
+ size = fontheight(p) * widthb;
+ memcpy(gbuf, cdat, size);
+ gly->ngmask = size;
+- TWDEBUG("End of get_glyph");
+ }
+
+ static int sisfb_update_var(int con, struct fb_info *info)
+ {
+-#ifdef SISFB_PAN
+ return(sisfb_pan_var(&fb_display[con].var));
+-#else
+- return 0;
+-#endif
+ }
+
+ static int sisfb_switch(int con, struct fb_info *info)
+@@ -1428,127 +1907,7 @@ static int sisfb_switch(int con, struct
+
+ static void sisfb_blank(int blank, struct fb_info *info)
+ {
+- u8 reg;
+-
+- inSISIDXREG(SISCR, 0x17, reg);
+-
+- if(blank > 0)
+- reg &= 0x7f;
+- else
+- reg |= 0x80;
+-
+- outSISIDXREG(SISCR, 0x17, reg);
+- outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */
+- outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */
+- printk(KERN_DEBUG "sisfb_blank() called (%d)\n", blank);
+-}
+-
+-
+-static int sisfb_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg, int con,
+- struct fb_info *info)
+-{
+- TWDEBUG("inside ioctl");
+- switch (cmd) {
+- case FBIO_ALLOC:
+- if (!capable(CAP_SYS_RAWIO))
+- return -EPERM;
+- sis_malloc((struct sis_memreq *) arg);
+- break;
+- case FBIO_FREE:
+- if (!capable(CAP_SYS_RAWIO))
+- return -EPERM;
+- sis_free(*(unsigned long *) arg);
+- break;
+- case FBIOGET_GLYPH:
+- sis_get_glyph(info,(SIS_GLYINFO *) arg);
+- break;
+- case FBIOGET_HWCINFO:
+- {
+- unsigned long *hwc_offset = (unsigned long *) arg;
+-
+- if (sisfb_caps & HW_CURSOR_CAP)
+- *hwc_offset = sisfb_hwcursor_vbase -
+- (unsigned long) ivideo.video_vbase;
+- else
+- *hwc_offset = 0;
+-
+- break;
+- }
+- case FBIOPUT_MODEINFO:
+- {
+- struct mode_info *x = (struct mode_info *)arg;
+-
+- ivideo.video_bpp = x->bpp;
+- ivideo.video_width = x->xres;
+- ivideo.video_height = x->yres;
+- ivideo.video_vwidth = x->v_xres;
+- ivideo.video_vheight = x->v_yres;
+- ivideo.org_x = x->org_x;
+- ivideo.org_y = x->org_y;
+- ivideo.refresh_rate = x->vrate;
+- ivideo.video_linelength = ivideo.video_vwidth * (ivideo.video_bpp >> 3);
+- switch(ivideo.video_bpp) {
+- case 8:
+- ivideo.DstColor = 0x0000;
+- ivideo.SiS310_AccelDepth = 0x00000000;
+- ivideo.video_cmap_len = 256;
+- break;
+- case 16:
+- ivideo.DstColor = 0x8000;
+- ivideo.SiS310_AccelDepth = 0x00010000;
+- ivideo.video_cmap_len = 16;
+- break;
+- case 32:
+- ivideo.DstColor = 0xC000;
+- ivideo.SiS310_AccelDepth = 0x00020000;
+- ivideo.video_cmap_len = 16;
+- break;
+- default:
+- ivideo.video_cmap_len = 16;
+- printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);
+- ivideo.accel = 0;
+- break;
+- }
+-
+- break;
+- }
+- case FBIOGET_DISPINFO:
+- sis_dispinfo((struct ap_data *)arg);
+- break;
+- case SISFB_GET_INFO: /* TW: New for communication with X driver */
+- {
+- sisfb_info *x = (sisfb_info *)arg;
+-
+- x->sisfb_id = SISFB_ID;
+- x->sisfb_version = VER_MAJOR;
+- x->sisfb_revision = VER_MINOR;
+- x->sisfb_patchlevel = VER_LEVEL;
+- x->chip_id = ivideo.chip_id;
+- x->memory = ivideo.video_size / 1024;
+- x->heapstart = ivideo.heapstart / 1024;
+- x->fbvidmode = sisfb_mode_no;
+- x->sisfb_caps = sisfb_caps;
+- x->sisfb_tqlen = 512; /* yet unused */
+- x->sisfb_pcibus = ivideo.pcibus;
+- x->sisfb_pcislot = ivideo.pcislot;
+- x->sisfb_pcifunc = ivideo.pcifunc;
+- x->sisfb_lcdpdc = sisfb_detectedpdc;
+- x->sisfb_lcda = sisfb_detectedlcda;
+- break;
+- }
+- case SISFB_GET_VBRSTATUS:
+- {
+- unsigned long *vbrstatus = (unsigned long *) arg;
+- if(sisfb_CheckVBRetrace()) *vbrstatus = 1;
+- else *vbrstatus = 0;
+- }
+- default:
+- return -EINVAL;
+- }
+- TWDEBUG("end of ioctl");
+- return 0;
+-
++ sisfb_myblank(blank);
+ }
+ #endif
+
+@@ -1575,11 +1934,9 @@ static int sisfb_get_cmap_len(const stru
+ rc = 256;
+ break;
+ case 16:
+- rc = 16;
+- break;
+ case 32:
+ rc = 16;
+- break;
++ break;
+ }
+ return rc;
+ }
+@@ -1596,7 +1953,7 @@ static int sisfb_setcolreg(unsigned regn
+ outSISREG(SISDACD, (red >> 10));
+ outSISREG(SISDACD, (green >> 10));
+ outSISREG(SISDACD, (blue >> 10));
+- if (ivideo.disp_state & DISPTYPE_DISP2) {
++ if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+ outSISREG(SISDAC2A, regno);
+ outSISREG(SISDAC2D, (red >> 8));
+ outSISREG(SISDAC2D, (green >> 8));
+@@ -1622,63 +1979,52 @@ static int sisfb_set_par(struct fb_info
+ {
+ int err;
+
+- TWDEBUG("inside set_par");
+ if((err = sisfb_do_set_var(&info->var, 1, info)))
+ return err;
+
+ sisfb_get_fix(&info->fix, info->currcon, info);
+
+- TWDEBUG("end of set_par");
+ return 0;
+ }
+
+ static int sisfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+ {
+- unsigned int htotal =
+- var->left_margin + var->xres + var->right_margin +
+- var->hsync_len;
+- unsigned int vtotal = 0;
++ unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
+ double drate = 0, hrate = 0;
+ int found_mode = 0;
+ int refresh_rate, search_idx;
++ BOOLEAN recalc_clock = FALSE;
++ u32 pixclock;
++
++ htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
++
++ vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
+
+- TWDEBUG("Inside check_var");
++ pixclock = var->pixclock;
+
+ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+- vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
+ vtotal <<= 1;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+- vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
+ vtotal <<= 2;
+ } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+- vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
+- var->vsync_len;
+- } else vtotal = var->upper_margin + var->yres + var->lower_margin +
+- var->vsync_len;
++ vtotal += var->yres;
++ vtotal <<= 1;
++ } else vtotal += var->yres;
+
+ if(!(htotal) || !(vtotal)) {
+ SISFAIL("sisfb: no valid timing data");
+ }
+
+- if((var->pixclock) && (htotal)) {
+- drate = 1E12 / var->pixclock;
+- hrate = drate / htotal;
+- refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+- } else refresh_rate = 60;
+-
+- /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
+- if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
+-
+ search_idx = 0;
+ while( (sisbios_mode[search_idx].mode_no != 0) &&
+ (sisbios_mode[search_idx].xres <= var->xres) ) {
+ if( (sisbios_mode[search_idx].xres == var->xres) &&
+ (sisbios_mode[search_idx].yres == var->yres) &&
+ (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
+- if(sisfb_validate_mode(search_idx) > 0) {
++ if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+ found_mode = 1;
+ break;
+ }
+@@ -1687,38 +2033,95 @@ static int sisfb_check_var(struct fb_var
+ }
+
+ if(!found_mode) {
+-
+- printk(KERN_ERR "sisfb: %dx%dx%d is no valid mode\n",
+- var->xres, var->yres, var->bits_per_pixel);
+-
++
+ search_idx = 0;
+ while(sisbios_mode[search_idx].mode_no != 0) {
+-
+ if( (var->xres <= sisbios_mode[search_idx].xres) &&
+- (var->yres <= sisbios_mode[search_idx].yres) &&
++ (var->yres <= sisbios_mode[search_idx].yres) &&
+ (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
+- if(sisfb_validate_mode(search_idx) > 0) {
++ if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+ found_mode = 1;
+ break;
+ }
+ }
+ search_idx++;
+- }
++ }
+ if(found_mode) {
++ printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
++ var->xres, var->yres, var->bits_per_pixel,
++ sisbios_mode[search_idx].xres,
++ sisbios_mode[search_idx].yres,
++ var->bits_per_pixel);
+ var->xres = sisbios_mode[search_idx].xres;
+ var->yres = sisbios_mode[search_idx].yres;
+- printk(KERN_DEBUG "sisfb: Adapted to mode %dx%dx%d\n",
+- var->xres, var->yres, var->bits_per_pixel);
+-
++
++
+ } else {
+- printk(KERN_ERR "sisfb: Failed to find similar mode to %dx%dx%d\n",
++ printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return -EINVAL;
+ }
+ }
+
+- /* TW: TODO: Check the refresh rate */
+-
++ if( ((ivideo.vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */
++ ((ivideo.vbflags & VB_30xBDH) && (ivideo.currentvbflags & CRT2_LCD))) &&
++ (var->bits_per_pixel == 8) ) {
++ refresh_rate = 60;
++ recalc_clock = TRUE;
++ } else if( (ivideo.current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */
++ (ivideo.current_vtotal == vtotal) &&
++ (ivideo.current_pixclock == pixclock) ) {
++ drate = 1E12 / pixclock;
++ hrate = drate / htotal;
++ refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
++ } else if( ( (ivideo.current_htotal != htotal) || /* x!=x | y!=y & c=c -> invalid pixclock */
++ (ivideo.current_vtotal != vtotal) ) &&
++ (ivideo.current_pixclock == var->pixclock) ) {
++ if(sisfb_lastrates[sisbios_mode[search_idx].mode_no]) {
++ refresh_rate = sisfb_lastrates[sisbios_mode[search_idx].mode_no];
++ } else if(sisfb_parm_rate != -1) {
++ refresh_rate = sisfb_parm_rate;
++ } else {
++ refresh_rate = 60;
++ }
++ recalc_clock = TRUE;
++ } else if((pixclock) && (htotal) && (vtotal)) {
++ drate = 1E12 / pixclock;
++ hrate = drate / htotal;
++ refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
++ } else if(ivideo.current_refresh_rate) {
++ refresh_rate = ivideo.current_refresh_rate;
++ recalc_clock = TRUE;
++ } else {
++ refresh_rate = 60;
++ recalc_clock = TRUE;
++ }
++
++ myrateindex = sisfb_search_refresh_rate(refresh_rate, search_idx);
++
++ /* Eventually recalculate timing and clock */
++ if(recalc_clock) {
++ if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
++ var->pixclock = (u32) (1E12 / sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
++ sisbios_mode[search_idx].mode_no, myrateindex));
++ sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
++ sisbios_mode[search_idx].mode_no, myrateindex,
++ &var->left_margin, &var->right_margin,
++ &var->upper_margin, &var->lower_margin,
++ &var->hsync_len, &var->vsync_len,
++ &var->sync, &var->vmode);
++ if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
++ var->pixclock <<= 1;
++ }
++ }
++
++ if(sisfb_thismonitor.datavalid) {
++ if(!sisfb_verify_rate(&sisfb_thismonitor, search_idx,
++ myrateindex, refresh_rate)) {
++ printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
++ }
++ }
++
+ /* Adapt RGB settings */
+ sisfb_bpp_to_var(var);
+
+@@ -1732,17 +2135,19 @@ static int sisfb_check_var(struct fb_var
+ if(var->xres != var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+- if(!sisfb_ypan) {
+- if(var->yres != var->yres_virtual)
+- var->yres_virtual = var->yres;
+- } else {
++ if(sisfb_ypan) {
+ /* TW: Now patch yres_virtual if we use panning */
+ /* *** May I do this? *** */
+ var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+- if(var->yres_virtual <= var->yres) {
++ if(var->yres_virtual <= var->yres) {
+ /* TW: Paranoia check */
+ var->yres_virtual = var->yres;
+- }
++ }
++ } else {
++ if(var->yres != var->yres_virtual)
++ var->yres_virtual = var->yres;
++ var->xoffset = 0;
++ var->yoffset = 0;
+ }
+
+ /* Truncate offsets to maximum if too high */
+@@ -1757,28 +2162,25 @@ static int sisfb_check_var(struct fb_var
+ var->green.msb_right =
+ var->blue.msb_right =
+ var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+-
+- TWDEBUG("end of check_var");
++
+ return 0;
+ }
+
+-#ifdef SISFB_PAN
+ static int sisfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info* info)
+ {
+ int err;
+-
+- TWDEBUG("inside pan_display");
+-
++
+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;
+ if (var->yoffset > (var->yres_virtual - var->yres))
+ return -EINVAL;
+
+ if (var->vmode & FB_VMODE_YWRAP) {
+- if (var->yoffset < 0
+- || var->yoffset >= info->var.yres_virtual
+- || var->xoffset) return -EINVAL;
++ if (var->yoffset < 0 ||
++ var->yoffset >= info->var.yres_virtual ||
++ var->xoffset)
++ return -EINVAL;
+ } else {
+ if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+ var->yoffset + info->var.yres > info->var.yres_virtual)
+@@ -1794,10 +2196,8 @@ static int sisfb_pan_display(struct fb_v
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+- TWDEBUG("end of pan_display");
+ return 0;
+ }
+-#endif
+
+ static int sisfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma)
+@@ -1806,7 +2206,6 @@ static int sisfb_mmap(struct fb_info *in
+ unsigned long off;
+ u32 len, mmio_off;
+
+- TWDEBUG("inside mmap");
+ if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
+
+ off = vma->vm_pgoff << PAGE_SHIFT;
+@@ -1844,139 +2243,143 @@ static int sisfb_mmap(struct fb_info *in
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+- TWDEBUG("end of mmap");
+ return 0;
+ }
+
+ static int sisfb_blank(int blank, struct fb_info *info)
+ {
+- u8 reg;
++ return(sisfb_myblank(blank));
++}
+
+- inSISIDXREG(SISCR, 0x17, reg);
++#endif
+
+- if(blank > 0)
+- reg &= 0x7f;
+- else
+- reg |= 0x80;
++/* ----------- FBDev related routines for all series ---------- */
+
+- outSISIDXREG(SISCR, 0x17, reg);
+- outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */
+- outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */
+- return(0);
+-}
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++static int sisfb_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg,
++ struct fb_info *info)
++#else
+ static int sisfb_ioctl(struct inode *inode, struct file *file,
+- unsigned int cmd, unsigned long arg,
++ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info)
++#endif
+ {
+- TWDEBUG("inside ioctl");
++ struct sis_memreq sismemreq;
++ struct ap_data sisapdata;
++ unsigned long sismembase = 0;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ SIS_GLYINFO sisglyinfo;
++#endif
++
+ switch (cmd) {
+ case FBIO_ALLOC:
+- if (!capable(CAP_SYS_RAWIO))
++ if(!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+- sis_malloc((struct sis_memreq *) arg);
++ if(copy_from_user(&sismemreq, (void *)arg, sizeof(sismemreq)))
++ return -EFAULT;
++ sis_malloc(&sismemreq);
++ if(copy_to_user((void *)arg, &sismemreq, sizeof(sismemreq))) {
++ sis_free(sismemreq.offset);
++ return -EFAULT;
++ }
+ break;
+ case FBIO_FREE:
+- if (!capable(CAP_SYS_RAWIO))
++ if(!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+- sis_free(*(unsigned long *) arg);
++ if(get_user(sismembase, (unsigned long *) arg))
++ return -EFAULT;
++ sis_free(sismembase);
+ break;
+- case FBIOGET_HWCINFO:
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ case FBIOGET_GLYPH:
++ if(copy_from_user(&sisglyinfo, (void *)arg, sizeof(sisglyinfo)))
++ return -EFAULT;
++ sis_get_glyph(info, &sisglyinfo);
++ break;
++ case FBIOPUT_MODEINFO:
+ {
+- unsigned long *hwc_offset = (unsigned long *) arg;
++ struct mode_info x;
+
+- if (sisfb_caps & HW_CURSOR_CAP)
+- *hwc_offset = sisfb_hwcursor_vbase -
+- (unsigned long) ivideo.video_vbase;
+- else
+- *hwc_offset = 0;
++ if(copy_from_user(&x, (void *)arg, sizeof(x)))
++ return -EFAULT;
+
++ ivideo.video_bpp = x.bpp;
++ ivideo.video_width = x.xres;
++ ivideo.video_height = x.yres;
++ ivideo.video_vwidth = x.v_xres;
++ ivideo.video_vheight = x.v_yres;
++ ivideo.org_x = x.org_x;
++ ivideo.org_y = x.org_y;
++ ivideo.refresh_rate = x.vrate;
++ ivideo.video_linelength = ivideo.video_vwidth * (ivideo.video_bpp >> 3);
++ sisfb_set_vparms();
+ break;
+ }
+- case FBIOPUT_MODEINFO:
++#endif
++ case FBIOGET_HWCINFO:
+ {
+- struct mode_info *x = (struct mode_info *)arg;
++ unsigned long myhwcoffset = 0;
+
+- ivideo.video_bpp = x->bpp;
+- ivideo.video_width = x->xres;
+- ivideo.video_height = x->yres;
+- ivideo.video_vwidth = x->v_xres;
+- ivideo.video_vheight = x->v_yres;
+- ivideo.org_x = x->org_x;
+- ivideo.org_y = x->org_y;
+- ivideo.refresh_rate = x->vrate;
+- ivideo.video_linelength = ivideo.video_vwidth * (ivideo.video_bpp >> 3);
+- switch(ivideo.video_bpp) {
+- case 8:
+- ivideo.DstColor = 0x0000;
+- ivideo.SiS310_AccelDepth = 0x00000000;
+- ivideo.video_cmap_len = 256;
+- break;
+- case 16:
+- ivideo.DstColor = 0x8000;
+- ivideo.SiS310_AccelDepth = 0x00010000;
+- ivideo.video_cmap_len = 16;
+- break;
+- case 32:
+- ivideo.DstColor = 0xC000;
+- ivideo.SiS310_AccelDepth = 0x00020000;
+- ivideo.video_cmap_len = 16;
+- break;
+- default:
+- ivideo.video_cmap_len = 16;
+- printk(KERN_ERR "sisfb: Unsupported accel depth %d", ivideo.video_bpp);
+- ivideo.accel = 0;
+- break;
+- }
++ if(sisfb_caps & HW_CURSOR_CAP)
++ myhwcoffset = sisfb_hwcursor_vbase -
++ (unsigned long) ivideo.video_vbase;
++
++ return put_user(myhwcoffset, (unsigned long *)arg);
+
+ break;
+ }
+ case FBIOGET_DISPINFO:
+- sis_dispinfo((struct ap_data *)arg);
++ sis_dispinfo(&sisapdata);
++ if(copy_to_user((void *)arg, &sisapdata, sizeof(sisapdata)))
++ return -EFAULT;
+ break;
+- case SISFB_GET_INFO: /* TW: New for communication with X driver */
++ case SISFB_GET_INFO: /* For communication with X driver */
+ {
+- sisfb_info *x = (sisfb_info *)arg;
++ sisfb_info x;
+
+- x->sisfb_id = SISFB_ID;
+- x->sisfb_version = VER_MAJOR;
+- x->sisfb_revision = VER_MINOR;
+- x->sisfb_patchlevel = VER_LEVEL;
+- x->chip_id = ivideo.chip_id;
+- x->memory = ivideo.video_size / 1024;
+- x->heapstart = ivideo.heapstart / 1024;
+- x->fbvidmode = sisfb_mode_no;
+- x->sisfb_caps = sisfb_caps;
+- x->sisfb_tqlen = 512; /* yet unused */
+- x->sisfb_pcibus = ivideo.pcibus;
+- x->sisfb_pcislot = ivideo.pcislot;
+- x->sisfb_pcifunc = ivideo.pcifunc;
+- x->sisfb_lcdpdc = sisfb_detectedpdc;
+- x->sisfb_lcda = sisfb_detectedlcda;
++ x.sisfb_id = SISFB_ID;
++ x.sisfb_version = VER_MAJOR;
++ x.sisfb_revision = VER_MINOR;
++ x.sisfb_patchlevel = VER_LEVEL;
++ x.chip_id = ivideo.chip_id;
++ x.memory = ivideo.video_size / 1024;
++ x.heapstart = ivideo.heapstart / 1024;
++ x.fbvidmode = sisfb_mode_no;
++ x.sisfb_caps = sisfb_caps;
++ x.sisfb_tqlen = 512; /* yet unused */
++ x.sisfb_pcibus = ivideo.pcibus;
++ x.sisfb_pcislot = ivideo.pcislot;
++ x.sisfb_pcifunc = ivideo.pcifunc;
++ x.sisfb_lcdpdc = sisfb_detectedpdc;
++ x.sisfb_lcda = sisfb_detectedlcda;
++ x.sisfb_vbflags = ivideo.vbflags;
++ x.sisfb_currentvbflags = ivideo.currentvbflags;
++ x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
++ x.sisfb_specialtiming = SiS_Pr.SiS_CustomT;
++ if(copy_to_user((void *)arg, &x, sizeof(x)))
++ return -EFAULT;
+ break;
+ }
+ case SISFB_GET_VBRSTATUS:
+ {
+- unsigned long *vbrstatus = (unsigned long *) arg;
+- if(sisfb_CheckVBRetrace()) *vbrstatus = 1;
+- else *vbrstatus = 0;
++ if(sisfb_CheckVBRetrace())
++ return put_user(1UL, (unsigned long *) arg);
++ else
++ return put_user(0UL, (unsigned long *) arg);
++ break;
+ }
+ default:
+ return -EINVAL;
+ }
+- TWDEBUG("end of ioctl");
+ return 0;
+-
+ }
+
+-#endif
+-
+-/* ----------- FBDev related routines for all series ---------- */
+
+ static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+ {
+- TWDEBUG("inside get_fix");
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+@@ -1987,45 +2390,47 @@ static int sisfb_get_fix(struct fb_fix_s
+
+ fix->smem_start = ivideo.video_base;
+
+- /* TW */
+ if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
+- if (ivideo.video_size > 0x1000000) {
+- fix->smem_len = 0xc00000;
+- } else if (ivideo.video_size > 0x800000)
+- fix->smem_len = 0x800000;
+- else
+- fix->smem_len = 0x400000;
++ if(sisvga_engine == SIS_300_VGA) {
++ if(ivideo.video_size > 0x1000000) {
++ fix->smem_len = 0xc00000;
++ } else if(ivideo.video_size > 0x800000)
++ fix->smem_len = 0x800000;
++ else
++ fix->smem_len = 0x400000;
++ } else {
++ fix->smem_len = ivideo.video_size - 0x100000;
++ }
+ } else
+ fix->smem_len = sisfb_mem * 1024;
+
+- fix->type = video_type;
++ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ if(ivideo.video_bpp == 8)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 0;
+-#ifdef SISFB_PAN
++
+ if(sisfb_ypan) fix->ypanstep = 1;
+-#endif
++
+ fix->ywrapstep = 0;
+ fix->line_length = ivideo.video_linelength;
+ fix->mmio_start = ivideo.mmio_base;
+ fix->mmio_len = sisfb_mmio_size;
+ if(sisvga_engine == SIS_300_VGA)
+ fix->accel = FB_ACCEL_SIS_GLAMOUR;
+- else if(ivideo.chip == SIS_330)
++ else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_660) || (ivideo.chip == SIS_760))
+ fix->accel = FB_ACCEL_SIS_XABRE;
+- else
++ else
+ fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
+-
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ fix->reserved[0] = ivideo.video_size & 0xFFFF;
+ fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
+ fix->reserved[2] = sisfb_caps;
+-#endif
++#endif
+
+- TWDEBUG("end of get_fix");
+ return 0;
+ }
+
+@@ -2033,17 +2438,15 @@ static int sisfb_get_fix(struct fb_fix_s
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ static struct fb_ops sisfb_ops = {
+- owner: THIS_MODULE,
+- fb_get_fix: sisfb_get_fix,
+- fb_get_var: sisfb_get_var,
+- fb_set_var: sisfb_set_var,
+- fb_get_cmap: sisfb_get_cmap,
+- fb_set_cmap: sisfb_set_cmap,
+-#ifdef SISFB_PAN
+- fb_pan_display: sisfb_pan_display,
+-#endif
+- fb_ioctl: sisfb_ioctl,
+- fb_mmap: sisfb_mmap,
++ .owner = THIS_MODULE,
++ .fb_get_fix = sisfb_get_fix,
++ .fb_get_var = sisfb_get_var,
++ .fb_set_var = sisfb_set_var,
++ .fb_get_cmap = sisfb_get_cmap,
++ .fb_set_cmap = sisfb_set_cmap,
++ .fb_pan_display = sisfb_pan_display,
++ .fb_ioctl = sisfb_ioctl,
++ .fb_mmap = sisfb_mmap,
+ };
+ #endif
+
+@@ -2056,9 +2459,7 @@ static struct fb_ops sisfb_ops = {
+ .fb_check_var = sisfb_check_var,
+ .fb_set_par = sisfb_set_par,
+ .fb_setcolreg = sisfb_setcolreg,
+-#ifdef SISFB_PAN
+ .fb_pan_display = sisfb_pan_display,
+-#endif
+ .fb_blank = sisfb_blank,
+ .fb_fillrect = fbcon_sis_fillrect,
+ .fb_copyarea = fbcon_sis_copyarea,
+@@ -2105,35 +2506,42 @@ static int sisfb_get_dram_size_300(void)
+
+ } else { /* 540, 630, 730 */
+
+- pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev);
+- if (pdev) {
+- pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);
+- pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+- ivideo.video_size = (unsigned int)(1 << (pci_data+21));
+- pdev_valid = 1;
+-
+- reg = SIS_DATA_BUS_64 << 6;
+- switch (pci_data) {
+- case BRI_DRAM_SIZE_2MB:
+- reg |= SIS_DRAM_SIZE_2MB;
+- break;
+- case BRI_DRAM_SIZE_4MB:
+- reg |= SIS_DRAM_SIZE_4MB;
+- break;
+- case BRI_DRAM_SIZE_8MB:
+- reg |= SIS_DRAM_SIZE_8MB;
+- break;
+- case BRI_DRAM_SIZE_16MB:
+- reg |= SIS_DRAM_SIZE_16MB;
+- break;
+- case BRI_DRAM_SIZE_32MB:
+- reg |= SIS_DRAM_SIZE_32MB;
+- break;
+- case BRI_DRAM_SIZE_64MB:
+- reg |= SIS_DRAM_SIZE_64MB;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
++ if ((pdev->vendor == PCI_VENDOR_ID_SI)
++ && (pdev->device == nbridge_id)) {
++ pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);
++ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
++ ivideo.video_size = (unsigned int)(1 << (pci_data+21));
++ pdev_valid = 1;
++
++ reg = SIS_DATA_BUS_64 << 6;
++ switch (pci_data) {
++ case BRI_DRAM_SIZE_2MB:
++ reg |= SIS_DRAM_SIZE_2MB;
++ break;
++ case BRI_DRAM_SIZE_4MB:
++ reg |= SIS_DRAM_SIZE_4MB;
++ break;
++ case BRI_DRAM_SIZE_8MB:
++ reg |= SIS_DRAM_SIZE_8MB;
++ break;
++ case BRI_DRAM_SIZE_16MB:
++ reg |= SIS_DRAM_SIZE_16MB;
++ break;
++ case BRI_DRAM_SIZE_32MB:
++ reg |= SIS_DRAM_SIZE_32MB;
++ break;
++ case BRI_DRAM_SIZE_64MB:
++ reg |= SIS_DRAM_SIZE_64MB;
++ break;
++ }
++ outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
+ break;
+ }
+- outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
+ }
+
+ if (!pdev_valid) return -1;
+@@ -2141,171 +2549,10 @@ static int sisfb_get_dram_size_300(void)
+ return 0;
+ }
+
+-static void sisfb_detect_VB_connect_300()
+-{
+- u8 sr16, sr17, cr32, temp;
+-
+- ivideo.TV_plug = ivideo.TV_type = 0;
+-
+- switch(ivideo.hasVB) {
+- case HASVB_LVDS_CHRONTEL:
+- case HASVB_CHRONTEL:
+- SiS_SenseCh();
+- break;
+- case HASVB_301:
+- case HASVB_302:
+- SiS_Sense30x();
+- break;
+- }
+-
+- inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
+- inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
+-
+- if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+-
+- if ((sr17 & 0x01) && !sisfb_crt1off)
+- sisfb_crt1off = 0;
+- else {
+- if (sr17 & 0x0E)
+- sisfb_crt1off = 1;
+- else
+- sisfb_crt1off = 0;
+- }
+-
+- if (sisfb_crt2type != -1)
+- /* TW: override detected CRT2 type */
+- ivideo.disp_state = sisfb_crt2type;
+- else if (sr17 & 0x04)
+- ivideo.disp_state = DISPTYPE_TV;
+- else if (sr17 & 0x02)
+- ivideo.disp_state = DISPTYPE_LCD;
+- else if (sr17 & 0x08 )
+- ivideo.disp_state = DISPTYPE_CRT2;
+- else
+- ivideo.disp_state = 0;
+-
+- if(sisfb_tvplug != -1)
+- /* PR/TW: override detected TV type */
+- ivideo.TV_plug = sisfb_tvplug;
+- else if (sr17 & 0x20)
+- ivideo.TV_plug = TVPLUG_SVIDEO;
+- else if (sr17 & 0x10)
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
+-
+- inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
+- if (sr16 & 0x20)
+- ivideo.TV_type = TVMODE_PAL;
+- else
+- ivideo.TV_type = TVMODE_NTSC;
+-
+- } else {
+-
+- if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+- sisfb_crt1off = 0;
+- else {
+- if (cr32 & 0x5F)
+- sisfb_crt1off = 1;
+- else
+- sisfb_crt1off = 0;
+- }
+-
+- if (sisfb_crt2type != -1)
+- /* TW: override detected CRT2 type */
+- ivideo.disp_state = sisfb_crt2type;
+- else if (cr32 & SIS_VB_TV)
+- ivideo.disp_state = DISPTYPE_TV;
+- else if (cr32 & SIS_VB_LCD)
+- ivideo.disp_state = DISPTYPE_LCD;
+- else if (cr32 & SIS_VB_CRT2)
+- ivideo.disp_state = DISPTYPE_CRT2;
+- else
+- ivideo.disp_state = 0;
+-
+- /* TW: Detect TV plug & type */
+- if(sisfb_tvplug != -1)
+- /* PR/TW: override with option */
+- ivideo.TV_plug = sisfb_tvplug;
+- else if (cr32 & SIS_VB_HIVISION) {
+- ivideo.TV_type = TVMODE_HIVISION;
+- ivideo.TV_plug = TVPLUG_SVIDEO;
+- }
+- else if (cr32 & SIS_VB_SVIDEO)
+- ivideo.TV_plug = TVPLUG_SVIDEO;
+- else if (cr32 & SIS_VB_COMPOSITE)
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
+- else if (cr32 & SIS_VB_SCART)
+- ivideo.TV_plug = TVPLUG_SCART;
+-
+- if (ivideo.TV_type == 0) {
+- inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
+- if (temp & 0x01)
+- ivideo.TV_type = TVMODE_PAL;
+- else
+- ivideo.TV_type = TVMODE_NTSC;
+- }
+-
+- }
+-
+- /* TW: Copy forceCRT1 option to CRT1off if option is given */
+- if (sisfb_forcecrt1 != -1) {
+- if(sisfb_forcecrt1) sisfb_crt1off = 0;
+- else sisfb_crt1off = 1;
+- }
+-}
+-
+-static void sisfb_get_VB_type_300(void)
+-{
+- u8 reg;
+-
+- if(ivideo.chip != SIS_300) {
+- if(!sisfb_has_VB_300()) {
+- inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
+- switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
+- case SIS_EXTERNAL_CHIP_LVDS:
+- ivideo.hasVB = HASVB_LVDS;
+- break;
+- case SIS_EXTERNAL_CHIP_TRUMPION:
+- ivideo.hasVB = HASVB_TRUMPION;
+- break;
+- case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+- ivideo.hasVB = HASVB_LVDS_CHRONTEL;
+- break;
+- case SIS_EXTERNAL_CHIP_CHRONTEL:
+- ivideo.hasVB = HASVB_CHRONTEL;
+- break;
+- default:
+- break;
+- }
+- }
+- } else {
+- sisfb_has_VB_300();
+- }
+-}
+-
+-static int sisfb_has_VB_300(void)
+-{
+- u8 vb_chipid;
+-
+- inSISIDXREG(SISPART4, 0x00, vb_chipid);
+- switch (vb_chipid) {
+- case 0x01:
+- ivideo.hasVB = HASVB_301;
+- break;
+- case 0x02:
+- ivideo.hasVB = HASVB_302;
+- break;
+- default:
+- ivideo.hasVB = HASVB_NONE;
+- return FALSE;
+- }
+- return TRUE;
+-
+-}
+-
+ #endif /* CONFIG_FB_SIS_300 */
+
+
+-#ifdef CONFIG_FB_SIS_315 /* for SiS 315/550/650/740/330 */
++#ifdef CONFIG_FB_SIS_315 /* for SiS 315/550/650/740/330/660/760 */
+
+ static int sisfb_get_dram_size_315(void)
+ {
+@@ -2314,21 +2561,33 @@ static int sisfb_get_dram_size_315(void)
+ u8 pci_data;
+ u8 reg = 0;
+
+- if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650 || ivideo.chip == SIS_740) {
++ if (ivideo.chip == SIS_550 ||
++ ivideo.chip == SIS_650 ||
++ ivideo.chip == SIS_740 ||
++ ivideo.chip == SIS_660 ||
++ ivideo.chip == SIS_760) {
+
+ #ifdef LINUXBIOS
+
+- while ((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev)) != NULL) {
+- if ((pdev->device == PCI_DEVICE_ID_SI_550) ||
+- (pdev->device == PCI_DEVICE_ID_SI_650) ||
+- (pdev->device == PCI_DEVICE_ID_SI_740)) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
++
++ if ( (pdev->vendor == PCI_VENDOR_ID_SI)
++ && ( (pdev->device == PCI_DEVICE_ID_SI_550) ||
++ (pdev->device == PCI_DEVICE_ID_SI_650) ||
++ (pdev->device == PCI_DEVICE_ID_SI_740) ||
++ (pdev->device == PCI_DEVICE_ID_SI_660) ||
++ (pdev->device == PCI_DEVICE_ID_SI_760))) {
+ pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+ ivideo.video_size = (unsigned int)(1 << (pci_data + 21));
+ pdev_valid = 1;
+
+- /* TW: Initialize SR14 "by hand" */
++ /* Initialize SR14 "by hand" */
+ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
+ reg &= 0xC0;
+ switch (pci_data) {
+@@ -2390,7 +2649,15 @@ static int sisfb_get_dram_size_315(void)
+ "now reading from PCI config\n");
+ pdev_valid = 0;
+
+- while ((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550, pdev)) != NULL) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
++
++ if ( (pdev->vendor == PCI_VENDOR_ID_SI)
++ && (pdev->device == PCI_DEVICE_ID_SI_550) ) {
++
+ pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
+ &pci_data);
+ pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+@@ -2415,6 +2682,7 @@ static int sisfb_get_dram_size_315(void)
+ return -1;
+ }
+ outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
++ }
+ }
+ if (!pdev_valid) {
+ printk(KERN_INFO "sisfb: Total confusion - No SiS PCI VGA device found?!\n");
+@@ -2425,7 +2693,7 @@ static int sisfb_get_dram_size_315(void)
+ #endif
+ return 0;
+
+- } else { /* 315 */
++ } else { /* 315, 330 */
+
+ inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
+ switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
+@@ -2458,7 +2726,7 @@ static int sisfb_get_dram_size_315(void)
+ reg >>= 2;
+
+ if(ivideo.chip == SIS_330) {
+-
++
+ if(reg) ivideo.video_size <<= 1;
+
+ } else {
+@@ -2470,7 +2738,7 @@ static int sisfb_get_dram_size_315(void)
+ case SIS315_DUAL_CHANNEL_1_RANK:
+ ivideo.video_size <<= 1;
+ break;
+- case SIS315_ASYM_DDR: /* TW: DDR asymentric */
++ case SIS315_ASYM_DDR: /* TW: DDR asymetric */
+ ivideo.video_size += (ivideo.video_size/2);
+ break;
+ }
+@@ -2483,127 +2751,241 @@ static int sisfb_get_dram_size_315(void)
+
+ }
+
+-static void sisfb_detect_VB_connect_315(void)
++#endif /* CONFIG_FB_SIS_315 */
++
++
++/* -------------- video bridge detection --------------- */
++
++static void sisfb_detect_VB_connect()
+ {
+- u8 cr32, temp=0;
++ u8 sr16, sr17, cr32, temp;
++
++ if(sisvga_engine == SIS_300_VGA) {
+
+- ivideo.TV_plug = ivideo.TV_type = 0;
++ inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
++
++ if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
++
++ /* Old BIOSes store the detected CRT2 type in SR17
++ * instead of CR32. However, since our detection
++ * routines store their results to CR32, we now copy
++ * the remaining bits (for LCD and VGA) to CR32 for
++ * unified usage.
++ * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2
++ * [4] AVIDEO [5] SVIDEO
++ */
++
++#if 0
++ if (sr17 & 0x01) orSISIDXREG(SISCR, 0x32, SIS_CRT1);
++ else andSISIDXREG(SISCR, 0x32, ~SIS_CRT1);
++
++ if (sr17 & 0x02) orSISIDXREG(SISCR, 0x32, SIS_VB_LCD);
++ else andSISIDXREG(SISCR, 0x32, ~SIS_VB_LCD);
++
++ /* no HiVision and no DVI connector here */
++ andSISIDXREG(SISCR, 0x32, ~0xc0);
++#endif
++
++ /* PAL/NTSC is stored on SR16 on such machines */
++ if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
++ inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
++ if (sr16 & 0x20)
++ ivideo.vbflags |= TV_PAL;
++ else
++ ivideo.vbflags |= TV_NTSC;
++ }
++
++ }
+
+- switch(ivideo.hasVB) {
+- case HASVB_LVDS_CHRONTEL:
+- case HASVB_CHRONTEL:
+- SiS_SenseCh();
+- break;
+- case HASVB_301:
+- case HASVB_302:
+- SiS_Sense30x();
+- break;
+ }
+
+ inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
+
+- if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
++ if (cr32 & SIS_CRT1)
+ sisfb_crt1off = 0;
+ else {
+- if (cr32 & 0x5F)
++ if (cr32 & 0x5F)
+ sisfb_crt1off = 1;
+ else
+ sisfb_crt1off = 0;
+ }
+
+- if (sisfb_crt2type != -1)
+- /* TW: Override with option */
+- ivideo.disp_state = sisfb_crt2type;
+- else if (cr32 & SIS_VB_TV)
+- ivideo.disp_state = DISPTYPE_TV;
+- else if (cr32 & SIS_VB_LCD)
+- ivideo.disp_state = DISPTYPE_LCD;
+- else if (cr32 & SIS_VB_CRT2)
+- ivideo.disp_state = DISPTYPE_CRT2;
+- else
+- ivideo.disp_state = 0;
++ ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
+
++ if (cr32 & SIS_VB_TV)
++ ivideo.vbflags |= CRT2_TV;
++ if (cr32 & SIS_VB_LCD)
++ ivideo.vbflags |= CRT2_LCD;
++ if (cr32 & SIS_VB_CRT2)
++ ivideo.vbflags |= CRT2_VGA;
++
++ /* TW: Detect/set TV plug & type */
+ if(sisfb_tvplug != -1)
+- /* PR/TW: Override with option */
+- ivideo.TV_plug = sisfb_tvplug;
+- else if (cr32 & SIS_VB_HIVISION) {
+- ivideo.TV_type = TVMODE_HIVISION;
+- ivideo.TV_plug = TVPLUG_SVIDEO;
+- }
++ ivideo.vbflags |= sisfb_tvplug;
++ if (cr32 & SIS_VB_HIVISION)
++ ivideo.vbflags |= (TV_HIVISION | TV_SVIDEO);
+ else if (cr32 & SIS_VB_SVIDEO)
+- ivideo.TV_plug = TVPLUG_SVIDEO;
++ ivideo.vbflags |= TV_SVIDEO;
+ else if (cr32 & SIS_VB_COMPOSITE)
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
++ ivideo.vbflags |= TV_AVIDEO;
+ else if (cr32 & SIS_VB_SCART)
+- ivideo.TV_plug = TVPLUG_SCART;
++ ivideo.vbflags |= TV_SCART;
+
+- if(ivideo.TV_type == 0) {
+- /* TW: PAL/NTSC changed for 650 */
+- if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) {
+-
+- inSISIDXREG(SISCR, 0x38, temp);
+- if(temp & 0x10)
+- ivideo.TV_type = TVMODE_PAL;
+- else
+- ivideo.TV_type = TVMODE_NTSC;
++ if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
++ if(sisvga_engine == SIS_300_VGA) {
++ inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
++ if (temp & 0x01)
++ ivideo.vbflags |= TV_PAL;
++ else
++ ivideo.vbflags |= TV_NTSC;
++ } else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip == SIS_330)) {
+
+- } else {
++ inSISIDXREG(SISCR, 0x38, temp);
++ if(temp & 0x10)
++ ivideo.vbflags |= TV_PAL;
++ else
++ ivideo.vbflags |= TV_NTSC;
+
+- inSISIDXREG(SISCR, 0x79, temp);
+- if(temp & 0x20)
+- ivideo.TV_type = TVMODE_PAL;
+- else
+- ivideo.TV_type = TVMODE_NTSC;
+- }
++ } else {
++
++ inSISIDXREG(SISCR, 0x79, temp);
++ if(temp & 0x20)
++ ivideo.vbflags |= TV_PAL;
++ else
++ ivideo.vbflags |= TV_NTSC;
++ }
+ }
+
+ /* TW: Copy forceCRT1 option to CRT1off if option is given */
+ if (sisfb_forcecrt1 != -1) {
+- if (sisfb_forcecrt1) sisfb_crt1off = 0;
+- else sisfb_crt1off = 1;
++ if(sisfb_forcecrt1) sisfb_crt1off = 0;
++ else sisfb_crt1off = 1;
+ }
+-}
+-
+-static void sisfb_get_VB_type_315(void)
+-{
+- u8 reg;
+
+- if (!sisfb_has_VB_315()) {
+- inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
+- switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
+- case SIS310_EXTERNAL_CHIP_LVDS:
+- ivideo.hasVB = HASVB_LVDS;
+- break;
+- case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+- ivideo.hasVB = HASVB_LVDS_CHRONTEL;
+- break;
+- default:
+- break;
+- }
+- }
+ }
+
+-
+-static int sisfb_has_VB_315(void)
++static void sisfb_get_VB_type(void)
+ {
+ u8 vb_chipid;
++ u8 reg;
++ char stdstr[] = "sisfb: Detected";
++ char bridgestr[] = "video bridge";
++ char lvdsstr[] = "LVDS transmitter";
++ char chrstr[] = "Chrontel TV encoder";
++
++ ivideo.hasVB = HASVB_NONE;
++ sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
++ sishw_ext.Is301BDH = FALSE;
++ sishw_ext.usExternalChip = 0;
+
+ inSISIDXREG(SISPART4, 0x00, vb_chipid);
+ switch (vb_chipid) {
+ case 0x01:
+ ivideo.hasVB = HASVB_301;
++ inSISIDXREG(SISPART4, 0x01, reg);
++ if(reg < 0xb0) {
++ ivideo.vbflags |= VB_301;
++ sishw_ext.ujVBChipID = VB_CHIP_301;
++ printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
++ } else if(reg < 0xd0) {
++ ivideo.vbflags |= VB_301B;
++ sishw_ext.ujVBChipID = VB_CHIP_301B;
++ printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
++ } else if(reg < 0xe0) {
++ ivideo.vbflags |= VB_301LV;
++ sishw_ext.ujVBChipID = VB_CHIP_301LV;
++ printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
++ } else if(reg <= 0xe1) {
++ ivideo.vbflags |= VB_302LV;
++ sishw_ext.ujVBChipID = VB_CHIP_302LV;
++ printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
++ }
+ break;
+ case 0x02:
+ ivideo.hasVB = HASVB_302;
++ inSISIDXREG(SISPART4, 0x01, reg);
++ if(reg < 0xd0) {
++ ivideo.vbflags |= VB_302B;
++ sishw_ext.ujVBChipID = VB_CHIP_302B;
++ printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
++ } else if(reg < 0xe0) {
++ ivideo.vbflags |= VB_301LV;
++ sishw_ext.ujVBChipID = VB_CHIP_301LV;
++ printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
++ } else if(reg <= 0xe1) {
++ ivideo.vbflags |= VB_302LV;
++ sishw_ext.ujVBChipID = VB_CHIP_302LV;
++ printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
++ }
+ break;
+- default:
+- ivideo.hasVB = HASVB_NONE;
+- return FALSE;
+ }
+- return TRUE;
+-}
+
+-#endif /* CONFIG_FB_SIS_315 */
++ if(ivideo.vbflags & (VB_301B | VB_302B)) {
++ inSISIDXREG(SISPART4,0x23,reg);
++ if(!(reg & 0x02)) {
++ sishw_ext.Is301BDH = TRUE;
++ ivideo.vbflags |= VB_30xBDH;
++ printk(KERN_INFO "This %s does not support LCD output\n", bridgestr);
++ }
++ }
++
++ if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) {
++ inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
++ reg &= SIS_EXTERNAL_CHIP_MASK;
++ reg >>= 1;
++ if(sisvga_engine == SIS_300_VGA) {
++ switch (reg) {
++ case SIS_EXTERNAL_CHIP_LVDS:
++ ivideo.hasVB = HASVB_LVDS;
++ ivideo.vbflags |= VB_LVDS;
++ sishw_ext.usExternalChip = 0x01;
++ printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
++ break;
++ case SIS_EXTERNAL_CHIP_TRUMPION:
++ ivideo.hasVB = HASVB_TRUMPION;
++ ivideo.vbflags |= VB_TRUMPION;
++ sishw_ext.usExternalChip = 0x02;
++ printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
++ break;
++ case SIS_EXTERNAL_CHIP_CHRONTEL:
++ ivideo.hasVB = HASVB_CHRONTEL;
++ ivideo.vbflags |= VB_CHRONTEL;
++ sishw_ext.usExternalChip = 0x04;
++ printk(KERN_INFO "%s %s\n", stdstr, chrstr);
++ break;
++ case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
++ ivideo.hasVB = HASVB_LVDS_CHRONTEL;
++ ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
++ sishw_ext.usExternalChip = 0x05;
++ printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
++ break;
++ }
++ } else {
++ switch (reg) {
++ case SIS310_EXTERNAL_CHIP_LVDS:
++ ivideo.hasVB = HASVB_LVDS;
++ ivideo.vbflags |= VB_LVDS;
++ sishw_ext.usExternalChip = 0x01;
++ printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
++ break;
++ case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
++ ivideo.hasVB = HASVB_LVDS_CHRONTEL;
++ ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
++ sishw_ext.usExternalChip = 0x05;
++ printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
++ break;
++ }
++ }
++
++ }
++
++ if(ivideo.vbflags & VB_SISBRIDGE) {
++ SiS_Sense30x();
++ } else if(ivideo.vbflags & VB_CHRONTEL) {
++ SiS_SenseCh();
++ }
++
++}
+
+ /* ------------------ Sensing routines ------------------ */
+
+@@ -2621,34 +3003,39 @@ SISDoSense(int tempbl, int tempbh, int t
+ inSISIDXREG(SISPART4,0x03,temp);
+ temp ^= 0x0e;
+ temp &= tempch;
+- return(temp);
++ return((temp == tempch));
+ }
+
+ void
+ SiS_Sense30x(void)
+ {
+- u8 backupP4_0d;
++ u8 backupP4_0d,backupP2_00;
+ u8 testsvhs_tempbl, testsvhs_tempbh;
+ u8 testsvhs_tempcl, testsvhs_tempch;
+ u8 testcvbs_tempbl, testcvbs_tempbh;
+ u8 testcvbs_tempcl, testcvbs_tempch;
+ u8 testvga2_tempbl, testvga2_tempbh;
+ u8 testvga2_tempcl, testvga2_tempch;
+- int myflag, result;
++ int myflag, result, haveresult, i, j;
++ char stdstr[] = "sisfb: Detected";
++ char tvstr[] = "TV connected to";
+
+ inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+ outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));
+
++ inSISIDXREG(SISPART2,0x00,backupP2_00);
++ outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
++
+ if(sisvga_engine == SIS_300_VGA) {
+
+- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
+- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
+- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+- if((sishw_ext.ujVBChipID != VB_CHIP_301) &&
+- (sishw_ext.ujVBChipID != VB_CHIP_302) ) {
+- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
+- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
+- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
++ if(ivideo.vbflags & (VB_301B|VB_302B|VB_301LV|VB_302LV)) {
++ testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
++ testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
++ testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
++ } else {
++ testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
++ testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
++ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+ }
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(myflag & 0x04) {
+@@ -2657,35 +3044,36 @@ SiS_Sense30x(void)
+ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+ }
+ testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
+- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
++ testsvhs_tempch = 0x04; testsvhs_tempcl = 0x04;
+ testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
++ if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
++ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
++ testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
++ }
+ if(ivideo.chip == SIS_300) {
+ inSISIDXREG(SISSR,0x3b,myflag);
+ if(!(myflag & 0x01)) {
+- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+- testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
++ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
++ testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+ }
+ }
+
+ } else {
+
+- testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
+- testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
+- testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+- if((sishw_ext.ujVBChipID != VB_CHIP_301) &&
+- (sishw_ext.ujVBChipID != VB_CHIP_302)) {
+- testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
+- testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
+- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
+- if(sishw_ext.ujVBChipID == VB_CHIP_301LV ||
+- sishw_ext.ujVBChipID == VB_CHIP_302LV) {
+- testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+- testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
+- testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
+- }
++ if(ivideo.vbflags & (VB_301B|VB_302B)) {
++ testvga2_tempbh = 0x01; testvga2_tempbl = 0x90;
++ testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
++ testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
++ } else if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
++ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
++ testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
++ testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
++ } else {
++ testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1;
++ testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
++ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
+ }
+- if(sishw_ext.ujVBChipID != VB_CHIP_301LV &&
+- sishw_ext.ujVBChipID != VB_CHIP_302LV) {
++ if(ivideo.vbflags & (VB_301|VB_301B|VB_302B)) {
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(myflag & 0x04) {
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd;
+@@ -2693,49 +3081,78 @@ SiS_Sense30x(void)
+ testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
+ }
+ }
+- if((sishw_ext.ujVBChipID == VB_CHIP_301LV) ||
+- (sishw_ext.ujVBChipID == VB_CHIP_302LV) ) {
++ if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
+ testvga2_tempbh = 0x00; testvga2_tempbl = 0x00;
+ testvga2_tempch = 0x00; testvga2_tempcl = 0x00;
+ testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
+ testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
+ } else {
+ testvga2_tempch = 0x0e; testvga2_tempcl = 0x08;
+- testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
++ testsvhs_tempch = 0x04; testsvhs_tempcl = 0x04;
+ testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
+ }
+ }
+
+ if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) {
+- result = SISDoSense(testvga2_tempbl, testvga2_tempbh,
+- testvga2_tempcl, testvga2_tempch);
+- if(result) {
+- printk(KERN_INFO "sisfb: Detected secondary VGA connection\n");
+- orSISIDXREG(SISCR, 0x32, 0x10);
+- }
++ haveresult = 0;
++ for(j = 0; j < 10; j++) {
++ result = 0;
++ for(i = 0; i < 3; i++) {
++ if(SISDoSense(testvga2_tempbl, testvga2_tempbh,
++ testvga2_tempcl, testvga2_tempch))
++ result++;
++ }
++ if((result == 0) || (result >= 2)) break;
++ }
++ if(result) {
++ printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
++ orSISIDXREG(SISCR, 0x32, 0x10);
++ } else {
++ andSISIDXREG(SISCR, 0x32, ~0x10);
++ }
++ }
++
++ haveresult = 0;
++ for(j = 0; j < 10; j++) {
++ result = 0;
++ for(i = 0; i < 3; i++) {
++ if(SISDoSense(testsvhs_tempbl, testsvhs_tempbh,
++ testsvhs_tempcl, testsvhs_tempch))
++ result++;
++ }
++ if((result == 0) || (result >= 2)) break;
+ }
+-
+- result = SISDoSense(testsvhs_tempbl, testsvhs_tempbh,
+- testsvhs_tempcl, testsvhs_tempch);
+ if(result) {
+- printk(KERN_INFO "sisfb: Detected TV connected to SVHS output\n");
+- /* TW: So we can be sure that there IS a SVHS output */
+- ivideo.TV_plug = TVPLUG_SVIDEO;
++ printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
++ ivideo.vbflags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
++ andSISIDXREG(SISCR, 0x32, ~0x05);
+ }
+
+ if(!result) {
+- result = SISDoSense(testcvbs_tempbl, testcvbs_tempbh,
+- testcvbs_tempcl, testcvbs_tempch);
++
++ haveresult = 0;
++ for(j = 0; j < 10; j++) {
++ result = 0;
++ for(i = 0; i < 3; i++) {
++ if(SISDoSense(testcvbs_tempbl, testcvbs_tempbh,
++ testcvbs_tempcl, testcvbs_tempch))
++ result++;
++ }
++ if((result == 0) || (result >= 2)) break;
++ }
+ if(result) {
+- printk(KERN_INFO "sisfb: Detected TV connected to CVBS output\n");
+- /* TW: So we can be sure that there IS a CVBS output */
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
++ printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
++ ivideo.vbflags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
++ andSISIDXREG(SISCR, 0x32, ~0x06);
++ } else {
++ andSISIDXREG(SISCR, 0x32, ~0x07);
+ }
+ }
+ SISDoSense(0, 0, 0, 0);
+
++ outSISIDXREG(SISPART2,0x00,backupP2_00);
+ outSISIDXREG(SISPART4,0x0d,backupP4_0d);
+ }
+
+@@ -2744,51 +3161,84 @@ void
+ SiS_SenseCh(void)
+ {
+
+- u8 temp1;
+-#ifdef CONFIG_FB_SIS_315
+- u8 temp2;
++ u8 temp1, temp2;
++#ifdef CONFIG_FB_SIS_300
++ unsigned char test[3];
++ int i;
+ #endif
++ char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
+
+ if(ivideo.chip < SIS_315H) {
+
+ #ifdef CONFIG_FB_SIS_300
+- SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* TW: Chrontel 7005 */
++ SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
++ SiS_SetChrontelGPIO(&SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
++ SiS_DDC2Delay(&SiS_Pr, 1000);
+ temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);
+- if ((temp1 >= 50) && (temp1 <= 100)) {
+- /* TW: Read power status */
++ /* TW: See Chrontel TB31 for explanation */
++ temp2 = SiS_GetCH700x(&SiS_Pr, 0x0e);
++ if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
++ SiS_SetCH700x(&SiS_Pr, 0x0b0e);
++ SiS_DDC2Delay(&SiS_Pr, 300);
++ }
++ temp2 = SiS_GetCH700x(&SiS_Pr, 0x25);
++ if(temp2 != temp1) temp1 = temp2;
++
++ if((temp1 >= 0x22) && (temp1 <= 0x50)) {
++ /* Read power status */
+ temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+ if((temp1 & 0x03) != 0x03) {
+- /* TW: Power all outputs */
+- SiS_SetCH70xxANDOR(&SiS_Pr, 0x030E,0xF8);
++ /* Power all outputs */
++ SiS_SetCH700x(&SiS_Pr, 0x0B0E);
++ SiS_DDC2Delay(&SiS_Pr, 300);
+ }
+- /* TW: Sense connected TV devices */
+- SiS_SetCH700x(&SiS_Pr, 0x0110);
+- SiS_SetCH700x(&SiS_Pr, 0x0010);
+- temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);
+- if(!(temp1 & 0x08)) {
+- printk(KERN_INFO
+- "sisfb: Chrontel: Detected TV connected to SVHS output\n");
+- /* TW: So we can be sure that there IS a SVHS output */
+- ivideo.TV_plug = TVPLUG_SVIDEO;
++ /* Sense connected TV devices */
++ for(i = 0; i < 3; i++) {
++ SiS_SetCH700x(&SiS_Pr, 0x0110);
++ SiS_DDC2Delay(&SiS_Pr, 0x96);
++ SiS_SetCH700x(&SiS_Pr, 0x0010);
++ SiS_DDC2Delay(&SiS_Pr, 0x96);
++ temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);
++ if(!(temp1 & 0x08)) test[i] = 0x02;
++ else if(!(temp1 & 0x02)) test[i] = 0x01;
++ else test[i] = 0;
++ SiS_DDC2Delay(&SiS_Pr, 0x96);
++ }
++
++ if(test[0] == test[1]) temp1 = test[0];
++ else if(test[0] == test[2]) temp1 = test[0];
++ else if(test[1] == test[2]) temp1 = test[1];
++ else {
++ printk(KERN_INFO
++ "sisfb: TV detection unreliable - test results varied\n");
++ temp1 = test[2];
++ }
++ if(temp1 == 0x02) {
++ printk(KERN_INFO "%s SVIDEO output\n", stdstr);
++ ivideo.vbflags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
+- } else if (!(temp1 & 0x02)) {
+- printk(KERN_INFO
+- "sisfb: Chrontel: Detected TV connected to CVBS output\n");
+- /* TW: So we can be sure that there IS a CVBS output */
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
++ andSISIDXREG(SISCR, 0x32, ~0x05);
++ } else if (temp1 == 0x01) {
++ printk(KERN_INFO "%s CVBS output\n", stdstr);
++ ivideo.vbflags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
++ andSISIDXREG(SISCR, 0x32, ~0x06);
+ } else {
+ SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
++ andSISIDXREG(SISCR, 0x32, ~0x07);
+ }
+ } else if(temp1 == 0) {
+ SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
++ andSISIDXREG(SISCR, 0x32, ~0x07);
+ }
++ /* Set general purpose IO for Chrontel communication */
++ SiS_SetChrontelGPIO(&SiS_Pr, 0x00);
+ #endif
+
+ } else {
+
+ #ifdef CONFIG_FB_SIS_315
+- SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* TW: Chrontel 7019 */
++ SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
+ temp1 = SiS_GetCH701x(&SiS_Pr, 0x49);
+ SiS_SetCH701x(&SiS_Pr, 0x2049);
+ SiS_DDC2Delay(&SiS_Pr, 0x96);
+@@ -2808,22 +3258,24 @@ SiS_SenseCh(void)
+ if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
+ switch(temp1) {
+ case 0x01:
+- printk(KERN_INFO
+- "sisfb: Chrontel: Detected TV connected to CVBS output\n");
+- ivideo.TV_plug = TVPLUG_COMPOSITE;
++ printk(KERN_INFO "%s CVBS output\n", stdstr);
++ ivideo.vbflags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
++ andSISIDXREG(SISCR, 0x32, ~0x06);
+ break;
+ case 0x02:
+- printk(KERN_INFO
+- "sisfb: Chrontel: Detected TV connected to SVHS output\n");
+- ivideo.TV_plug = TVPLUG_SVIDEO;
++ printk(KERN_INFO "%s SVIDEO output\n", stdstr);
++ ivideo.vbflags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
++ andSISIDXREG(SISCR, 0x32, ~0x05);
+ break;
+ case 0x04:
+- /* TW: This should not happen */
+- printk(KERN_INFO
+- "sisfb: Chrontel: Detected TV connected to SCART output\n");
++ printk(KERN_INFO "%s SCART output\n", stdstr);
++ orSISIDXREG(SISCR, 0x32, 0x04);
++ andSISIDXREG(SISCR, 0x32, ~0x03);
+ break;
++ default:
++ andSISIDXREG(SISCR, 0x32, ~0x07);
+ }
+ #endif
+
+@@ -2845,8 +3297,8 @@ static int sisfb_heap_init(void)
+ unsigned long *write_port = 0;
+ SIS_CMDTYPE cmd_type;
+ #ifndef AGPOFF
+- struct agp_kern_info *agp_info;
+- struct agp_memory *agp;
++ agp_kern_info *agp_info;
++ agp_memory *agp;
+ u32 agp_phys;
+ #endif
+ #endif
+@@ -2860,14 +3312,21 @@ static int sisfb_heap_init(void)
+ * in XF86Config-4.
+ * The heap start can also be specified by parameter "mem" when starting the sisfb
+ * driver. sisfb mem=1024 lets heap starts at 1MB, etc.
++ *
++ * On the 315 and Xabre series, the default is a 1MB heap since DRI is not
++ * supported there.
+ */
+ if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
+- if (ivideo.video_size > 0x1000000) {
++ if(sisvga_engine == SIS_300_VGA) {
++ if (ivideo.video_size > 0x1000000) {
+ ivideo.heapstart = 0xc00000;
+- } else if (ivideo.video_size > 0x800000) {
++ } else if (ivideo.video_size > 0x800000) {
+ ivideo.heapstart = 0x800000;
+- } else {
++ } else {
+ ivideo.heapstart = 0x400000;
++ }
++ } else {
++ ivideo.heapstart = ivideo.video_size - 0x100000;
+ }
+ } else {
+ ivideo.heapstart = sisfb_mem * 1024;
+@@ -2883,7 +3342,7 @@ static int sisfb_heap_init(void)
+ #ifdef CONFIG_FB_SIS_315
+ if (sisvga_engine == SIS_315_VGA) {
+ /* TW: Now initialize the 310 series' command queue mode.
+- * On 310/325, there are three queue modes available which
++ * On 315, there are three queue modes available which
+ * are chosen by setting bits 7:5 in SR26:
+ * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
+ * track of the queue, the FIFO, command parsing and so
+@@ -2923,8 +3382,8 @@ static int sisfb_heap_init(void)
+
+ #ifndef AGPOFF
+ if (sisfb_queuemode == AGP_CMD_QUEUE) {
+- agp_info = vmalloc(sizeof(*agp_info));
+- memset((void*)agp_info, 0x00, sizeof(*agp_info));
++ agp_info = vmalloc(sizeof(agp_kern_info));
++ memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
+ agp_copy_info(agp_info);
+
+ agp_backend_acquire();
+@@ -3025,10 +3484,6 @@ static int sisfb_heap_init(void)
+ break;
+
+ default: /* MMIO */
+- /* TW: This previously only wrote SIS_MMIO_CMD_ENABLE
+- * to IND_SIS_CMDQUEUE_SET. I doubt that this is
+- * enough. Reserve memory in any way.
+- */
+ sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+ sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
+
+@@ -3037,7 +3492,7 @@ static int sisfb_heap_init(void)
+
+ *write_port = *read_port;
+
+- /* TW: Set Auto_Correction bit */
++ /* Set Auto_Correction bit */
+ temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+ outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+
+@@ -3333,7 +3788,6 @@ void sis_malloc(struct sis_memreq *req)
+ req->offset = poh->offset;
+ req->size = poh->size;
+ }
+-
+ }
+
+ void sis_free(unsigned long base)
+@@ -3352,35 +3806,70 @@ void sis_free(unsigned long base)
+
+ static void sisfb_pre_setmode(void)
+ {
+- u8 cr30 = 0, cr31 = 0;
++ u8 cr30 = 0, cr31 = 0, cr33 = 0;
++
++ ivideo.currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+
+ inSISIDXREG(SISCR, 0x31, cr31);
+ cr31 &= ~0x60;
++ cr31 |= 0x04;
+
+- switch (ivideo.disp_state & DISPTYPE_DISP2) {
+- case DISPTYPE_CRT2:
+- cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+- cr31 |= SIS_DRIVER_MODE;
+- break;
+- case DISPTYPE_LCD:
+- cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+- cr31 |= SIS_DRIVER_MODE;
+- break;
+- case DISPTYPE_TV:
+- if (ivideo.TV_type == TVMODE_HIVISION)
++ cr33 = sisfb_rate_idx & 0x0F;
++
++ SiS_SetEnableDstn(&SiS_Pr, FALSE);
++ SiS_SetEnableFstn(&SiS_Pr, FALSE);
++
++ switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
++ case CRT2_TV:
++ ivideo.disp_state = DISPTYPE_TV;
++ if (ivideo.vbflags & TV_HIVISION) {
+ cr30 = (SIS_VB_OUTPUT_HIVISION | SIS_SIMULTANEOUS_VIEW_ENABLE);
+- else if (ivideo.TV_plug == TVPLUG_SVIDEO)
++ ivideo.currentvbflags |= (TV_HIVISION | TV_SVIDEO);
++ ivideo.TV_type = TVMODE_HIVISION;
++ ivideo.TV_plug = TVPLUG_SVIDEO;
++ } else if (ivideo.vbflags & TV_SVIDEO) {
+ cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
+- else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
++ ivideo.currentvbflags |= TV_SVIDEO;
++ ivideo.TV_plug = TVPLUG_SVIDEO;
++ } else if (ivideo.vbflags & TV_AVIDEO) {
+ cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
+- else if (ivideo.TV_plug == TVPLUG_SCART)
++ ivideo.currentvbflags |= TV_AVIDEO;
++ ivideo.TV_plug = TVPLUG_COMPOSITE;
++ } else if (ivideo.vbflags & TV_SCART) {
+ cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
++ ivideo.currentvbflags |= TV_SCART;
++ ivideo.TV_plug = TVPLUG_SCART;
++ }
+ cr31 |= SIS_DRIVER_MODE;
+
+- if (sisfb_tvmode == 1 || ivideo.TV_type == TVMODE_PAL)
+- cr31 |= 0x01;
+- else
+- cr31 &= ~0x01;
++ if(!(ivideo.vbflags & TV_HIVISION)) {
++ if (ivideo.vbflags & TV_PAL) {
++ cr31 |= 0x01;
++ ivideo.currentvbflags |= TV_PAL;
++ ivideo.TV_type = TVMODE_PAL;
++ } else {
++ cr31 &= ~0x01;
++ ivideo.currentvbflags |= TV_NTSC;
++ ivideo.TV_type = TVMODE_NTSC;
++ }
++ }
++ break;
++ case CRT2_LCD:
++ ivideo.disp_state = DISPTYPE_LCD;
++ cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
++ cr31 |= SIS_DRIVER_MODE;
++ SiS_SetEnableDstn(&SiS_Pr, sisfb_dstn);
++ SiS_SetEnableFstn(&SiS_Pr, sisfb_fstn);
++ break;
++ case CRT2_VGA:
++ ivideo.disp_state = DISPTYPE_CRT2;
++ cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
++ cr31 |= SIS_DRIVER_MODE;
++ if(sisfb_nocrt2rate) {
++ cr33 |= (sisbios_mode[sisfb_mode_idx].rate_idx << 4);
++ } else {
++ cr33 |= ((sisfb_rate_idx & 0x0F) << 4);
++ }
+ break;
+ default: /* disable CRT2 */
+ cr30 = 0x00;
+@@ -3389,8 +3878,14 @@ static void sisfb_pre_setmode(void)
+
+ outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR30, cr30);
+ outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR31, cr31);
++ outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
+
+- outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, (sisfb_rate_idx & 0x0F));
++#ifdef CONFIG_FB_SIS_315
++ if(sisvga_engine == SIS_315_VGA) {
++ /* Clear LCDA and PAL-N/M bits */
++ andSISIDXREG(SISCR,0x38,~0xc3);
++ }
++#endif
+
+ if(ivideo.accel) sisfb_syncaccel();
+
+@@ -3400,67 +3895,89 @@ static void sisfb_pre_setmode(void)
+ static void sisfb_post_setmode(void)
+ {
+ u8 reg;
++ BOOLEAN crt1isoff = FALSE;
++#ifdef CONFIG_FB_SIS_315
++ u8 reg1;
++#endif
++#ifdef CONFIG_FB_SIS_300
+ BOOLEAN doit = TRUE;
+-#if 0 /* TW: Wrong: Is not in MMIO space, but in RAM */
+- /* Backup mode number to MMIO space */
+- if(ivideo.mmio_vbase) {
+- *(volatile u8 *)(((u8*)ivideo.mmio_vbase) + 0x449) = (unsigned char)sisfb_mode_no;
+- }
+-#endif
+-
+- if (ivideo.video_bpp == 8) {
+- /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
+- if ((ivideo.hasVB == HASVB_LVDS) || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) {
+- doit = FALSE;
+- }
+- /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */
+- if ( (sishw_ext.Is301BDH) && (ivideo.disp_state & DISPTYPE_LCD) ) {
+- doit = FALSE;
+- }
+- }
+-
++#endif
+ /* TW: We can't switch off CRT1 if bridge is in slave mode */
+- if(ivideo.hasVB != HASVB_NONE) {
+- inSISIDXREG(SISPART1, 0x00, reg);
++ if(ivideo.vbflags & VB_VIDEOBRIDGE) {
++#ifdef CONFIG_FB_SIS_300
+ if(sisvga_engine == SIS_300_VGA) {
++ inSISIDXREG(SISPART1, 0x00, reg);
+ if((reg & 0xa0) == 0x20) {
+ doit = FALSE;
+ }
+ }
+- if(sisvga_engine == SIS_315_VGA) {
+- if((reg & 0x50) == 0x10) {
+- doit = FALSE;
+- }
+- }
++#endif
+ } else sisfb_crt1off = 0;
+
+- inSISIDXREG(SISCR, 0x17, reg);
+- if((sisfb_crt1off) && (doit))
+- reg &= ~0x80;
+- else
+- reg |= 0x80;
+- outSISIDXREG(SISCR, 0x17, reg);
++ if(sisvga_engine == SIS_300_VGA) {
+
+- andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
++#ifdef CONFIG_FB_SIS_300
++ if((sisfb_crt1off) && (doit)) {
++ crt1isoff = TRUE;
++ reg = 0x00;
++ } else {
++ crt1isoff = FALSE;
++ reg = 0x80;
++ }
++ setSISIDXREG(SISCR, 0x17, 0x7f, reg);
++#endif
++
++ } else {
++
++#ifdef CONFIG_FB_SIS_315
++ if(sisfb_crt1off) {
++ crt1isoff = TRUE;
++ reg = 0x40;
++ reg1 = 0xc0;
++ } else {
++ crt1isoff = FALSE;
++ reg = 0x00;
++ reg1 = 0x00;
+
+- if((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {
++ }
++ setSISIDXREG(SISCR, 0x63, ~0x40, reg);
++ setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
++#endif
++
++ }
++
++ if(crt1isoff) {
++ ivideo.currentvbflags &= ~VB_DISPTYPE_CRT1;
++ ivideo.currentvbflags |= VB_SINGLE_MODE;
++ ivideo.disp_state |= DISPMODE_SINGLE;
++ } else {
++ ivideo.currentvbflags |= VB_DISPTYPE_CRT1;
++ ivideo.disp_state |= DISPTYPE_CRT1;
++ if(ivideo.currentvbflags & VB_DISPTYPE_CRT2) {
++ ivideo.currentvbflags |= VB_MIRROR_MODE;
++ ivideo.disp_state |= DISPMODE_MIRROR;
++ } else {
++ ivideo.currentvbflags |= VB_SINGLE_MODE;
++ ivideo.disp_state |= DISPMODE_SINGLE;
++ }
++ }
+
+- inSISIDXREG(SISPART4, 0x01, reg);
++ andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+
+- if(reg < 0xB0) { /* Set filter for SiS301 */
++ if((ivideo.currentvbflags & CRT2_TV) && (ivideo.vbflags & VB_301)) { /* Set filter for SiS301 */
+
+ switch (ivideo.video_width) {
+ case 320:
+- filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
++ filter_tb = (ivideo.vbflags & TV_NTSC) ? 4 : 12;
+ break;
+ case 640:
+- filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
++ filter_tb = (ivideo.vbflags & TV_NTSC) ? 5 : 13;
+ break;
+ case 720:
+- filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
++ filter_tb = (ivideo.vbflags & TV_NTSC) ? 6 : 14;
+ break;
+ case 800:
+- filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
++ filter_tb = (ivideo.vbflags & TV_NTSC) ? 7 : 15;
+ break;
+ default:
+ filter = -1;
+@@ -3469,15 +3986,15 @@ static void sisfb_post_setmode(void)
+
+ orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+
+- if(ivideo.TV_type == TVMODE_NTSC) {
++ if(ivideo.vbflags & TV_NTSC) {
+
+ andSISIDXREG(SISPART2, 0x3a, 0x1f);
+
+- if (ivideo.TV_plug == TVPLUG_SVIDEO) {
++ if (ivideo.vbflags & TV_SVIDEO) {
+
+ andSISIDXREG(SISPART2, 0x30, 0xdf);
+
+- } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
++ } else if (ivideo.vbflags & TV_AVIDEO) {
+
+ orSISIDXREG(SISPART2, 0x30, 0x20);
+
+@@ -3503,15 +4020,15 @@ static void sisfb_post_setmode(void)
+ }
+ }
+
+- } else if(ivideo.TV_type == TVMODE_PAL) {
++ } else if(ivideo.vbflags & TV_PAL) {
+
+ andSISIDXREG(SISPART2, 0x3A, 0x1F);
+
+- if (ivideo.TV_plug == TVPLUG_SVIDEO) {
++ if (ivideo.vbflags & TV_SVIDEO) {
+
+ andSISIDXREG(SISPART2, 0x30, 0xDF);
+
+- } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
++ } else if (ivideo.vbflags & TV_AVIDEO) {
+
+ orSISIDXREG(SISPART2, 0x30, 0x20);
+
+@@ -3539,7 +4056,7 @@ static void sisfb_post_setmode(void)
+ }
+
+ if ((filter >= 0) && (filter <=7)) {
+- DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
++ DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
+ sis_TV_filter[filter_tb].filter[filter][0],
+ sis_TV_filter[filter_tb].filter[filter][1],
+ sis_TV_filter[filter_tb].filter[filter][2],
+@@ -3550,8 +4067,6 @@ static void sisfb_post_setmode(void)
+ outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
+ outSISIDXREG(SISPART2, 0x38, (sis_TV_filter[filter_tb].filter[filter][3]));
+ }
+-
+- }
+
+ }
+
+@@ -3567,8 +4082,10 @@ int sisfb_setup(char *options)
+ #endif
+
+ ivideo.refresh_rate = 0;
++ SiS_Pr.SiS_CustomT = CUT_NONE;
++ SiS_Pr.UsePanelScaler = -1;
+
+- printk(KERN_INFO "sisfb: Options %s\n", options);
++ printk(KERN_DEBUG "sisfb: Options %s\n", options);
+
+ if (!options || !*options)
+ return 0;
+@@ -3577,72 +4094,75 @@ int sisfb_setup(char *options)
+
+ if (!*this_opt) continue;
+
+- if (!strncmp(this_opt, "mode:", 5)) {
+- sisfb_search_mode(this_opt + 5);
+- } else if (!strncmp(this_opt, "vesa:", 5)) {
+- sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+- } else if (!strcmp(this_opt, "inverse")) {
++ if (!strnicmp(this_opt, "mode:", 5)) {
++ sisfb_search_mode(this_opt + 5, FALSE);
++ } else if (!strnicmp(this_opt, "vesa:", 5)) {
++ sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ } else if (!strnicmp(this_opt, "inverse", 7)) {
+ sisfb_inverse = 1;
+ /* fb_invert_cmaps(); */
+- } else if (!strncmp(this_opt, "font:", 5)) {
++ } else if (!strnicmp(this_opt, "font:", 5)) {
+ strcpy(sis_fb_info.fontname, this_opt + 5);
+-#endif
+- } else if (!strncmp(this_opt, "mode:", 5)) {
+- sisfb_search_mode(this_opt + 5);
+- } else if (!strncmp(this_opt, "vesa:", 5)) {
+- sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
+- } else if (!strncmp(this_opt, "vrate:", 6)) {
++#endif
++ } else if (!strnicmp(this_opt, "vrate:", 6)) {
+ ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
+- } else if (!strncmp(this_opt, "rate:", 5)) {
++ sisfb_parm_rate = ivideo.refresh_rate;
++ } else if (!strnicmp(this_opt, "rate:", 5)) {
+ ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
+- } else if (!strncmp(this_opt, "off", 3)) {
++ sisfb_parm_rate = ivideo.refresh_rate;
++ } else if (!strnicmp(this_opt, "off", 3)) {
+ sisfb_off = 1;
+- } else if (!strncmp(this_opt, "crt1off", 7)) {
++ } else if (!strnicmp(this_opt, "crt1off", 7)) {
+ sisfb_crt1off = 1;
+- } else if (!strncmp(this_opt, "filter:", 7)) {
++ } else if (!strnicmp(this_opt, "filter:", 7)) {
+ filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
+- } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
++ } else if (!strnicmp(this_opt, "forcecrt2type:", 14)) {
+ sisfb_search_crt2type(this_opt + 14);
+- } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
++ } else if (!strnicmp(this_opt, "forcecrt1:", 10)) {
+ sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
+- } else if (!strncmp(this_opt, "tvmode:",7)) {
++ } else if (!strnicmp(this_opt, "tvmode:",7)) {
+ sisfb_search_tvstd(this_opt + 7);
+- } else if (!strncmp(this_opt, "tvstandard:",11)) {
++ } else if (!strnicmp(this_opt, "tvstandard:",11)) {
+ sisfb_search_tvstd(this_opt + 7);
+- } else if (!strncmp(this_opt, "mem:",4)) {
++ } else if (!strnicmp(this_opt, "mem:",4)) {
+ sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
+- } else if (!strncmp(this_opt, "dstn", 4)) {
+- enable_dstn = 1;
+- /* TW: DSTN overrules forcecrt2type */
+- sisfb_crt2type = DISPTYPE_LCD;
+- } else if (!strncmp(this_opt, "queuemode:", 10)) {
++ } else if (!strnicmp(this_opt, "queuemode:", 10)) {
+ sisfb_search_queuemode(this_opt + 10);
+- } else if (!strncmp(this_opt, "pdc:", 4)) {
++ } else if (!strnicmp(this_opt, "pdc:", 4)) {
+ sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+ if(sisfb_pdc & ~0x3c) {
+ printk(KERN_INFO "sisfb: Illegal pdc parameter\n");
+ sisfb_pdc = 0;
+ }
+- } else if (!strncmp(this_opt, "noaccel", 7)) {
++ } else if (!strnicmp(this_opt, "noaccel", 7)) {
+ sisfb_accel = 0;
+- } else if (!strncmp(this_opt, "noypan", 6)) {
++ } else if (!strnicmp(this_opt, "noypan", 6)) {
+ sisfb_ypan = 0;
+- } else if (!strncmp(this_opt, "userom:", 7)) {
++ } else if (!strnicmp(this_opt, "userom:", 7)) {
+ sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
+- } else if (!strncmp(this_opt, "useoem:", 7)) {
++ } else if (!strnicmp(this_opt, "useoem:", 7)) {
+ sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
++ } else if (!strnicmp(this_opt, "nocrt2rate", 10)) {
++ sisfb_nocrt2rate = 1;
++ } else if (!strnicmp(this_opt, "scalelcd:", 9)) {
++ unsigned long temp = 2;
++ temp = simple_strtoul(this_opt + 9, NULL, 0);
++ if((temp == 0) || (temp == 1)) {
++ SiS_Pr.UsePanelScaler = temp ^ 1;
++ }
++ } else if (!strnicmp(this_opt, "specialtiming:", 14)) {
++ sisfb_search_specialtiming(this_opt + 14);
++ } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
++ sisfb_search_mode(this_opt, TRUE);
+ } else {
+ printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
+ }
+
+ /* TW: Acceleration only with MMIO mode */
+ if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
+- sisfb_ypan = 0;
+ sisfb_accel = 0;
+ }
+- /* TW: Panning only with acceleration */
+- if(sisfb_accel == 0) sisfb_ypan = 0;
+
+ }
+ return 0;
+@@ -3661,14 +4181,14 @@ static char *sis_find_rom(void)
+ char *sis_sig_300[4] = {
+ "300", "540", "630", "730"
+ };
+- char *sis_sig_310[7] = {
+- "315", "315", "315", "5315", "6325", "6325", "Xabre"
++ char *sis_sig_310[9] = {
++ "315", "315", "315", "5315", "6325", "6325", "Xabre", "6330", "6330"
+ };
+ ushort sis_nums_300[4] = {
+ SIS_300, SIS_540, SIS_630, SIS_730
+ };
+- unsigned short sis_nums_310[7] = {
+- SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740, SIS_330
++ unsigned short sis_nums_310[9] = {
++ SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740, SIS_330, SIS_660, SIS_760
+ };
+
+ for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+@@ -3705,7 +4225,7 @@ static char *sis_find_rom(void)
+ }
+ }
+ if(stage != 4) {
+- for(i = 0;(i < 7) && (stage != 4); i++) {
++ for(i = 0;(i < 9) && (stage != 4); i++) {
+ if(strncmp(sis_sig_310[i], rom, strlen(sis_sig_310[i])) == 0) {
+ if(sis_nums_310[i] == ivideo.chip) {
+ stage = 4;
+@@ -3735,7 +4255,7 @@ int __init sisfb_init(void)
+ int pdev_valid = 0;
+ u32 reg32;
+ u16 reg16;
+- u8 reg, reg1;
++ u8 reg;
+
+ /* outb(0x77, 0x80); */ /* What is this? */
+
+@@ -3751,18 +4271,24 @@ int __init sisfb_init(void)
+ if (sisfb_off)
+ return -ENXIO;
+
+- if (enable_dstn)
+- SiS_SetEnableDstn(&SiS_Pr);
+-
+ sisfb_registered = 0;
++ sisfb_thismonitor.datavalid = FALSE;
+
+ memset(&sis_fb_info, 0, sizeof(sis_fb_info));
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ memset(&sisfb_lastrates[0], 0, 128);
++#endif
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ memset(&sis_disp, 0, sizeof(sis_disp));
+ #endif
+
+- while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
++ pci_for_each_dev(pdev) {
++#else
++ while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
++#endif
+ for (b = sisdev_list; b->vendor; b++) {
+ if ((b->vendor == pdev->vendor)
+ && (b->device == pdev->device)) {
+@@ -3804,18 +4330,17 @@ int __init sisfb_init(void)
+ break;
+ case PCI_DEVICE_ID_SI_630_VGA:
+ {
++ ivideo.chip = SIS_630;
+ sisfb_set_reg4(0xCF8, 0x80000000);
+ reg32 = sisfb_get_reg3(0xCFC);
+ if(reg32 == 0x07301039) {
+ ivideo.chip = SIS_730;
+-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info.modename, "SIS 730");
+ #else
+ strcpy(myid, "SIS 730");
+-#endif
+- } else
+- ivideo.chip = SIS_630;
+-
++#endif
++ }
+ sisvga_engine = SIS_300_VGA;
+ sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
+ sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
+@@ -3860,11 +4385,11 @@ int __init sisfb_init(void)
+ reg32 = sisfb_get_reg3(0xCFC);
+ if(reg32 == 0x07401039) {
+ ivideo.chip = SIS_740;
+-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+ strcpy(sis_fb_info.modename, "SIS 740");
+ #else
+- strcpy(myid, "SIS 740");
+-#endif
++ strcpy(myid, "SIS 740");
++#endif
+ }
+ sisvga_engine = SIS_315_VGA;
+ sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+@@ -3877,6 +4402,24 @@ int __init sisfb_init(void)
+ sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
+ sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
+ break;
++ case PCI_DEVICE_ID_SI_660_VGA:
++ {
++ ivideo.chip = SIS_660;
++ sisfb_set_reg4(0xCF8, 0x80000000);
++ reg32 = sisfb_get_reg3(0xCFC);
++ if(reg32 == 0x07601039) {
++ ivideo.chip = SIS_760;
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
++ strcpy(sis_fb_info.modename, "SIS 760");
++#else
++ strcpy(myid, "SIS 760");
++#endif
++ }
++ sisvga_engine = SIS_315_VGA;
++ sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
++ sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
++ break;
++ }
+ #endif
+ default:
+ return -ENODEV;
+@@ -3903,29 +4446,31 @@ int __init sisfb_init(void)
+ SiS_Pr.SiS_CHOverScan = -1;
+ SiS_Pr.SiS_ChSW = FALSE;
+ SiS_Pr.SiS_UseLCDA = FALSE;
+- SiS_Pr.UsePanelScaler = -1;
+ SiSRegInit(&SiS_Pr, (USHORT)sishw_ext.ulIOAddress);
+
+ #ifdef CONFIG_FB_SIS_300
+- /* TW: Find PCI systems for Chrontel/ISA bridge manipulation */
++ /* TW: Find PCI systems for Chrontel/GPIO communication setup */
+ if(ivideo.chip == SIS_630) {
+- int i=0;
+- do {
+- if(mychswtable[i].subsysVendor == ivideo.subsysvendor &&
+- mychswtable[i].subsysCard == ivideo.subsysdevice) {
+- SiS_Pr.SiS_ChSW = TRUE;
+- }
+- i++;
+- } while(mychswtable[i].subsysVendor != 0);
++ int i=0;
++ do {
++ if(mychswtable[i].subsysVendor == ivideo.subsysvendor &&
++ mychswtable[i].subsysCard == ivideo.subsysdevice) {
++ SiS_Pr.SiS_ChSW = TRUE;
++ printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
++ mychswtable[i].vendorName, mychswtable[i].cardName);
++ break;
++ }
++ i++;
++ } while(mychswtable[i].subsysVendor != 0);
+ }
+ #endif
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+-#ifdef MODULE
++#ifdef MODULE
+ inSISIDXREG(SISCR,0x34,reg);
+- if(reg & 0x80) {
++ if((reg & 0x80) && (reg != 0xff)) {
+ if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
+ printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
+ return -EBUSY;
+@@ -3938,7 +4483,7 @@ int __init sisfb_init(void)
+
+ #ifdef CONFIG_FB_SIS_300
+ if (sisvga_engine == SIS_300_VGA) {
+- outSISIDXREG(SISSR, 0x28, 0x37);
++ outSISIDXREG(SISSR, 0x28, 0x37); /* Reset memory clock */
+
+ outSISIDXREG(SISSR, 0x29, 0x61);
+
+@@ -3946,7 +4491,9 @@ int __init sisfb_init(void)
+ }
+ #endif
+ #ifdef CONFIG_FB_SIS_315
+- if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650 || ivideo.chip == SIS_740) {
++ if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650 ||
++ ivideo.chip == SIS_740 || ivideo.chip == SIS_660 ||
++ ivideo.chip == SIS_760) {
+ outSISIDXREG(SISSR, 0x28, 0x5a);
+
+ outSISIDXREG(SISSR, 0x29, 0x64);
+@@ -3967,6 +4514,8 @@ int __init sisfb_init(void)
+ case SIS_550:
+ case SIS_650:
+ case SIS_740:
++ case SIS_660:
++ case SIS_760:
+ sishw_ext.bIntegratedMMEnabled = TRUE;
+ break;
+ default:
+@@ -4006,13 +4555,56 @@ int __init sisfb_init(void)
+ sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
+ strcpy(sishw_ext.szVBIOSVer, "0.84");
+
+- /* TW: Mode numbers for 1280x960 are different for 300 and 310/325 series */
++ /* Find systems for special custom timing */
++ if((sishw_ext.UseROM) && (SiS_Pr.SiS_CustomT == CUT_NONE)) {
++ int i=0,j;
++ unsigned char *biosver = sishw_ext.pjVirtualRomBase + 0x06;
++ unsigned char *biosdate = sishw_ext.pjVirtualRomBase + 0x2c;
++ BOOLEAN footprint;
++ unsigned long chksum = 0;
++
++ for(i=0; i<32768; i++) chksum += sishw_ext.pjVirtualRomBase[i];
++
++ i=0;
++ do {
++ if( (mycustomttable[i].chipID == ivideo.chip) &&
++ ((!strlen(mycustomttable[i].biosversion)) ||
++ (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion)))) &&
++ ((!strlen(mycustomttable[i].biosdate)) ||
++ (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate)))) &&
++ ((!mycustomttable[i].bioschksum) ||
++ (mycustomttable[i].bioschksum == chksum)) &&
++ (mycustomttable[i].pcisubsysvendor == ivideo.subsysvendor) &&
++ (mycustomttable[i].pcisubsyscard == ivideo.subsysdevice) ) {
++ footprint = TRUE;
++ for(j=0; j<5; j++) {
++ if(mycustomttable[i].biosFootprintAddr[j]) {
++ if(sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
++ mycustomttable[i].biosFootprintData[j])
++ footprint = FALSE;
++ }
++ }
++ if(footprint) {
++ SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
++ printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
++ mycustomttable[i].vendorName,
++ mycustomttable[i].cardName);
++ break;
++ }
++ }
++ i++;
++ } while(mycustomttable[i].chipID);
++ }
++
++#ifdef CONFIG_FB_SIS_300
++ /* Mode numbers for 1280x768 are different for 300 and 315 series */
+ if(sisvga_engine == SIS_300_VGA) {
+- sisbios_mode[MODEINDEX_1280x960].mode_no = 0x6e;
+- sisbios_mode[MODEINDEX_1280x960+1].mode_no = 0x6f;
+- sisbios_mode[MODEINDEX_1280x960+2].mode_no = 0x7b;
+- sisbios_mode[MODEINDEX_1280x960+3].mode_no = 0x7b;
++ sisbios_mode[MODEINDEX_1280x768].mode_no = 0x55;
++ sisbios_mode[MODEINDEX_1280x768+1].mode_no = 0x5a;
++ sisbios_mode[MODEINDEX_1280x768+2].mode_no = 0x5b;
++ sisbios_mode[MODEINDEX_1280x768+3].mode_no = 0x5b;
+ }
++#endif
+
+ sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
+ if (sishw_ext.pSR == NULL) {
+@@ -4168,120 +4760,53 @@ int __init sisfb_init(void)
+
+ ivideo.mtrr = (unsigned int) 0;
+
+- if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+-
+-#ifdef CONFIG_FB_SIS_300
+- if (sisvga_engine == SIS_300_VGA) {
+- sisfb_get_VB_type_300();
+- }
+-#endif
++ ivideo.vbflags = 0;
+
+-#ifdef CONFIG_FB_SIS_315
+- if (sisvga_engine == SIS_315_VGA) {
+- sisfb_get_VB_type_315();
+- }
+-#endif
++ if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+
+ sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+ sishw_ext.Is301BDH = FALSE;
+ sishw_ext.usExternalChip = 0;
+
+- switch (ivideo.hasVB) {
++ sisfb_get_VB_type();
+
+- case HASVB_301:
+- inSISIDXREG(SISPART4, 0x01, reg);
+- if (reg >= 0xE0) {
+- sishw_ext.ujVBChipID = VB_CHIP_302LV;
+- printk(KERN_INFO "sisfb: SiS302LV bridge detected (revision 0x%02x)\n",reg);
+- } else if (reg >= 0xD0) {
+- sishw_ext.ujVBChipID = VB_CHIP_301LV;
+- printk(KERN_INFO "sisfb: SiS301LV bridge detected (revision 0x%02x)\n",reg);
+- } else if (reg >= 0xB0) {
+- sishw_ext.ujVBChipID = VB_CHIP_301B;
+- inSISIDXREG(SISPART4,0x23,reg1);
+- if(!(reg1 & 0x02)) sishw_ext.Is301BDH = TRUE;
+- printk(KERN_INFO "sisfb: SiS301B%s bridge detected (revision 0x%02x)\n",
+- (sishw_ext.Is301BDH ? "-DH" : ""), reg);
+- } else {
+- sishw_ext.ujVBChipID = VB_CHIP_301;
+- printk(KERN_INFO "sisfb: SiS301 bridge detected\n");
+- }
+- break;
+- case HASVB_302:
+- inSISIDXREG(SISPART4, 0x01, reg);
+- if (reg >= 0xE0) {
+- sishw_ext.ujVBChipID = VB_CHIP_302LV;
+- printk(KERN_INFO "sisfb: SiS302LV bridge detected (revision 0x%02x)\n",reg);
+- } else if (reg >= 0xD0) {
+- sishw_ext.ujVBChipID = VB_CHIP_301LV;
+- printk(KERN_INFO "sisfb: SiS302LV bridge detected (revision 0x%02x)\n",reg);
+- } else if (reg >= 0xB0) {
+- inSISIDXREG(SISPART4,0x23,reg1);
+- if(!(reg1 & 0x02)) sishw_ext.Is301BDH = TRUE;
+- sishw_ext.ujVBChipID = VB_CHIP_302B;
+- printk(KERN_INFO "sisfb: SiS302B%s bridge detected (revision 0x%02x)\n",
+- (sishw_ext.Is301BDH ? "-DH" : ""), reg);
+- } else {
+- sishw_ext.ujVBChipID = VB_CHIP_302;
+- printk(KERN_INFO "sisfb: SiS302 bridge detected\n");
+- }
+- break;
+- case HASVB_LVDS:
+- sishw_ext.usExternalChip = 0x1;
+- printk(KERN_INFO "sisfb: LVDS transmitter detected\n");
+- break;
+- case HASVB_TRUMPION:
+- sishw_ext.usExternalChip = 0x2;
+- printk(KERN_INFO "sisfb: Trumpion Zurac LVDS scaler detected\n");
+- break;
+- case HASVB_CHRONTEL:
+- sishw_ext.usExternalChip = 0x4;
+- printk(KERN_INFO "sisfb: Chrontel TV encoder detected\n");
+- break;
+- case HASVB_LVDS_CHRONTEL:
+- sishw_ext.usExternalChip = 0x5;
+- printk(KERN_INFO "sisfb: LVDS transmitter and Chrontel TV encoder detected\n");
+- break;
+- default:
+- printk(KERN_INFO "sisfb: No or unknown bridge type detected\n");
+- break;
++ if(ivideo.vbflags & VB_VIDEOBRIDGE) {
++ sisfb_detect_VB_connect();
+ }
+
+- if (ivideo.hasVB != HASVB_NONE) {
+-#ifdef CONFIG_FB_SIS_300
+- if (sisvga_engine == SIS_300_VGA) {
+- sisfb_detect_VB_connect_300();
+- }
+-#endif
+-#ifdef CONFIG_FB_SIS_315
+- if (sisvga_engine == SIS_315_VGA) {
+- sisfb_detect_VB_connect_315();
+- }
+-#endif
+- }
++ ivideo.currentvbflags = ivideo.vbflags & VB_VIDEOBRIDGE;
+
+- if (ivideo.disp_state & DISPTYPE_DISP2) {
+- if (sisfb_crt1off)
+- ivideo.disp_state |= DISPMODE_SINGLE;
+- else
+- ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+- } else {
+- ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
++ if(ivideo.vbflags & VB_VIDEOBRIDGE) {
++ if(sisfb_crt2type != -1) {
++ if((sisfb_crt2type == CRT2_LCD) && (ivideo.vbflags & CRT2_LCD)) {
++ ivideo.currentvbflags |= CRT2_LCD;
++ } else if(sisfb_crt2type != CRT2_LCD) {
++ ivideo.currentvbflags |= sisfb_crt2type;
++ }
++ } else {
++ /* Chrontel 700x TV detection often unreliable, therefore use a
++ * different default order on such machines
++ */
++ if((sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
++ if(ivideo.vbflags & CRT2_LCD) ivideo.currentvbflags |= CRT2_LCD;
++ else if(ivideo.vbflags & CRT2_TV) ivideo.currentvbflags |= CRT2_TV;
++ else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
++ } else {
++ if(ivideo.vbflags & CRT2_TV) ivideo.currentvbflags |= CRT2_TV;
++ else if(ivideo.vbflags & CRT2_LCD) ivideo.currentvbflags |= CRT2_LCD;
++ else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
++ }
++ }
+ }
+
+- if (ivideo.disp_state & DISPTYPE_LCD) {
+- if (!enable_dstn) {
+- inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
+- reg &= 0x0f;
+- if (sisvga_engine == SIS_300_VGA) {
+- sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+- } else {
+- sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+- }
+- } else {
+- /* TW: FSTN/DSTN */
+- sishw_ext.ulCRT2LCDType = LCD_320x480;
+- }
++ if(ivideo.vbflags & CRT2_LCD) {
++ inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
++ reg &= 0x0f;
++ if(sisvga_engine == SIS_300_VGA) {
++ sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
++ } else {
++ sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
++ }
+ }
+
+ sisfb_detectedpdc = 0;
+@@ -4289,9 +4814,7 @@ int __init sisfb_init(void)
+ #ifdef CONFIG_FB_SIS_300
+ /* TW: Save the current PanelDelayCompensation if the LCD is currently used */
+ if(sisvga_engine == SIS_300_VGA) {
+- if((sishw_ext.usExternalChip == 0x01) || /* LVDS */
+- (sishw_ext.usExternalChip == 0x05) || /* LVDS+Chrontel */
+- (sishw_ext.Is301BDH)) { /* 301B-DH */
++ if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
+ int tmp;
+ inSISIDXREG(SISCR,0x30,tmp);
+ if(tmp & 0x20) {
+@@ -4320,54 +4843,57 @@ int __init sisfb_init(void)
+ #ifdef CONFIG_FB_SIS_315
+ /* TW: Try to find about LCDA */
+ if(sisvga_engine == SIS_315_VGA) {
+- if((sishw_ext.ujVBChipID == VB_CHIP_302B) ||
+- (sishw_ext.ujVBChipID == VB_CHIP_301LV) ||
+- (sishw_ext.ujVBChipID == VB_CHIP_302LV)) {
+- int tmp;
+- inSISIDXREG(SISCR,0x34,tmp);
+- if(tmp <= 0x13) {
+- /* Currently on LCDA? (Some BIOSes leave CR38) */
+- inSISIDXREG(SISCR,0x38,tmp);
+- if((tmp & 0x03) == 0x03) {
+- SiS_Pr.SiS_UseLCDA = TRUE;
+- } else {
+- /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
+- inSISIDXREG(SISCR,0x35,tmp);
+- if(tmp & 0x01) {
+- SiS_Pr.SiS_UseLCDA = TRUE;
+- } else {
+- /* Currently on LCD? If so, we can find out
+- by peeking the mode register
+- */
+- inSISIDXREG(SISCR,0x30,tmp);
+- if(tmp & 0x20) {
+- inSISIDXREG(SISPART1,0x13,tmp);
+- if(tmp & 0x04) {
+- SiS_Pr.SiS_UseLCDA = TRUE;
+- }
+- }
+- }
+- }
+- }
+- if(SiS_Pr.SiS_UseLCDA) {
+- sisfb_detectedlcda = 0x03;
+- printk(KERN_INFO
+- "sisfb: Bridge uses LCDA for low resolution and text modes\n");
+- }
++ if(ivideo.vbflags & (VB_302B | VB_301LV | VB_302LV)) {
++ int tmp;
++ inSISIDXREG(SISCR,0x34,tmp);
++ if((tmp <= 0x13) || (tmp == 0xff)) {
++ /* Currently on LCDA? (Some BIOSes leave CR38) */
++ inSISIDXREG(SISCR,0x38,tmp);
++ if((tmp & 0x03) == 0x03) SiS_Pr.SiS_UseLCDA = TRUE;
++ else {
++ /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
++ inSISIDXREG(SISCR,0x35,tmp);
++ if(tmp & 0x01) SiS_Pr.SiS_UseLCDA = TRUE;
++ else {
++ /* Currently on LCD? If so, we can find out
++ * by peeking the mode register
++ */
++ inSISIDXREG(SISCR,0x30,tmp);
++ if(tmp & 0x20) {
++ inSISIDXREG(SISPART1,0x13,tmp);
++ if(tmp & 0x04) SiS_Pr.SiS_UseLCDA = TRUE;
++ }
++ }
++ }
++ }
++ if(SiS_Pr.SiS_UseLCDA) {
++ sisfb_detectedlcda = 0x03;
++ printk(KERN_DEBUG
++ "sisfb: Bridge uses LCDA for low resolution and text modes\n");
++ }
+ }
+ }
+ #endif
+ #endif
+
++ if (!sisfb_crt1off) {
++ sisfb_handle_ddc(&sisfb_thismonitor, 0);
++ } else {
++ if ((ivideo.vbflags & (VB_301|VB_301B|VB_302B)) &&
++ (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
++ sisfb_handle_ddc(&sisfb_thismonitor, 1);
++ }
++ }
++
+ if (sisfb_mode_idx >= 0)
+- sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx);
++ sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
+
+ if (sisfb_mode_idx < 0) {
+- switch (ivideo.disp_state & DISPTYPE_DISP2) {
+- case DISPTYPE_LCD:
++ switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
++ case CRT2_LCD:
+ sisfb_mode_idx = DEFAULT_LCDMODE;
+ break;
+- case DISPTYPE_TV:
++ case CRT2_TV:
+ sisfb_mode_idx = DEFAULT_TVMODE;
+ break;
+ default:
+@@ -4379,39 +4905,27 @@ int __init sisfb_init(void)
+ sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+
+ if (ivideo.refresh_rate != 0)
+- sisfb_search_refresh_rate(ivideo.refresh_rate);
++ sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
+
+ if (sisfb_rate_idx == 0) {
+ sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+ ivideo.refresh_rate = 60;
+ }
+
++ if (sisfb_thismonitor.datavalid) {
++ if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
++ sisfb_rate_idx, ivideo.refresh_rate)) {
++ printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
++ }
++ }
++
+ ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+ ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
+ ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
+ ivideo.org_x = ivideo.org_y = 0;
+ ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
+- switch(ivideo.video_bpp) {
+- case 8:
+- ivideo.DstColor = 0x0000;
+- ivideo.SiS310_AccelDepth = 0x00000000;
+- ivideo.video_cmap_len = 256;
+- break;
+- case 16:
+- ivideo.DstColor = 0x8000;
+- ivideo.SiS310_AccelDepth = 0x00010000;
+- ivideo.video_cmap_len = 16;
+- break;
+- case 32:
+- ivideo.DstColor = 0xC000;
+- ivideo.SiS310_AccelDepth = 0x00020000;
+- ivideo.video_cmap_len = 16;
+- break;
+- default:
+- ivideo.video_cmap_len = 16;
+- printk(KERN_INFO "sisfb: Unsupported depth %d", ivideo.video_bpp);
+- break;
+- }
++
++ sisfb_set_vparms();
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+@@ -4424,27 +4938,49 @@ int __init sisfb_init(void)
+ sisfb_pre_setmode();
+
+ if (SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
+- printk(KERN_ERR "sisfb: Setting mode[0x%x] failed, using default mode\n",
++ printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
+ sisfb_mode_no);
+- return -1;
++ vfree(sishw_ext.pSR);
++ vfree(sishw_ext.pCR);
++ release_mem_region(ivideo.video_base, ivideo.video_size);
++ release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
++ return -EINVAL;
+ }
+
+ outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+ sisfb_post_setmode();
+
++ ivideo.accel = 0;
++ if(sisfb_accel) {
++ ivideo.accel = -1;
++ default_var.accel_flags |= FB_ACCELF_TEXT;
++ sisfb_initaccel();
++ }
++
+ sisfb_crtc_to_var(&default_var);
+
++ sis_fb_info.node = -1;
++ sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
++ sis_fb_info.blank = &sisfb_blank;
++ sis_fb_info.fbops = &sisfb_ops;
++ sis_fb_info.switch_con = &sisfb_switch;
++ sis_fb_info.updatevar = &sisfb_update_var;
++ sis_fb_info.changevar = NULL;
++ sis_fb_info.disp = &sis_disp;
++
++ sisfb_set_disp(-1, &default_var, &sis_fb_info);
++
+ #else /* --------- For 2.5: Setup a somewhat sane default var ------------ */
+
+ printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
+ ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
+ ivideo.refresh_rate);
+-
++
+ default_var.xres = default_var.xres_virtual = ivideo.video_width;
+ default_var.yres = default_var.yres_virtual = ivideo.video_height;
+ default_var.bits_per_pixel = ivideo.video_bpp;
+-
++
+ sisfb_bpp_to_var(&default_var);
+
+ default_var.pixclock = (u32) (1E12 /
+@@ -4457,28 +4993,10 @@ int __init sisfb_init(void)
+ &default_var.upper_margin, &default_var.lower_margin,
+ &default_var.hsync_len, &default_var.vsync_len,
+ &default_var.sync, &default_var.vmode)) {
+-
+- if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+- default_var.yres <<= 1;
+- default_var.yres_virtual <<= 1;
+- } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+- default_var.pixclock >>= 1;
+- default_var.yres >>= 1;
+- default_var.yres_virtual >>= 1;
+- }
+-
++ if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
++ default_var.pixclock <<= 1;
++ }
+ }
+-#ifdef SISFB_PAN
+- if(sisfb_ypan) {
+- default_var.yres_virtual =
+- ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
+- if(default_var.yres_virtual <= default_var.yres) {
+- default_var.yres_virtual = default_var.yres;
+- }
+- }
+-#endif
+-
+-#endif
+
+ ivideo.accel = 0;
+ if(sisfb_accel) {
+@@ -4487,20 +5005,14 @@ int __init sisfb_init(void)
+ sisfb_initaccel();
+ }
+
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) /* ---- 2.4 series init ---- */
+- sis_fb_info.node = -1;
+- sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
+- sis_fb_info.blank = &sisfb_blank;
+- sis_fb_info.fbops = &sisfb_ops;
+- sis_fb_info.switch_con = &sisfb_switch;
+- sis_fb_info.updatevar = &sisfb_update_var;
+- sis_fb_info.changevar = NULL;
+- sis_fb_info.disp = &sis_disp;
+-
+- sisfb_set_disp(-1, &default_var, &sis_fb_info);
+-#endif
++ if(sisfb_ypan) {
++ default_var.yres_virtual =
++ ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
++ if(default_var.yres_virtual <= default_var.yres) {
++ default_var.yres_virtual = default_var.yres;
++ }
++ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) /* ---- 2.5 series init ---- */
+ sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
+ sis_fb_info.var = default_var;
+ sis_fb_info.fix = sisfb_fix;
+@@ -4513,6 +5025,8 @@ int __init sisfb_init(void)
+ fb_alloc_cmap(&sis_fb_info.cmap, 256 , 0);
+ #endif
+
++ printk(KERN_INFO "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
++
+ #ifdef CONFIG_MTRR
+ ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
+ (unsigned int) ivideo.video_size,
+@@ -4520,20 +5034,28 @@ int __init sisfb_init(void)
+ if(ivideo.mtrr) {
+ printk(KERN_INFO "sisfb: Added MTRRs\n");
+ }
++
+ #endif
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ vc_resize_con(1, 1, 0);
+ #endif
+
+- TWDEBUG("Before calling register_framebuffer");
+-
+- if(register_framebuffer(&sis_fb_info) < 0)
++ if(register_framebuffer(&sis_fb_info) < 0) {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++ vfree(sishw_ext.pSR);
++ vfree(sishw_ext.pCR);
++ release_mem_region(ivideo.video_base, ivideo.video_size);
++ release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
++#endif
++ printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+ return -EINVAL;
+-
++ }
++
+ sisfb_registered = 1;
+
+ printk(KERN_INFO "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
++ printk(KERN_INFO "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
+
+ printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %s\n",
+ sisfb_accel ? "enabled" : "disabled",
+@@ -4547,9 +5069,11 @@ int __init sisfb_init(void)
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+- sis_fb_info.node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
++ sis_fb_info.node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+ #endif
+
++ printk(KERN_INFO "sisfb: (C) 2001-2003 Thomas Winischhofer. All rights reserved.\n");
++
+ } /* TW: if mode = "none" */
+ return 0;
+ }
+@@ -4562,7 +5086,6 @@ static int vesa = -1;
+ static unsigned int rate = 0;
+ static unsigned int crt1off = 1;
+ static unsigned int mem = 0;
+-static unsigned int dstn = 0;
+ static char *forcecrt2type = NULL;
+ static int forcecrt1 = -1;
+ static char *queuemode = NULL;
+@@ -4575,25 +5098,33 @@ static int inverse = 0;
+ static int userom = 1;
+ static int useoem = -1;
+ static char *tvstandard = NULL;
++static int nocrt2rate = 0;
++static int scalelcd = -1;
++static char *specialtiming = NULL;
+
+-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/740/330 framebuffer driver");
++MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/740/330/660/760 framebuffer driver");
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("SiS; Thomas Winischhofer <thomas@winischhofer.net>; Various others");
++MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Various others");
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ MODULE_PARM(mode, "s");
+ MODULE_PARM_DESC(mode,
+ "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+- "800x600x16 (default: none if sisfb is a module; this leaves the\n"
+- "console untouched and the driver will only do the video memory\n"
+- "management for eg. DRM/DRI; 800x600x8 if sisfb is in the kernel)");
++ "1024x768x16. Other formats supported include XxY-Depth and\n"
++ "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
++ "number, it will be interpreted as a VESA mode number. (default: none if\n"
++ "sisfb is a module; this leaves the console untouched and the driver will\n"
++ "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
++ "is in the kernel)");
+ #endif
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ MODULE_PARM(mode, "s");
+ MODULE_PARM_DESC(mode,
+- "\nSelects the desired default display mode in the format [X]x[Y]x[Depth],\n"
+- "eg. 1024x768x16 (default: 800x600x8)");
+-#endif
++ "\nSelects the desired default display mode in the format XxYxDepth,\n"
++ "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
++ "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
++ "number, it will be interpreted as a VESA mode number. (default: 800x600x8)");
++#endif
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ MODULE_PARM(vesa, "i");
+@@ -4603,17 +5134,18 @@ MODULE_PARM_DESC(vesa,
+ "and the driver will only do the video memory management for eg. DRM/DRI;\n"
+ "0x0103 if sisfb is in the kernel)");
+ #endif
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ MODULE_PARM(vesa, "i");
+ MODULE_PARM_DESC(vesa,
+ "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+ "0x117 (default: 0x0103)");
+-#endif
++#endif
+
+ MODULE_PARM(rate, "i");
+ MODULE_PARM_DESC(rate,
+ "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
+- "(default: 60)");
++ "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
++ "will be ignored (default: 60)");
+
+ MODULE_PARM(crt1off, "i");
+ MODULE_PARM_DESC(crt1off,
+@@ -4624,14 +5156,9 @@ MODULE_PARM_DESC(filter,
+ "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
+ "(Possible values 0-7, default: [no filter])");
+
+-MODULE_PARM(dstn, "i");
+-MODULE_PARM_DESC(dstn,
+- "\nSelects DSTN/FSTN display mode for SiS550. This sets CRT2 type to LCD and\n"
+- "overrides forcecrt2type setting. (1=ON, 0=OFF) (default: 0)");
+-
+ MODULE_PARM(queuemode, "s");
+ MODULE_PARM_DESC(queuemode,
+- "\nSelects the queue mode on 315/550/650/740/330. Possible choices are AGP, VRAM or\n"
++ "\nSelects the queue mode on 315/550/650/740/330/660. Possible choices are AGP, VRAM,\n"
+ "MMIO. AGP is only available if the kernel has AGP support. The queue mode is\n"
+ "important to programs using the 2D/3D accelerator of the SiS chip. The modes\n"
+ "require a totally different way of programming the engines. If any mode than\n"
+@@ -4642,11 +5169,12 @@ MODULE_PARM_DESC(queuemode,
+ MODULE_PARM(mem, "i");
+ MODULE_PARM_DESC(mem,
+ "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+- "for video RAM management for eg. DRM/DRI. The default depends on the amount\n"
+- "of video RAM available. If 8MB of video RAM or less is available, the heap\n"
+- "starts at 4096KB, if between 8 and 16MB are available at 8192KB, otherwise\n"
+- "at 12288KB. The value is to be specified without 'KB' and should match\n"
+- "the MaxXFBMem setting for XFree 4.x (x>=2).");
++ "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
++ "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
++ "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
++ "otherwise at 12288KB. On 315 and Xabre series, the heap is 1MB by default. The\n"
++ "value is to be specified without 'KB' and should match the MaxXFBMem setting for\n"
++ "XFree 4.x (x>=2).");
+
+ MODULE_PARM(forcecrt2type, "s");
+ MODULE_PARM_DESC(forcecrt2type,
+@@ -4673,56 +5201,76 @@ MODULE_PARM_DESC(pdc,
+ MODULE_PARM(noaccel, "i");
+ MODULE_PARM_DESC(noaccel,
+ "\nIf set to anything other than 0, 2D acceleration and y-panning will be\n"
+- "disabled. (default: 0)");
++ "disabled. (default: 0)");
+
+ MODULE_PARM(noypan, "i");
+ MODULE_PARM_DESC(noypan,
+ "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+- "will be performed by redrawing the screen. This required 2D acceleration, so\n"
+- "if the option noaccel is set, y-panning will be disabled. (default: 0)");
++ "will be performed by redrawing the screen. (default: 0)");
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ MODULE_PARM(inverse, "i");
+ MODULE_PARM_DESC(inverse,
+ "\nSetting this to anything but 0 should invert the display colors, but this\n"
+- "does not seem to work. (default: 0)");
++ "does not seem to work. (default: 0)");
+ #endif
+
+ MODULE_PARM(userom, "i");
+ MODULE_PARM_DESC(userom,
+ "\nSetting this to 0 keeps sisfb from using the video BIOS data which is needed\n"
+- "for some LCD and TV setup. (default: 1)");
++ "for some LCD and TV setup. (default: 1)");
+
+ MODULE_PARM(useoem, "i");
+ MODULE_PARM_DESC(useoem,
+ "\nSetting this to 0 keeps sisfb from using its internel OEM data for some LCD\n"
+- "panels and TV connector types. (default: auto)");
++ "panels and TV connector types. (default: [auto])");
+
+ MODULE_PARM(tvstandard, "s");
+ MODULE_PARM_DESC(tvstandard,
+ "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
+- "pal and ntsc. (default: auto)");
++ "pal and ntsc. (default: [auto])");
++
++MODULE_PARM(nocrt2rate, "i");
++MODULE_PARM_DESC(nocrt2rate,
++ "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
++ "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)");
++
++MODULE_PARM(scalelcd, "i");
++MODULE_PARM_DESC(scalelcd,
++ "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
++ "native resolution. Setting it to 0 will disable scaling; if the panel can scale\n"
++ "by itself, it will probably do this, otherwise you will see a black bar around\n"
++ "the screen image. Default: [autodetect if panel can scale]");
++
++MODULE_PARM(specialtiming, "s");
+
+ int init_module(void)
+ {
+ int err;
+-
++
++ SiS_Pr.UsePanelScaler = -1;
++ SiS_Pr.SiS_CustomT = CUT_NONE;
++
++ ivideo.refresh_rate = sisfb_parm_rate = rate;
++
++ if((scalelcd == 0) || (scalelcd == 1)) {
++ SiS_Pr.UsePanelScaler = scalelcd ^ 1;
++ }
++
+ if(mode)
+- sisfb_search_mode(mode);
++ sisfb_search_mode(mode, FALSE);
+ else if(vesa != -1)
+- sisfb_search_vesamode(vesa);
+- else
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ sisfb_search_vesamode(vesa, FALSE);
++ else
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ /* For 2.4, set mode=none if no mode is given */
+ sisfb_mode_idx = MODE_INDEX_NONE;
+ #endif
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+- /* For 2.5, we don't need this "mode=none" stuff anymore */
++ /* For 2.5, we don't need this "mode=none" stuff anymore */
+ sisfb_mode_idx = DEFAULT_MODE;
+ #endif
+
+- ivideo.refresh_rate = rate;
+-
+ if(forcecrt2type)
+ sisfb_search_crt2type(forcecrt2type);
+
+@@ -4745,9 +5293,6 @@ int init_module(void)
+
+ if(noypan == 1) sisfb_ypan = 0;
+ else if(noypan == 0) sisfb_ypan = 1;
+-
+- /* TW: Panning only with acceleration */
+- if(sisfb_accel == 0) sisfb_ypan = 0;
+
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ if(inverse) sisfb_inverse = 1;
+@@ -4759,17 +5304,11 @@ int init_module(void)
+
+ sisfb_useoem = useoem;
+
+- enable_dstn = dstn;
+-
+- /* TW: DSTN overrules forcecrt2type */
+- if (enable_dstn) sisfb_crt2type = DISPTYPE_LCD;
+-
+ if (queuemode) sisfb_search_queuemode(queuemode);
+
+ /* TW: If other queuemode than MMIO, disable 2D accel and ypan */
+ if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
+ sisfb_accel = 0;
+- sisfb_ypan = 0;
+ }
+
+ if(pdc) {
+@@ -4778,6 +5317,11 @@ int init_module(void)
+ }
+ }
+
++ sisfb_nocrt2rate = nocrt2rate;
++
++ if(specialtiming)
++ sisfb_search_specialtiming(specialtiming);
++
+ if((err = sisfb_init()) < 0) return err;
+
+ return 0;
+@@ -4788,7 +5332,7 @@ void cleanup_module(void)
+ /* TW: Release mem regions */
+ release_mem_region(ivideo.video_base, ivideo.video_size);
+ release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+-
++
+ #ifdef CONFIG_MTRR
+ /* TW: Release MTRR region */
+ if(ivideo.mtrr) {
+@@ -4802,11 +5346,17 @@ void cleanup_module(void)
+ if(sisfb_registered) {
+ unregister_framebuffer(&sis_fb_info);
+ }
+-
++
+ if(sishw_ext.pSR) vfree(sishw_ext.pSR);
+ if(sishw_ext.pCR) vfree(sishw_ext.pCR);
+
+- /* TODO: Restore the initial mode */
++ /* TODO: Restore the initial mode
++ * This sounds easy but is as good as impossible
++ * on many machines with SiS chip and video bridge
++ * since text modes are always set up differently
++ * from machine to machine. Depends on the type
++ * of integration between chipset and bridge.
++ */
+
+ printk(KERN_INFO "sisfb: Module unloaded\n");
+ }
+--- linux-2.6.0-test6/drivers/video/sis/sis_main.h 2003-06-14 12:18:04.000000000 -0700
++++ 25/drivers/video/sis/sis_main.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,8 +1,6 @@
+ #ifndef _SISFB_MAIN
+ #define _SISFB_MAIN
+
+-/* Comments and changes marked with "TW" by Thomas Winischhofer <thomas@winischhofer.net> */
+-
+ #include "vstruct.h"
+
+ /* ------------------- Constant Definitions ------------------------- */
+@@ -14,11 +12,11 @@
+
+ #define VER_MAJOR 1
+ #define VER_MINOR 6
+-#define VER_LEVEL 1
++#define VER_LEVEL 13
+
+ #include "sis.h"
+
+-/* TW: To be included in pci_ids.h */
++/* To be included in pci_ids.h */
+ #ifndef PCI_DEVICE_ID_SI_650_VGA
+ #define PCI_DEVICE_ID_SI_650_VGA 0x6325
+ #endif
+@@ -31,13 +29,22 @@
+ #ifndef PCI_DEVICE_ID_SI_330
+ #define PCI_DEVICE_ID_SI_330 0x0330
+ #endif
++#ifndef PCI_DEVICE_ID_SI_660
++#define PCI_DEVICE_ID_SI_660 0x0660
++#endif
++#ifndef PCI_DEVICE_ID_SI_660_VGA
++#define PCI_DEVICE_ID_SI_660_VGA 0x6330
++#endif
++#ifndef PCI_DEVICE_ID_SI_760
++#define PCI_DEVICE_ID_SI_760 0x0760
++#endif
+
+ /* To be included in fb.h */
+ #ifndef FB_ACCEL_SIS_GLAMOUR_2
+ #define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */
+ #endif
+ #ifndef FB_ACCEL_SIS_XABRE
+-#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */
++#define FB_ACCEL_SIS_XABRE 41 /* SiS 330, 660, 760 ("Xabre") */
+ #endif
+
+ #define MAX_ROM_SCAN 0x10000
+@@ -53,13 +60,12 @@
+ #define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */
+ #endif
+
+-/* For 315 series */
++/* For 315/Xabre series */
+ #ifdef CONFIG_FB_SIS_315
+ #define COMMAND_QUEUE_AREA_SIZE 0x80000 /* 512K */
+ #define COMMAND_QUEUE_THRESHOLD 0x1F
+ #endif
+
+-/* TW */
+ #define HW_CURSOR_AREA_SIZE_315 0x4000 /* 16K */
+ #define HW_CURSOR_AREA_SIZE_300 0x1000 /* 4K */
+
+@@ -283,48 +289,46 @@
+ /* Fbcon variables */
+ static struct fb_info sis_fb_info;
+
+-static int video_type = FB_TYPE_PACKED_PIXELS;
+-
+ static struct fb_var_screeninfo default_var = {
+- .xres = 0,
+- .yres = 0,
+- .xres_virtual = 0,
+- .yres_virtual = 0,
+- .xoffset = 0,
+- .yoffset = 0,
+- .bits_per_pixel = 0,
+- .grayscale = 0,
+- .red = {0, 8, 0},
+- .green = {0, 8, 0},
+- .blue = {0, 8, 0},
+- .transp = {0, 0, 0},
+- .nonstd = 0,
+- .activate = FB_ACTIVATE_NOW,
+- .height = -1,
+- .width = -1,
+- .accel_flags = 0,
+- .pixclock = 0,
+- .left_margin = 0,
+- .right_margin = 0,
+- .upper_margin = 0,
+- .lower_margin = 0,
+- .hsync_len = 0,
+- .vsync_len = 0,
+- .sync = 0,
+- .vmode = FB_VMODE_NONINTERLACED,
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+- .reserved = {0, 0, 0, 0, 0, 0}
+-#endif
++ .xres = 0,
++ .yres = 0,
++ .xres_virtual = 0,
++ .yres_virtual = 0,
++ .xoffset = 0,
++ .yoffset = 0,
++ .bits_per_pixel = 0,
++ .grayscale = 0,
++ .red = {0, 8, 0},
++ .green = {0, 8, 0},
++ .blue = {0, 8, 0},
++ .transp = {0, 0, 0},
++ .nonstd = 0,
++ .activate = FB_ACTIVATE_NOW,
++ .height = -1,
++ .width = -1,
++ .accel_flags = 0,
++ .pixclock = 0,
++ .left_margin = 0,
++ .right_margin = 0,
++ .upper_margin = 0,
++ .lower_margin = 0,
++ .hsync_len = 0,
++ .vsync_len = 0,
++ .sync = 0,
++ .vmode = FB_VMODE_NONINTERLACED,
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
++ .reserved = {0, 0, 0, 0, 0, 0}
++#endif
+ };
+
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ static struct fb_fix_screeninfo sisfb_fix = {
+ .id = "SiS",
+ .type = FB_TYPE_PACKED_PIXELS,
+- .xpanstep = 1,
++ .xpanstep = 0,
+ .ypanstep = 1,
+ };
+-static char myid[20];
++static char myid[40];
+ static u32 pseudo_palette[17];
+ #endif
+
+@@ -347,26 +351,24 @@ static union {
+ } sis_fbcon_cmap;
+
+ static int sisfb_inverse = 0;
++static int currcon = 0;
+ #endif
+
+-/* display status */
++/* global flags */
+ static int sisfb_off = 0;
+ static int sisfb_crt1off = 0;
+ static int sisfb_forcecrt1 = -1;
+ static int sisvga_enabled = 0;
+ static int sisfb_userom = 1;
+ static int sisfb_useoem = -1;
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+-static int currcon = 0;
+-#endif
+-
+-/* global flags */
+-static int sisfb_registered;
+-static int sisfb_tvmode = 0;
++static int sisfb_parm_rate = -1;
++static int sisfb_registered = 0;
+ static int sisfb_mem = 0;
+ static int sisfb_pdc = 0;
+-static int enable_dstn = 0;
+ static int sisfb_ypan = -1;
++static int sisfb_nocrt2rate = 0;
++static int sisfb_dstn = 0;
++static int sisfb_fstn = 0;
+
+ VGA_ENGINE sisvga_engine = UNKNOWN_VGA;
+ int sisfb_accel = -1;
+@@ -375,22 +377,22 @@ int sisfb_accel = -1;
+ static int sisfb_hwcursor_size = 0;
+ static int sisfb_CRT2_write_enable = 0;
+
+-int sisfb_crt2type = -1; /* TW: CRT2 type (for overriding autodetection) */
+-int sisfb_tvplug = -1; /* PR: Tv plug type (for overriding autodetection) */
++int sisfb_crt2type = -1; /* CRT2 type (for overriding autodetection) */
++int sisfb_tvplug = -1; /* Tv plug type (for overriding autodetection) */
+
+-int sisfb_queuemode = -1; /* TW: Use MMIO queue mode by default (310/325 series only) */
++int sisfb_queuemode = -1; /* Use MMIO queue mode by default (315 series only) */
+
+ unsigned char sisfb_detectedpdc = 0;
+
+ unsigned char sisfb_detectedlcda = 0xff;
+
+-/* data for sis components */
++/* data for sis hardware ("par") */
+ struct video_info ivideo;
+
+-/* TW: For ioctl SISFB_GET_INFO */
++/* For ioctl SISFB_GET_INFO */
+ sisfb_info sisfbinfo;
+
+-/* TW: Hardware extension; contains data on hardware */
++/* Hardware extension; contains data on hardware */
+ HW_DEVICE_EXTENSION sishw_ext = {
+ NULL, NULL, FALSE, NULL, NULL,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+@@ -399,10 +401,10 @@ HW_DEVICE_EXTENSION sishw_ext = {
+ 0
+ };
+
+-/* TW: SiS private structure */
++/* SiS private structure */
+ SiS_Private SiS_Pr;
+
+-/* card parameters */
++/* Card parameters */
+ static unsigned long sisfb_mmio_size = 0;
+ static u8 sisfb_caps = 0;
+
+@@ -412,7 +414,7 @@ typedef enum _SIS_CMDTYPE {
+ VM_CMD_QUEUE,
+ } SIS_CMDTYPE;
+
+-/* Supported SiS Chips list */
++/* List of supported chips */
+ static struct board {
+ u16 vendor, device;
+ const char *name;
+@@ -424,16 +426,17 @@ static struct board {
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315, "SIS 315"},
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO, "SIS 315PRO"},
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, "SIS 550 VGA"},
+- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, "SIS 650/M650/651/740 VGA"},
++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, "SIS 650/M650/651/M652/740 VGA"},
+ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330, "SIS 330"},
++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, "SIS 660/M660/760/M760 VGA"},
+ {0, 0, NULL}
+ };
+
+ #define MD_SIS300 1
+ #define MD_SIS315 2
+
+-/* mode table */
+-/* NOT const - will be patched for 1280x960 mode number chaos reasons */
++/* Mode table */
++/* NOT const - will be patched for 1280x768 mode number chaos reasons */
+ struct _sisbios_mode {
+ char name[15];
+ u8 mode_no;
+@@ -447,14 +450,33 @@ struct _sisbios_mode {
+ u16 rows;
+ u8 chipset;
+ } sisbios_mode[] = {
+-#define MODE_INDEX_NONE 0 /* TW: index for mode=none */
+- {"none", 0xFF, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_SIS300|MD_SIS315}, /* TW: for mode "none" */
+- {"320x240x16", 0x56, 0x0000, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS315},
+- {"320x480x8", 0x5A, 0x0000, 0x0000, 320, 480, 8, 1, 40, 30, MD_SIS315}, /* TW: FSTN */
+- {"320x480x16", 0x5B, 0x0000, 0x0000, 320, 480, 16, 1, 40, 30, MD_SIS315}, /* TW: FSTN */
+- {"640x480x8", 0x2E, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_SIS300|MD_SIS315},
++#define MODE_INDEX_NONE 0 /* index for mode=none */
++ {"none", 0xff, 0x0000, 0x0000, 0, 0, 0, 0, 0, 0, MD_SIS300|MD_SIS315},
++ {"320x200x8", 0x59, 0x0138, 0x0000, 320, 200, 8, 1, 40, 12, MD_SIS300|MD_SIS315},
++ {"320x200x16", 0x41, 0x010e, 0x0000, 320, 200, 16, 1, 40, 12, MD_SIS300|MD_SIS315},
++ {"320x200x24", 0x4f, 0x0000, 0x0000, 320, 200, 32, 1, 40, 12, MD_SIS300|MD_SIS315}, /* TW: That's for people who mix up color- and fb depth */
++ {"320x200x32", 0x4f, 0x0000, 0x0000, 320, 200, 32, 1, 40, 12, MD_SIS300|MD_SIS315},
++ {"320x240x8", 0x50, 0x0132, 0x0000, 320, 240, 8, 1, 40, 15, MD_SIS300|MD_SIS315},
++ {"320x240x16", 0x56, 0x0135, 0x0000, 320, 240, 16, 1, 40, 15, MD_SIS300|MD_SIS315},
++ {"320x240x24", 0x53, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
++ {"320x240x32", 0x53, 0x0000, 0x0000, 320, 240, 32, 1, 40, 15, MD_SIS300|MD_SIS315},
++ {"320x240x8", 0x5a, 0x0132, 0x0000, 320, 480, 8, 1, 40, 30, MD_SIS315}, /* TW: FSTN */
++ {"320x240x16", 0x5b, 0x0135, 0x0000, 320, 480, 16, 1, 40, 30, MD_SIS315}, /* TW: FSTN */
++ {"400x300x8", 0x51, 0x0133, 0x0000, 400, 300, 8, 1, 50, 18, MD_SIS300|MD_SIS315},
++ {"400x300x16", 0x57, 0x0136, 0x0000, 400, 300, 16, 1, 50, 18, MD_SIS300|MD_SIS315},
++ {"400x300x24", 0x54, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315},
++ {"400x300x32", 0x54, 0x0000, 0x0000, 400, 300, 32, 1, 50, 18, MD_SIS300|MD_SIS315},
++ {"512x384x8", 0x52, 0x0000, 0x0000, 512, 384, 8, 1, 64, 24, MD_SIS300|MD_SIS315},
++ {"512x384x16", 0x58, 0x0000, 0x0000, 512, 384, 16, 1, 64, 24, MD_SIS300|MD_SIS315},
++ {"512x384x24", 0x5c, 0x0000, 0x0000, 512, 384, 32, 1, 64, 24, MD_SIS300|MD_SIS315},
++ {"512x384x32", 0x5c, 0x0000, 0x0000, 512, 384, 32, 1, 64, 24, MD_SIS300|MD_SIS315},
++ {"640x400x8", 0x2f, 0x0000, 0x0000, 640, 400, 8, 1, 80, 25, MD_SIS300|MD_SIS315},
++ {"640x400x16", 0x5d, 0x0000, 0x0000, 640, 400, 16, 1, 80, 25, MD_SIS300|MD_SIS315},
++ {"640x400x24", 0x5e, 0x0000, 0x0000, 640, 400, 32, 1, 80, 25, MD_SIS300|MD_SIS315},
++ {"640x400x32", 0x5e, 0x0000, 0x0000, 640, 400, 32, 1, 80, 25, MD_SIS300|MD_SIS315},
++ {"640x480x8", 0x2e, 0x0101, 0x0101, 640, 480, 8, 1, 80, 30, MD_SIS300|MD_SIS315},
+ {"640x480x16", 0x44, 0x0111, 0x0111, 640, 480, 16, 1, 80, 30, MD_SIS300|MD_SIS315},
+- {"640x480x24", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_SIS300|MD_SIS315}, /* TW: That's for people who mix up color- and fb depth */
++ {"640x480x24", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_SIS300|MD_SIS315},
+ {"640x480x32", 0x62, 0x013a, 0x0112, 640, 480, 32, 1, 80, 30, MD_SIS300|MD_SIS315},
+ {"720x480x8", 0x31, 0x0000, 0x0000, 720, 480, 8, 1, 90, 30, MD_SIS300|MD_SIS315},
+ {"720x480x16", 0x33, 0x0000, 0x0000, 720, 480, 16, 1, 90, 30, MD_SIS300|MD_SIS315},
+@@ -464,63 +486,87 @@ struct _sisbios_mode {
+ {"720x576x16", 0x34, 0x0000, 0x0000, 720, 576, 16, 1, 90, 36, MD_SIS300|MD_SIS315},
+ {"720x576x24", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_SIS300|MD_SIS315},
+ {"720x576x32", 0x36, 0x0000, 0x0000, 720, 576, 32, 1, 90, 36, MD_SIS300|MD_SIS315},
++ {"768x576x8", 0x5f, 0x0000, 0x0000, 768, 576, 8, 1, 96, 36, MD_SIS300|MD_SIS315},
++ {"768x576x16", 0x60, 0x0000, 0x0000, 768, 576, 16, 1, 96, 36, MD_SIS300|MD_SIS315},
++ {"768x576x24", 0x61, 0x0000, 0x0000, 768, 576, 32, 1, 96, 36, MD_SIS300|MD_SIS315},
++ {"768x576x32", 0x61, 0x0000, 0x0000, 768, 576, 32, 1, 96, 36, MD_SIS300|MD_SIS315},
+ {"800x480x8", 0x70, 0x0000, 0x0000, 800, 480, 8, 1, 100, 30, MD_SIS300|MD_SIS315},
+ {"800x480x16", 0x7a, 0x0000, 0x0000, 800, 480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
+ {"800x480x24", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+ {"800x480x32", 0x76, 0x0000, 0x0000, 800, 480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+-#define DEFAULT_MODE 20 /* TW: index for 800x600x8 */
+-#define DEFAULT_LCDMODE 20 /* TW: index for 800x600x8 */
+-#define DEFAULT_TVMODE 20 /* TW: index for 800x600x8 */
++#define DEFAULT_MODE 43 /* index for 800x600x8 */
++#define DEFAULT_LCDMODE 43 /* index for 800x600x8 */
++#define DEFAULT_TVMODE 43 /* index for 800x600x8 */
+ {"800x600x8", 0x30, 0x0103, 0x0103, 800, 600, 8, 2, 100, 37, MD_SIS300|MD_SIS315},
+ {"800x600x16", 0x47, 0x0114, 0x0114, 800, 600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
+ {"800x600x24", 0x63, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+ {"800x600x32", 0x63, 0x013b, 0x0115, 800, 600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
++ {"848x480x8", 0x39, 0x0000, 0x0000, 848, 480, 8, 2, 106, 30, MD_SIS300|MD_SIS315},
++ {"848x480x16", 0x3b, 0x0000, 0x0000, 848, 480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
++ {"848x480x24", 0x3e, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
++ {"848x480x32", 0x3e, 0x0000, 0x0000, 848, 480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
++ {"856x480x8", 0x3f, 0x0000, 0x0000, 856, 480, 8, 2, 107, 30, MD_SIS300|MD_SIS315},
++ {"856x480x16", 0x42, 0x0000, 0x0000, 856, 480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
++ {"856x480x24", 0x45, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
++ {"856x480x32", 0x45, 0x0000, 0x0000, 856, 480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+ {"1024x576x8", 0x71, 0x0000, 0x0000, 1024, 576, 8, 1, 128, 36, MD_SIS300|MD_SIS315},
+ {"1024x576x16", 0x74, 0x0000, 0x0000, 1024, 576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
+ {"1024x576x24", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+ {"1024x576x32", 0x77, 0x0000, 0x0000, 1024, 576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+- {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_SIS300 }, /* TW: 300 series only */
++ {"1024x600x8", 0x20, 0x0000, 0x0000, 1024, 600, 8, 1, 128, 37, MD_SIS300 },
+ {"1024x600x16", 0x21, 0x0000, 0x0000, 1024, 600, 16, 1, 128, 37, MD_SIS300 },
+ {"1024x600x24", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_SIS300 },
+ {"1024x600x32", 0x22, 0x0000, 0x0000, 1024, 600, 32, 1, 128, 37, MD_SIS300 },
+ {"1024x768x8", 0x38, 0x0105, 0x0105, 1024, 768, 8, 2, 128, 48, MD_SIS300|MD_SIS315},
+- {"1024x768x16", 0x4A, 0x0117, 0x0117, 1024, 768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
++ {"1024x768x16", 0x4a, 0x0117, 0x0117, 1024, 768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
+ {"1024x768x24", 0x64, 0x013c, 0x0118, 1024, 768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+ {"1024x768x32", 0x64, 0x013c, 0x0118, 1024, 768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+- {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_SIS300 }, /* TW: 300 series only */
++ {"1152x768x8", 0x23, 0x0000, 0x0000, 1152, 768, 8, 1, 144, 48, MD_SIS300 },
+ {"1152x768x16", 0x24, 0x0000, 0x0000, 1152, 768, 16, 1, 144, 48, MD_SIS300 },
+ {"1152x768x24", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_SIS300 },
+ {"1152x768x32", 0x25, 0x0000, 0x0000, 1152, 768, 32, 1, 144, 48, MD_SIS300 },
++ {"1152x864x8", 0x29, 0x0000, 0x0000, 1152, 864, 8, 1, 144, 54, MD_SIS300|MD_SIS315},
++ {"1152x864x16", 0x2a, 0x0000, 0x0000, 1152, 864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
++ {"1152x864x24", 0x2b, 0x0000, 0x0000, 1152, 864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
++ {"1152x864x32", 0x2b, 0x0000, 0x0000, 1152, 864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+ {"1280x720x8", 0x79, 0x0000, 0x0000, 1280, 720, 8, 1, 160, 45, MD_SIS300|MD_SIS315},
+ {"1280x720x16", 0x75, 0x0000, 0x0000, 1280, 720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
+ {"1280x720x24", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+ {"1280x720x32", 0x78, 0x0000, 0x0000, 1280, 720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+- {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_SIS315}, /* TW: 310/325 series only */
+- {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_SIS315},
+- {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS315},
+- {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS315},
+-#define MODEINDEX_1280x960 48
+- {"1280x960x8", 0x7C, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_SIS300|MD_SIS315}, /* TW: Modenumbers being patched */
+- {"1280x960x16", 0x7D, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+- {"1280x960x24", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+- {"1280x960x32", 0x7E, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+- {"1280x1024x8", 0x3A, 0x0107, 0x0107, 1280, 1024, 8, 2, 160, 64, MD_SIS300|MD_SIS315},
+- {"1280x1024x16", 0x4D, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
++#define MODEINDEX_1280x768 79
++ {"1280x768x8", 0x23, 0x0000, 0x0000, 1280, 768, 8, 1, 160, 48, MD_SIS300|MD_SIS315},
++ {"1280x768x16", 0x24, 0x0000, 0x0000, 1280, 768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
++ {"1280x768x24", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
++ {"1280x768x32", 0x25, 0x0000, 0x0000, 1280, 768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
++ {"1280x960x8", 0x7c, 0x0000, 0x0000, 1280, 960, 8, 1, 160, 60, MD_SIS300|MD_SIS315},
++ {"1280x960x16", 0x7d, 0x0000, 0x0000, 1280, 960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
++ {"1280x960x24", 0x7e, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
++ {"1280x960x32", 0x7e, 0x0000, 0x0000, 1280, 960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
++ {"1280x1024x8", 0x3a, 0x0107, 0x0107, 1280, 1024, 8, 2, 160, 64, MD_SIS300|MD_SIS315},
++ {"1280x1024x16", 0x4d, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+ {"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+ {"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+- {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_SIS315}, /* TW: 310/325 series only */
++ {"1360x768x8", 0x48, 0x0000, 0x0000, 1360, 768, 8, 1, 170, 48, MD_SIS300|MD_SIS315},
++ {"1360x768x16", 0x4b, 0x0000, 0x0000, 1360, 768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
++ {"1360x768x24", 0x4e, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
++ {"1360x768x32", 0x4e, 0x0000, 0x0000, 1360, 768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
++ {"1360x1024x8", 0x67, 0x0000, 0x0000, 1360, 1024, 8, 1, 170, 64, MD_SIS300 },
++ {"1360x1024x16", 0x6f, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300 },
++ {"1360x1024x24", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
++ {"1360x1024x32", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300 },
++ {"1400x1050x8", 0x26, 0x0000, 0x0000, 1400, 1050, 8, 1, 175, 65, MD_SIS315},
+ {"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65, MD_SIS315},
+ {"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
+ {"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65, MD_SIS315},
+- {"1600x1200x8", 0x3C, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_SIS300|MD_SIS315},
+- {"1600x1200x16", 0x3D, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
++ {"1600x1200x8", 0x3c, 0x0130, 0x011c, 1600, 1200, 8, 1, 200, 75, MD_SIS300|MD_SIS315},
++ {"1600x1200x16", 0x3d, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+ {"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+ {"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+ {"1920x1440x8", 0x68, 0x013f, 0x0000, 1920, 1440, 8, 1, 240, 75, MD_SIS300|MD_SIS315},
+ {"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
+- {"1920x1440x24", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+- {"1920x1440x32", 0x6B, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+- {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_SIS315}, /* TW: 310/325 series only */
++ {"1920x1440x24", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
++ {"1920x1440x32", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
++ {"2048x1536x8", 0x6c, 0x0000, 0x0000, 2048, 1536, 8, 1, 256, 96, MD_SIS315},
+ {"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96, MD_SIS315},
+ {"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315},
+ {"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96, MD_SIS315},
+@@ -538,37 +584,36 @@ u8 sisfb_rate_idx = 0;
+
+ /* TW: CR36 evaluation */
+ const USHORT sis300paneltype[] =
+- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+- LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
+- LCD_320x480, LCD_1024x768, LCD_1024x768, LCD_1024x768,
+- LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768 };
++ { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
++ LCD_1280x960, LCD_640x480, LCD_1024x600, LCD_1152x768,
++ LCD_1024x768, LCD_1024x768, LCD_1024x768, LCD_1024x768,
++ LCD_1024x768, LCD_1024x768, LCD_320x480, LCD_1024x768 };
+
+ const USHORT sis310paneltype[] =
+- { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
+- LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
+- LCD_1152x768, LCD_1400x1050,LCD_1280x768, LCD_1600x1200,
+- LCD_320x480, LCD_1024x768, LCD_1024x768, LCD_1024x768 };
++ { LCD_UNKNOWN, LCD_800x600, LCD_1024x768, LCD_1280x1024,
++ LCD_640x480, LCD_1024x600, LCD_1152x864, LCD_1280x960,
++ LCD_1152x768, LCD_1400x1050, LCD_1280x768, LCD_1600x1200,
++ LCD_640x480_2, LCD_640x480_3, LCD_320x480, LCD_1024x768 };
++
++#define FL_550_DSTN 0x01
++#define FL_550_FSTN 0x02
+
+ static const struct _sis_crt2type {
+ char name[10];
+ int type_no;
+ int tvplug_no;
++ unsigned short flags;
+ } sis_crt2type[] = {
+- {"NONE", 0, -1},
+- {"LCD", DISPTYPE_LCD, -1},
+- {"TV", DISPTYPE_TV, -1},
+- {"VGA", DISPTYPE_CRT2, -1},
+- {"SVIDEO", DISPTYPE_TV, TVPLUG_SVIDEO},
+- {"COMPOSITE", DISPTYPE_TV, TVPLUG_COMPOSITE},
+- {"SCART", DISPTYPE_TV, TVPLUG_SCART},
+- {"none", 0, -1},
+- {"lcd", DISPTYPE_LCD, -1},
+- {"tv", DISPTYPE_TV, -1},
+- {"vga", DISPTYPE_CRT2, -1},
+- {"svideo", DISPTYPE_TV, TVPLUG_SVIDEO},
+- {"composite", DISPTYPE_TV, TVPLUG_COMPOSITE},
+- {"scart", DISPTYPE_TV, TVPLUG_SCART},
+- {"\0", -1, -1}
++ {"NONE", 0, -1, 0},
++ {"LCD", CRT2_LCD, -1, 0},
++ {"TV", CRT2_TV, -1, 0},
++ {"VGA", CRT2_VGA, -1, 0},
++ {"SVIDEO", CRT2_TV, TV_SVIDEO, 0},
++ {"COMPOSITE", CRT2_TV, TV_AVIDEO, 0},
++ {"SCART", CRT2_TV, TV_SCART, 0},
++ {"DSTN", CRT2_LCD, -1, FL_550_DSTN},
++ {"FSTN", CRT2_LCD, -1, FL_550_FSTN},
++ {"\0", -1, -1, 0}
+ };
+
+ /* Queue mode selection for 310 series */
+@@ -579,9 +624,6 @@ static const struct _sis_queuemode {
+ {"AGP", AGP_CMD_QUEUE},
+ {"VRAM", VM_CMD_QUEUE},
+ {"MMIO", MMIO_CMD},
+- {"agp", AGP_CMD_QUEUE},
+- {"vram", VM_CMD_QUEUE},
+- {"mmio", MMIO_CMD},
+ {"\0", -1}
+ };
+
+@@ -590,10 +632,8 @@ static const struct _sis_tvtype {
+ char name[6];
+ int type_no;
+ } sis_tvtype[] = {
+- {"PAL", 1},
+- {"NTSC", 2},
+- {"pal", 1},
+- {"ntsc", 2},
++ {"PAL", TV_PAL},
++ {"NTSC", TV_NTSC},
+ {"\0", -1}
+ };
+
+@@ -602,33 +642,102 @@ static const struct _sis_vrate {
+ u16 xres;
+ u16 yres;
+ u16 refresh;
++ BOOLEAN SiS730valid32bpp;
+ } sisfb_vrate[] = {
+- {1, 640, 480, 60}, {2, 640, 480, 72}, {3, 640, 480, 75}, {4, 640, 480, 85},
+- {5, 640, 480,100}, {6, 640, 480, 120}, {7, 640, 480, 160}, {8, 640, 480, 200},
+- {1, 720, 480, 60},
+- {1, 720, 576, 58},
+- {1, 800, 480, 60}, {2, 800, 480, 75}, {3, 800, 480, 85},
+- {1, 800, 600, 56}, {2, 800, 600, 60}, {3, 800, 600, 72}, {4, 800, 600, 75},
+- {5, 800, 600, 85}, {6, 800, 600, 100}, {7, 800, 600, 120}, {8, 800, 600, 160},
+- {1, 1024, 768, 43}, {2, 1024, 768, 60}, {3, 1024, 768, 70}, {4, 1024, 768, 75},
+- {5, 1024, 768, 85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
+- {1, 1024, 576, 60}, {2, 1024, 576, 75}, {3, 1024, 576, 85},
+- {1, 1024, 600, 60},
+- {1, 1152, 768, 60},
+- {1, 1280, 720, 60}, {2, 1280, 720, 75}, {3, 1280, 720, 85},
+- {1, 1280, 768, 60},
+- {1, 1280, 1024, 43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
+- {1, 1280, 960, 70},
+- {1, 1400, 1050, 60},
+- {1, 1600, 1200, 60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
+- {5, 1600, 1200, 85}, {6, 1600, 1200, 100}, {7, 1600, 1200, 120},
+- {1, 1920, 1440, 60}, {2, 1920, 1440, 65}, {3, 1920, 1440, 70}, {4, 1920, 1440, 75},
+- {5, 1920, 1440, 85}, {6, 1920, 1440, 100},
+- {1, 2048, 1536, 60}, {2, 2048, 1536, 65}, {3, 2048, 1536, 70}, {4, 2048, 1536, 75},
+- {5, 2048, 1536, 85},
+- {0, 0, 0, 0}
++ {1, 320, 200, 70, TRUE},
++ {1, 320, 240, 60, TRUE},
++ {1, 320, 480, 60, TRUE},
++ {1, 400, 300, 60, TRUE},
++ {1, 512, 384, 60, TRUE},
++ {1, 640, 400, 72, TRUE},
++ {1, 640, 480, 60, TRUE}, {2, 640, 480, 72, TRUE}, {3, 640, 480, 75, TRUE},
++ {4, 640, 480, 85, TRUE}, {5, 640, 480, 100, TRUE}, {6, 640, 480, 120, TRUE},
++ {7, 640, 480, 160, TRUE}, {8, 640, 480, 200, TRUE},
++ {1, 720, 480, 60, TRUE},
++ {1, 720, 576, 58, TRUE},
++ {1, 800, 480, 60, TRUE}, {2, 800, 480, 75, TRUE}, {3, 800, 480, 85, TRUE},
++ {1, 800, 600, 56, TRUE}, {2, 800, 600, 60, TRUE}, {3, 800, 600, 72, TRUE},
++ {4, 800, 600, 75, TRUE}, {5, 800, 600, 85, TRUE}, {6, 800, 600, 105, TRUE},
++ {7, 800, 600, 120, TRUE}, {8, 800, 600, 160, TRUE},
++ {1, 848, 480, 39, TRUE}, {2, 848, 480, 60, TRUE},
++ {1, 856, 480, 39, TRUE}, {2, 856, 480, 60, TRUE},
++ {1, 1024, 576, 60, TRUE}, {2, 1024, 576, 75, TRUE}, {3, 1024, 576, 85, TRUE},
++ {1, 1024, 600, 60, TRUE},
++ {1, 1024, 768, 43, TRUE}, {2, 1024, 768, 60, TRUE}, {3, 1024, 768, 70, FALSE},
++ {4, 1024, 768, 75, FALSE}, {5, 1024, 768, 85, TRUE}, {6, 1024, 768, 100, TRUE},
++ {7, 1024, 768, 120, TRUE},
++ {1, 1152, 768, 60, TRUE},
++ {1, 1152, 864, 75, TRUE}, {2, 1152, 864, 84, TRUE},
++ {1, 1280, 720, 60, TRUE}, {2, 1280, 720, 75, TRUE}, {3, 1280, 720, 85, TRUE},
++ {1, 1280, 768, 60, TRUE},
++ {1, 1280, 960, 60, TRUE}, {2, 1280, 960, 85, TRUE},
++ {1, 1280, 1024, 43, TRUE}, {2, 1280, 1024, 60, TRUE}, {3, 1280, 1024, 75, TRUE},
++ {4, 1280, 1024, 85, TRUE},
++ {1, 1360, 768, 60, TRUE},
++ {1, 1360, 1024, 59, TRUE},
++ {1, 1400, 1050, 60, TRUE}, {2, 1400, 1050, 75, TRUE},
++ {1, 1600, 1200, 60, TRUE}, {2, 1600, 1200, 65, TRUE}, {3, 1600, 1200, 70, TRUE},
++ {4, 1600, 1200, 75, TRUE}, {5, 1600, 1200, 85, TRUE}, {6, 1600, 1200, 100, TRUE},
++ {7, 1600, 1200, 120, TRUE},
++ {1, 1920, 1440, 60, TRUE}, {2, 1920, 1440, 65, TRUE}, {3, 1920, 1440, 70, TRUE},
++ {4, 1920, 1440, 75, TRUE}, {5, 1920, 1440, 85, TRUE}, {6, 1920, 1440, 100, TRUE},
++ {1, 2048, 1536, 60, TRUE}, {2, 2048, 1536, 65, TRUE}, {3, 2048, 1536, 70, TRUE},
++ {4, 2048, 1536, 75, TRUE}, {5, 2048, 1536, 85, TRUE},
++ {0, 0, 0, 0, FALSE}
+ };
+
++static struct sisfb_monitor {
++ u16 hmin;
++ u16 hmax;
++ u16 vmin;
++ u16 vmax;
++ u32 dclockmax;
++ u8 feature;
++ BOOLEAN datavalid;
++} sisfb_thismonitor;
++
++static const struct _sisfbddcsmodes {
++ u32 mask;
++ u16 h;
++ u16 v;
++ u32 d;
++} sisfb_ddcsmodes[] = {
++ { 0x10000, 67, 75, 108000},
++ { 0x08000, 48, 72, 50000},
++ { 0x04000, 46, 75, 49500},
++ { 0x01000, 35, 43, 44900},
++ { 0x00800, 48, 60, 65000},
++ { 0x00400, 56, 70, 75000},
++ { 0x00200, 60, 75, 78800},
++ { 0x00100, 80, 75, 135000},
++ { 0x00020, 31, 60, 25200},
++ { 0x00008, 38, 72, 31500},
++ { 0x00004, 37, 75, 31500},
++ { 0x00002, 35, 56, 36000},
++ { 0x00001, 38, 60, 40000}
++};
++
++static const struct _sisfbddcfmodes {
++ u16 x;
++ u16 y;
++ u16 v;
++ u16 h;
++ u32 d;
++} sisfb_ddcfmodes[] = {
++ { 1280, 1024, 85, 92, 157500},
++ { 1600, 1200, 60, 75, 162000},
++ { 1600, 1200, 65, 82, 175500},
++ { 1600, 1200, 70, 88, 189000},
++ { 1600, 1200, 75, 94, 202500},
++ { 1600, 1200, 85, 107,229500},
++ { 1920, 1440, 60, 90, 234000},
++ { 1920, 1440, 75, 113,297000}
++};
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
++static u8 sisfb_lastrates[128];
++#endif
++
+ static const struct _chswtable {
+ int subsysVendor;
+ int subsysCard;
+@@ -636,9 +745,61 @@ static const struct _chswtable {
+ char *cardName;
+ } mychswtable[] = {
+ { 0x1631, 0x1002, "Mitachi", "0x1002" },
++ { 0x1071, 0x7521, "Mitac" , "7521P" },
+ { 0, 0, "" , "" }
+ };
+
++static const struct _customttable {
++ unsigned short chipID;
++ char *biosversion;
++ char *biosdate;
++ unsigned long bioschksum;
++ unsigned short biosFootprintAddr[5];
++ unsigned char biosFootprintData[5];
++ unsigned short pcisubsysvendor;
++ unsigned short pcisubsyscard;
++ char *vendorName;
++ char *cardName;
++ unsigned long SpecialID;
++ char *optionName;
++} mycustomttable[] = {
++ { SIS_630, "2.00.07", "09/27/2002-13:38:25",
++ 0x3240A8,
++ { 0x220, 0x227, 0x228, 0x229, 0x22a },
++ { 0x01, 0xe3, 0x9a, 0x6a, 0x00 },
++ 0x1039, 0x6300,
++ "Barco", "iQ R200L/300/400", CUT_BARCO1366, "BARCO1366"
++ },
++ { SIS_630, "2.00.07", "09/27/2002-13:38:25",
++ 0x323FBD,
++ { 0x220, 0x227, 0x228, 0x229, 0x22a },
++ { 0x00, 0x5a, 0x64, 0x41, 0x00 },
++ 0x1039, 0x6300,
++ "Barco", "iQ G200L/300/400/500", CUT_BARCO1024, "BARCO1024"
++ },
++ { SIS_650, "", "",
++ 0,
++ { 0, 0, 0, 0, 0 },
++ { 0, 0, 0, 0, 0 },
++ 0x0e11, 0x083c,
++ "Compaq", "Presario 3045US", CUT_COMPAQ12802, "COMPAQ1280"
++ },
++ { 4321, "", "", /* This is hopefully NEVER autodetected */
++ 0,
++ { 0, 0, 0, 0, 0 },
++ { 0, 0, 0, 0, 0 },
++ 0, 0,
++ "Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
++ },
++ { 0, "", "",
++ 0,
++ { 0, 0, 0, 0 },
++ { 0, 0, 0, 0 },
++ 0, 0,
++ "", "", CUT_NONE, ""
++ }
++};
++
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ /* Offscreen layout */
+ typedef struct _SIS_GLYINFO {
+@@ -677,7 +838,6 @@ static unsigned long sisfb_heap_end;
+ static unsigned long sisfb_heap_size;
+ static SIS_HEAP sisfb_heap;
+
+-// Eden Chen
+ static const struct _sis_TV_filter {
+ u8 filter[9][4];
+ } sis_TV_filter[] = {
+@@ -829,9 +989,8 @@ static const struct _sis_TV_filter {
+
+ static int filter = -1;
+ static unsigned char filter_tb;
+-//~Eden Chen
+
+-/* ---------------------- Routine prototypes ------------------------- */
++/* ---------------------- Prototypes ------------------------- */
+
+ /* Interface used by the world */
+ #ifndef MODULE
+@@ -894,10 +1053,6 @@ extern void fbcon_sis_fillrect(struc
+ const struct fb_fillrect *rect);
+ extern void fbcon_sis_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area);
+-#if 0
+-extern void cfb_imageblit(struct fb_info *info,
+- const struct fb_image *image);
+-#endif
+ extern int fbcon_sis_sync(struct fb_info *info);
+ static int sisfb_ioctl(struct inode *inode,
+ struct file *file,
+@@ -912,7 +1067,7 @@ extern int sisfb_mode_rate_to_ddata
+ unsigned int *left_margin, unsigned int *right_margin,
+ unsigned int *upper_margin, unsigned int *lower_margin,
+ unsigned int *hsync_len, unsigned int *vsync_len,
+- unsigned int *sync, unsigned int *vmode);
++ unsigned int *sync, unsigned int *vmode);
+ #endif
+
+ static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+@@ -923,9 +1078,9 @@ extern int sisfb_initaccel(void);
+ extern void sisfb_syncaccel(void);
+
+ /* Internal general routines */
+-static void sisfb_search_mode(const char *name);
+-static int sisfb_validate_mode(int modeindex);
+-static u8 sisfb_search_refresh_rate(unsigned int rate);
++static void sisfb_search_mode(char *name, BOOLEAN quiet);
++static int sisfb_validate_mode(int modeindex, unsigned long vbflags);
++static u8 sisfb_search_refresh_rate(unsigned int rate, int index);
+ static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info);
+@@ -939,6 +1094,12 @@ static BOOLEAN sisfb_CheckVBRetrace(voi
+ static BOOLEAN sisfbcheckvretracecrt2(void);
+ static BOOLEAN sisfbcheckvretracecrt1(void);
+ static BOOLEAN sisfb_bridgeisslave(void);
++static void sisfb_detect_VB_connect(void);
++static void sisfb_get_VB_type(void);
++
++static void sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno);
++static BOOLEAN sisfb_interpret_edid(struct sisfb_monitor *monitor, unsigned char *buffer);
++
+
+ /* SiS-specific Export functions */
+ void sis_dispinfo(struct ap_data *rec);
+@@ -952,15 +1113,9 @@ u32 sisfb_get_reg3(u16 port)
+ /* Chipset-dependent internal routines */
+ #ifdef CONFIG_FB_SIS_300
+ static int sisfb_get_dram_size_300(void);
+-static void sisfb_detect_VB_connect_300(void);
+-static void sisfb_get_VB_type_300(void);
+-static int sisfb_has_VB_300(void);
+ #endif
+ #ifdef CONFIG_FB_SIS_315
+ static int sisfb_get_dram_size_315(void);
+-static void sisfb_detect_VB_connect_315(void);
+-static void sisfb_get_VB_type_315(void);
+-static int sisfb_has_VB_315(void);
+ #endif
+
+ /* Internal heap routines */
+@@ -978,23 +1133,33 @@ BOOLEAN sisfb_query_VGA_config_s
+ BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_DEVICE_INFO psishw_ext,
+ unsigned long offset, unsigned long set, unsigned long *value);
+
+-
+ /* Routines from init.c/init301.c */
+ extern void SiSRegInit(SiS_Private *SiS_Pr, USHORT BaseAddr);
+ extern BOOLEAN SiSInit(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+ extern BOOLEAN SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension, USHORT ModeNo);
+-extern void SiS_SetEnableDstn(SiS_Private *SiS_Pr);
++extern void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
++extern void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
+ extern void SiS_LongWait(SiS_Private *SiS_Pr);
+
+-/* TW: Chrontel TV functions */
++extern BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension,
++ unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
++
++/* Chrontel TV functions */
+ extern USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
+ extern void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
+ extern USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
+ extern void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
+ extern void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
+ extern void SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
++extern void SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
++extern USHORT SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
++ USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
++extern void SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
++extern void SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
++extern void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
++extern void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_DEVICE_INFO HwDeviceExtension);
+
+-/* TW: Sensing routines */
++/* Sensing routines */
+ void SiS_Sense30x(void);
+ int SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+ void SiS_SenseCh(void);
+--- linux-2.6.0-test6/drivers/video/sis/vgatypes.h 2003-06-14 12:17:55.000000000 -0700
++++ 25/drivers/video/sis/vgatypes.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,3 +1,36 @@
++/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/vgatypes.h,v 1.0 2001/06/15 21:23:00 dawes Exp $ */
++/*
++ * General type definitions for universal mode switching modules
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Thomas Winischhofer <thomas@winischhofer.net>
++ * Silicon Integrated Systems
++ *
++ */
+ #ifndef _VGATYPES_
+ #define _VGATYPES_
+
+@@ -5,7 +38,7 @@
+ #include "xf86Pci.h"
+ #endif
+
+-#ifdef LINUX_KERNEL /* TW: We don't want the X driver to depend on kernel source */
++#ifdef LINUX_KERNEL /* We don't want the X driver to depend on kernel source */
+ #include <linux/ioctl.h>
+ #endif
+
+@@ -72,18 +105,15 @@ typedef void VOID;
+ typedef UCHAR BOOLEAN;
+ #endif
+
+-#ifndef WINCE_HEADER
+ #ifndef bool
+ typedef UCHAR bool;
+ #endif
+-#endif /*WINCE_HEADER*/
+
+ #ifndef VBIOS_VER_MAX_LENGTH
+ #define VBIOS_VER_MAX_LENGTH 4
+ #endif
+
+ #ifndef LINUX_KERNEL /* For kernel, this is defined in sisfb.h */
+-#ifndef WIN2000
+ #ifndef SIS_CHIP_TYPE
+ typedef enum _SIS_CHIP_TYPE {
+ SIS_VGALegacy = 0,
+@@ -101,19 +131,19 @@ typedef enum _SIS_CHIP_TYPE {
+ SIS_550,
+ SIS_650,
+ SIS_740,
+- SIS_330,
++ SIS_330,
++ SIS_660,
++ SIS_760,
+ MAX_SIS_CHIP
+ } SIS_CHIP_TYPE;
+ #endif
+ #endif
+-#endif
+
+-#ifndef WIN2000
+ #ifndef SIS_VB_CHIP_TYPE
+ typedef enum _SIS_VB_CHIP_TYPE {
+ VB_CHIP_Legacy = 0,
+ VB_CHIP_301,
+- VB_CHIP_301B,
++ VB_CHIP_301B,
+ VB_CHIP_301LV,
+ VB_CHIP_302,
+ VB_CHIP_302B,
+@@ -122,9 +152,7 @@ typedef enum _SIS_VB_CHIP_TYPE {
+ MAX_VB_CHIP
+ } SIS_VB_CHIP_TYPE;
+ #endif
+-#endif
+
+-#ifndef WIN2000
+ #ifndef SIS_LCD_TYPE
+ typedef enum _SIS_LCD_TYPE {
+ LCD_INVALID = 0,
+@@ -136,18 +164,20 @@ typedef enum _SIS_LCD_TYPE {
+ LCD_1600x1200,
+ LCD_1920x1440,
+ LCD_2048x1536,
+- LCD_320x480, /* TW: FSTN */
++ LCD_320x480, /* FSTN, DSTN */
+ LCD_1400x1050,
+ LCD_1152x864,
+ LCD_1152x768,
+ LCD_1280x768,
+ LCD_1024x600,
++ LCD_640x480_2, /* FSTN, DSTN */
++ LCD_640x480_3, /* FSTN, DSTN */
++ LCD_848x480,
++ LCD_CUSTOM,
+ LCD_UNKNOWN
+ } SIS_LCD_TYPE;
+ #endif
+-#endif
+
+-#ifndef WIN2000 /* mark by Paul, Move definition to sisv.h*/
+ #ifndef PSIS_DSReg
+ typedef struct _SIS_DSReg
+ {
+@@ -162,7 +192,6 @@ typedef struct _SIS_HW_DEVICE_INFO SIS_
+
+ typedef BOOLEAN (*PSIS_QUERYSPACE) (PSIS_HW_DEVICE_INFO, ULONG, ULONG, ULONG *);
+
+-
+ struct _SIS_HW_DEVICE_INFO
+ {
+ PVOID pDevice; /* The pointer to the physical device data structure
+@@ -173,7 +202,7 @@ struct _SIS_HW_DEVICE_INFO
+ /* Note:ROM image file is the file of VBIOS ROM */
+
+ BOOLEAN UseROM; /* TW: Use the ROM image if provided */
+-
++
+ UCHAR *pjCustomizedROMImage;/* base virtual address of ROM image file. */
+ /* wincE:ROM image file is the file for OEM */
+ /* customized table */
+@@ -195,7 +224,7 @@ struct _SIS_HW_DEVICE_INFO
+ /* defined in the data structure type */
+ /* "SIS_VB_CHIP_TYPE" */
+
+- USHORT usExternalChip; /* NO VB or other video bridge(not */
++ USHORT usExternalChip; /* NO VB or other video bridge (other than */
+ /* SiS video bridge) */
+ /* if ujVBChipID = VB_CHIP_UNKNOWN, */
+ /* then bit0=1 : LVDS,bit1=1 : trumpion, */
+@@ -207,7 +236,7 @@ struct _SIS_HW_DEVICE_INFO
+ /* 011:Trumpion LVDS Scaling Chip */
+ /* 100:LVDS(LCD-out)+Chrontel 7005 */
+ /* 101:Single Chrontel 7005 */
+- /* TW: This has changed on 310/325 series! */
++ /* TW: This has changed on 315 series! */
+
+ ULONG ulCRT2LCDType; /* defined in the data structure type */
+ /* "SIS_LCD_TYPE" */
+@@ -244,7 +273,6 @@ struct _SIS_HW_DEVICE_INFO
+ #endif
+ };
+ #endif
+-#endif
+
+
+ /* TW: Addtional IOCTL for communication sisfb <> X driver */
+@@ -284,12 +312,16 @@ struct _SISFB_INFO {
+
+ unsigned char sisfb_lcda;
+
+- char reserved[235]; /* for future use */
++ unsigned long sisfb_vbflags;
++ unsigned long sisfb_currentvbflags;
++
++ int sisfb_scalelcd;
++ unsigned long sisfb_specialtiming;
++
++ char reserved[219]; /* for future use */
+ };
+ #endif
+
+-#ifndef WIN2000
+-#ifndef WINCE_HEADER
+ #ifndef BUS_DATA_TYPE
+ typedef enum _BUS_DATA_TYPE {
+ ConfigurationSpaceUndefined = -1,
+@@ -307,7 +339,6 @@ typedef enum _BUS_DATA_TYPE {
+ MaximumBusDataType
+ } BUS_DATA_TYPE, *PBUS_DATA_TYPE;
+ #endif
+-#endif /* WINCE_HEADER */
+
+ #ifndef PCI_TYPE0_ADDRESSES
+ #define PCI_TYPE0_ADDRESSES 6
+@@ -317,7 +348,6 @@ typedef enum _BUS_DATA_TYPE {
+ #define PCI_TYPE1_ADDRESSES 2
+ #endif
+
+-#ifndef WINCE_HEADER
+ #ifndef PCI_COMMON_CONFIG
+ typedef struct _PCI_COMMON_CONFIG {
+ USHORT VendorID; /* (ro) */
+@@ -355,7 +385,6 @@ typedef struct _PCI_COMMON_CONFIG {
+
+ } PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;
+ #endif
+-#endif /* WINCE_HEADER */
+
+ #ifndef FIELD_OFFSET
+ #define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
+@@ -364,6 +393,6 @@ typedef struct _PCI_COMMON_CONFIG {
+ #ifndef PCI_COMMON_HDR_LENGTH
+ #define PCI_COMMON_HDR_LENGTH (FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceSpecific))
+ #endif
+-#endif
+
+ #endif
++
+--- linux-2.6.0-test6/drivers/video/sis/vstruct.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/drivers/video/sis/vstruct.h 2003-10-05 00:34:22.000000000 -0700
+@@ -1,3 +1,37 @@
++/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/vstruct.h,v 1.0 2001/06/15 21:23:00 dawes Exp $ */
++/*
++ * General structure definitions for universal mode switching modules
++ *
++ * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
++ *
++ * If distributed as part of the linux kernel, the contents of this file
++ * is entirely covered by the GPL.
++ *
++ * Otherwise, the following terms apply:
++ *
++ * Permission to use, copy, modify, distribute, and sell this software and its
++ * documentation for any purpose is hereby granted without fee, provided that
++ * the above copyright notice appear in all copies and that both that
++ * copyright notice and this permission notice appear in supporting
++ * documentation, and that the name of the copyright holder not be used in
++ * advertising or publicity pertaining to distribution of the software without
++ * specific, written prior permission. The copyright holder makes no representations
++ * about the suitability of this software for any purpose. It is provided
++ * "as is" without express or implied warranty.
++ *
++ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
++ * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
++ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
++ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
++ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Authors: Thomas Winischhofer <thomas@winischhofer.net>
++ * Silicon Integrated Systems
++ *
++ */
++
+ #ifdef _INIT_
+ #define EXTERN
+ #else
+@@ -58,7 +92,6 @@ typedef struct _SiS_LVDSCRT1DataStruct
+ UCHAR CR[15];
+ } SiS_LVDSCRT1DataStruct;
+
+-/*add for LCDA*/
+ typedef struct _SiS_LCDACRT1DataStruct
+ {
+ UCHAR CR[17];
+@@ -111,9 +144,7 @@ typedef struct _SiS_ExtStruct
+ UCHAR Ext_ModeID;
+ USHORT Ext_ModeFlag;
+ USHORT Ext_ModeInfo;
+- USHORT Ext_Point;
+ USHORT Ext_VESAID;
+- UCHAR Ext_VESAMEMSize;
+ UCHAR Ext_RESINFO;
+ UCHAR VB_ExtTVFlickerIndex;
+ UCHAR VB_ExtTVEdgeIndex;
+@@ -130,7 +161,6 @@ typedef struct _SiS_Ext2Struct
+ UCHAR ModeID;
+ USHORT XRes;
+ USHORT YRes;
+- USHORT ROM_OFFSET;
+ } SiS_Ext2Struct;
+
+ typedef struct _SiS_Part2PortTblStruct
+@@ -183,6 +213,15 @@ typedef struct _SiS_ModeResInfoStruct
+
+ typedef UCHAR DRAM4Type[4];
+
++/* Defines for SiS_Customt */
++#define CUT_NONE 0
++#define CUT_FORCENONE 1
++#define CUT_BARCO1366 2
++#define CUT_BARCO1024 3
++#define CUT_COMPAQ1280 4
++#define CUT_COMPAQ12802 5
++#define CUT_PANEL848 6
++
+ typedef struct _SiS_Private
+ {
+ #ifdef LINUX_KERNEL
+@@ -198,25 +237,34 @@ typedef struct _SiS_Private
+ USHORT SiS_P3c7;
+ USHORT SiS_P3c8;
+ USHORT SiS_P3c9;
++ USHORT SiS_P3cb;
++ USHORT SiS_P3cd;
+ USHORT SiS_P3da;
+ USHORT SiS_Part1Port;
+ USHORT SiS_Part2Port;
+ USHORT SiS_Part3Port;
+ USHORT SiS_Part4Port;
+ USHORT SiS_Part5Port;
++ USHORT SiS_VidCapt;
++ USHORT SiS_VidPlay;
+ USHORT SiS_IF_DEF_LVDS;
+ USHORT SiS_IF_DEF_TRUMPION;
+ USHORT SiS_IF_DEF_DSTN;
+ USHORT SiS_IF_DEF_FSTN;
+ USHORT SiS_IF_DEF_CH70xx;
+ USHORT SiS_IF_DEF_HiVision;
++ USHORT SiS_SysFlags;
+ UCHAR SiS_VGAINFO;
++#ifndef LINUX_KERNEL
++ USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
++#endif
+ BOOLEAN SiS_UseROM;
+ int SiS_CHOverScan;
+ BOOLEAN SiS_CHSOverScan;
+ BOOLEAN SiS_ChSW;
+ BOOLEAN SiS_UseLCDA;
+ int SiS_UseOEM;
++ ULONG SiS_CustomT;
+ USHORT SiS_Backup70xx;
+ USHORT SiS_CRT1Mode;
+ USHORT SiS_flag_clearbuffer;
+@@ -270,15 +318,18 @@ typedef struct _SiS_Private
+ USHORT SiS_Panel1280x768;
+ USHORT SiS_Panel1024x600;
+ USHORT SiS_Panel640x480;
++ USHORT SiS_Panel640x480_2;
++ USHORT SiS_Panel640x480_3;
+ USHORT SiS_Panel1152x864;
++ USHORT SiS_PanelCustom;
++ USHORT SiS_PanelBarco1366;
+ USHORT SiS_PanelMax;
+ USHORT SiS_PanelMinLVDS;
+ USHORT SiS_PanelMin301;
+ USHORT SiS_ChrontelInit;
+
+- /* Pointers: */
+ const SiS_StStruct *SiS_SModeIDTable;
+- const SiS_StandTableStruct *SiS_StandTable;
++ SiS_StandTableStruct *SiS_StandTable;
+ const SiS_ExtStruct *SiS_EModeIDTable;
+ const SiS_Ext2Struct *SiS_RefIndex;
+ const SiS_VBModeStruct *SiS_VBModeIDTable;
+@@ -316,7 +367,7 @@ typedef struct _SiS_Private
+ const USHORT *pSiS_RGBSenseData;
+ const USHORT *pSiS_VideoSenseData;
+ const USHORT *pSiS_YCSenseData;
+- const USHORT *pSiS_RGBSenseData2; /*301b*/
++ const USHORT *pSiS_RGBSenseData2;
+ const USHORT *pSiS_VideoSenseData2;
+ const USHORT *pSiS_YCSenseData2;
+ #endif
+@@ -340,15 +391,18 @@ typedef struct _SiS_Private
+ const SiS_LCDDataStruct *SiS_LCD1280x960Data;
+ const SiS_LCDDataStruct *SiS_NoScaleData1400x1050;
+ const SiS_LCDDataStruct *SiS_NoScaleData1600x1200;
++ const SiS_LCDDataStruct *SiS_NoScaleData1280x768;
+ const SiS_LCDDataStruct *SiS_StLCD1400x1050Data;
+ const SiS_LCDDataStruct *SiS_StLCD1600x1200Data;
++ const SiS_LCDDataStruct *SiS_StLCD1280x768Data;
+ const SiS_LCDDataStruct *SiS_ExtLCD1400x1050Data;
+ const SiS_LCDDataStruct *SiS_ExtLCD1600x1200Data;
++ const SiS_LCDDataStruct *SiS_ExtLCD1280x768Data;
++ const SiS_LCDDataStruct *SiS_NoScaleData;
+ const SiS_TVDataStruct *SiS_StPALData;
+ const SiS_TVDataStruct *SiS_ExtPALData;
+ const SiS_TVDataStruct *SiS_StNTSCData;
+ const SiS_TVDataStruct *SiS_ExtNTSCData;
+-/* const SiS_TVDataStruct *SiS_St1HiTVData; */
+ const SiS_TVDataStruct *SiS_St2HiTVData;
+ const SiS_TVDataStruct *SiS_ExtHiTVData;
+ const UCHAR *SiS_NTSCTiming;
+@@ -381,12 +435,19 @@ typedef struct _SiS_Private
+ const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_1;
+ const SiS_LVDSDataStruct *SiS_LVDS1152x768Data_2;
+ const SiS_LVDSDataStruct *SiS_LVDS640x480Data_1;
++ const SiS_LVDSDataStruct *SiS_LVDS640x480Data_2;
+ const SiS_LVDSDataStruct *SiS_LVDS320x480Data_1;
+ const SiS_LVDSDataStruct *SiS_LCDA1400x1050Data_1;
+ const SiS_LVDSDataStruct *SiS_LCDA1400x1050Data_2;
+ const SiS_LVDSDataStruct *SiS_LCDA1600x1200Data_1;
+ const SiS_LVDSDataStruct *SiS_LCDA1600x1200Data_2;
+ const SiS_LVDSDataStruct *SiS_LVDSXXXxXXXData_1;
++ const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_1;
++ const SiS_LVDSDataStruct *SiS_LVDSBARCO1366Data_2;
++ const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_1;
++ const SiS_LVDSDataStruct *SiS_LVDSBARCO1024Data_2;
++ const SiS_LVDSDataStruct *SiS_LVDS848x480Data_1;
++ const SiS_LVDSDataStruct *SiS_LVDS848x480Data_2;
+ const SiS_LVDSDataStruct *SiS_CHTVUNTSCData;
+ const SiS_LVDSDataStruct *SiS_CHTVONTSCData;
+ const SiS_LVDSDataStruct *SiS_CHTVUPALData;
+@@ -478,6 +539,12 @@ typedef struct _SiS_Private
+ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT11600x1200_2_H;
+ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1;
+ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1XXXxXXX_1_H;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_1_H;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_2_H;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3;
++ const SiS_LVDSCRT1DataStruct *SiS_LVDSCRT1640x480_3_H;
+ const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UNTSC;
+ const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1ONTSC;
+ const SiS_LVDSCRT1DataStruct *SiS_CHTVCRT1UPAL;
+@@ -507,7 +574,6 @@ typedef struct _SiS_Private
+ const SiS_LCDACRT1DataStruct *SiS_LCDACRT11400x1050_2_H;
+ const SiS_LCDACRT1DataStruct *SiS_LCDACRT11600x1200_2_H;
+
+- /* TW: New for 650/301LV */
+ const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
+ const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
+ const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_1;
+@@ -539,6 +605,9 @@ typedef struct _SiS_Private
+ const UCHAR *SiS_CHTVVCLKUPALN;
+ const UCHAR *SiS_CHTVVCLKOPALN;
+ const UCHAR *SiS_CHTVVCLKSOPAL;
++
++ USHORT PanelXRes;
++ USHORT PanelYRes;
+
+ BOOLEAN UseCustomMode;
+ BOOLEAN CRT1UsesCustomMode;
+@@ -560,8 +629,11 @@ typedef struct _SiS_Private
+ UCHAR CSR2B;
+ UCHAR CSR2C;
+ USHORT CSRClock;
++ USHORT CSRClock_CRT1;
+ USHORT CModeFlag;
++ USHORT CModeFlag_CRT1;
+ USHORT CInfoFlag;
++
+ BOOLEAN SiS_CHPALM;
+ BOOLEAN SiS_CHPALN;
+
+@@ -578,7 +650,21 @@ typedef struct _SiS_Private
+ UCHAR Backup_1c;
+ UCHAR Backup_1d;
+
+- int UsePanelScaler;
++ int UsePanelScaler;
++
++ USHORT CP_Vendor, CP_Product;
++ BOOLEAN CP_HaveCustomData;
++ int CP_PreferredX, CP_PreferredY;
++ int CP_MaxX, CP_MaxY, CP_MaxClock;
++ int CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
++ int CP_HTotal[7], CP_VTotal[7];
++ int CP_HSyncStart[7], CP_VSyncStart[7];
++ int CP_HSyncEnd[7], CP_VSyncEnd[7];
++ int CP_HBlankStart[7], CP_VBlankStart[7];
++ int CP_HBlankEnd[7], CP_VBlankEnd[7];
++ int CP_Clock[7];
++ BOOLEAN CP_DataValid[7];
++ BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+ } SiS_Private;
+
+ #endif
+--- linux-2.6.0-test6/drivers/video/skeletonfb.c 2003-06-14 12:17:59.000000000 -0700
++++ 25/drivers/video/skeletonfb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -1,7 +1,7 @@
+ /*
+ * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
+ *
+- * Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)
++ * Modified to new api Jan 2001 by James Simmons (jsimmons@infradead.org)
+ *
+ * Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+@@ -469,15 +469,71 @@ void xxxfb_imageblit(struct fb_info *p,
+ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+ {
+ /*
+- * @set: Which fields we are altering in struct fb_cursor
++ * @set: Which fields we are altering in struct fb_cursor
+ * @enable: Disable or enable the cursor
+- * @rop: The bit operation we want to do.
+- * @mask: This is the cursor mask bitmap.
+- * @dest: A image of the area we are going to display the cursor.
+- * Used internally by the driver.
+- * @hot: The hot spot.
+- * @image: The actual data for the cursor image.
+- */
++ * @rop: The bit operation we want to do.
++ * @hot: The hot spot.
++ * @image: The actual data for the cursor image.
++ * @mask: This is the cursor mask bitmap.
++ */
++
++ /* Disable hardware cursor. We don't want to display the cursor
++ while changing it. Note we use the enable and rop fields in
++ struct fb_cursor that is apart of struct fb_info. Not the
++ cursor data passed in from userland. */
++
++ if (cursor->set & FB_CUR_SETHOT) {
++ info->cursor.hot = cursor->hot;
++ /* Set the hardware cursor's hot spot */
++ }
++
++ if (cursor->set & FB_CUR_SETPOS) {
++ info->cursor.image.dx = cursor->image.dx;
++ info->cursor.image.dy = cursor->image.dy;
++ /* Set the hardware cursor's position */
++ }
++
++ if (cursor->set & FB_CUR_SETSIZE) {
++ info->cursor.image.height = cursor->image.height;
++ info->cursor.image.width = cursor->image.width;
++ /* Set the hardware cursor's size */
++ }
++
++ if (cursor->set & FB_CUR_SETCMAP) {
++ if (cursor->image.depth == 1) {
++ info->cursor.image.fg_color = cursor->image.fg_color;
++ info->cursor.image.bg_color = cursor->image.bg_color;
++ } else {
++ if (cursor->image.cmap.len)
++ fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap, 0);
++ }
++ info->curosr.image.depth = cursor->image.depth;
++
++ /* Set the hardware cursor's color map */
++ }
++
++ /*
++ * Set the cursor shape. The two pieces needed to create
++ * the final image is mask and image.data. The mask is
++ * combined with image.data according to the rop field.
++ */
++ if (cursor->set & FB_CUR_SETSHAPE) {
++ switch (info->cursor.rop) {
++ case ROP_XOR:
++ /* ... */
++ break;
++ case ROP_COPY:
++ default:
++ /* ... */
++ break;
++ }
++ /* ... */
++ }
++
++ if (info->cursor.enable) {
++ /* Now we turn the hardware cursor on */
++ }
++ return 0;
+ }
+
+ /**
+--- linux-2.6.0-test6/drivers/video/softcursor.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/drivers/video/softcursor.c 2003-10-05 00:34:28.000000000 -0700
+@@ -21,8 +21,13 @@ int soft_cursor(struct fb_info *info, st
+ {
+ unsigned int scan_align = info->pixmap.scan_align - 1;
+ unsigned int buf_align = info->pixmap.buf_align - 1;
+- unsigned int i, size, dsize, s_pitch, d_pitch;
+- u8 *dst, src[64];
++ u8 *dst = (u8 *) info->cursor.image.data;
++ unsigned int i, size, pitch;
++
++ pitch = ((info->cursor.image.width + 7) >> 3) + scan_align;
++ pitch &= ~scan_align;
++ size = pitch * info->cursor.image.height + buf_align;
++ size &= ~buf_align;
+
+ if (cursor->set & FB_CUR_SETSIZE) {
+ info->cursor.image.height = cursor->image.height;
+@@ -48,34 +53,33 @@ int soft_cursor(struct fb_info *info, st
+ info->cursor.image.depth = cursor->image.depth;
+ }
+
+- s_pitch = (info->cursor.image.width + 7) >> 3;
+- dsize = s_pitch * info->cursor.image.height;
+- d_pitch = (s_pitch + scan_align) & ~scan_align;
+- size = d_pitch * info->cursor.image.height + buf_align;
+- size &= ~buf_align;
+- dst = info->pixmap.addr + fb_get_buffer_offset(info, size);
+-
+- if (info->cursor.enable) {
++ if (cursor->set & FB_CUR_SETSHAPE) {
+ switch (info->cursor.rop) {
+ case ROP_XOR:
+- for (i = 0; i < dsize; i++)
+- src[i] = cursor->image.data[i] ^ info->cursor.mask[i];
++ for (i = 0; i < size; i++)
++ dst[i] ^= info->cursor.mask[i];
+ break;
+ case ROP_COPY:
+ default:
+- for (i = 0; i < dsize; i++)
+- src[i] = cursor->image.data[i] & info->cursor.mask[i];
++ for (i = 0; i < size; i++)
++ dst[i] &= info->cursor.mask[i];
+ break;
+ }
+- } else
+- memcpy(src, cursor->image.data, dsize);
+-
+- move_buf_aligned(info, dst, src, d_pitch, s_pitch, info->cursor.image.height);
+- info->cursor.image.data = dst;
++ }
+
+- info->fbops->fb_imageblit(info, &info->cursor.image);
+- atomic_dec(&info->pixmap.count);
+- smp_mb__after_atomic_dec();
++ if (!info->cursor.enable) {
++ for (i = 0; i < size; i++)
++ dst[i] ^= info->cursor.mask[i];
++ }
++
++ if (info->cursor.image.data)
++ info->fbops->fb_imageblit(info, &info->cursor.image);
++
++ if (!info->cursor.enable) {
++ for (i = 0; i < size; i++)
++ dst[i] ^= info->cursor.mask[i];
++ }
++
+ return 0;
+ }
+
+--- linux-2.6.0-test6/drivers/video/sstfb.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/drivers/video/sstfb.c 2003-10-05 00:33:24.000000000 -0700
+@@ -94,7 +94,6 @@
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+ #include <linux/init.h>
+-#include <linux/version.h>
+ #include <linux/slab.h>
+ #include <asm/io.h>
+ #include <asm/ioctl.h>
+--- linux-2.6.0-test6/drivers/video/stifb.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/drivers/video/stifb.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1238,7 +1238,7 @@ stifb_init_fb(struct sti_struct *sti, in
+
+
+ /* get framebuffer physical and virtual base addr & len (64bit ready) */
+- fix->smem_start = fb->sti->regions_phys[1] | 0xffffffff00000000;
++ fix->smem_start = F_EXTEND(fb->sti->regions_phys[1]);
+ fix->smem_len = fb->sti->regions[1].region_desc.length * 4096;
+
+ fix->line_length = (fb->sti->glob_cfg->total_x * bpp) / 8;
+--- linux-2.6.0-test6/drivers/video/valkyriefb.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/drivers/video/valkyriefb.c 2003-10-05 00:34:22.000000000 -0700
+@@ -51,7 +51,6 @@
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/fb.h>
+-#include <linux/selection.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <linux/nvram.h>
+--- linux-2.6.0-test6/fs/adfs/super.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/adfs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -18,6 +18,7 @@
+ #include <linux/init.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
++#include <linux/parser.h>
+
+ #include <asm/bitops.h>
+ #include <asm/uaccess.h>
+@@ -133,50 +134,56 @@ static void adfs_put_super(struct super_
+ sb->s_fs_info = NULL;
+ }
+
++enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err};
++
++static match_table_t tokens = {
++ {Opt_uid, "uid=%u"},
++ {Opt_gid, "gid=%u"},
++ {Opt_ownmask, "ownmask=%o"},
++ {Opt_othmask, "othmask=%o"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(struct super_block *sb, char *options)
+ {
+- char *value, *opt;
++ char *p;
+ struct adfs_sb_info *asb = ADFS_SB(sb);
++ int option;
+
+ if (!options)
+ return 0;
+
+- while ((opt = strsep(&options, ",")) != NULL) {
+- if (!*opt)
++ while ((p = strsep(&options, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- value = strchr(opt, '=');
+- if (value)
+- *value++ = '\0';
+
+- if (!strcmp(opt, "uid")) { /* owner of all files */
+- if (!value || !*value)
+- return -EINVAL;
+- asb->s_uid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- } else
+- if (!strcmp(opt, "gid")) { /* group owner of all files */
+- if (!value || !*value)
+- return -EINVAL;
+- asb->s_gid = simple_strtoul(value, &value, 0);
+- if (*value)
+- return -EINVAL;
+- } else
+- if (!strcmp(opt, "ownmask")) { /* owner permission mask */
+- if (!value || !*value)
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_uid:
++ if (match_int(args, &option))
+ return -EINVAL;
+- asb->s_owner_mask = simple_strtoul(value, &value, 8);
+- if (*value)
++ asb->s_uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(args, &option))
+ return -EINVAL;
+- } else
+- if (!strcmp(opt, "othmask")) { /* others permission mask */
+- if (!value || !*value)
++ asb->s_gid = option;
++ break;
++ case Opt_ownmask:
++ if (match_octal(args, &option))
+ return -EINVAL;
+- asb->s_other_mask = simple_strtoul(value, &value, 8);
+- if (*value)
++ asb->s_owner_mask = option;
++ break;
++ case Opt_othmask:
++ if (match_octal(args, &option))
+ return -EINVAL;
+- } else { /* eh? say again. */
+- printk("ADFS-fs: unrecognised mount option %s\n", opt);
++ asb->s_other_mask = option;
++ break;
++ default:
++ printk("ADFS-fs: unrecognised mount option \"%s\" "
++ "or missing value\n", p);
+ return -EINVAL;
+ }
+ }
+--- linux-2.6.0-test6/fs/affs/file.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/affs/file.c 2003-10-05 00:33:24.000000000 -0700
+@@ -39,7 +39,7 @@ static int affs_grow_extcache(struct ino
+ static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
+ static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
+ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
+-static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
++static ssize_t affs_file_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos);
+ static int affs_file_open(struct inode *inode, struct file *filp);
+ static int affs_file_release(struct inode *inode, struct file *filp);
+
+@@ -491,7 +491,8 @@ affs_getemptyblk_ino(struct inode *inode
+ }
+
+ static ssize_t
+-affs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
++affs_file_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
+ {
+ ssize_t retval;
+
+--- linux-2.6.0-test6/fs/affs/super.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/fs/affs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -28,6 +28,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
++#include <linux/parser.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+
+@@ -142,12 +143,37 @@ static struct super_operations affs_sops
+ .remount_fs = affs_remount,
+ };
+
++enum {
++ Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect,
++ Opt_reserved, Opt_root, Opt_setgid, Opt_setuid,
++ Opt_verbose, Opt_volume, Opt_ignore, Opt_err,
++};
++
++static match_table_t tokens = {
++ {Opt_bs, "bs=%d"},
++ {Opt_mode, "mode=%o"},
++ {Opt_mufs, "mufs"},
++ {Opt_prefix, "prefix=%s"},
++ {Opt_protect, "protect"},
++ {Opt_reserved, "reserved=%d"},
++ {Opt_root, "root=%d"},
++ {Opt_setgid, "setgid=%d"},
++ {Opt_setuid, "setuid=%d"},
++ {Opt_verbose, "verbose"},
++ {Opt_volume, "volume=%s"},
++ {Opt_ignore, "grpquota"},
++ {Opt_ignore, "noquota"},
++ {Opt_ignore, "quota"},
++ {Opt_ignore, "usrquota"},
++ {Opt_err, NULL},
++};
++
+ static int
+ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root,
+ int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
+ {
+- char *this_char, *value, *optn;
+- int f;
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
+
+ /* Fill in defaults */
+
+@@ -161,109 +187,85 @@ parse_options(char *options, uid_t *uid,
+ *mount_opts = 0;
+ if (!options)
+ return 1;
+- while ((this_char = strsep(&options, ",")) != NULL) {
+- if (!*this_char)
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token, n, option;
++ if (!*p)
+ continue;
+- f = 0;
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+- if ((optn = "protect") && !strcmp(this_char, optn)) {
+- if (value)
+- goto out_inv_arg;
+- *mount_opts |= SF_IMMUTABLE;
+- } else if ((optn = "verbose") && !strcmp(this_char, optn)) {
+- if (value)
+- goto out_inv_arg;
+- *mount_opts |= SF_VERBOSE;
+- } else if ((optn = "mufs") && !strcmp(this_char, optn)) {
+- if (value)
+- goto out_inv_arg;
+- *mount_opts |= SF_MUFS;
+- } else if ((f = !strcmp(this_char,"setuid")) || !strcmp(this_char,"setgid")) {
+- if (value) {
+- if (!*value) {
+- printk("AFFS: Argument for set[ug]id option missing\n");
+- return 0;
+- } else {
+- (f ? *uid : *gid) = simple_strtoul(value,&value,0);
+- if (*value) {
+- printk("AFFS: Bad set[ug]id argument\n");
+- return 0;
+- }
+- *mount_opts |= f ? SF_SETUID : SF_SETGID;
+- }
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_bs:
++ if (match_int(&args[0], &n))
++ return -EINVAL;
++ if (n != 512 && n != 1024 && n != 2048
++ && n != 4096) {
++ printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
++ return 0;
+ }
+- } else if (!strcmp(this_char,"prefix")) {
+- optn = "prefix";
+- if (!value || !*value)
+- goto out_no_arg;
++ *blocksize = n;
++ break;
++ case Opt_mode:
++ if (match_octal(&args[0], &option))
++ return 1;
++ *mode = option & 0777;
++ *mount_opts |= SF_SETMODE;
++ break;
++ case Opt_mufs:
++ *mount_opts |= SF_MUFS;
++ break;
++ case Opt_prefix:
+ if (*prefix) { /* Free any previous prefix */
+ kfree(*prefix);
+ *prefix = NULL;
+ }
+- *prefix = kmalloc(strlen(value) + 1,GFP_KERNEL);
++ *prefix = match_strdup(&args[0]);
+ if (!*prefix)
+ return 0;
+- strcpy(*prefix,value);
+ *mount_opts |= SF_PREFIX;
+- } else if (!strcmp(this_char,"volume")) {
+- optn = "volume";
+- if (!value || !*value)
+- goto out_no_arg;
+- strlcpy(volume,value,31);
+- } else if (!strcmp(this_char,"mode")) {
+- optn = "mode";
+- if (!value || !*value)
+- goto out_no_arg;
+- *mode = simple_strtoul(value,&value,8) & 0777;
+- if (*value)
+- return 0;
+- *mount_opts |= SF_SETMODE;
+- } else if (!strcmp(this_char,"reserved")) {
+- optn = "reserved";
+- if (!value || !*value)
+- goto out_no_arg;
+- *reserved = simple_strtoul(value,&value,0);
+- if (*value)
+- return 0;
+- } else if (!strcmp(this_char,"root")) {
+- optn = "root";
+- if (!value || !*value)
+- goto out_no_arg;
+- *root = simple_strtoul(value,&value,0);
+- if (*value)
+- return 0;
+- } else if (!strcmp(this_char,"bs")) {
+- optn = "bs";
+- if (!value || !*value)
+- goto out_no_arg;
+- *blocksize = simple_strtoul(value,&value,0);
+- if (*value)
+- return 0;
+- if (*blocksize != 512 && *blocksize != 1024 && *blocksize != 2048
+- && *blocksize != 4096) {
+- printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
+- return 0;
+- }
+- } else if (!strcmp (this_char, "grpquota")
+- || !strcmp (this_char, "noquota")
+- || !strcmp (this_char, "quota")
+- || !strcmp (this_char, "usrquota"))
+- /* Silently ignore the quota options */
+- ;
+- else {
+- printk("AFFS: Unrecognized mount option %s\n", this_char);
++ break;
++ case Opt_protect:
++ *mount_opts |= SF_IMMUTABLE;
++ break;
++ case Opt_reserved:
++ if (match_int(&args[0], reserved))
++ return 1;
++ break;
++ case Opt_root:
++ if (match_int(&args[0], root))
++ return 1;
++ break;
++ case Opt_setgid:
++ if (match_int(&args[0], &option))
++ return 1;
++ *gid = option;
++ *mount_opts |= SF_SETGID;
++ break;
++ case Opt_setuid:
++ if (match_int(&args[0], &option))
++ return -EINVAL;
++ *uid = option;
++ *mount_opts |= SF_SETUID;
++ break;
++ case Opt_verbose:
++ *mount_opts |= SF_VERBOSE;
++ break;
++ case Opt_volume: {
++ char *vol = match_strdup(&args[0]);
++ strlcpy(volume, vol, 32);
++ kfree(vol);
++ break;
++ }
++ case Opt_ignore:
++ /* Silently ignore the quota options */
++ break;
++ default:
++ printk("AFFS: Unrecognized mount option \"%s\" "
++ "or missing value\n", p);
+ return 0;
+ }
+ }
+ return 1;
+-
+-out_no_arg:
+- printk("AFFS: The %s option requires an argument\n", optn);
+- return 0;
+-out_inv_arg:
+- printk("AFFS: Option %s does not take an argument\n", optn);
+- return 0;
+ }
+
+ /* This function definitely needs to be split up. Some fine day I'll
+--- linux-2.6.0-test6/fs/aio.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/aio.c 2003-10-05 00:37:05.000000000 -0700
+@@ -27,6 +27,8 @@
+ #include <linux/aio.h>
+ #include <linux/highmem.h>
+ #include <linux/workqueue.h>
++#include <linux/writeback.h>
++#include <linux/pagemap.h>
+
+ #include <asm/kmap_types.h>
+ #include <asm/uaccess.h>
+@@ -38,6 +40,9 @@
+ #define dprintk(x...) do { ; } while (0)
+ #endif
+
++long aio_run = 0; /* for testing only */
++long aio_wakeups = 0; /* for testing only */
++
+ /*------ sysctl variables----*/
+ atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */
+ unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
+@@ -47,6 +52,7 @@ static kmem_cache_t *kiocb_cachep;
+ static kmem_cache_t *kioctx_cachep;
+
+ static struct workqueue_struct *aio_wq;
++static struct workqueue_struct *aio_fput_wq;
+
+ /* Used for rare fput completion. */
+ static void aio_fput_routine(void *);
+@@ -74,6 +80,7 @@ static int __init aio_setup(void)
+ panic("unable to create kioctx cache");
+
+ aio_wq = create_workqueue("aio");
++ aio_fput_wq = create_workqueue("aio_fput");
+
+ pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
+
+@@ -281,6 +288,7 @@ static void aio_cancel_all(struct kioctx
+ struct kiocb *iocb = list_kiocb(pos);
+ list_del_init(&iocb->ki_list);
+ cancel = iocb->ki_cancel;
++ kiocbSetCancelled(iocb);
+ if (cancel) {
+ iocb->ki_users++;
+ spin_unlock_irq(&ctx->ctx_lock);
+@@ -341,6 +349,11 @@ void exit_aio(struct mm_struct *mm)
+ aio_cancel_all(ctx);
+
+ wait_for_all_aios(ctx);
++ /*
++ * this is an overkill, but ensures we don't leave
++ * the ctx on the aio_wq
++ */
++ flush_workqueue(aio_wq);
+
+ if (1 != atomic_read(&ctx->users))
+ printk(KERN_DEBUG
+@@ -395,6 +408,7 @@ static struct kiocb *__aio_get_req(struc
+ req->ki_cancel = NULL;
+ req->ki_retry = NULL;
+ req->ki_user_obj = NULL;
++ INIT_LIST_HEAD(&req->ki_run_list);
+
+ /* Check if the completion queue has enough free space to
+ * accept an event from this io.
+@@ -494,7 +508,7 @@ static int __aio_put_req(struct kioctx *
+ spin_lock(&fput_lock);
+ list_add(&req->ki_list, &fput_head);
+ spin_unlock(&fput_lock);
+- queue_work(aio_wq, &fput_work);
++ queue_work(aio_fput_wq, &fput_work);
+ } else
+ really_put_req(ctx, req);
+ return 1;
+@@ -536,65 +550,307 @@ struct kioctx *lookup_ioctx(unsigned lon
+ return ioctx;
+ }
+
++/*
++ * use_mm
++ * Makes the calling kernel thread take on the specified
++ * mm context.
++ * Called by the retry thread execute retries within the
++ * iocb issuer's mm context, so that copy_from/to_user
++ * operations work seamlessly for aio.
++ * (Note: this routine is intended to be called only
++ * from a kernel thread context)
++ */
+ static void use_mm(struct mm_struct *mm)
+ {
+- struct mm_struct *active_mm = current->active_mm;
++ struct mm_struct *active_mm;
++ struct task_struct *tsk = current;
++
++ task_lock(tsk);
++ active_mm = tsk->active_mm;
+ atomic_inc(&mm->mm_count);
+- current->mm = mm;
+- if (mm != active_mm) {
+- current->active_mm = mm;
+- activate_mm(active_mm, mm);
+- }
++ tsk->mm = mm;
++ tsk->active_mm = mm;
++ activate_mm(active_mm, mm);
++ task_unlock(tsk);
++
+ mmdrop(active_mm);
+ }
+
+-static void unuse_mm(struct mm_struct *mm)
++/*
++ * unuse_mm
++ * Reverses the effect of use_mm, i.e. releases the
++ * specified mm context which was earlier taken on
++ * by the calling kernel thread
++ * (Note: this routine is intended to be called only
++ * from a kernel thread context)
++ *
++ * Comments: Called with ctx->ctx_lock held. This nests
++ * task_lock instead ctx_lock.
++ */
++void unuse_mm(struct mm_struct *mm)
+ {
+- current->mm = NULL;
++ struct task_struct *tsk = current;
++
++ task_lock(tsk);
++ tsk->mm = NULL;
+ /* active_mm is still 'mm' */
+- enter_lazy_tlb(mm, current);
++ enter_lazy_tlb(mm, tsk);
++ task_unlock(tsk);
+ }
+
+-/* Run on kevent's context. FIXME: needs to be per-cpu and warn if an
+- * operation blocks.
++/*
++ * Queue up a kiocb to be retried. Assumes that the kiocb
++ * has already been marked as kicked, and places it on
++ * the retry run list for the corresponding ioctx, if it
++ * isn't already queued. Returns 1 if it actually queued
++ * the kiocb (to tell the caller to activate the work
++ * queue to process it), or 0, if it found that it was
++ * already queued.
++ *
++ * Should be called with the spin lock iocb->ki_ctx->ctx_lock
++ * held
+ */
+-static void aio_kick_handler(void *data)
++static inline int __queue_kicked_iocb(struct kiocb *iocb)
+ {
+- struct kioctx *ctx = data;
++ struct kioctx *ctx = iocb->ki_ctx;
+
+- use_mm(ctx->mm);
++ if (list_empty(&iocb->ki_run_list)) {
++ list_add_tail(&iocb->ki_run_list,
++ &ctx->run_list);
++ iocb->ki_queued++;
++ return 1;
++ }
++ return 0;
++}
+
+- spin_lock_irq(&ctx->ctx_lock);
+- while (!list_empty(&ctx->run_list)) {
+- struct kiocb *iocb;
+- long ret;
++/* aio_run_iocb
++ * This is the core aio execution routine. It is
++ * invoked both for initial i/o submission and
++ * subsequent retries via the aio_kick_handler.
++ * Expects to be invoked with iocb->ki_ctx->lock
++ * already held. The lock is released and reaquired
++ * as needed during processing.
++ *
++ * Calls the iocb retry method (already setup for the
++ * iocb on initial submission) for operation specific
++ * handling, but takes care of most of common retry
++ * execution details for a given iocb. The retry method
++ * needs to be non-blocking as far as possible, to avoid
++ * holding up other iocbs waiting to be serviced by the
++ * retry kernel thread.
++ *
++ * The trickier parts in this code have to do with
++ * ensuring that only one retry instance is in progress
++ * for a given iocb at any time. Providing that guarantee
++ * simplifies the coding of individual aio operations as
++ * it avoids various potential races.
++ */
++static ssize_t aio_run_iocb(struct kiocb *iocb)
++{
++ struct kioctx *ctx = iocb->ki_ctx;
++ ssize_t (*retry)(struct kiocb *);
++ ssize_t ret;
+
+- iocb = list_entry(ctx->run_list.next, struct kiocb,
+- ki_run_list);
+- list_del(&iocb->ki_run_list);
+- iocb->ki_users ++;
+- spin_unlock_irq(&ctx->ctx_lock);
++ if (iocb->ki_retried++ > 1024*1024) {
++ printk("Maximal retry count. Bytes done %Zd\n",
++ iocb->ki_nbytes - iocb->ki_left);
++ return -EAGAIN;
++ }
++
++ if (!(iocb->ki_retried & 0xff)) {
++ pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n",
++ iocb->ki_retried,
++ iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
++ iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
++ }
++
++ if (!(retry = iocb->ki_retry)) {
++ printk("aio_run_iocb: iocb->ki_retry = NULL\n");
++ return 0;
++ }
++
++ /*
++ * We don't want the next retry iteration for this
++ * operation to start until this one has returned and
++ * updated the iocb state. However, wait_queue functions
++ * can trigger a kick_iocb from interrupt context in the
++ * meantime, indicating that data is available for the next
++ * iteration. We want to remember that and enable the
++ * next retry iteration _after_ we are through with
++ * this one.
++ *
++ * So, in order to be able to register a "kick", but
++ * prevent it from being queued now, we clear the kick
++ * flag, but make the kick code *think* that the iocb is
++ * still on the run list until we are actually done.
++ * When we are done with this iteration, we check if
++ * the iocb was kicked in the meantime and if so, queue
++ * it up afresh.
++ */
++
++ kiocbClearKicked(iocb);
++
++ /*
++ * This is so that aio_complete knows it doesn't need to
++ * pull the iocb off the run list (We can't just call
++ * INIT_LIST_HEAD because we don't want a kick_iocb to
++ * queue this on the run list yet)
++ */
++ iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
++ iocb->ki_retry = NULL;
++ spin_unlock_irq(&ctx->ctx_lock);
++
++ /* Quit retrying if the i/o has been cancelled */
++ if (kiocbIsCancelled(iocb)) {
++ ret = -EINTR;
++ aio_complete(iocb, ret, 0);
++ /* must not access the iocb after this */
++ goto out;
++ }
++
++ /*
++ * Now we are all set to call the retry method in async
++ * context. By setting this thread's io_wait context
++ * to point to the wait queue entry inside the currently
++ * running iocb for the duration of the retry, we ensure
++ * that async notification wakeups are queued by the
++ * operation instead of blocking waits, and when notified,
++ * cause the iocb to be kicked for continuation (through
++ * the aio_wake_function callback).
++ */
++ BUG_ON(current->io_wait != NULL);
++ current->io_wait = &iocb->ki_wait;
++ ret = retry(iocb);
++ current->io_wait = NULL;
+
+- kiocbClearKicked(iocb);
+- ret = iocb->ki_retry(iocb);
++ if (-EIOCBRETRY != ret) {
+ if (-EIOCBQUEUED != ret) {
++ BUG_ON(!list_empty(&iocb->ki_wait.task_list));
+ aio_complete(iocb, ret, 0);
+- iocb = NULL;
++ /* must not access the iocb after this */
+ }
++ } else {
++ /*
++ * Issue an additional retry to avoid waiting forever if
++ * no waits were queued (e.g. in case of a short read).
++ */
++ if (list_empty(&iocb->ki_wait.task_list))
++ kiocbSetKicked(iocb);
++ }
++out:
++ spin_lock_irq(&ctx->ctx_lock);
+
+- spin_lock_irq(&ctx->ctx_lock);
+- if (NULL != iocb)
+- __aio_put_req(ctx, iocb);
++ if (-EIOCBRETRY == ret) {
++ /*
++ * OK, now that we are done with this iteration
++ * and know that there is more left to go,
++ * this is where we let go so that a subsequent
++ * "kick" can start the next iteration
++ */
++ iocb->ki_retry = retry;
++ /* will make __queue_kicked_iocb succeed from here on */
++ INIT_LIST_HEAD(&iocb->ki_run_list);
++ /* we must queue the next iteration ourselves, if it
++ * has already been kicked */
++ if (kiocbIsKicked(iocb)) {
++ __queue_kicked_iocb(iocb);
++ }
+ }
++ return ret;
++}
++
++/*
++ * __aio_run_iocbs:
++ * Process all pending retries queued on the ioctx
++ * run list.
++ * Assumes it is operating within the aio issuer's mm
++ * context. Expects to be called with ctx->ctx_lock held
++ */
++static void __aio_run_iocbs(struct kioctx *ctx)
++{
++ struct kiocb *iocb;
++ int count = 0;
++
++ while (!list_empty(&ctx->run_list)) {
++ iocb = list_entry(ctx->run_list.next, struct kiocb,
++ ki_run_list);
++ list_del(&iocb->ki_run_list);
++ /*
++ * Hold an extra reference while retrying i/o.
++ */
++ iocb->ki_users++; /* grab extra reference */
++ aio_run_iocb(iocb);
++ if (__aio_put_req(ctx, iocb)) /* drop extra ref */
++ put_ioctx(ctx);
++ count++;
++ }
++ aio_run++;
++}
++
++/*
++ * aio_run_iocbs:
++ * Process all pending retries queued on the ioctx
++ * run list.
++ * Assumes it is operating within the aio issuer's mm
++ * context.
++ */
++static inline void aio_run_iocbs(struct kioctx *ctx)
++{
++ spin_lock_irq(&ctx->ctx_lock);
++ __aio_run_iocbs(ctx);
+ spin_unlock_irq(&ctx->ctx_lock);
++}
++
++/*
++ * aio_kick_handler:
++ * Work queue handler triggered to process pending
++ * retries on an ioctx. Takes on the aio issuer's
++ * mm context before running the iocbs.
++ * Run on aiod's context.
++ */
++static void aio_kick_handler(void *data)
++{
++ struct kioctx *ctx = data;
+
++ use_mm(ctx->mm);
++ spin_lock_irq(&ctx->ctx_lock);
++ __aio_run_iocbs(ctx);
+ unuse_mm(ctx->mm);
++ spin_unlock_irq(&ctx->ctx_lock);
+ }
+
+-void kick_iocb(struct kiocb *iocb)
++
++/*
++ * Called by kick_iocb to queue the kiocb for retry
++ * and if required activate the aio work queue to process
++ * it
++ */
++void queue_kicked_iocb(struct kiocb *iocb)
+ {
+ struct kioctx *ctx = iocb->ki_ctx;
++ unsigned long flags;
++ int run = 0;
+
++ WARN_ON((!list_empty(&iocb->ki_wait.task_list)));
++
++ spin_lock_irqsave(&ctx->ctx_lock, flags);
++ run = __queue_kicked_iocb(iocb);
++ spin_unlock_irqrestore(&ctx->ctx_lock, flags);
++ if (run) {
++ queue_work(aio_wq, &ctx->wq);
++ aio_wakeups++;
++ }
++}
++
++/*
++ * kick_iocb:
++ * Called typically from a wait queue callback context
++ * (aio_wake_function) to trigger a retry of the iocb.
++ * The retry is usually executed by aio workqueue
++ * threads (See aio_kick_handler).
++ */
++void kick_iocb(struct kiocb *iocb)
++{
+ /* sync iocbs are easy: they can only ever be executing from a
+ * single context. */
+ if (is_sync_kiocb(iocb)) {
+@@ -603,12 +859,10 @@ void kick_iocb(struct kiocb *iocb)
+ return;
+ }
+
++ iocb->ki_kicked++;
++ /* If its already kicked we shouldn't queue it again */
+ if (!kiocbTryKick(iocb)) {
+- unsigned long flags;
+- spin_lock_irqsave(&ctx->ctx_lock, flags);
+- list_add_tail(&iocb->ki_run_list, &ctx->run_list);
+- spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+- schedule_work(&ctx->wq);
++ queue_kicked_iocb(iocb);
+ }
+ }
+
+@@ -661,6 +915,9 @@ int aio_complete(struct kiocb *iocb, lon
+ */
+ spin_lock_irqsave(&ctx->ctx_lock, flags);
+
++ if (iocb->ki_run_list.prev && !list_empty(&iocb->ki_run_list))
++ list_del_init(&iocb->ki_run_list);
++
+ ring = kmap_atomic(info->ring_pages[0], KM_IRQ1);
+
+ tail = info->tail;
+@@ -689,6 +946,11 @@ int aio_complete(struct kiocb *iocb, lon
+
+ pr_debug("added to ring %p at [%lu]\n", iocb, tail);
+
++ pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n",
++ iocb->ki_retried,
++ iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
++ iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
++
+ /* everything turned out well, dispose of the aiocb. */
+ ret = __aio_put_req(ctx, iocb);
+
+@@ -803,6 +1065,7 @@ static int read_events(struct kioctx *ct
+ int i = 0;
+ struct io_event ent;
+ struct timeout to;
++ int event_loop = 0; /* testing only */
+
+ /* needed to zero any padding within an entry (there shouldn't be
+ * any, but C is fun!
+@@ -852,7 +1115,6 @@ static int read_events(struct kioctx *ct
+ add_wait_queue_exclusive(&ctx->wait, &wait);
+ do {
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+-
+ ret = aio_read_evt(ctx, &ent);
+ if (ret)
+ break;
+@@ -862,6 +1124,7 @@ static int read_events(struct kioctx *ct
+ if (to.timed_out) /* Only check after read evt */
+ break;
+ schedule();
++ event_loop++;
+ if (signal_pending(tsk)) {
+ ret = -EINTR;
+ break;
+@@ -889,6 +1152,9 @@ static int read_events(struct kioctx *ct
+ if (timeout)
+ clear_timeout(&to);
+ out:
++ pr_debug("event loop executed %d times\n", event_loop);
++ pr_debug("aio_run %ld\n", aio_run);
++ pr_debug("aio_wakeups %ld\n", aio_wakeups);
+ return i ? i : ret;
+ }
+
+@@ -918,6 +1184,11 @@ static void io_destroy(struct kioctx *io
+
+ aio_cancel_all(ioctx);
+ wait_for_all_aios(ioctx);
++ /*
++ * this is an overkill, but ensures we don't leave
++ * the ctx on the aio_wq
++ */
++ flush_workqueue(aio_wq);
+ put_ioctx(ioctx); /* once for the lookup */
+ }
+
+@@ -980,13 +1251,192 @@ asmlinkage long sys_io_destroy(aio_conte
+ return -EINVAL;
+ }
+
++/*
++ * Retry method for aio_read (also used for first time submit)
++ * Responsible for updating iocb state as retries progress
++ */
++static ssize_t aio_pread(struct kiocb *iocb)
++{
++ struct file *file = iocb->ki_filp;
++ ssize_t ret = 0;
++
++ ret = file->f_op->aio_read(iocb, iocb->ki_buf,
++ iocb->ki_left, iocb->ki_pos);
++
++ /*
++ * Can't just depend on iocb->ki_left to determine
++ * whether we are done. This may have been a short read.
++ */
++ if (ret > 0) {
++ iocb->ki_buf += ret;
++ iocb->ki_left -= ret;
++
++ ret = -EIOCBRETRY;
++ }
++
++ /* This means we must have transferred all that we could */
++ /* No need to retry anymore */
++ if ((ret == 0) || (iocb->ki_left == 0))
++ ret = iocb->ki_nbytes - iocb->ki_left;
++
++ return ret;
++}
++
++/*
++ * Retry method for aio_write (also used for first time submit)
++ * Responsible for updating iocb state as retries progress
++ */
++static ssize_t aio_pwrite(struct kiocb *iocb)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ ssize_t ret = 0;
++
++ ret = file->f_op->aio_write(iocb, iocb->ki_buf,
++ iocb->ki_left, iocb->ki_pos);
++
++ /*
++ * Even if iocb->ki_left = 0, we may need to wait
++ * for a balance_dirty_pages to complete
++ */
++ if (ret > 0) {
++ iocb->ki_buf += iocb->ki_buf ? ret : 0;
++ iocb->ki_left -= ret;
++
++ ret = -EIOCBRETRY;
++ }
++
++ /* This means we must have transferred all that we could */
++ /* No need to retry anymore unless we need to osync data */
++ if (ret == 0) {
++ ret = iocb->ki_nbytes - iocb->ki_left;
++ if (!iocb->ki_buf)
++ return ret;
++
++ /* Set things up for potential O_SYNC */
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ iocb->ki_buf = NULL;
++ iocb->ki_pos -= ret; /* back up fpos */
++ iocb->ki_left = ret; /* sync what we have written out */
++ iocb->ki_nbytes = ret;
++ ret = -EIOCBRETRY;
++ }
++ }
++
++ return ret;
++}
++
++static ssize_t aio_fdsync(struct kiocb *iocb)
++{
++ struct file *file = iocb->ki_filp;
++ ssize_t ret = -EINVAL;
++
++ if (file->f_op->aio_fsync)
++ ret = file->f_op->aio_fsync(iocb, 1);
++ return ret;
++}
++
++static ssize_t aio_fsync(struct kiocb *iocb)
++{
++ struct file *file = iocb->ki_filp;
++ ssize_t ret = -EINVAL;
++
++ if (file->f_op->aio_fsync)
++ ret = file->f_op->aio_fsync(iocb, 0);
++ return ret;
++}
++
++/*
++ * aio_setup_iocb:
++ * Performs the initial checks and aio retry method
++ * setup for the kiocb at the time of io submission.
++ */
++ssize_t aio_setup_iocb(struct kiocb *kiocb)
++{
++ struct file *file = kiocb->ki_filp;
++ ssize_t ret = 0;
++
++ switch (kiocb->ki_opcode) {
++ case IOCB_CMD_PREAD:
++ ret = -EBADF;
++ if (unlikely(!(file->f_mode & FMODE_READ)))
++ break;
++ ret = -EFAULT;
++ if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
++ kiocb->ki_left)))
++ break;
++ ret = -EINVAL;
++ if (file->f_op->aio_read)
++ kiocb->ki_retry = aio_pread;
++ break;
++ case IOCB_CMD_PWRITE:
++ ret = -EBADF;
++ if (unlikely(!(file->f_mode & FMODE_WRITE)))
++ break;
++ ret = -EFAULT;
++ if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
++ kiocb->ki_left)))
++ break;
++ ret = -EINVAL;
++ if (file->f_op->aio_write)
++ kiocb->ki_retry = aio_pwrite;
++ break;
++ case IOCB_CMD_FDSYNC:
++ ret = -EINVAL;
++ if (file->f_op->aio_fsync)
++ kiocb->ki_retry = aio_fdsync;
++ break;
++ case IOCB_CMD_FSYNC:
++ ret = -EINVAL;
++ if (file->f_op->aio_fsync)
++ kiocb->ki_retry = aio_fsync;
++ break;
++ default:
++ dprintk("EINVAL: io_submit: no operation provided\n");
++ ret = -EINVAL;
++ }
++
++ if (!kiocb->ki_retry)
++ return ret;
++
++ return 0;
++}
++
++/*
++ * aio_wake_function:
++ * wait queue callback function for aio notification,
++ * Simply triggers a retry of the operation via kick_iocb.
++ *
++ * This callback is specified in the wait queue entry in
++ * a kiocb (current->io_wait points to this wait queue
++ * entry when an aio operation executes; it is used
++ * instead of a synchronous wait when an i/o blocking
++ * condition is encountered during aio).
++ *
++ * Note:
++ * This routine is executed with the wait queue lock held.
++ * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests
++ * the ioctx lock inside the wait queue lock. This is safe
++ * because this callback isn't used for wait queues which
++ * are nested inside ioctx lock (i.e. ctx->wait)
++ */
++int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync)
++{
++ struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
++
++ list_del_init(&wait->task_list);
++ kick_iocb(iocb);
++ return 1;
++}
++
+ int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+ struct iocb *iocb)
+ {
+ struct kiocb *req;
+ struct file *file;
+ ssize_t ret;
+- char *buf;
++ int need_putctx;
+
+ /* enforce forwards compatibility on users */
+ if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
+@@ -1027,51 +1477,41 @@ int io_submit_one(struct kioctx *ctx, st
+ req->ki_user_data = iocb->aio_data;
+ req->ki_pos = iocb->aio_offset;
+
+- buf = (char *)(unsigned long)iocb->aio_buf;
++ req->ki_buf = (char *)(unsigned long)iocb->aio_buf;
++ req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
++ req->ki_opcode = iocb->aio_lio_opcode;
++ init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
++ INIT_LIST_HEAD(&req->ki_wait.task_list);
++ req->ki_run_list.next = req->ki_run_list.prev = NULL;
++ req->ki_retry = NULL;
++ req->ki_retried = 0;
++ req->ki_kicked = 0;
++ req->ki_queued = 0;
++ aio_run = 0;
++ aio_wakeups = 0;
+
+- switch (iocb->aio_lio_opcode) {
+- case IOCB_CMD_PREAD:
+- ret = -EBADF;
+- if (unlikely(!(file->f_mode & FMODE_READ)))
+- goto out_put_req;
+- ret = -EFAULT;
+- if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes)))
+- goto out_put_req;
+- ret = -EINVAL;
+- if (file->f_op->aio_read)
+- ret = file->f_op->aio_read(req, buf,
+- iocb->aio_nbytes, req->ki_pos);
+- break;
+- case IOCB_CMD_PWRITE:
+- ret = -EBADF;
+- if (unlikely(!(file->f_mode & FMODE_WRITE)))
+- goto out_put_req;
+- ret = -EFAULT;
+- if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes)))
+- goto out_put_req;
+- ret = -EINVAL;
+- if (file->f_op->aio_write)
+- ret = file->f_op->aio_write(req, buf,
+- iocb->aio_nbytes, req->ki_pos);
+- break;
+- case IOCB_CMD_FDSYNC:
+- ret = -EINVAL;
+- if (file->f_op->aio_fsync)
+- ret = file->f_op->aio_fsync(req, 1);
+- break;
+- case IOCB_CMD_FSYNC:
+- ret = -EINVAL;
+- if (file->f_op->aio_fsync)
+- ret = file->f_op->aio_fsync(req, 0);
+- break;
+- default:
+- dprintk("EINVAL: io_submit: no operation provided\n");
+- ret = -EINVAL;
+- }
++ ret = aio_setup_iocb(req);
++
++ if (ret)
++ goto out_put_req;
++
++ spin_lock_irq(&ctx->ctx_lock);
++ /*
++ * Hold an extra reference while submitting the i/o.
++ * This prevents races between the aio code path referencing the
++ * req (after submitting it) and aio_complete() freeing the req.
++ */
++ req->ki_users++; /* grab extra reference */
++ ret = aio_run_iocb(req);
++ need_putctx = __aio_put_req(ctx, req); /* drop the extra reference */
++ spin_unlock_irq(&ctx->ctx_lock);
++
++ if (-EIOCBRETRY == ret)
++ queue_work(aio_wq, &ctx->wq);
++
++ if (need_putctx)
++ put_ioctx(ctx);
+
+- if (likely(-EIOCBQUEUED == ret))
+- return 0;
+- aio_complete(req, ret, 0);
+ return 0;
+
+ out_put_req:
+--- linux-2.6.0-test6/fs/autofs4/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/autofs4/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/file.h>
+ #include <linux/pagemap.h>
++#include <linux/parser.h>
+ #include <asm/bitops.h>
+ #include "autofs_i.h"
+ #include <linux/module.h>
+@@ -94,11 +95,25 @@ static struct super_operations autofs4_s
+ .statfs = simple_statfs,
+ };
+
++enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
++
++static match_table_t tokens = {
++ {Opt_fd, "fd=%d"},
++ {Opt_uid, "uid=%d"},
++ {Opt_gid, "gid=%d"},
++ {Opt_pgrp, "pgrp=%d"},
++ {Opt_minproto, "minproto=%d"},
++ {Opt_maxproto, "maxproto=%d"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
+ pid_t *pgrp, int *minproto, int *maxproto)
+ {
+- char *this_char, *value;
+-
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
++ int option;
++
+ *uid = current->uid;
+ *gid = current->gid;
+ *pgrp = process_group(current);
+@@ -108,55 +123,48 @@ static int parse_options(char *options,
+
+ *pipefd = -1;
+
+- if ( !options ) return 1;
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++ if (!options)
++ return 1;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+- if (!strcmp(this_char,"fd")) {
+- if (!value || !*value)
+- return 1;
+- *pipefd = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"uid")) {
+- if (!value || !*value)
+- return 1;
+- *uid = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"gid")) {
+- if (!value || !*value)
+- return 1;
+- *gid = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"pgrp")) {
+- if (!value || !*value)
+- return 1;
+- *pgrp = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"minproto")) {
+- if (!value || !*value)
+- return 1;
+- *minproto = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"maxproto")) {
+- if (!value || !*value)
+- return 1;
+- *maxproto = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_fd:
++ if (match_int(args, pipefd))
++ return 1;
++ break;
++ case Opt_uid:
++ if (match_int(args, &option))
++ return 1;
++ *uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(args, &option))
++ return 1;
++ *gid = option;
++ break;
++ case Opt_pgrp:
++ if (match_int(args, &option))
++ return 1;
++ *pgrp = option;
++ break;
++ case Opt_minproto:
++ if (match_int(args, &option))
++ return 1;
++ *minproto = option;
++ break;
++ case Opt_maxproto:
++ if (match_int(args, &option))
++ return 1;
++ *maxproto = option;
++ break;
++ default:
++ return 1;
+ }
+- else break;
+ }
+ return (*pipefd < 0);
+ }
+--- linux-2.6.0-test6/fs/autofs/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/autofs/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -14,6 +14,7 @@
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+ #include <linux/file.h>
++#include <linux/parser.h>
+ #include <asm/bitops.h>
+ #include "autofs_i.h"
+ #include <linux/module.h>
+@@ -45,10 +46,24 @@ static struct super_operations autofs_so
+ .statfs = simple_statfs,
+ };
+
++enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
++
++static match_table_t autofs_tokens = {
++ {Opt_fd, "fd=%d"},
++ {Opt_uid, "uid=%d"},
++ {Opt_gid, "gid=%d"},
++ {Opt_pgrp, "pgrp=%d"},
++ {Opt_minproto, "minproto=%d"},
++ {Opt_maxproto, "maxproto=%d"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto)
+ {
+- char *this_char, *value;
+-
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
++ int option;
++
+ *uid = current->uid;
+ *gid = current->gid;
+ *pgrp = process_group(current);
+@@ -57,55 +72,49 @@ static int parse_options(char *options,
+
+ *pipefd = -1;
+
+- if ( !options ) return 1;
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++ if (!options)
++ return 1;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+- if (!strcmp(this_char,"fd")) {
+- if (!value || !*value)
+- return 1;
+- *pipefd = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"uid")) {
+- if (!value || !*value)
+- return 1;
+- *uid = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"gid")) {
+- if (!value || !*value)
+- return 1;
+- *gid = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"pgrp")) {
+- if (!value || !*value)
+- return 1;
+- *pgrp = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"minproto")) {
+- if (!value || !*value)
+- return 1;
+- *minproto = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
+- }
+- else if (!strcmp(this_char,"maxproto")) {
+- if (!value || !*value)
+- return 1;
+- *maxproto = simple_strtoul(value,&value,0);
+- if (*value)
+- return 1;
++
++ token = match_token(p, autofs_tokens, args);
++ switch (token) {
++ case Opt_fd:
++ if (match_int(&args[0], &option))
++ return 1;
++ *pipefd = option;
++ break;
++ case Opt_uid:
++ if (match_int(&args[0], &option))
++ return 1;
++ *uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(&args[0], &option))
++ return 1;
++ *gid = option;
++ break;
++ case Opt_pgrp:
++ if (match_int(&args[0], &option))
++ return 1;
++ *pgrp = option;
++ break;
++ case Opt_minproto:
++ if (match_int(&args[0], &option))
++ return 1;
++ *minproto = option;
++ break;
++ case Opt_maxproto:
++ if (match_int(&args[0], &option))
++ return 1;
++ *maxproto = option;
++ break;
++ default:
++ return 1;
+ }
+- else break;
+ }
+ return (*pipefd < 0);
+ }
+--- linux-2.6.0-test6/fs/befs/linuxvfs.c 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/befs/linuxvfs.c 2003-10-05 00:33:24.000000000 -0700
+@@ -13,6 +13,7 @@
+ #include <linux/nls.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
++#include <linux/parser.h>
+
+ #include "befs.h"
+ #include "btree.h"
+@@ -39,7 +40,7 @@ static struct inode *befs_alloc_inode(st
+ static void befs_destroy_inode(struct inode *inode);
+ static int befs_init_inodecache(void);
+ static void befs_destroy_inodecache(void);
+-static int befs_readlink(struct dentry *, char *, int);
++static int befs_readlink(struct dentry *, char __user *, int);
+ static int befs_follow_link(struct dentry *, struct nameidata *nd);
+ static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
+ char **out, int *out_len);
+@@ -494,7 +495,7 @@ befs_follow_link(struct dentry *dentry,
+ }
+
+ static int
+-befs_readlink(struct dentry *dentry, char *buffer, int buflen)
++befs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+ {
+ struct super_block *sb = dentry->d_sb;
+ befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+@@ -667,12 +668,27 @@ befs_nls2utf(struct super_block *sb, con
+ return -EILSEQ;
+ }
+
++/**
++ * Use the
++ *
++ */
++enum {
++ Opt_uid, Opt_gid, Opt_charset, Opt_debug,
++};
++
++static match_table_t befs_tokens = {
++ {Opt_uid, "uid=%d"},
++ {Opt_gid, "gid=%d"},
++ {Opt_charset, "iocharset=%s"},
++ {Opt_debug, "debug"}
++};
++
+ static int
+ parse_options(char *options, befs_mount_options * opts)
+ {
+- char *this_char;
+- char *value;
+- int ret = 1;
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
++ int option;
+
+ /* Initialize options */
+ opts->uid = 0;
+@@ -683,64 +699,56 @@ parse_options(char *options, befs_mount_
+ opts->debug = 0;
+
+ if (!options)
+- return ret;
+-
+- while ((this_char = strsep(&options, ",")) != NULL) {
+-
+- if ((value = strchr(this_char, '=')) != NULL)
+- *value++ = 0;
++ return 1;
+
+- if (!strcmp(this_char, "uid")) {
+- if (!value || !*value) {
+- ret = 0;
+- } else {
+- opts->uid = simple_strtoul(value, &value, 0);
+- opts->use_uid = 1;
+- if (*value) {
+- printk(KERN_ERR "BEFS: Invalid uid "
+- "option: %s\n", value);
+- ret = 0;
+- }
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
++ continue;
++
++ token = match_token(p, befs_tokens, args);
++ switch (token) {
++ case Opt_uid:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0) {
++ printk(KERN_ERR "BeFS: Invalid uid %d, "
++ "using default\n", option);
++ break;
+ }
+- } else if (!strcmp(this_char, "gid")) {
+- if (!value || !*value)
+- ret = 0;
+- else {
+- opts->gid = simple_strtoul(value, &value, 0);
+- opts->use_gid = 1;
+- if (*value) {
+- printk(KERN_ERR
+- "BEFS: Invalid gid option: "
+- "%s\n", value);
+- ret = 0;
+- }
++ opts->uid = option;
++ opts->use_uid = 1;
++ break;
++ case Opt_gid:
++ if (match_int(&args[0], &option))
++ return 0;
++ if (option < 0) {
++ printk(KERN_ERR "BeFS: Invalid gid %d, "
++ "using default\n", option);
++ break;
+ }
+- } else if (!strcmp(this_char, "iocharset") && value) {
+- char *p = value;
+- int len;
+-
+- while (*value && *value != ',')
+- value++;
+- len = value - p;
+- if (len) {
+- char *buffer = kmalloc(len + 1, GFP_NOFS);
+- if (buffer) {
+- opts->iocharset = buffer;
+- memcpy(buffer, p, len);
+- buffer[len] = 0;
+-
+- } else {
+- printk(KERN_ERR "BEFS: "
+- "cannot allocate memory\n");
+- ret = 0;
+- }
++ opts->gid = option;
++ opts->use_gid = 1;
++ break;
++ case Opt_charset:
++ kfree(opts->iocharset);
++ opts->iocharset = match_strdup(&args[0]);
++ if (!opts->iocharset) {
++ printk(KERN_ERR "BeFS: allocation failure for "
++ "iocharset string\n");
++ return 0;
+ }
+- } else if (!strcmp(this_char, "debug")) {
++ break;
++ case Opt_debug:
+ opts->debug = 1;
++ break;
++ default:
++ printk(KERN_ERR "BeFS: Unrecognized mount option \"%s\" "
++ "or missing value\n", p);
++ return 0;
+ }
+ }
+-
+- return ret;
++ return 1;
+ }
+
+ /* This function has the responsibiltiy of getting the
+@@ -939,9 +947,19 @@ init_befs_fs(void)
+
+ err = befs_init_inodecache();
+ if (err)
+- return err;
++ goto unaquire_none;
++
++ err = register_filesystem(&befs_fs_type);
++ if (err)
++ goto unaquire_inodecache;
++
++ return 0;
++
++unaquire_inodecache:
++ befs_destroy_inodecache();
+
+- return register_filesystem(&befs_fs_type);
++unaquire_none:
++ return err;
+ }
+
+ static void __exit
+--- linux-2.6.0-test6/fs/binfmt_elf.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/binfmt_elf.c 2003-10-05 00:36:15.000000000 -0700
+@@ -134,7 +134,7 @@ create_elf_tables(struct linux_binprm *b
+ elf_addr_t *sp, *u_platform;
+ const char *k_platform = ELF_PLATFORM;
+ int items;
+- elf_addr_t elf_info[40];
++ elf_addr_t *elf_info;
+ int ei_index = 0;
+ struct task_struct *tsk = current;
+
+@@ -169,6 +169,7 @@ create_elf_tables(struct linux_binprm *b
+ }
+
+ /* Create the ELF interpreter info */
++ elf_info = (elf_addr_t *) current->mm->saved_auxv;
+ #define NEW_AUX_ENT(id, val) \
+ do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)
+
+@@ -196,8 +197,13 @@ create_elf_tables(struct linux_binprm *b
+ if (k_platform) {
+ NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(long)u_platform);
+ }
+- NEW_AUX_ENT(AT_NULL, 0);
+ #undef NEW_AUX_ENT
++ /* AT_NULL is zero; clear the rest too */
++ memset(&elf_info[ei_index], 0,
++ sizeof current->mm->saved_auxv - ei_index * sizeof elf_info[0]);
++
++ /* And advance past the AT_NULL entry. */
++ ei_index += 2;
+
+ sp = STACK_ADD(p, ei_index);
+
+@@ -1078,7 +1084,7 @@ static void fill_prstatus(struct elf_prs
+ prstatus->pr_pid = p->pid;
+ prstatus->pr_ppid = p->parent->pid;
+ prstatus->pr_pgrp = process_group(p);
+- prstatus->pr_sid = p->session;
++ prstatus->pr_sid = process_session(p);
+ jiffies_to_timeval(p->utime, &prstatus->pr_utime);
+ jiffies_to_timeval(p->stime, &prstatus->pr_stime);
+ jiffies_to_timeval(p->cutime, &prstatus->pr_cutime);
+@@ -1106,7 +1112,7 @@ static void fill_psinfo(struct elf_prpsi
+ psinfo->pr_pid = p->pid;
+ psinfo->pr_ppid = p->parent->pid;
+ psinfo->pr_pgrp = process_group(p);
+- psinfo->pr_sid = p->session;
++ psinfo->pr_sid = process_session(p);
+
+ i = p->state ? ffz(~p->state) + 1 : 0;
+ psinfo->pr_state = i;
+@@ -1186,7 +1192,7 @@ static int elf_dump_thread_status(long s
+ */
+ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
+ {
+-#define NUM_NOTES 5
++#define NUM_NOTES 6
+ int has_dumped = 0;
+ mm_segment_t fs;
+ int segs;
+@@ -1196,7 +1202,7 @@ static int elf_core_dump(long signr, str
+ struct elfhdr *elf = NULL;
+ off_t offset = 0, dataoff;
+ unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
+- int numnote = NUM_NOTES;
++ int numnote;
+ struct memelfnote *notes = NULL;
+ struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
+ struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
+@@ -1208,6 +1214,7 @@ static int elf_core_dump(long signr, str
+ elf_fpxregset_t *xfpu = NULL;
+ #endif
+ int thread_status_size = 0;
++ elf_addr_t *auxv;
+
+ /*
+ * We no longer stop all VM operations.
+@@ -1287,18 +1294,25 @@ static int elf_core_dump(long signr, str
+
+ fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
+
++ numnote = 3;
++
++ auxv = (elf_addr_t *) current->mm->saved_auxv;
++
++ i = 0;
++ do
++ i += 2;
++ while (auxv[i - 2] != AT_NULL);
++ fill_note(¬es[numnote++], "CORE", NT_AUXV,
++ i * sizeof (elf_addr_t), auxv);
++
+ /* Try to dump the FPU. */
+ if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu)))
+- fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
+- else
+- --numnote;
++ fill_note(notes + numnote++,
++ "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
+ #ifdef ELF_CORE_COPY_XFPREGS
+ if (elf_core_copy_task_xfpregs(current, xfpu))
+- fill_note(notes +4, "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
+- else
+- --numnote;
+-#else
+- numnote--;
++ fill_note(notes + numnote++,
++ "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu);
+ #endif
+
+ fs = get_fs();
+--- linux-2.6.0-test6/fs/block_dev.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/block_dev.c 2003-10-05 00:34:12.000000000 -0700
+@@ -25,6 +25,22 @@
+ #include <linux/namei.h>
+ #include <asm/uaccess.h>
+
++struct bdev_inode {
++ struct block_device bdev;
++ struct inode vfs_inode;
++};
++
++static inline struct bdev_inode *BDEV_I(struct inode *inode)
++{
++ return container_of(inode, struct bdev_inode, vfs_inode);
++}
++
++inline struct block_device *I_BDEV(struct inode *inode)
++{
++ return &BDEV_I(inode)->bdev;
++}
++
++EXPORT_SYMBOL(I_BDEV);
+
+ static sector_t max_block(struct block_device *bdev)
+ {
+@@ -70,6 +86,8 @@ int set_blocksize(struct block_device *b
+ return 0;
+ }
+
++EXPORT_SYMBOL(set_blocksize);
++
+ int sb_set_blocksize(struct super_block *sb, int size)
+ {
+ int bits;
+@@ -82,6 +100,8 @@ int sb_set_blocksize(struct super_block
+ return sb->s_blocksize;
+ }
+
++EXPORT_SYMBOL(sb_set_blocksize);
++
+ int sb_min_blocksize(struct super_block *sb, int size)
+ {
+ int minsize = bdev_hardsect_size(sb->s_bdev);
+@@ -90,14 +110,16 @@ int sb_min_blocksize(struct super_block
+ return sb_set_blocksize(sb, size);
+ }
+
++EXPORT_SYMBOL(sb_min_blocksize);
++
+ static int
+ blkdev_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh, int create)
+ {
+- if (iblock >= max_block(inode->i_bdev))
++ if (iblock >= max_block(I_BDEV(inode)))
+ return -EIO;
+
+- bh->b_bdev = inode->i_bdev;
++ bh->b_bdev = I_BDEV(inode);
+ bh->b_blocknr = iblock;
+ set_buffer_mapped(bh);
+ return 0;
+@@ -107,10 +129,10 @@ static int
+ blkdev_get_blocks(struct inode *inode, sector_t iblock,
+ unsigned long max_blocks, struct buffer_head *bh, int create)
+ {
+- if ((iblock + max_blocks) > max_block(inode->i_bdev))
++ if ((iblock + max_blocks) > max_block(I_BDEV(inode)))
+ return -EIO;
+
+- bh->b_bdev = inode->i_bdev;
++ bh->b_bdev = I_BDEV(inode);
+ bh->b_blocknr = iblock;
+ bh->b_size = max_blocks << inode->i_blkbits;
+ set_buffer_mapped(bh);
+@@ -122,9 +144,9 @@ blkdev_direct_IO(int rw, struct kiocb *i
+ loff_t offset, unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+
+- return blockdev_direct_IO(rw, iocb, inode, inode->i_bdev, iov, offset,
++ return blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
+ nr_segs, blkdev_get_blocks, NULL);
+ }
+
+@@ -155,11 +177,10 @@ static int blkdev_commit_write(struct fi
+ */
+ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
+ {
+- struct inode *bd_inode;
++ struct inode *bd_inode = file->f_mapping->host;
+ loff_t size;
+ loff_t retval;
+
+- bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
+ down(&bd_inode->i_sem);
+ size = i_size_read(bd_inode);
+
+@@ -182,15 +203,13 @@ static loff_t block_llseek(struct file *
+ }
+
+ /*
+- * Filp may be NULL when we are called by an msync of a vma
+- * since the vma has no handle.
++ * Filp is never NULL; the only case when ->fsync() is called with
++ * NULL first argument is nfsd_sync_dir() and that's not a directory.
+ */
+
+ static int block_fsync(struct file *filp, struct dentry *dentry, int datasync)
+ {
+- struct inode * inode = dentry->d_inode;
+-
+- return sync_blockdev(inode->i_bdev);
++ return sync_blockdev(I_BDEV(filp->f_mapping->host));
+ }
+
+ /*
+@@ -200,16 +219,6 @@ static int block_fsync(struct file *filp
+ static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+ static kmem_cache_t * bdev_cachep;
+
+-struct bdev_inode {
+- struct block_device bdev;
+- struct inode vfs_inode;
+-};
+-
+-static inline struct bdev_inode *BDEV_I(struct inode *inode)
+-{
+- return container_of(inode, struct bdev_inode, vfs_inode);
+-}
+-
+ static struct inode *bdev_alloc_inode(struct super_block *sb)
+ {
+ struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, SLAB_KERNEL);
+@@ -243,7 +252,6 @@ static inline void __bd_forget(struct in
+ {
+ list_del_init(&inode->i_devices);
+ inode->i_bdev = NULL;
+- inode->i_mapping = &inode->i_data;
+ }
+
+ static void bdev_clear_inode(struct inode *inode)
+@@ -358,6 +366,8 @@ struct block_device *bdget(dev_t dev)
+ return bdev;
+ }
+
++EXPORT_SYMBOL(bdget);
++
+ long nr_blockdev_pages(void)
+ {
+ struct list_head *p;
+@@ -376,27 +386,29 @@ void bdput(struct block_device *bdev)
+ {
+ iput(bdev->bd_inode);
+ }
++
++EXPORT_SYMBOL(bdput);
+
+-int bd_acquire(struct inode *inode)
++static struct block_device *bd_acquire(struct inode *inode)
+ {
+ struct block_device *bdev;
+ spin_lock(&bdev_lock);
+- if (inode->i_bdev && igrab(inode->i_bdev->bd_inode)) {
++ bdev = inode->i_bdev;
++ if (bdev && igrab(bdev->bd_inode)) {
+ spin_unlock(&bdev_lock);
+- return 0;
++ return bdev;
+ }
+ spin_unlock(&bdev_lock);
+ bdev = bdget(inode->i_rdev);
+- if (!bdev)
+- return -ENOMEM;
+- spin_lock(&bdev_lock);
+- if (inode->i_bdev)
+- __bd_forget(inode);
+- inode->i_bdev = bdev;
+- inode->i_mapping = bdev->bd_inode->i_mapping;
+- list_add(&inode->i_devices, &bdev->bd_inodes);
+- spin_unlock(&bdev_lock);
+- return 0;
++ if (bdev) {
++ spin_lock(&bdev_lock);
++ if (inode->i_bdev)
++ __bd_forget(inode);
++ inode->i_bdev = bdev;
++ list_add(&inode->i_devices, &bdev->bd_inodes);
++ spin_unlock(&bdev_lock);
++ }
++ return bdev;
+ }
+
+ /* Call when you free inode */
+@@ -444,6 +456,8 @@ int bd_claim(struct block_device *bdev,
+ return res;
+ }
+
++EXPORT_SYMBOL(bd_claim);
++
+ void bd_release(struct block_device *bdev)
+ {
+ spin_lock(&bdev_lock);
+@@ -454,6 +468,8 @@ void bd_release(struct block_device *bde
+ spin_unlock(&bdev_lock);
+ }
+
++EXPORT_SYMBOL(bd_release);
++
+ /*
+ * Tries to open block device by device number. Use it ONLY if you
+ * really do not have anything better - i.e. when you are behind a
+@@ -471,6 +487,8 @@ struct block_device *open_by_devnum(dev_
+ return err ? ERR_PTR(err) : bdev;
+ }
+
++EXPORT_SYMBOL(open_by_devnum);
++
+ /*
+ * This routine checks whether a removable media has been changed,
+ * and invalidates all buffer-cache-entries in that case. This
+@@ -500,6 +518,8 @@ int check_disk_change(struct block_devic
+ return 1;
+ }
+
++EXPORT_SYMBOL(check_disk_change);
++
+ static void bd_set_size(struct block_device *bdev, loff_t size)
+ {
+ unsigned bsize = bdev_hardsect_size(bdev);
+@@ -513,13 +533,14 @@ static void bd_set_size(struct block_dev
+ bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+ }
+
+-static int do_open(struct block_device *bdev, struct inode *inode, struct file *file)
++static int do_open(struct block_device *bdev, struct file *file)
+ {
+ struct module *owner = NULL;
+ struct gendisk *disk;
+ int ret = -ENXIO;
+ int part;
+
++ file->f_mapping = bdev->bd_inode->i_mapping;
+ lock_kernel();
+ disk = get_gendisk(bdev->bd_dev, &part);
+ if (!disk) {
+@@ -536,7 +557,7 @@ static int do_open(struct block_device *
+ if (!part) {
+ struct backing_dev_info *bdi;
+ if (disk->fops->open) {
+- ret = disk->fops->open(inode, file);
++ ret = disk->fops->open(bdev, file);
+ if (ret)
+ goto out_first;
+ }
+@@ -581,7 +602,7 @@ static int do_open(struct block_device *
+ module_put(owner);
+ if (bdev->bd_contains == bdev) {
+ if (bdev->bd_disk->fops->open) {
+- ret = bdev->bd_disk->fops->open(inode, file);
++ ret = bdev->bd_disk->fops->open(bdev, file);
+ if (ret)
+ goto out;
+ }
+@@ -629,9 +650,11 @@ int blkdev_get(struct block_device *bdev
+ fake_file.f_dentry = &fake_dentry;
+ fake_dentry.d_inode = bdev->bd_inode;
+
+- return do_open(bdev, bdev->bd_inode, &fake_file);
++ return do_open(bdev, &fake_file);
+ }
+
++EXPORT_SYMBOL(blkdev_get);
++
+ int blkdev_open(struct inode * inode, struct file * filp)
+ {
+ struct block_device *bdev;
+@@ -645,10 +668,9 @@ int blkdev_open(struct inode * inode, st
+ */
+ filp->f_flags |= O_LARGEFILE;
+
+- bd_acquire(inode);
+- bdev = inode->i_bdev;
++ bdev = bd_acquire(inode);
+
+- res = do_open(bdev, inode, filp);
++ res = do_open(bdev, filp);
+ if (res)
+ return res;
+
+@@ -662,10 +684,11 @@ int blkdev_open(struct inode * inode, st
+ return res;
+ }
+
++EXPORT_SYMBOL(blkdev_open);
++
+ int blkdev_put(struct block_device *bdev, int kind)
+ {
+ int ret = 0;
+- struct inode *bd_inode = bdev->bd_inode;
+ struct gendisk *disk = bdev->bd_disk;
+
+ down(&bdev->bd_sem);
+@@ -674,14 +697,14 @@ int blkdev_put(struct block_device *bdev
+ switch (kind) {
+ case BDEV_FILE:
+ case BDEV_FS:
+- sync_blockdev(bd_inode->i_bdev);
++ sync_blockdev(bdev);
+ break;
+ }
+ kill_bdev(bdev);
+ }
+ if (bdev->bd_contains == bdev) {
+ if (disk->fops->release)
+- ret = disk->fops->release(bd_inode, NULL);
++ ret = disk->fops->release(disk);
+ } else {
+ down(&bdev->bd_contains->bd_sem);
+ bdev->bd_contains->bd_part_count--;
+@@ -710,11 +733,14 @@ int blkdev_put(struct block_device *bdev
+ return ret;
+ }
+
+-int blkdev_close(struct inode * inode, struct file * filp)
++EXPORT_SYMBOL(blkdev_put);
++
++static int blkdev_close(struct inode * inode, struct file * filp)
+ {
+- if (inode->i_bdev->bd_holder == filp)
+- bd_release(inode->i_bdev);
+- return blkdev_put(inode->i_bdev, BDEV_FILE);
++ struct block_device *bdev = I_BDEV(filp->f_mapping->host);
++ if (bdev->bd_holder == filp)
++ bd_release(bdev);
++ return blkdev_put(bdev, BDEV_FILE);
+ }
+
+ static ssize_t blkdev_file_write(struct file *file, const char __user *buf,
+@@ -733,6 +759,11 @@ static ssize_t blkdev_file_aio_write(str
+ return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
+ }
+
++static int block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
++ unsigned long arg)
++{
++ return blkdev_ioctl(I_BDEV(file->f_mapping->host), file, cmd, arg);
++}
+
+ struct address_space_operations def_blk_aops = {
+ .readpage = blkdev_readpage,
+@@ -754,22 +785,26 @@ struct file_operations def_blk_fops = {
+ .aio_write = blkdev_file_aio_write,
+ .mmap = generic_file_mmap,
+ .fsync = block_fsync,
+- .ioctl = blkdev_ioctl,
++ .ioctl = block_ioctl,
+ .readv = generic_file_readv,
+ .writev = generic_file_writev,
+ .sendfile = generic_file_sendfile,
+ };
+
++EXPORT_SYMBOL(def_blk_fops);
++
+ int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
+ {
+ int res;
+ mm_segment_t old_fs = get_fs();
+ set_fs(KERNEL_DS);
+- res = blkdev_ioctl(bdev->bd_inode, NULL, cmd, arg);
++ res = blkdev_ioctl(bdev, NULL, cmd, arg);
+ set_fs(old_fs);
+ return res;
+ }
+
++EXPORT_SYMBOL(ioctl_by_bdev);
++
+ /**
+ * lookup_bdev - lookup a struct block_device by name
+ *
+@@ -800,11 +835,10 @@ struct block_device *lookup_bdev(const c
+ error = -EACCES;
+ if (nd.mnt->mnt_flags & MNT_NODEV)
+ goto fail;
+- error = bd_acquire(inode);
+- if (error)
++ error = -ENOMEM;
++ bdev = bd_acquire(inode);
++ if (!bdev)
+ goto fail;
+- bdev = inode->i_bdev;
+-
+ out:
+ path_release(&nd);
+ return bdev;
+@@ -854,6 +888,8 @@ blkdev_put:
+ return ERR_PTR(error);
+ }
+
++EXPORT_SYMBOL(open_bdev_excl);
++
+ /**
+ * close_bdev_excl - release a blockdevice openen by open_bdev_excl()
+ *
+@@ -867,3 +903,5 @@ void close_bdev_excl(struct block_device
+ bd_release(bdev);
+ blkdev_put(bdev, kind);
+ }
++
++EXPORT_SYMBOL(close_bdev_excl);
+--- linux-2.6.0-test6/fs/buffer.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/buffer.c 2003-10-05 00:36:59.000000000 -0700
+@@ -116,27 +116,50 @@ void unlock_buffer(struct buffer_head *b
+ }
+
+ /*
+- * Block until a buffer comes unlocked. This doesn't stop it
++ * Wait until a buffer comes unlocked. This doesn't stop it
+ * from becoming locked again - you have to lock it yourself
+ * if you want to preserve its state.
++ * If the wait queue parameter specifies an async i/o callback,
++ * then instead of blocking, we just queue up the callback
++ * on the wait queue for async notification when the buffer gets
++ * unlocked.
++ * A NULL wait queue parameter defaults to synchronous behaviour
+ */
+-void __wait_on_buffer(struct buffer_head * bh)
++int __wait_on_buffer_wq(struct buffer_head * bh, wait_queue_t *wait)
+ {
+ wait_queue_head_t *wqh = bh_waitq_head(bh);
+- DEFINE_WAIT(wait);
++ DEFINE_WAIT(local_wait);
++
++ if (!wait)
++ wait = &local_wait;
+
+ if (atomic_read(&bh->b_count) == 0 &&
+ (!bh->b_page || !PageLocked(bh->b_page)))
+ buffer_error();
+
+ do {
+- prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
++ prepare_to_wait(wqh, wait, TASK_UNINTERRUPTIBLE);
+ if (buffer_locked(bh)) {
+ blk_run_queues();
++ if (!is_sync_wait(wait)) {
++ /*
++ * if we've queued an async wait queue
++ * callback do not block; just tell the
++ * caller to return and retry later when
++ * the callback is notified
++ */
++ return -EIOCBRETRY;
++ }
+ io_schedule();
+ }
+ } while (buffer_locked(bh));
+- finish_wait(wqh, &wait);
++ finish_wait(wqh, wait);
++ return 0;
++}
++
++void __wait_on_buffer(struct buffer_head * bh)
++{
++ __wait_on_buffer_wq(bh, NULL);
+ }
+
+ static void
+@@ -314,8 +337,7 @@ int file_fsync(struct file *filp, struct
+ asmlinkage long sys_fsync(unsigned int fd)
+ {
+ struct file * file;
+- struct dentry * dentry;
+- struct inode * inode;
++ struct address_space *mapping;
+ int ret, err;
+
+ ret = -EBADF;
+@@ -323,8 +345,7 @@ asmlinkage long sys_fsync(unsigned int f
+ if (!file)
+ goto out;
+
+- dentry = file->f_dentry;
+- inode = dentry->d_inode;
++ mapping = file->f_mapping;
+
+ ret = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync) {
+@@ -333,17 +354,17 @@ asmlinkage long sys_fsync(unsigned int f
+ }
+
+ /* We need to protect against concurrent writers.. */
+- down(&inode->i_sem);
++ down(&mapping->host->i_sem);
+ current->flags |= PF_SYNCWRITE;
+- ret = filemap_fdatawrite(inode->i_mapping);
+- err = file->f_op->fsync(file, dentry, 0);
++ ret = filemap_fdatawrite(mapping);
++ err = file->f_op->fsync(file, file->f_dentry, 0);
+ if (!ret)
+ ret = err;
+- err = filemap_fdatawait(inode->i_mapping);
++ err = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = err;
+ current->flags &= ~PF_SYNCWRITE;
+- up(&inode->i_sem);
++ up(&mapping->host->i_sem);
+
+ out_putf:
+ fput(file);
+@@ -354,8 +375,7 @@ out:
+ asmlinkage long sys_fdatasync(unsigned int fd)
+ {
+ struct file * file;
+- struct dentry * dentry;
+- struct inode * inode;
++ struct address_space *mapping;
+ int ret, err;
+
+ ret = -EBADF;
+@@ -363,24 +383,23 @@ asmlinkage long sys_fdatasync(unsigned i
+ if (!file)
+ goto out;
+
+- dentry = file->f_dentry;
+- inode = dentry->d_inode;
+-
+ ret = -EINVAL;
+ if (!file->f_op || !file->f_op->fsync)
+ goto out_putf;
+
+- down(&inode->i_sem);
++ mapping = file->f_mapping;
++
++ down(&mapping->host->i_sem);
+ current->flags |= PF_SYNCWRITE;
+- ret = filemap_fdatawrite(inode->i_mapping);
+- err = file->f_op->fsync(file, dentry, 1);
++ ret = filemap_fdatawrite(mapping);
++ err = file->f_op->fsync(file, file->f_dentry, 1);
+ if (!ret)
+ ret = err;
+- err = filemap_fdatawait(inode->i_mapping);
++ err = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = err;
+ current->flags &= ~PF_SYNCWRITE;
+- up(&inode->i_sem);
++ up(&mapping->host->i_sem);
+
+ out_putf:
+ fput(file);
+@@ -1296,9 +1315,12 @@ void __bforget(struct buffer_head *bh)
+ __brelse(bh);
+ }
+
+-static struct buffer_head *__bread_slow(struct buffer_head *bh)
++static struct buffer_head *__bread_slow_wq(struct buffer_head *bh,
++ wait_queue_t *wait)
+ {
+- lock_buffer(bh);
++ if (-EIOCBRETRY == lock_buffer_wq(bh, wait))
++ return ERR_PTR(-EIOCBRETRY);
++
+ if (buffer_uptodate(bh)) {
+ unlock_buffer(bh);
+ return bh;
+@@ -1308,7 +1330,8 @@ static struct buffer_head *__bread_slow(
+ get_bh(bh);
+ bh->b_end_io = end_buffer_read_sync;
+ submit_bh(READ, bh);
+- wait_on_buffer(bh);
++ if (-EIOCBRETRY == wait_on_buffer_wq(bh, wait))
++ return ERR_PTR(-EIOCBRETRY);
+ if (buffer_uptodate(bh))
+ return bh;
+ }
+@@ -1316,6 +1339,11 @@ static struct buffer_head *__bread_slow(
+ return NULL;
+ }
+
++static inline struct buffer_head *__bread_slow(struct buffer_head *bh)
++{
++ return __bread_slow_wq(bh, NULL);
++}
++
+ /*
+ * Per-cpu buffer LRU implementation. To reduce the cost of __find_get_block().
+ * The bhs[] array is sorted - newest buffer is at bhs[0]. Buffers have their
+@@ -1503,6 +1531,18 @@ __bread(struct block_device *bdev, secto
+ }
+ EXPORT_SYMBOL(__bread);
+
++struct buffer_head *
++__bread_wq(struct block_device *bdev, sector_t block, int size,
++ wait_queue_t *wait)
++{
++ struct buffer_head *bh = __getblk(bdev, block, size);
++
++ if (!buffer_uptodate(bh))
++ bh = __bread_slow_wq(bh, wait);
++ return bh;
++}
++EXPORT_SYMBOL(__bread_wq);
++
+ /*
+ * invalidate_bh_lrus() is called rarely - at unmount. Because it is only for
+ * unmount it only needs to ensure that all buffers from the target device are
+@@ -1980,8 +2020,9 @@ static int __block_prepare_write(struct
+ /*
+ * If we issued read requests - let them complete.
+ */
+- while(wait_bh > wait) {
+- wait_on_buffer(*--wait_bh);
++ while (wait_bh > wait) {
++ if ((err = wait_on_buffer_wq(*--wait_bh, current->io_wait)))
++ return err;
+ if (!buffer_uptodate(*wait_bh))
+ return -EIO;
+ }
+@@ -3035,3 +3076,32 @@ void __init buffer_init(void)
+ (void *)(long)smp_processor_id());
+ register_cpu_notifier(&buffer_nb);
+ }
++
++EXPORT_SYMBOL(__bforget);
++EXPORT_SYMBOL(__brelse);
++EXPORT_SYMBOL(__wait_on_buffer);
++EXPORT_SYMBOL(__wait_on_buffer_wq);
++EXPORT_SYMBOL(block_commit_write);
++EXPORT_SYMBOL(block_prepare_write);
++EXPORT_SYMBOL(block_read_full_page);
++EXPORT_SYMBOL(block_sync_page);
++EXPORT_SYMBOL(block_truncate_page);
++EXPORT_SYMBOL(block_write_full_page);
++EXPORT_SYMBOL(buffer_insert_list);
++EXPORT_SYMBOL(cont_prepare_write);
++EXPORT_SYMBOL(end_buffer_async_write);
++EXPORT_SYMBOL(end_buffer_read_sync);
++EXPORT_SYMBOL(end_buffer_write_sync);
++EXPORT_SYMBOL(file_fsync);
++EXPORT_SYMBOL(fsync_bdev);
++EXPORT_SYMBOL(fsync_buffers_list);
++EXPORT_SYMBOL(generic_block_bmap);
++EXPORT_SYMBOL(generic_commit_write);
++EXPORT_SYMBOL(generic_cont_expand);
++EXPORT_SYMBOL(init_buffer);
++EXPORT_SYMBOL(invalidate_bdev);
++EXPORT_SYMBOL(ll_rw_block);
++EXPORT_SYMBOL(mark_buffer_dirty);
++EXPORT_SYMBOL(submit_bh);
++EXPORT_SYMBOL(sync_dirty_buffer);
++EXPORT_SYMBOL(unlock_buffer);
+--- linux-2.6.0-test6/fs/coda/file.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/coda/file.c 2003-10-05 00:34:03.000000000 -0700
+@@ -89,6 +89,7 @@ coda_file_mmap(struct file *coda_file, s
+
+ coda_inode = coda_file->f_dentry->d_inode;
+ host_inode = host_file->f_dentry->d_inode;
++ coda_file->f_mapping = host_file->f_mapping;
+ if (coda_inode->i_mapping == &coda_inode->i_data)
+ coda_inode->i_mapping = host_inode->i_mapping;
+
+--- linux-2.6.0-test6/fs/compat_ioctl.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/compat_ioctl.c 2003-10-05 00:34:44.000000000 -0700
+@@ -106,6 +106,7 @@
+ #include <linux/nbd.h>
+ #include <linux/random.h>
+ #include <linux/filter.h>
++#include <linux/msdos_fs.h>
+
+ #undef INCLUDES
+ #endif
+@@ -576,54 +577,45 @@ static int ethtool_ioctl(unsigned int fd
+
+ static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
+ {
+- struct ifreq ifr;
++ struct ifreq kifr;
++ struct ifreq *uifr;
++ struct ifreq32 *ifr32 = (struct ifreq32 *) arg;
+ mm_segment_t old_fs;
+- int err, len;
++ int err;
+ u32 data;
+-
+- if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+- return -EFAULT;
+- ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL);
+- if (!ifr.ifr_data)
+- return -EAGAIN;
++ void *datap;
+
+ switch (cmd) {
+ case SIOCBONDENSLAVE:
+ case SIOCBONDRELEASE:
+ case SIOCBONDSETHWADDR:
+ case SIOCBONDCHANGEACTIVE:
+- len = IFNAMSIZ * sizeof(char);
+- break;
++ if (copy_from_user(&kifr, ifr32, sizeof(struct ifreq32)))
++ return -EFAULT;
++
++ old_fs = get_fs();
++ set_fs (KERNEL_DS);
++ err = sys_ioctl (fd, cmd, (unsigned long)&kifr);
++ set_fs (old_fs);
++
++ return err;
+ case SIOCBONDSLAVEINFOQUERY:
+- len = sizeof(struct ifslave);
+- break;
+ case SIOCBONDINFOQUERY:
+- len = sizeof(struct ifbond);
+- break;
+- default:
+- err = -EINVAL;
+- goto out;
+- };
++ uifr = compat_alloc_user_space(sizeof(*uifr));
++ if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
++ return -EFAULT;
+
+- __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+- if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) {
+- err = -EFAULT;
+- goto out;
+- }
++ if (get_user(data, &ifr32->ifr_ifru.ifru_data))
++ return -EFAULT;
+
+- old_fs = get_fs();
+- set_fs (KERNEL_DS);
+- err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+- set_fs (old_fs);
+- if (!err) {
+- len = copy_to_user(compat_ptr(data), ifr.ifr_data, len);
+- if (len)
+- err = -EFAULT;
+- }
++ datap = compat_ptr(data);
++ if (put_user(datap, &uifr->ifr_ifru.ifru_data))
++ return -EFAULT;
+
+-out:
+- free_page((unsigned long)ifr.ifr_data);
+- return err;
++ return sys_ioctl (fd, cmd, (unsigned long)uifr);
++ default:
++ return -EINVAL;
++ };
+ }
+
+ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+@@ -1035,6 +1027,7 @@ static int sg_build_iovec(sg_io_hdr_t *s
+ return -EFAULT;
+ }
+
++ sgio->dxferp = iov;
+ return 0;
+ }
+
+@@ -1581,7 +1574,7 @@ static int vt_check(struct file *file)
+ * To have permissions to do most of the vt ioctls, we either have
+ * to be the owner of the tty, or super-user.
+ */
+- if (current->tty == tty || capable(CAP_SYS_ADMIN))
++ if (process_tty(current) == tty || capable(CAP_SYS_ADMIN))
+ return 1;
+ return 0;
+ }
+@@ -2310,6 +2303,572 @@ static int mtd_rw_oob(unsigned int fd, u
+ return err;
+ }
+
++#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2])
++#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2])
++
++static long
++put_dirent32 (struct dirent *d, struct compat_dirent *d32)
++{
++ int ret;
++
++ if ((ret = verify_area(VERIFY_WRITE, d32,
++ sizeof(struct compat_dirent))))
++ return ret;
++
++ __put_user(d->d_ino, &d32->d_ino);
++ __put_user(d->d_off, &d32->d_off);
++ __put_user(d->d_reclen, &d32->d_reclen);
++ __copy_to_user(d32->d_name, d->d_name, d->d_reclen);
++ return ret;
++}
++
++static int vfat_ioctl32(unsigned fd, unsigned cmd, void *ptr)
++{
++ int ret;
++ mm_segment_t oldfs = get_fs();
++ struct dirent d[2];
++
++ switch(cmd)
++ {
++ case VFAT_IOCTL_READDIR_BOTH32:
++ cmd = VFAT_IOCTL_READDIR_BOTH;
++ break;
++ case VFAT_IOCTL_READDIR_SHORT32:
++ cmd = VFAT_IOCTL_READDIR_SHORT;
++ break;
++ }
++
++ set_fs(KERNEL_DS);
++ ret = sys_ioctl(fd,cmd,(unsigned long)&d);
++ set_fs(oldfs);
++ if (ret >= 0) {
++ ret |= put_dirent32(&d[0], (struct compat_dirent *)ptr);
++ ret |= put_dirent32(&d[1], ((struct compat_dirent *)ptr) + 1);
++ }
++ return ret;
++}
++
++#define REISERFS_IOC_UNPACK32 _IOW(0xCD,1,int)
++
++static int reiserfs_ioctl32(unsigned fd, unsigned cmd, unsigned long ptr)
++{
++ if (cmd == REISERFS_IOC_UNPACK32)
++ cmd = REISERFS_IOC_UNPACK;
++
++ return sys_ioctl(fd,cmd,ptr);
++}
++
++struct raw32_config_request
++{
++ compat_int_t raw_minor;
++ __u64 block_major;
++ __u64 block_minor;
++} __attribute__((packed));
++
++static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req)
++{
++ __u32 lo_maj, hi_maj, lo_min, hi_min;
++ int ret;
++
++ if ((ret = verify_area(VERIFY_READ, user_req,
++ sizeof(struct raw32_config_request))))
++ return ret;
++
++ __get_user(req->raw_minor, &user_req->raw_minor);
++ __get_user(lo_maj, (__u32*)&user_req->block_major);
++ __get_user(hi_maj, ((__u32*)(&user_req->block_major) + 1));
++ __get_user(lo_min, (__u32*)&user_req->block_minor);
++ __get_user(hi_min, ((__u32*)(&user_req->block_minor) + 1));
++
++ req->block_major = lo_maj | (((__u64)hi_maj) << 32);
++ req->block_minor = lo_min | (((__u64)lo_min) << 32);
++
++ return ret;
++}
++
++static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request *user_req)
++{
++ int ret;
++
++ if ((ret = verify_area(VERIFY_WRITE, user_req,
++ sizeof(struct raw32_config_request))))
++ return ret;
++
++ __put_user(req->raw_minor, &user_req->raw_minor);
++ __put_user((__u32)(req->block_major), (__u32*)&user_req->block_major);
++ __put_user((__u32)(req->block_major >> 32), ((__u32*)(&user_req->block_major) + 1));
++ __put_user((__u32)(req->block_minor), (__u32*)&user_req->block_minor);
++ __put_user((__u32)(req->block_minor >> 32), ((__u32*)(&user_req->block_minor) + 1));
++
++ return ret;
++}
++
++static int raw_ioctl(unsigned fd, unsigned cmd, void *ptr)
++{
++ int ret;
++
++ switch (cmd) {
++ case RAW_SETBIND:
++ case RAW_GETBIND: {
++ struct raw_config_request req;
++ struct raw32_config_request *user_req = ptr;
++ mm_segment_t oldfs = get_fs();
++
++ if ((ret = get_raw32_request(&req, user_req)))
++ return ret;
++
++ set_fs(KERNEL_DS);
++ ret = sys_ioctl(fd,cmd,(unsigned long)&req);
++ set_fs(oldfs);
++
++ if ((!ret) && (cmd == RAW_GETBIND)) {
++ ret = set_raw32_request(&req, user_req);
++ }
++ break;
++ }
++ default:
++ ret = sys_ioctl(fd,cmd,(unsigned long)ptr);
++ break;
++ }
++ return ret;
++}
++
++struct serial_struct32 {
++ compat_int_t type;
++ compat_int_t line;
++ compat_uint_t port;
++ compat_int_t irq;
++ compat_int_t flags;
++ compat_int_t xmit_fifo_size;
++ compat_int_t custom_divisor;
++ compat_int_t baud_base;
++ unsigned short close_delay;
++ char io_type;
++ char reserved_char[1];
++ compat_int_t hub6;
++ unsigned short closing_wait; /* time to wait before closing */
++ unsigned short closing_wait2; /* no longer used... */
++ compat_uint_t iomem_base;
++ unsigned short iomem_reg_shift;
++ unsigned int port_high;
++ compat_int_t reserved[1];
++};
++
++static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr)
++{
++ typedef struct serial_struct SS;
++ typedef struct serial_struct32 SS32;
++ struct serial_struct32 *ss32 = ptr;
++ int err;
++ struct serial_struct ss;
++ mm_segment_t oldseg = get_fs();
++ __u32 udata;
++
++ if (cmd == TIOCSSERIAL) {
++ if (verify_area(VERIFY_READ, ss32, sizeof(SS32)))
++ return -EFAULT;
++ __copy_from_user(&ss, ss32, offsetof(SS32, iomem_base));
++ __get_user(udata, &ss32->iomem_base);
++ ss.iomem_base = compat_ptr(udata);
++ __get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
++ __get_user(ss.port_high, &ss32->port_high);
++ ss.iomap_base = 0UL;
++ }
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
++ set_fs(oldseg);
++ if (cmd == TIOCGSERIAL && err >= 0) {
++ if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32)))
++ return -EFAULT;
++ __copy_to_user(ss32,&ss,offsetof(SS32,iomem_base));
++ __put_user((unsigned long)ss.iomem_base >> 32 ?
++ 0xffffffff : (unsigned)(unsigned long)ss.iomem_base,
++ &ss32->iomem_base);
++ __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift);
++ __put_user(ss.port_high, &ss32->port_high);
++
++ }
++ return err;
++}
++
++struct usbdevfs_ctrltransfer32 {
++ u8 bRequestType;
++ u8 bRequest;
++ u16 wValue;
++ u16 wIndex;
++ u16 wLength;
++ u32 timeout; /* in milliseconds */
++ compat_caddr_t data;
++};
++
++#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
++
++static int do_usbdevfs_control(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ struct usbdevfs_ctrltransfer kctrl;
++ struct usbdevfs_ctrltransfer32 *uctrl;
++ mm_segment_t old_fs;
++ __u32 udata;
++ void *uptr, *kptr;
++ int err;
++
++ uctrl = (struct usbdevfs_ctrltransfer32 *) arg;
++
++ if (copy_from_user(&kctrl, uctrl,
++ (sizeof(struct usbdevfs_ctrltransfer32) -
++ sizeof(compat_caddr_t))))
++ return -EFAULT;
++
++ if (get_user(udata, &uctrl->data))
++ return -EFAULT;
++ uptr = compat_ptr(udata);
++ /* In usbdevice_fs, it limits the control buffer to a page,
++ * for simplicity so do we.
++ */
++ if (!uptr || kctrl.wLength > PAGE_SIZE)
++ return -EINVAL;
++
++ kptr = (void *)__get_free_page(GFP_KERNEL);
++
++ if ((kctrl.bRequestType & USB_DIR_IN) == 0) {
++ err = -EFAULT;
++ if (copy_from_user(kptr, uptr, kctrl.wLength))
++ goto out;
++ }
++
++ kctrl.data = kptr;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd, USBDEVFS_CONTROL, (unsigned long)&kctrl);
++ set_fs(old_fs);
++
++ if (err >= 0 &&
++ ((kctrl.bRequestType & USB_DIR_IN) != 0)) {
++ if (copy_to_user(uptr, kptr, kctrl.wLength))
++ err = -EFAULT;
++ }
++
++out:
++ free_page((unsigned long) kptr);
++ return err;
++}
++
++
++struct usbdevfs_bulktransfer32 {
++ compat_uint_t ep;
++ compat_uint_t len;
++ compat_uint_t timeout; /* in milliseconds */
++ compat_caddr_t data;
++};
++
++#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
++
++static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ struct usbdevfs_bulktransfer kbulk;
++ struct usbdevfs_bulktransfer32 *ubulk;
++ mm_segment_t old_fs;
++ __u32 udata;
++ void *uptr, *kptr;
++ int err;
++
++ ubulk = (struct usbdevfs_bulktransfer32 *) arg;
++
++ if (get_user(kbulk.ep, &ubulk->ep) ||
++ get_user(kbulk.len, &ubulk->len) ||
++ get_user(kbulk.timeout, &ubulk->timeout) ||
++ get_user(udata, &ubulk->data))
++ return -EFAULT;
++
++ uptr = compat_ptr(udata);
++
++ /* In usbdevice_fs, it limits the control buffer to a page,
++ * for simplicity so do we.
++ */
++ if (!uptr || kbulk.len > PAGE_SIZE)
++ return -EINVAL;
++
++ kptr = (void *) __get_free_page(GFP_KERNEL);
++
++ if ((kbulk.ep & 0x80) == 0) {
++ err = -EFAULT;
++ if (copy_from_user(kptr, uptr, kbulk.len))
++ goto out;
++ }
++
++ kbulk.data = kptr;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd, USBDEVFS_BULK, (unsigned long) &kbulk);
++ set_fs(old_fs);
++
++ if (err >= 0 &&
++ ((kbulk.ep & 0x80) != 0)) {
++ if (copy_to_user(uptr, kptr, kbulk.len))
++ err = -EFAULT;
++ }
++
++out:
++ free_page((unsigned long) kptr);
++ return err;
++}
++
++/* This needs more work before we can enable it. Unfortunately
++ * because of the fancy asynchronous way URB status/error is written
++ * back to userspace, we'll need to fiddle with USB devio internals
++ * and/or reimplement entirely the frontend of it ourselves. -DaveM
++ *
++ * The issue is:
++ *
++ * When an URB is submitted via usbdevicefs it is put onto an
++ * asynchronous queue. When the URB completes, it may be reaped
++ * via another ioctl. During this reaping the status is written
++ * back to userspace along with the length of the transfer.
++ *
++ * We must translate into 64-bit kernel types so we pass in a kernel
++ * space copy of the usbdevfs_urb structure. This would mean that we
++ * must do something to deal with the async entry reaping. First we
++ * have to deal somehow with this transitory memory we've allocated.
++ * This is problematic since there are many call sites from which the
++ * async entries can be destroyed (and thus when we'd need to free up
++ * this kernel memory). One of which is the close() op of usbdevicefs.
++ * To handle that we'd need to make our own file_operations struct which
++ * overrides usbdevicefs's release op with our own which runs usbdevicefs's
++ * real release op then frees up the kernel memory.
++ *
++ * But how to keep track of these kernel buffers? We'd need to either
++ * keep track of them in some table _or_ know about usbdevicefs internals
++ * (ie. the exact layout of its file private, which is actually defined
++ * in linux/usbdevice_fs.h, the layout of the async queues are private to
++ * devio.c)
++ *
++ * There is one possible other solution I considered, also involving knowledge
++ * of usbdevicefs internals:
++ *
++ * After an URB is submitted, we "fix up" the address back to the user
++ * space one. This would work if the status/length fields written back
++ * by the async URB completion lines up perfectly in the 32-bit type with
++ * the 64-bit kernel type. Unfortunately, it does not because the iso
++ * frame descriptors, at the end of the struct, can be written back.
++ *
++ * I think we'll just need to simply duplicate the devio URB engine here.
++ */
++#if 0
++struct usbdevfs_urb32 {
++ unsigned char type;
++ unsigned char endpoint;
++ compat_int_t status;
++ compat_uint_t flags;
++ compat_caddr_t buffer;
++ compat_int_t buffer_length;
++ compat_int_t actual_length;
++ compat_int_t start_frame;
++ compat_int_t number_of_packets;
++ compat_int_t error_count;
++ compat_uint_t signr;
++ compat_caddr_t usercontext; /* unused */
++ struct usbdevfs_iso_packet_desc iso_frame_desc[0];
++};
++
++#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
++
++static int get_urb32(struct usbdevfs_urb *kurb,
++ struct usbdevfs_urb32 *uurb)
++{
++ if (get_user(kurb->type, &uurb->type) ||
++ __get_user(kurb->endpoint, &uurb->endpoint) ||
++ __get_user(kurb->status, &uurb->status) ||
++ __get_user(kurb->flags, &uurb->flags) ||
++ __get_user(kurb->buffer_length, &uurb->buffer_length) ||
++ __get_user(kurb->actual_length, &uurb->actual_length) ||
++ __get_user(kurb->start_frame, &uurb->start_frame) ||
++ __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
++ __get_user(kurb->error_count, &uurb->error_count) ||
++ __get_user(kurb->signr, &uurb->signr))
++ return -EFAULT;
++
++ kurb->usercontext = 0; /* unused currently */
++
++ return 0;
++}
++
++/* Just put back the values which usbdevfs actually changes. */
++static int put_urb32(struct usbdevfs_urb *kurb,
++ struct usbdevfs_urb32 *uurb)
++{
++ if (put_user(kurb->status, &uurb->status) ||
++ __put_user(kurb->actual_length, &uurb->actual_length) ||
++ __put_user(kurb->error_count, &uurb->error_count))
++ return -EFAULT;
++
++ if (kurb->number_of_packets != 0) {
++ int i;
++
++ for (i = 0; i < kurb->number_of_packets; i++) {
++ if (__put_user(kurb->iso_frame_desc[i].actual_length,
++ &uurb->iso_frame_desc[i].actual_length) ||
++ __put_user(kurb->iso_frame_desc[i].status,
++ &uurb->iso_frame_desc[i].status))
++ return -EFAULT;
++ }
++ }
++
++ return 0;
++}
++
++static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
++ struct usbdevfs_urb32 *uurb)
++{
++ unsigned int totlen;
++ int i;
++
++ if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
++ kurb->number_of_packets = 0;
++ return 0;
++ }
++
++ if (kurb->number_of_packets < 1 ||
++ kurb->number_of_packets > 128)
++ return -EINVAL;
++
++ if (copy_from_user(&kurb->iso_frame_desc[0],
++ &uurb->iso_frame_desc[0],
++ sizeof(struct usbdevfs_iso_packet_desc) *
++ kurb->number_of_packets))
++ return -EFAULT;
++
++ totlen = 0;
++ for (i = 0; i < kurb->number_of_packets; i++) {
++ unsigned int this_len;
++
++ this_len = kurb->iso_frame_desc[i].length;
++ if (this_len > 1023)
++ return -EINVAL;
++
++ totlen += this_len;
++ }
++
++ if (totlen > 32768)
++ return -EINVAL;
++
++ kurb->buffer_length = totlen;
++
++ return 0;
++}
++
++static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ struct usbdevfs_urb *kurb;
++ struct usbdevfs_urb32 *uurb;
++ mm_segment_t old_fs;
++ __u32 udata;
++ void *uptr, *kptr;
++ unsigned int buflen;
++ int err;
++
++ uurb = (struct usbdevfs_urb32 *) arg;
++
++ err = -ENOMEM;
++ kurb = kmalloc(sizeof(struct usbdevfs_urb) +
++ (sizeof(struct usbdevfs_iso_packet_desc) * 128),
++ GFP_KERNEL);
++ if (!kurb)
++ goto out;
++
++ err = -EFAULT;
++ if (get_urb32(kurb, uurb))
++ goto out;
++
++ err = get_urb32_isoframes(kurb, uurb);
++ if (err)
++ goto out;
++
++ err = -EFAULT;
++ if (__get_user(udata, &uurb->buffer))
++ goto out;
++ uptr = compat_ptr(udata);
++
++ buflen = kurb->buffer_length;
++ err = verify_area(VERIFY_WRITE, uptr, buflen);
++ if (err)
++ goto out;
++
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
++ set_fs(old_fs);
++
++ if (err >= 0) {
++ /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
++ if (put_urb32(kurb, uurb)) {
++ err = -EFAULT;
++ }
++ }
++
++out:
++ kfree(kurb);
++ return err;
++}
++#endif
++
++#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
++#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
++
++static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ mm_segment_t old_fs;
++ void *kptr;
++ int err;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd,
++ (cmd == USBDEVFS_REAPURB32 ?
++ USBDEVFS_REAPURB :
++ USBDEVFS_REAPURBNDELAY),
++ (unsigned long) &kptr);
++ set_fs(old_fs);
++
++ if (err >= 0 &&
++ put_user((u32)(u64)kptr, (u32 *)arg))
++ err = -EFAULT;
++
++ return err;
++}
++
++struct usbdevfs_disconnectsignal32 {
++ compat_int_t signr;
++ compat_caddr_t context;
++};
++
++#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
++
++static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned long arg)
++{
++ struct usbdevfs_disconnectsignal kdis;
++ struct usbdevfs_disconnectsignal32 *udis;
++ mm_segment_t old_fs;
++ u32 uctx;
++ int err;
++
++ udis = (struct usbdevfs_disconnectsignal32 *) arg;
++
++ if (get_user(kdis.signr, &udis->signr) ||
++ __get_user(uctx, &udis->context))
++ return -EFAULT;
++
++ kdis.context = (void *) (long)uctx;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = sys_ioctl(fd, USBDEVFS_DISCSIGNAL, (unsigned long) &kdis);
++ set_fs(old_fs);
++
++ return err;
++}
+ #undef CODE
+ #endif
+
+@@ -2451,6 +3010,22 @@ HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_io
+ HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget)
+ HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset)
+ HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64)
+-
++/* vfat */
++HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
++HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
++HANDLE_IOCTL(REISERFS_IOC_UNPACK32, reiserfs_ioctl32)
++/* Raw devices */
++HANDLE_IOCTL(RAW_SETBIND, raw_ioctl)
++HANDLE_IOCTL(RAW_GETBIND, raw_ioctl)
++/* Serial */
++HANDLE_IOCTL(TIOCGSERIAL, serial_struct_ioctl)
++HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
++/* Usbdevfs */
++HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
++HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
++/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
++HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
++HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
++HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
+ #undef DECLARES
+ #endif
+--- linux-2.6.0-test6/fs/dcache.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/dcache.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1639,3 +1639,27 @@ void __init vfs_caches_init(unsigned lon
+ bdev_cache_init();
+ chrdev_init();
+ }
++
++EXPORT_SYMBOL(d_alloc);
++EXPORT_SYMBOL(d_alloc_anon);
++EXPORT_SYMBOL(d_alloc_root);
++EXPORT_SYMBOL(d_delete);
++EXPORT_SYMBOL(d_find_alias);
++EXPORT_SYMBOL(d_instantiate);
++EXPORT_SYMBOL(d_invalidate);
++EXPORT_SYMBOL(d_lookup);
++EXPORT_SYMBOL(d_move);
++EXPORT_SYMBOL(d_path);
++EXPORT_SYMBOL(d_prune_aliases);
++EXPORT_SYMBOL(d_rehash);
++EXPORT_SYMBOL(d_splice_alias);
++EXPORT_SYMBOL(d_validate);
++EXPORT_SYMBOL(dget_locked);
++EXPORT_SYMBOL(dput);
++EXPORT_SYMBOL(find_inode_number);
++EXPORT_SYMBOL(have_submounts);
++EXPORT_SYMBOL(is_subdir);
++EXPORT_SYMBOL(names_cachep);
++EXPORT_SYMBOL(shrink_dcache_anon);
++EXPORT_SYMBOL(shrink_dcache_parent);
++EXPORT_SYMBOL(shrink_dcache_sb);
+--- linux-2.6.0-test6/fs/devfs/base.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/devfs/base.c 2003-10-05 00:36:10.000000000 -0700
+@@ -973,8 +973,9 @@ static struct devfs_entry *_devfs_search
+
+ /**
+ * _devfs_alloc_entry - Allocate a devfs entry.
+- * @name: The name of the entry.
+- * @namelen: The number of characters in @name.
++ * @name: the name of the entry
++ * @namelen: the number of characters in @name
++ * @mode: the mode for the entry
+ *
+ * Allocate a devfs entry and returns a pointer to the entry on success, else
+ * %NULL.
+@@ -1954,15 +1955,9 @@ static int devfs_notify_change (struct d
+ return 0;
+ } /* End Function devfs_notify_change */
+
+-static void devfs_clear_inode (struct inode *inode)
+-{
+- if ( S_ISBLK (inode->i_mode) ) bdput (inode->i_bdev);
+-} /* End Function devfs_clear_inode */
+-
+ static struct super_operations devfs_sops =
+ {
+ .drop_inode = generic_delete_inode,
+- .clear_inode = devfs_clear_inode,
+ .statfs = simple_statfs,
+ };
+
+@@ -2014,11 +2009,7 @@ static struct inode *_devfs_get_vfs_inod
+ inode->i_rdev = de->u.cdev.dev;
+ }
+ else if ( S_ISBLK (de->mode) )
+- {
+- inode->i_rdev = de->u.bdev.dev;
+- if (bd_acquire (inode) != 0)
+- PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino);
+- }
++ init_special_inode(inode, de->mode, de->u.bdev.dev);
+ else if ( S_ISFIFO (de->mode) )
+ inode->i_fop = &def_fifo_fops;
+ else if ( S_ISDIR (de->mode) )
+@@ -2117,11 +2108,7 @@ static int devfs_open (struct inode *ino
+ if (de == NULL) return -ENODEV;
+ if ( S_ISDIR (de->mode) ) return 0;
+ file->private_data = de->info;
+- if ( S_ISBLK (inode->i_mode) )
+- {
+- file->f_op = &def_blk_fops;
+- err = def_blk_fops.open (inode, file); /* Module refcount unchanged */
+- } else if (S_ISCHR(inode->i_mode)) {
++ if (S_ISCHR(inode->i_mode)) {
+ ops = devfs_get_ops (de); /* Now have module refcount */
+ file->f_op = ops;
+ if (file->f_op)
+--- linux-2.6.0-test6/fs/direct-io.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/direct-io.c 2003-10-05 00:36:53.000000000 -0700
+@@ -51,6 +51,10 @@
+ *
+ * If blkfactor is zero then the user's request was aligned to the filesystem's
+ * blocksize.
++ *
++ * needs_locking is set for regular files on direct-IO-naive filesystems. It
++ * determines whether we need to do the fancy locking which prevents direct-IO
++ * from being able to read uninitialised disk blocks.
+ */
+
+ struct dio {
+@@ -58,6 +62,7 @@ struct dio {
+ struct bio *bio; /* bio under assembly */
+ struct inode *inode;
+ int rw;
++ int needs_locking; /* doesn't change */
+ unsigned blkbits; /* doesn't change */
+ unsigned blkfactor; /* When we're using an alignment which
+ is finer than the filesystem's soft
+@@ -205,6 +210,8 @@ static void dio_complete(struct dio *dio
+ {
+ if (dio->end_io)
+ dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
++ if (dio->needs_locking)
++ up_read(&dio->inode->i_alloc_sem);
+ }
+
+ /*
+@@ -448,6 +455,7 @@ static int get_more_blocks(struct dio *d
+ unsigned long fs_count; /* Number of filesystem-sized blocks */
+ unsigned long dio_count;/* Number of dio_block-sized blocks */
+ unsigned long blkmask;
++ int beyond_eof = 0;
+
+ /*
+ * If there was a memory error and we've overwritten all the
+@@ -465,8 +473,19 @@ static int get_more_blocks(struct dio *d
+ if (dio_count & blkmask)
+ fs_count++;
+
++ if (dio->needs_locking) {
++ if (dio->block_in_file >= (i_size_read(dio->inode) >>
++ dio->blkbits))
++ beyond_eof = 1;
++ }
++ /*
++ * For writes inside i_size we forbid block creations: only
++ * overwrites are permitted. We fall back to buffered writes
++ * at a higher level for inside-i_size block-instantiating
++ * writes.
++ */
+ ret = (*dio->get_blocks)(dio->inode, fs_startblk, fs_count,
+- map_bh, dio->rw == WRITE);
++ map_bh, (dio->rw == WRITE) && beyond_eof);
+ }
+ return ret;
+ }
+@@ -773,6 +792,10 @@ do_holes:
+ if (!buffer_mapped(map_bh)) {
+ char *kaddr;
+
++ /* AKPM: eargh, -ENOTBLK is a hack */
++ if (dio->rw == WRITE)
++ return -ENOTBLK;
++
+ if (dio->block_in_file >=
+ i_size_read(dio->inode)>>blkbits) {
+ /* We hit eof */
+@@ -838,21 +861,21 @@ out:
+ return ret;
+ }
+
++/*
++ * Releases both i_sem and i_alloc_sem
++ */
+ static int
+ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
+ const struct iovec *iov, loff_t offset, unsigned long nr_segs,
+- unsigned blkbits, get_blocks_t get_blocks, dio_iodone_t end_io)
++ unsigned blkbits, get_blocks_t get_blocks, dio_iodone_t end_io,
++ struct dio *dio)
+ {
+ unsigned long user_addr;
+ int seg;
+ int ret = 0;
+ int ret2;
+- struct dio *dio;
+ size_t bytes;
+
+- dio = kmalloc(sizeof(*dio), GFP_KERNEL);
+- if (!dio)
+- return -ENOMEM;
+ dio->is_async = !is_sync_kiocb(iocb);
+
+ dio->bio = NULL;
+@@ -863,7 +886,6 @@ direct_io_worker(int rw, struct kiocb *i
+ dio->start_zero_done = 0;
+ dio->block_in_file = offset >> blkbits;
+ dio->blocks_available = 0;
+-
+ dio->cur_page = NULL;
+
+ dio->boundary = 0;
+@@ -946,6 +968,13 @@ direct_io_worker(int rw, struct kiocb *i
+ dio_bio_submit(dio);
+
+ /*
++ * All new block allocations have been performed. We can let i_sem
++ * go now.
++ */
++ if (dio->needs_locking)
++ up(&dio->inode->i_sem);
++
++ /*
+ * OK, all BIOs are submitted, so we can decrement bio_count to truly
+ * reflect the number of to-be-processed BIOs.
+ */
+@@ -980,11 +1009,17 @@ direct_io_worker(int rw, struct kiocb *i
+
+ /*
+ * This is a library function for use by filesystem drivers.
++ *
++ * For writes to S_ISREG files, we are called under i_sem and return with i_sem
++ * held, even though it is internally dropped.
++ *
++ * For writes to S_ISBLK files, i_sem is not held on entry; it is never taken.
+ */
+ int
+-blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
++__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+ struct block_device *bdev, const struct iovec *iov, loff_t offset,
+- unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io)
++ unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
++ int needs_special_locking)
+ {
+ int seg;
+ size_t size;
+@@ -993,6 +1028,8 @@ blockdev_direct_IO(int rw, struct kiocb
+ unsigned bdev_blkbits = 0;
+ unsigned blocksize_mask = (1 << blkbits) - 1;
+ ssize_t retval = -EINVAL;
++ struct dio *dio;
++ int needs_locking;
+
+ if (bdev)
+ bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
+@@ -1018,8 +1055,37 @@ blockdev_direct_IO(int rw, struct kiocb
+ }
+ }
+
+- retval = direct_io_worker(rw, iocb, inode, iov, offset,
+- nr_segs, blkbits, get_blocks, end_io);
++ dio = kmalloc(sizeof(*dio), GFP_KERNEL);
++ retval = -ENOMEM;
++ if (!dio)
++ goto out;
++
++ /*
++ * For regular files,
++ * readers need to grab i_sem and i_alloc_sem
++ * writers need to grab i_alloc_sem only (i_sem is already held)
++ */
++ needs_locking = 0;
++ if (S_ISREG(inode->i_mode) && needs_special_locking) {
++ needs_locking = 1;
++ if (rw == READ) {
++ down(&inode->i_sem);
++ retval = filemap_write_and_wait(inode->i_mapping);
++ if (retval) {
++ up(&inode->i_sem);
++ kfree(dio);
++ goto out;
++ }
++ }
++ down_read(&inode->i_alloc_sem);
++ }
++ dio->needs_locking = needs_locking;
++
++ retval = direct_io_worker(rw, iocb, inode, iov, offset,
++ nr_segs, blkbits, get_blocks, end_io, dio);
++ if (needs_locking && rw == WRITE)
++ down(&inode->i_sem);
+ out:
+ return retval;
+ }
++EXPORT_SYMBOL(__blockdev_direct_IO);
+--- linux-2.6.0-test6/fs/dquot.c 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/dquot.c 2003-10-05 00:36:15.000000000 -0700
+@@ -668,12 +668,12 @@ static void print_warning(struct dquot *
+
+ if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags)))
+ return;
+- tty_write_message(current->tty, dquot->dq_sb->s_id);
++ tty_write_message(process_tty(current), dquot->dq_sb->s_id);
+ if (warntype == ISOFTWARN || warntype == BSOFTWARN)
+- tty_write_message(current->tty, ": warning, ");
++ tty_write_message(process_tty(current), ": warning, ");
+ else
+- tty_write_message(current->tty, ": write failed, ");
+- tty_write_message(current->tty, quotatypes[dquot->dq_type]);
++ tty_write_message(process_tty(current), ": write failed, ");
++ tty_write_message(process_tty(current), quotatypes[dquot->dq_type]);
+ switch (warntype) {
+ case IHARDWARN:
+ msg = " file limit reached.\n";
+@@ -694,7 +694,7 @@ static void print_warning(struct dquot *
+ msg = " block quota exceeded.\n";
+ break;
+ }
+- tty_write_message(current->tty, msg);
++ tty_write_message(process_tty(current), msg);
+ }
+
+ static inline void flush_warnings(struct dquot **dquots, char *warntype)
+--- linux-2.6.0-test6/fs/efs/super.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/fs/efs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -218,7 +218,11 @@ int efs_fill_super(struct super_block *s
+ memset(sb, 0, sizeof(struct efs_sb_info));
+
+ s->s_magic = EFS_SUPER_MAGIC;
+- sb_set_blocksize(s, EFS_BLOCKSIZE);
++ if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
++ printk(KERN_ERR "EFS: device does not support %d byte blocks\n",
++ EFS_BLOCKSIZE);
++ goto out_no_fs_ul;
++ }
+
+ /* read the vh (volume header) block */
+ bh = sb_bread(s, 0);
+--- linux-2.6.0-test6/fs/eventpoll.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/eventpoll.c 2003-10-05 00:34:03.000000000 -0700
+@@ -740,6 +740,7 @@ static int ep_getfd(int *efd, struct ino
+ d_add(dentry, inode);
+ file->f_vfsmnt = mntget(eventpoll_mnt);
+ file->f_dentry = dget(dentry);
++ file->f_mapping = inode->i_mapping;
+
+ file->f_pos = 0;
+ file->f_flags = O_RDONLY;
+--- linux-2.6.0-test6/fs/exec.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/exec.c 2003-10-05 00:36:15.000000000 -0700
+@@ -83,6 +83,8 @@ int register_binfmt(struct linux_binfmt
+ return 0;
+ }
+
++EXPORT_SYMBOL(register_binfmt);
++
+ int unregister_binfmt(struct linux_binfmt * fmt)
+ {
+ struct linux_binfmt ** tmp = &formats;
+@@ -100,6 +102,8 @@ int unregister_binfmt(struct linux_binfm
+ return -EINVAL;
+ }
+
++EXPORT_SYMBOL(unregister_binfmt);
++
+ static inline void put_binfmt(struct linux_binfmt * fmt)
+ {
+ module_put(fmt->module);
+@@ -281,6 +285,8 @@ int copy_strings_kernel(int argc,char **
+ return r;
+ }
+
++EXPORT_SYMBOL(copy_strings_kernel);
++
+ #ifdef CONFIG_MMU
+ /*
+ * This routine is used to map in a page into an address space: needed by
+@@ -443,6 +449,8 @@ int setup_arg_pages(struct linux_binprm
+ return 0;
+ }
+
++EXPORT_SYMBOL(setup_arg_pages);
++
+ #define free_arg_pages(bprm) do { } while (0)
+
+ #else
+@@ -493,6 +501,8 @@ out:
+ goto out;
+ }
+
++EXPORT_SYMBOL(open_exec);
++
+ int kernel_read(struct file *file, unsigned long offset,
+ char *addr, unsigned long count)
+ {
+@@ -508,6 +518,8 @@ int kernel_read(struct file *file, unsig
+ return result;
+ }
+
++EXPORT_SYMBOL(kernel_read);
++
+ static int exec_mmap(struct mm_struct *mm)
+ {
+ struct task_struct *tsk;
+@@ -584,6 +596,11 @@ static inline int de_thread(struct task_
+ newsig->group_stop_count = 0;
+ newsig->curr_target = NULL;
+ init_sigpending(&newsig->shared_pending);
++
++ newsig->pgrp = oldsig->pgrp;
++ newsig->session = oldsig->session;
++ newsig->leader = oldsig->leader;
++ newsig->tty_old_pgrp = oldsig->tty_old_pgrp;
+ }
+
+ if (thread_group_empty(current))
+@@ -822,6 +839,8 @@ out:
+ return retval;
+ }
+
++EXPORT_SYMBOL(flush_old_exec);
++
+ /*
+ * We mustn't allow tracing of suid binaries, unless
+ * the tracer has the capability to trace anything..
+@@ -878,6 +897,8 @@ int prepare_binprm(struct linux_binprm *
+ return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
+ }
+
++EXPORT_SYMBOL(prepare_binprm);
++
+ /*
+ * This function is used to produce the new IDs and capabilities
+ * from the old ones and the file's capabilities.
+@@ -918,6 +939,8 @@ void compute_creds(struct linux_binprm *
+ security_bprm_compute_creds(bprm);
+ }
+
++EXPORT_SYMBOL(compute_creds);
++
+ void remove_arg_zero(struct linux_binprm *bprm)
+ {
+ if (bprm->argc) {
+@@ -942,6 +965,8 @@ inside:
+ }
+ }
+
++EXPORT_SYMBOL(remove_arg_zero);
++
+ /*
+ * cycle the list of binary formats handler, until one recognizes the image
+ */
+@@ -1037,6 +1062,8 @@ int search_binary_handler(struct linux_b
+ return retval;
+ }
+
++EXPORT_SYMBOL(search_binary_handler);
++
+ /*
+ * sys_execve() executes a new program.
+ */
+@@ -1133,6 +1160,8 @@ out_file:
+ return retval;
+ }
+
++EXPORT_SYMBOL(do_execve);
++
+ int set_binfmt(struct linux_binfmt *new)
+ {
+ struct linux_binfmt *old = current->binfmt;
+@@ -1147,6 +1176,8 @@ int set_binfmt(struct linux_binfmt *new)
+ return 0;
+ }
+
++EXPORT_SYMBOL(set_binfmt);
++
+ #define CORENAME_MAX_SIZE 64
+
+ /* format_corename will inspect the pattern parameter, and output a
+--- linux-2.6.0-test6/fs/ext2/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/ext2/inode.c 2003-10-05 00:36:59.000000000 -0700
+@@ -257,11 +257,12 @@ static int ext2_block_to_path(struct ino
+ * or when it reads all @depth-1 indirect blocks successfully and finds
+ * the whole chain, all way to the data (returns %NULL, *err == 0).
+ */
+-static Indirect *ext2_get_branch(struct inode *inode,
++static Indirect *ext2_get_branch_wq(struct inode *inode,
+ int depth,
+ int *offsets,
+ Indirect chain[4],
+- int *err)
++ int *err,
++ wait_queue_t *wait)
+ {
+ struct super_block *sb = inode->i_sb;
+ Indirect *p = chain;
+@@ -273,8 +274,8 @@ static Indirect *ext2_get_branch(struct
+ if (!p->key)
+ goto no_block;
+ while (--depth) {
+- bh = sb_bread(sb, le32_to_cpu(p->key));
+- if (!bh)
++ bh = sb_bread_wq(sb, le32_to_cpu(p->key), wait);
++ if (!bh || IS_ERR(bh))
+ goto failure;
+ read_lock(&EXT2_I(inode)->i_meta_lock);
+ if (!verify_chain(chain, p))
+@@ -292,11 +293,21 @@ changed:
+ *err = -EAGAIN;
+ goto no_block;
+ failure:
+- *err = -EIO;
++ *err = IS_ERR(bh) ? PTR_ERR(bh) : -EIO;
+ no_block:
+ return p;
+ }
+
++static Indirect *ext2_get_branch(struct inode *inode,
++ int depth,
++ int *offsets,
++ Indirect chain[4],
++ int *err)
++{
++ return ext2_get_branch_wq(inode, depth, offsets, chain,
++ err, NULL);
++}
++
+ /**
+ * ext2_find_near - find a place for allocation with sufficient locality
+ * @inode: owner
+@@ -536,7 +547,8 @@ changed:
+ * reachable from inode.
+ */
+
+-static int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
++static int ext2_get_block_wq(struct inode *inode, sector_t iblock,
++ struct buffer_head *bh_result, int create, wait_queue_t *wait)
+ {
+ int err = -EIO;
+ int offsets[4];
+@@ -551,7 +563,8 @@ static int ext2_get_block(struct inode *
+ goto out;
+
+ reread:
+- partial = ext2_get_branch(inode, depth, offsets, chain, &err);
++ partial = ext2_get_branch_wq(inode, depth, offsets, chain, &err,
++ wait);
+
+ /* Simplest case - block found, no allocation needed */
+ if (!partial) {
+@@ -565,7 +578,7 @@ got_it:
+ }
+
+ /* Next simple case - plain lookup or failed read of indirect block */
+- if (!create || err == -EIO) {
++ if (!create || err == -EIO || err == -EIOCBRETRY) {
+ cleanup:
+ while (partial > chain) {
+ brelse(partial->bh);
+@@ -606,6 +619,19 @@ changed:
+ goto reread;
+ }
+
++static int ext2_get_block_async(struct inode *inode, sector_t iblock,
++ struct buffer_head *bh_result, int create)
++{
++ return ext2_get_block_wq(inode, iblock, bh_result, create,
++ current->io_wait);
++}
++
++static int ext2_get_block(struct inode *inode, sector_t iblock,
++ struct buffer_head *bh_result, int create)
++{
++ return ext2_get_block_wq(inode, iblock, bh_result, create, NULL);
++}
++
+ static int ext2_writepage(struct page *page, struct writeback_control *wbc)
+ {
+ return block_write_full_page(page, ext2_get_block, wbc);
+@@ -627,7 +653,7 @@ static int
+ ext2_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+ {
+- return block_prepare_write(page,from,to,ext2_get_block);
++ return block_prepare_write(page,from,to,ext2_get_block_async);
+ }
+
+ static int
+@@ -659,7 +685,7 @@ ext2_direct_IO(int rw, struct kiocb *ioc
+ loff_t offset, unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ offset, nr_segs, ext2_get_blocks, NULL);
+@@ -1228,6 +1254,7 @@ static int ext2_update_inode(struct inod
+ raw_inode->i_block[0] = 0;
+ raw_inode->i_block[1] =
+ cpu_to_le32(new_encode_dev(inode->i_rdev));
++ raw_inode->i_block[2] = 0;
+ }
+ } else for (n = 0; n < EXT2_N_BLOCKS; n++)
+ raw_inode->i_block[n] = ei->i_data[n];
+--- linux-2.6.0-test6/fs/ext2/super.c 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/ext2/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -22,6 +22,7 @@
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/blkdev.h>
++#include <linux/parser.h>
+ #include <linux/random.h>
+ #include <linux/buffer_head.h>
+ #include <linux/smp_lock.h>
+@@ -265,149 +266,157 @@ static unsigned long get_sb_block(void *
+ return sb_block;
+ }
+
+-static int want_value(char *value, char *option)
+-{
+- if (!value || !*value) {
+- printk(KERN_NOTICE "EXT2-fs: the %s option needs an argument\n",
+- option);
+- return -1;
+- }
+- return 0;
+-}
+-
+-static int want_null_value(char *value, char *option)
+-{
+- if (*value) {
+- printk(KERN_NOTICE "EXT2-fs: Invalid %s argument: %s\n",
+- option, value);
+- return -1;
+- }
+- return 0;
+-}
++enum {
++ Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
++ Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
++ Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
++ Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
++ Opt_ignore, Opt_err,
++};
+
+-static int want_numeric(char *value, char *option, unsigned long *number)
+-{
+- if (want_value(value, option))
+- return -1;
+- *number = simple_strtoul(value, &value, 0);
+- if (want_null_value(value, option))
+- return -1;
+- return 0;
+-}
++static match_table_t tokens = {
++ {Opt_bsd_df, "bsddf"},
++ {Opt_minix_df, "minixdf"},
++ {Opt_grpid, "grpid"},
++ {Opt_grpid, "bsdgroups"},
++ {Opt_nogrpid, "nogrpid"},
++ {Opt_nogrpid, "sysvgroups"},
++ {Opt_resgid, "resgid=%d"},
++ {Opt_resuid, "resuid=%d"},
++ {Opt_sb, "sb=%d"},
++ {Opt_err_cont, "errors=continue"},
++ {Opt_err_panic, "errors=panic"},
++ {Opt_err_ro, "errors=remount-ro"},
++ {Opt_nouid32, "nouid32"},
++ {Opt_nocheck, "check=none"},
++ {Opt_nocheck, "nocheck"},
++ {Opt_check, "check"},
++ {Opt_debug, "debug"},
++ {Opt_oldalloc, "oldalloc"},
++ {Opt_orlov, "orlov"},
++ {Opt_nobh, "nobh"},
++ {Opt_user_xattr, "user_xattr"},
++ {Opt_nouser_xattr, "nouser_xattr"},
++ {Opt_acl, "acl"},
++ {Opt_noacl, "noacl"},
++ {Opt_ignore, "grpquota"},
++ {Opt_ignore, "noquota"},
++ {Opt_ignore, "quota"},
++ {Opt_ignore, "usrquota"},
++ {Opt_err, NULL}
++};
+
+-/*
+- * This function has been shamelessly adapted from the msdos fs
+- */
+ static int parse_options (char * options,
+ struct ext2_sb_info *sbi)
+ {
+- char * this_char;
+- char * value;
++ char * p;
++ substring_t args[MAX_OPT_ARGS];
++ unsigned long kind = EXT2_MOUNT_ERRORS_CONT;
++ int option;
+
+ if (!options)
+ return 1;
+- while ((this_char = strsep (&options, ",")) != NULL) {
+- if (!*this_char)
++
++ while ((p = strsep (&options, ",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr (this_char, '=')) != NULL)
+- *value++ = 0;
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_bsd_df:
++ clear_opt (sbi->s_mount_opt, MINIX_DF);
++ break;
++ case Opt_minix_df:
++ set_opt (sbi->s_mount_opt, MINIX_DF);
++ break;
++ case Opt_grpid:
++ set_opt (sbi->s_mount_opt, GRPID);
++ break;
++ case Opt_nogrpid:
++ clear_opt (sbi->s_mount_opt, GRPID);
++ break;
++ case Opt_resuid:
++ if (match_int(&args[0], &option))
++ return 0;
++ sbi->s_resuid = option;
++ break;
++ case Opt_resgid:
++ if (match_int(&args[0], &option))
++ return 0;
++ sbi->s_resgid = option;
++ break;
++ case Opt_sb:
++ /* handled by get_sb_block() instead of here */
++ /* *sb_block = match_int(&args[0]); */
++ break;
++ case Opt_err_panic:
++ kind = EXT2_MOUNT_ERRORS_PANIC;
++ break;
++ case Opt_err_ro:
++ kind = EXT2_MOUNT_ERRORS_RO;
++ break;
++ case Opt_err_cont:
++ kind = EXT2_MOUNT_ERRORS_CONT;
++ break;
++ case Opt_nouid32:
++ set_opt (sbi->s_mount_opt, NO_UID32);
++ break;
++ case Opt_check:
++#ifdef CONFIG_EXT2_CHECK
++ set_opt (sbi->s_mount_opt, CHECK);
++#else
++ printk("EXT2 Check option not supported\n");
++#endif
++ break;
++ case Opt_nocheck:
++ clear_opt (sbi->s_mount_opt, CHECK);
++ break;
++ case Opt_debug:
++ set_opt (sbi->s_mount_opt, DEBUG);
++ break;
++ case Opt_oldalloc:
++ set_opt (sbi->s_mount_opt, OLDALLOC);
++ break;
++ case Opt_orlov:
++ clear_opt (sbi->s_mount_opt, OLDALLOC);
++ break;
++ case Opt_nobh:
++ set_opt (sbi->s_mount_opt, NOBH);
++ break;
+ #ifdef CONFIG_EXT2_FS_XATTR
+- if (!strcmp (this_char, "user_xattr"))
++ case Opt_user_xattr:
+ set_opt (sbi->s_mount_opt, XATTR_USER);
+- else if (!strcmp (this_char, "nouser_xattr"))
++ break;
++ case Opt_nouser_xattr:
+ clear_opt (sbi->s_mount_opt, XATTR_USER);
+- else
++ break;
++#else
++ case Opt_user_xattr:
++ case Opt_nouser_xattr:
++ printk("EXT2 (no)user_xattr options not supported\n");
++ break;
+ #endif
+ #ifdef CONFIG_EXT2_FS_POSIX_ACL
+- if (!strcmp(this_char, "acl"))
++ case Opt_acl:
+ set_opt(sbi->s_mount_opt, POSIX_ACL);
+- else if (!strcmp(this_char, "noacl"))
++ break;
++ case Opt_noacl:
+ clear_opt(sbi->s_mount_opt, POSIX_ACL);
+- else
+-#endif
+- if (!strcmp (this_char, "bsddf"))
+- clear_opt (sbi->s_mount_opt, MINIX_DF);
+- else if (!strcmp (this_char, "nouid32")) {
+- set_opt (sbi->s_mount_opt, NO_UID32);
+- }
+- else if (!strcmp (this_char, "check")) {
+- if (!value || !*value || !strcmp (value, "none"))
+- clear_opt (sbi->s_mount_opt, CHECK);
+- else
+-#ifdef CONFIG_EXT2_CHECK
+- set_opt (sbi->s_mount_opt, CHECK);
++ break;
+ #else
+- printk("EXT2 Check option not supported\n");
++ case Opt_acl:
++ case Opt_noacl:
++ printk("EXT2 (no)acl options not supported\n");
++ break;
+ #endif
+- }
+- else if (!strcmp (this_char, "debug"))
+- set_opt (sbi->s_mount_opt, DEBUG);
+- else if (!strcmp (this_char, "errors")) {
+- if (!value || !*value) {
+- printk ("EXT2-fs: the errors option requires "
+- "an argument\n");
+- return 0;
+- }
+- if (!strcmp (value, "continue")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_RO);
+- clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- set_opt (sbi->s_mount_opt, ERRORS_CONT);
+- }
+- else if (!strcmp (value, "remount-ro")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+- clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- set_opt (sbi->s_mount_opt, ERRORS_RO);
+- }
+- else if (!strcmp (value, "panic")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+- clear_opt (sbi->s_mount_opt, ERRORS_RO);
+- set_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- }
+- else {
+- printk ("EXT2-fs: Invalid errors option: %s\n",
+- value);
+- return 0;
+- }
+- }
+- else if (!strcmp (this_char, "grpid") ||
+- !strcmp (this_char, "bsdgroups"))
+- set_opt (sbi->s_mount_opt, GRPID);
+- else if (!strcmp (this_char, "minixdf"))
+- set_opt (sbi->s_mount_opt, MINIX_DF);
+- else if (!strcmp (this_char, "nocheck"))
+- clear_opt (sbi->s_mount_opt, CHECK);
+- else if (!strcmp (this_char, "nogrpid") ||
+- !strcmp (this_char, "sysvgroups"))
+- clear_opt (sbi->s_mount_opt, GRPID);
+- else if (!strcmp (this_char, "resgid")) {
+- unsigned long v;
+- if (want_numeric(value, "resgid", &v))
+- return 0;
+- sbi->s_resgid = v;
+- }
+- else if (!strcmp (this_char, "resuid")) {
+- unsigned long v;
+- if (want_numeric(value, "resuid", &v))
+- return 0;
+- sbi->s_resuid = v;
+- }
+- else if (!strcmp (this_char, "oldalloc"))
+- set_opt (sbi->s_mount_opt, OLDALLOC);
+- else if (!strcmp (this_char, "orlov"))
+- clear_opt (sbi->s_mount_opt, OLDALLOC);
+- else if (!strcmp (this_char, "nobh"))
+- set_opt(sbi->s_mount_opt, NOBH);
+- /* Silently ignore the quota options */
+- else if (!strcmp (this_char, "grpquota")
+- || !strcmp (this_char, "noquota")
+- || !strcmp (this_char, "quota")
+- || !strcmp (this_char, "usrquota"))
+- /* Don't do anything ;-) */ ;
+- else {
+- printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
++ case Opt_ignore:
++ break;
++ default:
+ return 0;
+ }
+ }
++ sbi->s_mount_opt |= kind;
+ return 1;
+ }
+
+--- linux-2.6.0-test6/fs/ext3/file.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/ext3/file.c 2003-10-05 00:33:24.000000000 -0700
+@@ -47,7 +47,7 @@ static int ext3_release_file (struct ino
+ * the caller didn't specify O_LARGEFILE. On 64bit systems we force
+ * on this flag in sys_open.
+ */
+-static int ext3_open_file (struct inode * inode, struct file * filp)
++static int ext3_open_file (struct inode *inode, struct file *filp)
+ {
+ if (!(filp->f_flags & O_LARGEFILE) &&
+ inode->i_size > 0x7FFFFFFFLL)
+@@ -56,7 +56,7 @@ static int ext3_open_file (struct inode
+ }
+
+ static ssize_t
+-ext3_file_write(struct kiocb *iocb, const char *buf, size_t count, loff_t pos)
++ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
+ {
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_dentry->d_inode;
+@@ -117,8 +117,8 @@ struct file_operations ext3_file_operati
+ .llseek = generic_file_llseek,
+ .read = do_sync_read,
+ .write = do_sync_write,
+- .aio_read = generic_file_aio_read,
+- .aio_write = ext3_file_write,
++ .aio_read = generic_file_aio_read,
++ .aio_write = ext3_file_write,
+ .readv = generic_file_readv,
+ .writev = generic_file_writev,
+ .ioctl = ext3_ioctl,
+--- linux-2.6.0-test6/fs/ext3/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/ext3/inode.c 2003-10-05 00:36:12.000000000 -0700
+@@ -812,15 +812,17 @@ out:
+ if (err == -EAGAIN)
+ goto changed;
+
+- if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0)
++ down(&ei->truncate_sem);
++ if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) {
++ up(&ei->truncate_sem);
+ goto changed;
++ }
+
+ left = (chain + depth) - partial;
+
+ /*
+ * Block out ext3_truncate while we alter the tree
+ */
+- down_read(&ei->truncate_sem);
+ err = ext3_alloc_branch(handle, inode, left, goal,
+ offsets+(partial-chain), partial);
+
+@@ -832,7 +834,7 @@ out:
+ if (!err)
+ err = ext3_splice_branch(handle, inode, iblock, chain,
+ partial, left);
+- up_read(&ei->truncate_sem);
++ up(&ei->truncate_sem);
+ if (err == -EAGAIN)
+ goto changed;
+ if (err)
+@@ -1537,7 +1539,7 @@ static int ext3_direct_IO(int rw, struct
+ unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+ struct ext3_inode_info *ei = EXT3_I(inode);
+ handle_t *handle = NULL;
+ int ret;
+@@ -2205,7 +2207,7 @@ void ext3_truncate(struct inode * inode)
+ * From here we block out all ext3_get_block() callers who want to
+ * modify the block allocation tree.
+ */
+- down_write(&ei->truncate_sem);
++ down(&ei->truncate_sem);
+
+ if (n == 1) { /* direct blocks */
+ ext3_free_data(handle, inode, NULL, i_data+offsets[0],
+@@ -2269,7 +2271,7 @@ do_indirects:
+ case EXT3_TIND_BLOCK:
+ ;
+ }
+- up_write(&ei->truncate_sem);
++ up(&ei->truncate_sem);
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ ext3_mark_inode_dirty(handle, inode);
+
+@@ -2679,6 +2681,7 @@ static int ext3_do_update_inode(handle_t
+ raw_inode->i_block[0] = 0;
+ raw_inode->i_block[1] =
+ cpu_to_le32(new_encode_dev(inode->i_rdev));
++ raw_inode->i_block[2] = 0;
+ }
+ } else for (block = 0; block < EXT3_N_BLOCKS; block++)
+ raw_inode->i_block[block] = ei->i_data[block];
+--- linux-2.6.0-test6/fs/ext3/super.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/ext3/super.c 2003-10-05 00:36:12.000000000 -0700
+@@ -27,6 +27,7 @@
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/blkdev.h>
++#include <linux/parser.h>
+ #include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+@@ -459,7 +460,7 @@ static void init_once(void * foo, kmem_c
+ #ifdef CONFIG_EXT3_FS_XATTR
+ init_rwsem(&ei->xattr_sem);
+ #endif
+- init_rwsem(&ei->truncate_sem);
++ init_MUTEX(&ei->truncate_sem);
+ inode_init_once(&ei->vfs_inode);
+ }
+ }
+@@ -526,36 +527,54 @@ static struct export_operations ext3_exp
+ .get_parent = ext3_get_parent,
+ };
+
++enum {
++ Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
++ Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
++ Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
++ Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_noload,
++ Opt_commit, Opt_journal_update, Opt_journal_inum,
++ Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
++ Opt_ignore, Opt_err,
++};
+
+-static int want_value(char *value, char *option)
+-{
+- if (!value || !*value) {
+- printk(KERN_NOTICE "EXT3-fs: the %s option needs an argument\n",
+- option);
+- return -1;
+- }
+- return 0;
+-}
+-
+-static int want_null_value(char *value, char *option)
+-{
+- if (*value) {
+- printk(KERN_NOTICE "EXT3-fs: Invalid %s argument: %s\n",
+- option, value);
+- return -1;
+- }
+- return 0;
+-}
+-
+-static int want_numeric(char *value, char *option, unsigned long *number)
+-{
+- if (want_value(value, option))
+- return -1;
+- *number = simple_strtoul(value, &value, 0);
+- if (want_null_value(value, option))
+- return -1;
+- return 0;
+-}
++static match_table_t tokens = {
++ {Opt_bsd_df, "bsddf"},
++ {Opt_minix_df, "minixdf"},
++ {Opt_grpid, "grpid"},
++ {Opt_grpid, "bsdgroups"},
++ {Opt_nogrpid, "nogrpid"},
++ {Opt_nogrpid, "sysvgroups"},
++ {Opt_resgid, "resgid=%d"},
++ {Opt_resuid, "resuid=%d"},
++ {Opt_sb, "sb=%d"},
++ {Opt_err_cont, "errors=continue"},
++ {Opt_err_panic, "errors=panic"},
++ {Opt_err_ro, "errors=remount-ro"},
++ {Opt_nouid32, "nouid32"},
++ {Opt_nocheck, "nocheck"},
++ {Opt_nocheck, "check=none"},
++ {Opt_check, "check"},
++ {Opt_debug, "debug"},
++ {Opt_oldalloc, "oldalloc"},
++ {Opt_orlov, "orlov"},
++ {Opt_user_xattr, "user_xattr"},
++ {Opt_nouser_xattr, "nouser_xattr"},
++ {Opt_acl, "acl"},
++ {Opt_noacl, "noacl"},
++ {Opt_noload, "noload"},
++ {Opt_commit, "commit=%u"},
++ {Opt_journal_update, "journal=update"},
++ {Opt_journal_inum, "journal=%u"},
++ {Opt_abort, "abort"},
++ {Opt_data_journal, "data=journal"},
++ {Opt_data_ordered, "data=ordered"},
++ {Opt_data_writeback, "data=writeback"},
++ {Opt_ignore, "grpquota"},
++ {Opt_ignore, "noquota"},
++ {Opt_ignore, "quota"},
++ {Opt_ignore, "usrquota"},
++ {Opt_err, NULL}
++};
+
+ static unsigned long get_sb_block(void **data)
+ {
+@@ -577,175 +596,180 @@ static unsigned long get_sb_block(void *
+ return sb_block;
+ }
+
+-/*
+- * This function has been shamelessly adapted from the msdos fs
+- */
+ static int parse_options (char * options, struct ext3_sb_info *sbi,
+ unsigned long * inum, int is_remount)
+ {
+- char * this_char;
+- char * value;
++ char * p;
++ substring_t args[MAX_OPT_ARGS];
++ int data_opt = 0;
++ int option;
+
+ if (!options)
+ return 1;
+- while ((this_char = strsep (&options, ",")) != NULL) {
+- if (!*this_char)
++
++ while ((p = strsep (&options, ",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr (this_char, '=')) != NULL)
+- *value++ = 0;
+-#ifdef CONFIG_EXT3_FS_XATTR
+- if (!strcmp (this_char, "user_xattr"))
+- set_opt (sbi->s_mount_opt, XATTR_USER);
+- else if (!strcmp (this_char, "nouser_xattr"))
+- clear_opt (sbi->s_mount_opt, XATTR_USER);
+- else
+-#endif
+-#ifdef CONFIG_EXT3_FS_POSIX_ACL
+- if (!strcmp(this_char, "acl"))
+- set_opt (sbi->s_mount_opt, POSIX_ACL);
+- else if (!strcmp(this_char, "noacl"))
+- clear_opt (sbi->s_mount_opt, POSIX_ACL);
+- else
+-#endif
+- if (!strcmp (this_char, "bsddf"))
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_bsd_df:
+ clear_opt (sbi->s_mount_opt, MINIX_DF);
+- else if (!strcmp (this_char, "nouid32")) {
++ break;
++ case Opt_minix_df:
++ set_opt (sbi->s_mount_opt, MINIX_DF);
++ break;
++ case Opt_grpid:
++ set_opt (sbi->s_mount_opt, GRPID);
++ break;
++ case Opt_nogrpid:
++ clear_opt (sbi->s_mount_opt, GRPID);
++ break;
++ case Opt_resuid:
++ if (match_int(&args[0], &option))
++ return 0;
++ sbi->s_resuid = option;
++ break;
++ case Opt_resgid:
++ if (match_int(&args[0], &option))
++ return 0;
++ sbi->s_resgid = option;
++ break;
++ case Opt_sb:
++ /* handled by get_sb_block() instead of here */
++ /* *sb_block = match_int(&args[0]); */
++ break;
++ case Opt_err_panic:
++ clear_opt (sbi->s_mount_opt, ERRORS_CONT);
++ clear_opt (sbi->s_mount_opt, ERRORS_RO);
++ set_opt (sbi->s_mount_opt, ERRORS_PANIC);
++ break;
++ case Opt_err_ro:
++ clear_opt (sbi->s_mount_opt, ERRORS_CONT);
++ clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
++ set_opt (sbi->s_mount_opt, ERRORS_RO);
++ break;
++ case Opt_err_cont:
++ clear_opt (sbi->s_mount_opt, ERRORS_RO);
++ clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
++ set_opt (sbi->s_mount_opt, ERRORS_CONT);
++ break;
++ case Opt_nouid32:
+ set_opt (sbi->s_mount_opt, NO_UID32);
+- }
+- else if (!strcmp (this_char, "abort"))
+- set_opt (sbi->s_mount_opt, ABORT);
+- else if (!strcmp (this_char, "check")) {
+- if (!value || !*value || !strcmp (value, "none"))
+- clear_opt (sbi->s_mount_opt, CHECK);
+- else
++ break;
++ case Opt_check:
+ #ifdef CONFIG_EXT3_CHECK
+- set_opt (sbi->s_mount_opt, CHECK);
++ set_opt (sbi->s_mount_opt, CHECK);
+ #else
+- printk(KERN_ERR
+- "EXT3 Check option not supported\n");
++ printk(KERN_ERR
++ "EXT3 Check option not supported\n");
+ #endif
+- }
+- else if (!strcmp (this_char, "debug"))
+- set_opt (sbi->s_mount_opt, DEBUG);
+- else if (!strcmp (this_char, "errors")) {
+- if (want_value(value, "errors"))
+- return 0;
+- if (!strcmp (value, "continue")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_RO);
+- clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- set_opt (sbi->s_mount_opt, ERRORS_CONT);
+- }
+- else if (!strcmp (value, "remount-ro")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+- clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- set_opt (sbi->s_mount_opt, ERRORS_RO);
+- }
+- else if (!strcmp (value, "panic")) {
+- clear_opt (sbi->s_mount_opt, ERRORS_CONT);
+- clear_opt (sbi->s_mount_opt, ERRORS_RO);
+- set_opt (sbi->s_mount_opt, ERRORS_PANIC);
+- }
+- else {
+- printk (KERN_ERR
+- "EXT3-fs: Invalid errors option: %s\n",
+- value);
+- return 0;
+- }
+- }
+- else if (!strcmp (this_char, "grpid") ||
+- !strcmp (this_char, "bsdgroups"))
+- set_opt (sbi->s_mount_opt, GRPID);
+- else if (!strcmp (this_char, "minixdf"))
+- set_opt (sbi->s_mount_opt, MINIX_DF);
+- else if (!strcmp (this_char, "nocheck"))
++ break;
++ case Opt_nocheck:
+ clear_opt (sbi->s_mount_opt, CHECK);
+- else if (!strcmp (this_char, "nogrpid") ||
+- !strcmp (this_char, "sysvgroups"))
+- clear_opt (sbi->s_mount_opt, GRPID);
+- else if (!strcmp (this_char, "resgid")) {
+- unsigned long v;
+- if (want_numeric(value, "resgid", &v))
+- return 0;
+- sbi->s_resgid = v;
+- }
+- else if (!strcmp (this_char, "resuid")) {
+- unsigned long v;
+- if (want_numeric(value, "resuid", &v))
+- return 0;
+- sbi->s_resuid = v;
+- }
+- else if (!strcmp (this_char, "oldalloc"))
++ break;
++ case Opt_debug:
++ set_opt (sbi->s_mount_opt, DEBUG);
++ break;
++ case Opt_oldalloc:
+ set_opt (sbi->s_mount_opt, OLDALLOC);
+- else if (!strcmp (this_char, "orlov"))
++ break;
++ case Opt_orlov:
+ clear_opt (sbi->s_mount_opt, OLDALLOC);
+- /* Silently ignore the quota options */
+- else if (!strcmp (this_char, "grpquota")
+- || !strcmp (this_char, "noquota")
+- || !strcmp (this_char, "quota")
+- || !strcmp (this_char, "usrquota"))
+- /* Don't do anything ;-) */ ;
+- else if (!strcmp (this_char, "journal")) {
++ break;
++#ifdef CONFIG_EXT3_FS_XATTR
++ case Opt_user_xattr:
++ set_opt (sbi->s_mount_opt, XATTR_USER);
++ break;
++ case Opt_nouser_xattr:
++ clear_opt (sbi->s_mount_opt, XATTR_USER);
++ break;
++#else
++ case Opt_user_xattr:
++ case Opt_nouser_xattr:
++ printk("EXT3 (no)user_xattr options not supported\n");
++ break;
++#endif
++#ifdef CONFIG_EXT3_FS_POSIX_ACL
++ case Opt_acl:
++ set_opt(sbi->s_mount_opt, POSIX_ACL);
++ break;
++ case Opt_noacl:
++ clear_opt(sbi->s_mount_opt, POSIX_ACL);
++ break;
++#else
++ case Opt_acl:
++ case Opt_noacl:
++ printk("EXT3 (no)acl options not supported\n");
++ break;
++#endif
++ case Opt_journal_update:
+ /* @@@ FIXME */
+ /* Eventually we will want to be able to create
+- a journal file here. For now, only allow the
+- user to specify an existing inode to be the
+- journal file. */
++ a journal file here. For now, only allow the
++ user to specify an existing inode to be the
++ journal file. */
+ if (is_remount) {
+ printk(KERN_ERR "EXT3-fs: cannot specify "
+ "journal on remount\n");
+ return 0;
+ }
+-
+- if (want_value(value, "journal"))
++ set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
++ break;
++ case Opt_journal_inum:
++ if (is_remount) {
++ printk(KERN_ERR "EXT3-fs: cannot specify "
++ "journal on remount\n");
+ return 0;
+- if (!strcmp (value, "update"))
+- set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
+- else if (want_numeric(value, "journal", inum))
++ }
++ if (match_int(&args[0], &option))
+ return 0;
+- }
+- else if (!strcmp (this_char, "noload"))
++ *inum = option;
++ break;
++ case Opt_noload:
+ set_opt (sbi->s_mount_opt, NOLOAD);
+- else if (!strcmp (this_char, "data")) {
+- int data_opt = 0;
+-
+- if (want_value(value, "data"))
+- return 0;
+- if (!strcmp (value, "journal"))
+- data_opt = EXT3_MOUNT_JOURNAL_DATA;
+- else if (!strcmp (value, "ordered"))
+- data_opt = EXT3_MOUNT_ORDERED_DATA;
+- else if (!strcmp (value, "writeback"))
+- data_opt = EXT3_MOUNT_WRITEBACK_DATA;
+- else {
+- printk (KERN_ERR
+- "EXT3-fs: Invalid data option: %s\n",
+- value);
++ break;
++ case Opt_commit:
++ if (match_int(&args[0], &option))
+ return 0;
+- }
++ sbi->s_commit_interval = HZ * option;
++ break;
++ case Opt_data_journal:
++ data_opt = EXT3_MOUNT_JOURNAL_DATA;
++ goto datacheck;
++ case Opt_data_ordered:
++ data_opt = EXT3_MOUNT_ORDERED_DATA;
++ goto datacheck;
++ case Opt_data_writeback:
++ data_opt = EXT3_MOUNT_WRITEBACK_DATA;
++ datacheck:
+ if (is_remount) {
+- if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS) !=
+- data_opt) {
++ if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
++ != data_opt) {
+ printk(KERN_ERR
+- "EXT3-fs: cannot change data "
+- "mode on remount\n");
++ "EXT3-fs: cannot change data "
++ "mode on remount\n");
+ return 0;
+ }
+ } else {
+ sbi->s_mount_opt &= ~EXT3_MOUNT_DATA_FLAGS;
+ sbi->s_mount_opt |= data_opt;
+ }
+- } else if (!strcmp (this_char, "commit")) {
+- unsigned long v;
+- if (want_numeric(value, "commit", &v))
+- return 0;
+- sbi->s_commit_interval = (HZ * v);
+- } else {
+- printk (KERN_ERR
+- "EXT3-fs: Unrecognized mount option %s\n",
+- this_char);
++ break;
++ case Opt_abort:
++ set_opt(sbi->s_mount_opt, ABORT);
++ break;
++ case Opt_ignore:
++ break;
++ default:
++ printk (KERN_ERR
++ "EXT3-fs: Unrecognized mount option \"%s\" "
++ "or missing value\n", p);
+ return 0;
+ }
+ }
++
+ return 1;
+ }
+
+--- linux-2.6.0-test6/fs/ext3/symlink.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/fs/ext3/symlink.c 2003-10-05 00:33:24.000000000 -0700
+@@ -22,7 +22,8 @@
+ #include <linux/ext3_fs.h>
+ #include "xattr.h"
+
+-static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
++static int
++ext3_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+ {
+ struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
+ return vfs_readlink(dentry, buffer, buflen, (char*)ei->i_data);
+--- linux-2.6.0-test6/fs/fat/dir.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/fat/dir.c 2003-10-05 00:33:24.000000000 -0700
+@@ -663,7 +663,7 @@ int fat_dir_ioctl(struct inode * inode,
+ return -EINVAL;
+ }
+
+- d1 = (struct dirent *)arg;
++ d1 = (struct dirent __user *)arg;
+ if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
+ return -EFAULT;
+ /*
+--- linux-2.6.0-test6/fs/fat/inode.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/fat/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -20,6 +20,7 @@
+ #include <linux/buffer_head.h>
+ #include <linux/mount.h>
+ #include <linux/vfs.h>
++#include <linux/parser.h>
+ #include <asm/unaligned.h>
+
+ /*
+@@ -183,20 +184,6 @@ void fat_put_super(struct super_block *s
+ kfree(sbi);
+ }
+
+-static int simple_getbool(char *s, int *setval)
+-{
+- if (s) {
+- if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true"))
+- *setval = 1;
+- else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false"))
+- *setval = 0;
+- else
+- return 0;
+- } else
+- *setval = 1;
+- return 1;
+-}
+-
+ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
+ {
+ struct msdos_sb_info *sbi = MSDOS_SB(mnt->mnt_sb);
+@@ -259,11 +246,95 @@ static int fat_show_options(struct seq_f
+ return 0;
+ }
+
++static void print_obsolete_option(char *optname)
++{
++ printk(KERN_INFO "FAT: %s option is obsolete, "
++ "not supported now\n", optname);
++}
++
++enum {
++ Opt_blocksize, Opt_charset, Opt_check_n, Opt_check_r, Opt_check_s,
++ Opt_fat, Opt_codepage, Opt_conv_a, Opt_conv_b, Opt_conv_t,
++ Opt_debug, Opt_dots, Opt_err, Opt_gid, Opt_immutable,
++ Opt_nocase, Opt_nodots, Opt_quiet, Opt_showexec, Opt_uid,
++ Opt_shortname_lower, Opt_shortname_win95, Opt_shortname_winnt, Opt_shortname_mixed,
++ Opt_umask, Opt_dmask, Opt_fmask, Opt_posix, Opt_cvf_format, Opt_cvf_options,
++ Opt_utf8_off, Opt_utf8_no, Opt_utf8_false,
++ Opt_utf8_on, Opt_utf8_yes, Opt_utf8_true, Opt_utf8_opt,
++ Opt_uni_xl_off, Opt_uni_xl_no, Opt_uni_xl_false,
++ Opt_uni_xl_on, Opt_uni_xl_yes, Opt_uni_xl_true, Opt_uni_xl_opt,
++ Opt_nonumtail_off, Opt_nonumtail_no, Opt_nonumtail_false,
++ Opt_nonumtail_on, Opt_nonumtail_yes, Opt_nonumtail_true, Opt_nonumtail_opt,
++};
++
++static match_table_t FAT_tokens = {
++ {Opt_check_r, "check=relaxed"},
++ {Opt_check_s, "check=strict"},
++ {Opt_check_n, "check=normal"},
++ {Opt_check_r, "check=r"},
++ {Opt_check_s, "check=s"},
++ {Opt_check_n, "check=n"},
++ {Opt_conv_b, "conv=binary"},
++ {Opt_conv_t, "conv=text"},
++ {Opt_conv_a, "conv=auto"},
++ {Opt_conv_b, "conv=b"},
++ {Opt_conv_t, "conv=t"},
++ {Opt_conv_a, "conv=a"},
++ {Opt_nodots, "nodots"},
++ {Opt_nodots, "dotsOK=no"},
++ {Opt_dots, "dotsOK=yes"},
++ {Opt_dots, "dots"},
++ {Opt_uid, "uid=%d"},
++ {Opt_gid, "gid=%d"},
++ {Opt_umask, "umask=%o"},
++ {Opt_dmask, "dmask=%o"},
++ {Opt_fmask, "fmask=%o"},
++ {Opt_fat, "fat=%d"},
++ {Opt_codepage, "codepage=%d"},
++ {Opt_charset, "iocharset=%s"},
++ {Opt_blocksize, "blocksize=%d"},
++ {Opt_nocase, "nocase"},
++ {Opt_cvf_format, "cvf_format=%20s"},
++ {Opt_cvf_options, "cvf_options=%100s"},
++ {Opt_shortname_lower, "shortname=lower"},
++ {Opt_shortname_win95, "shortname=win95"},
++ {Opt_shortname_winnt, "shortname=winnt"},
++ {Opt_shortname_mixed, "shortname=mixed"},
++ {Opt_utf8_off, "utf8=0"}, /* 0 or no or false */
++ {Opt_utf8_no, "utf8=no"},
++ {Opt_utf8_false, "utf8=false"},
++ {Opt_utf8_on, "utf8=1"}, /* empty or 1 or yes or true */
++ {Opt_utf8_yes, "utf8=yes"},
++ {Opt_utf8_true, "utf8=true"},
++ {Opt_utf8_opt, "utf8"},
++ {Opt_uni_xl_off, "uni_xlate=0"}, /* 0 or no or false */
++ {Opt_uni_xl_no, "uni_xlate=no"},
++ {Opt_uni_xl_false, "uni_xlate=false"},
++ {Opt_uni_xl_on, "uni_xlate=1"}, /* empty or 1 or yes or true */
++ {Opt_uni_xl_yes, "uni_xlate=yes"},
++ {Opt_uni_xl_true, "uni_xlate=true"},
++ {Opt_uni_xl_opt, "uni_xlate"},
++ {Opt_nonumtail_off, "nonumtail=0"}, /* 0 or no or false */
++ {Opt_nonumtail_no, "nonumtail=no"},
++ {Opt_nonumtail_false, "nonumtail=false"},
++ {Opt_nonumtail_on, "nonumtail=1"}, /* empty or 1 or yes or true */
++ {Opt_nonumtail_yes, "nonumtail=yes"},
++ {Opt_nonumtail_true, "nonumtail=true"},
++ {Opt_nonumtail_opt, "nonumtail"},
++ {Opt_quiet, "quiet"},
++ {Opt_showexec, "showexec"},
++ {Opt_debug, "debug"},
++ {Opt_immutable, "sys_immutable"},
++ {Opt_posix, "posix"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options, int is_vfat, int *debug,
+ struct fat_mount_options *opts)
+ {
+- char *this_char, *value, *p;
+- int ret = 1, val, len;
++ char *p;
++ substring_t args[MAX_OPT_ARGS];
++ int option;
+
+ opts->isvfat = is_vfat;
+
+@@ -284,183 +355,198 @@ static int parse_options(char *options,
+ *debug = 0;
+
+ if (!options)
+- goto out;
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++ return 1;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+
+- if (!strcmp(this_char,"check") && value) {
+- if (value[0] && !value[1] && strchr("rns",*value))
+- opts->name_check = *value;
+- else if (!strcmp(value,"relaxed"))
+- opts->name_check = 'r';
+- else if (!strcmp(value,"normal"))
+- opts->name_check = 'n';
+- else if (!strcmp(value,"strict"))
+- opts->name_check = 's';
+- else ret = 0;
+- }
+- else if (!strcmp(this_char,"conv") && value) {
+- printk(KERN_INFO "FAT: conv option is obsolete, "
+- "not supported now\n");
+- }
+- else if (!strcmp(this_char,"nocase")) {
++ token = match_token(p, FAT_tokens, args);
++ switch (token) {
++ case Opt_check_s:
++ opts->name_check = 's';
++ break;
++ case Opt_check_r:
++ opts->name_check = 'r';
++ break;
++ case Opt_check_n:
++ opts->name_check = 'n';
++ break;
++ case Opt_dots: /* msdos specific */
++ if (!is_vfat)
++ opts->dotsOK = 1;
++ break;
++ case Opt_nodots: /* msdos specific */
++ if (!is_vfat)
++ opts->dotsOK = 0;
++ break;
++ case Opt_nocase:
+ if (!is_vfat)
+ opts->nocase = 1;
+ else {
+- /* for backward compatible */
++ /* for backward compatibility */
+ opts->shortname = VFAT_SFN_DISPLAY_WIN95
+ | VFAT_SFN_CREATE_WIN95;
+ }
+- }
+- else if (!strcmp(this_char,"showexec")) {
++ break;
++ case Opt_quiet:
++ opts->quiet = 1;
++ break;
++ case Opt_showexec:
+ opts->showexec = 1;
+- }
+- else if (!strcmp(this_char,"uid")) {
+- if (!value || !*value) ret = 0;
+- else {
+- opts->fs_uid = simple_strtoul(value,&value,0);
+- if (*value) ret = 0;
+- }
+- }
+- else if (!strcmp(this_char,"gid")) {
+- if (!value || !*value) ret= 0;
+- else {
+- opts->fs_gid = simple_strtoul(value,&value,0);
+- if (*value) ret = 0;
+- }
+- }
+- else if (!strcmp(this_char,"umask")) {
+- if (!value || !*value) ret = 0;
+- else {
+- opts->fs_fmask = opts->fs_dmask =
+- simple_strtoul(value,&value,8);
+- if (*value) ret = 0;
+- }
+- }
+- else if (!strcmp(this_char,"fmask")) {
+- if (!value || !*value) ret = 0;
+- else {
+- opts->fs_fmask = simple_strtoul(value,&value,8);
+- if (*value) ret = 0;
+- }
+- }
+- else if (!strcmp(this_char,"dmask")) {
+- if (!value || !*value) ret = 0;
+- else {
+- opts->fs_dmask = simple_strtoul(value,&value,8);
+- if (*value) ret = 0;
+- }
+- }
+- else if (!strcmp(this_char,"debug")) {
+- if (value) ret = 0;
+- else *debug = 1;
+- }
+- else if (!strcmp(this_char,"fat")) {
+- printk(KERN_INFO "FAT: fat option is obsolete, "
+- "not supported now\n");
+- }
+- else if (!strcmp(this_char,"quiet")) {
+- if (value) ret = 0;
+- else opts->quiet = 1;
+- }
+- else if (!strcmp(this_char,"blocksize")) {
+- printk(KERN_INFO "FAT: blocksize option is obsolete, "
+- "not supported now\n");
+- }
+- else if (!strcmp(this_char,"sys_immutable")) {
+- if (value) ret = 0;
+- else opts->sys_immutable = 1;
+- }
+- else if (!strcmp(this_char,"codepage") && value) {
+- opts->codepage = simple_strtoul(value,&value,0);
+- if (*value) ret = 0;
+- }
+-
+- /* msdos specific */
+- else if (!is_vfat && !strcmp(this_char,"dots")) {
+- opts->dotsOK = 1;
+- }
+- else if (!is_vfat && !strcmp(this_char,"nodots")) {
+- opts->dotsOK = 0;
+- }
+- else if (!is_vfat && !strcmp(this_char,"dotsOK") && value) {
+- if (!strcmp(value,"yes")) opts->dotsOK = 1;
+- else if (!strcmp(value,"no")) opts->dotsOK = 0;
+- else ret = 0;
+- }
++ break;
++ case Opt_debug:
++ *debug = 1;
++ break;
++ case Opt_immutable:
++ opts->sys_immutable = 1;
++ break;
++ case Opt_uid:
++ if (match_int(&args[0], &option))
++ return 0;
++ opts->fs_uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(&args[0], &option))
++ return 0;
++ opts->fs_gid = option;
++ break;
++ case Opt_umask:
++ if (match_octal(&args[0], &option))
++ return 0;
++ opts->fs_fmask = opts->fs_dmask = option;
++ break;
++ case Opt_dmask:
++ if (match_octal(&args[0], &option))
++ return 0;
++ opts->fs_dmask = option;
++ break;
++ case Opt_fmask:
++ if (match_octal(&args[0], &option))
++ return 0;
++ opts->fs_fmask = option;
++ break;
++ case Opt_codepage:
++ if (match_int(&args[0], &option))
++ return 0;
++ opts->codepage = option;
++ printk("MSDOS FS: Using codepage %d\n",
++ opts->codepage);
++ break;
+
+ /* vfat specific */
+- else if (is_vfat && !strcmp(this_char,"iocharset") && value) {
+- p = value;
+- while (*value && *value != ',')
+- value++;
+- len = value - p;
+- if (len) {
+- char *buffer;
+-
+- if (opts->iocharset != NULL) {
+- kfree(opts->iocharset);
+- opts->iocharset = NULL;
+- }
+- buffer = kmalloc(len + 1, GFP_KERNEL);
+- if (buffer != NULL) {
+- opts->iocharset = buffer;
+- memcpy(buffer, p, len);
+- buffer[len] = 0;
+- } else
+- ret = 0;
++ case Opt_charset:
++ if (is_vfat) {
++ kfree(opts->iocharset);
++ opts->iocharset = match_strdup(&args[0]);
++ if (!opts->iocharset)
++ return 0;
++ printk("MSDOS FS: IO charset %s\n",
++ opts->iocharset);
+ }
+- }
+- else if (is_vfat && !strcmp(this_char,"utf8")) {
+- ret = simple_getbool(value, &val);
+- if (ret) opts->utf8 = val;
+- }
+- else if (is_vfat && !strcmp(this_char,"uni_xlate")) {
+- ret = simple_getbool(value, &val);
+- if (ret) opts->unicode_xlate = val;
+- }
+- else if (is_vfat && !strcmp(this_char,"posix")) {
+- printk(KERN_INFO "FAT: posix option is obsolete, "
+- "not supported now\n");
+- }
+- else if (is_vfat && !strcmp(this_char,"nonumtail")) {
+- ret = simple_getbool(value, &val);
+- if (ret) {
+- opts->numtail = !val;
+- }
+- }
+- else if (is_vfat && !strcmp(this_char, "shortname")) {
+- if (!strcmp(value, "lower"))
++ break;
++ case Opt_shortname_lower:
++ if (is_vfat) {
+ opts->shortname = VFAT_SFN_DISPLAY_LOWER
+ | VFAT_SFN_CREATE_WIN95;
+- else if (!strcmp(value, "win95"))
++ }
++ break;
++ case Opt_shortname_win95:
++ if (is_vfat) {
+ opts->shortname = VFAT_SFN_DISPLAY_WIN95
+ | VFAT_SFN_CREATE_WIN95;
+- else if (!strcmp(value, "winnt"))
++ }
++ break;
++ case Opt_shortname_winnt:
++ if (is_vfat) {
+ opts->shortname = VFAT_SFN_DISPLAY_WINNT
+ | VFAT_SFN_CREATE_WINNT;
+- else if (!strcmp(value, "mixed"))
++ }
++ break;
++ case Opt_shortname_mixed:
++ if (is_vfat) {
+ opts->shortname = VFAT_SFN_DISPLAY_WINNT
+ | VFAT_SFN_CREATE_WIN95;
+- else
+- ret = 0;
+- } else {
+- printk(KERN_ERR "FAT: Unrecognized mount option %s\n",
+- this_char);
+- ret = 0;
+- }
++ }
++ break;
++ case Opt_utf8_off: /* 0 or no or false */
++ case Opt_utf8_no:
++ case Opt_utf8_false:
++ if (is_vfat) {
++ opts->utf8 = 0;
++ }
++ break;
++ case Opt_utf8_on: /* empty or 1 or yes or true */
++ case Opt_utf8_opt:
++ case Opt_utf8_yes:
++ case Opt_utf8_true:
++ if (is_vfat) {
++ opts->utf8 = 1;
++ }
++ break;
++ case Opt_uni_xl_off: /* 0 or no or false */
++ case Opt_uni_xl_no:
++ case Opt_uni_xl_false:
++ if (is_vfat) {
++ opts->unicode_xlate = 0;
++ }
++ break;
++ case Opt_uni_xl_on: /* empty or 1 or yes or true */
++ case Opt_uni_xl_yes:
++ case Opt_uni_xl_true:
++ case Opt_uni_xl_opt:
++ if (is_vfat) {
++ opts->unicode_xlate = 1;
++ }
++ break;
++ case Opt_nonumtail_off: /* 0 or no or false */
++ case Opt_nonumtail_no:
++ case Opt_nonumtail_false:
++ if (is_vfat) {
++ opts->numtail = 1; /* negated option */
++ }
++ break;
++ case Opt_nonumtail_on: /* empty or 1 or yes or true */
++ case Opt_nonumtail_yes:
++ case Opt_nonumtail_true:
++ case Opt_nonumtail_opt:
++ if (is_vfat) {
++ opts->numtail = 0; /* negated option */
++ }
++ break;
+
+- if (ret == 0)
++ /* obsolete mount options */
++ case Opt_conv_b:
++ case Opt_conv_t:
++ case Opt_conv_a:
++ print_obsolete_option("conv");
++ break;
++ case Opt_blocksize:
++ print_obsolete_option("blocksize");
++ break;
++ case Opt_posix:
++ print_obsolete_option("posix");
++ break;
++ case Opt_fat:
++ print_obsolete_option("fat");
++ break;
++ case Opt_cvf_format:
++ case Opt_cvf_options:
++ print_obsolete_option("cvf");
+ break;
++ /* unknown option */
++ default:
++ printk(KERN_ERR "FAT: Unrecognized mount option \"%s\" "
++ "or missing value\n", p);
++ return 0;
++ }
+ }
+-out:
++
+ if (opts->unicode_xlate)
+ opts->utf8 = 0;
+
+- return ret;
++ return 1;
+ }
+
+ static int fat_calc_dir_size(struct inode *inode)
+--- linux-2.6.0-test6/fs/fcntl.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/fcntl.c 2003-10-05 00:34:08.000000000 -0700
+@@ -229,8 +229,8 @@ static int setfl(int fd, struct file * f
+ arg |= O_NONBLOCK;
+
+ if (arg & O_DIRECT) {
+- if (!inode->i_mapping || !inode->i_mapping->a_ops ||
+- !inode->i_mapping->a_ops->direct_IO)
++ if (!filp->f_mapping || !filp->f_mapping->a_ops ||
++ !filp->f_mapping->a_ops->direct_IO)
+ return -EINVAL;
+ }
+
+@@ -619,3 +619,6 @@ module_init(fasync_init)
+
+ EXPORT_SYMBOL(f_setown);
+ EXPORT_SYMBOL(f_delown);
++#ifdef CONFIG_NET
++EXPORT_SYMBOL(__kill_fasync);
++#endif
+--- linux-2.6.0-test6/fs/file_table.c 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/file_table.c 2003-10-05 00:34:03.000000000 -0700
+@@ -114,6 +114,7 @@ int open_private_file(struct file *filp,
+ filp->f_mode = (flags+1) & O_ACCMODE;
+ atomic_set(&filp->f_count, 1);
+ filp->f_dentry = dentry;
++ filp->f_mapping = dentry->d_inode->i_mapping;
+ filp->f_uid = current->fsuid;
+ filp->f_gid = current->fsgid;
+ filp->f_op = dentry->d_inode->i_fop;
+@@ -285,3 +286,5 @@ void __init files_init(unsigned long mem
+ files_stat.max_files = NR_FILE;
+ }
+
++/* Needed by unix.o */
++EXPORT_SYMBOL(files_stat);
+--- linux-2.6.0-test6/fs/freevxfs/vxfs_immed.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/fs/freevxfs/vxfs_immed.c 2003-10-05 00:33:24.000000000 -0700
+@@ -39,7 +39,7 @@
+ #include "vxfs_inode.h"
+
+
+-static int vxfs_immed_readlink(struct dentry *, char *, int);
++static int vxfs_immed_readlink(struct dentry *, char __user *, int);
+ static int vxfs_immed_follow_link(struct dentry *, struct nameidata *);
+
+ static int vxfs_immed_readpage(struct file *, struct page *);
+@@ -77,7 +77,7 @@ struct address_space_operations vxfs_imm
+ * Number of bytes successfully copied to userspace.
+ */
+ static int
+-vxfs_immed_readlink(struct dentry *dp, char *bp, int buflen)
++vxfs_immed_readlink(struct dentry *dp, char __user *bp, int buflen)
+ {
+ struct vxfs_inode_info *vip = VXFS_INO(dp->d_inode);
+
+--- linux-2.6.0-test6/fs/fs-writeback.c 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/fs-writeback.c 2003-10-05 00:34:09.000000000 -0700
+@@ -510,7 +510,7 @@ void write_inode_now(struct inode *inode
+ * OSYNC_INODE: the inode itself
+ */
+
+-int generic_osync_inode(struct inode *inode, int what)
++int generic_osync_inode(struct inode *inode, struct address_space *mapping, int what)
+ {
+ int err = 0;
+ int need_write_inode_now = 0;
+@@ -518,14 +518,14 @@ int generic_osync_inode(struct inode *in
+
+ current->flags |= PF_SYNCWRITE;
+ if (what & OSYNC_DATA)
+- err = filemap_fdatawrite(inode->i_mapping);
++ err = filemap_fdatawrite(mapping);
+ if (what & (OSYNC_METADATA|OSYNC_DATA)) {
+- err2 = sync_mapping_buffers(inode->i_mapping);
++ err2 = sync_mapping_buffers(mapping);
+ if (!err)
+ err = err2;
+ }
+ if (what & OSYNC_DATA) {
+- err2 = filemap_fdatawait(inode->i_mapping);
++ err2 = filemap_fdatawait(mapping);
+ if (!err)
+ err = err2;
+ }
+--- linux-2.6.0-test6/fs/hfs/file.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/fs/hfs/file.c 2003-10-05 00:33:24.000000000 -0700
+@@ -25,10 +25,10 @@
+
+ /*================ Forward declarations ================*/
+
+-static hfs_rwret_t hfs_file_read(struct file *, char *, hfs_rwarg_t,
++static hfs_rwret_t hfs_file_read(struct file *, char __user *, hfs_rwarg_t,
+ loff_t *);
+-static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t,
+- loff_t *);
++static hfs_rwret_t hfs_file_write(struct file *, const char __user *,
++ hfs_rwarg_t, loff_t *);
+ static void hfs_file_truncate(struct inode *);
+
+ /*================ Global variables ================*/
+@@ -139,7 +139,7 @@ int hfs_get_block(struct inode *inode, s
+ * user-space at the address 'buf'. Returns the number of bytes
+ * successfully transferred. This function checks the arguments, does
+ * some setup and then calls hfs_do_read() to do the actual transfer. */
+-static hfs_rwret_t hfs_file_read(struct file * filp, char * buf,
++static hfs_rwret_t hfs_file_read(struct file *filp, char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+@@ -181,7 +181,7 @@ static hfs_rwret_t hfs_file_read(struct
+ * 'file->f_pos' from user-space at the address 'buf'. The return
+ * value is the number of bytes actually transferred.
+ */
+-static hfs_rwret_t hfs_file_write(struct file * filp, const char * buf,
++static hfs_rwret_t hfs_file_write(struct file *filp, const char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+@@ -242,7 +242,7 @@ static void hfs_file_truncate(struct ino
+ *
+ * Like copy_to_user() while translating CR->NL.
+ */
+-static inline void xlate_to_user(char *buf, const char *data, int count)
++static inline void xlate_to_user(char __user *buf, const char *data, int count)
+ {
+ char ch;
+
+@@ -257,7 +257,8 @@ static inline void xlate_to_user(char *b
+ *
+ * Like copy_from_user() while translating NL->CR;
+ */
+-static inline int xlate_from_user(char *data, const char *buf, int count)
++static inline
++int xlate_from_user(char *data, const char __user *buf, int count)
+ {
+ int i;
+
+@@ -290,8 +291,8 @@ static inline int xlate_from_user(char *
+ * This is based on Linus's minix_file_read().
+ * It has been changed to take into account that HFS files have no holes.
+ */
+-hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
+- char * buf, hfs_u32 count)
++hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork *fork, hfs_u32 pos,
++ char __user *buf, hfs_u32 count)
+ {
+ hfs_s32 size, chars, offset, block, blocks, read = 0;
+ int bhrequest, uptodate;
+@@ -436,8 +437,8 @@ hfs_s32 hfs_do_read(struct inode *inode,
+ *
+ * This is just a minor edit of Linus's minix_file_write().
+ */
+-hfs_s32 hfs_do_write(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
+- const char * buf, hfs_u32 count)
++hfs_s32 hfs_do_write(struct inode *inode, struct hfs_fork *fork, hfs_u32 pos,
++ const char __user *buf, hfs_u32 count)
+ {
+ hfs_s32 written, c;
+ struct buffer_head * bh;
+--- linux-2.6.0-test6/fs/hfs/file_cap.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/fs/hfs/file_cap.c 2003-10-05 00:33:24.000000000 -0700
+@@ -29,9 +29,9 @@
+ /*================ Forward declarations ================*/
+ static loff_t cap_info_llseek(struct file *, loff_t,
+ int);
+-static hfs_rwret_t cap_info_read(struct file *, char *,
++static hfs_rwret_t cap_info_read(struct file *, char __user *,
+ hfs_rwarg_t, loff_t *);
+-static hfs_rwret_t cap_info_write(struct file *, const char *,
++static hfs_rwret_t cap_info_write(struct file *, const char __user *,
+ hfs_rwarg_t, loff_t *);
+ /*================ Function-like macros ================*/
+
+@@ -121,7 +121,7 @@ static loff_t cap_info_llseek(struct fil
+ * 'file->f_pos' to user-space at the address 'buf'. The return value
+ * is the number of bytes actually transferred.
+ */
+-static hfs_rwret_t cap_info_read(struct file *filp, char *buf,
++static hfs_rwret_t cap_info_read(struct file *filp, char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+@@ -189,7 +189,7 @@ static hfs_rwret_t cap_info_read(struct
+ * '*ppos' from user-space at the address 'buf'.
+ * The return value is the number of bytes actually transferred.
+ */
+-static hfs_rwret_t cap_info_write(struct file *filp, const char *buf,
++static hfs_rwret_t cap_info_write(struct file *filp, const char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+--- linux-2.6.0-test6/fs/hfs/file_hdr.c 2003-06-14 12:18:25.000000000 -0700
++++ 25/fs/hfs/file_hdr.c 2003-10-05 00:33:24.000000000 -0700
+@@ -41,8 +41,9 @@
+
+ /*================ Forward declarations ================*/
+ static loff_t hdr_llseek(struct file *, loff_t, int);
+-static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);
+-static hfs_rwret_t hdr_write(struct file *, const char *,
++static hfs_rwret_t hdr_read(struct file *, char __user *,
++ hfs_rwarg_t, loff_t *);
++static hfs_rwret_t hdr_write(struct file *, const char __user *,
+ hfs_rwarg_t, loff_t *);
+ /*================ Global variables ================*/
+
+@@ -382,7 +383,7 @@ loff_t hdr_llseek(struct file *file, lof
+ * successfully transferred.
+ */
+ /* XXX: what about the entry count changing on us? */
+-static hfs_rwret_t hdr_read(struct file * filp, char * buf,
++static hfs_rwret_t hdr_read(struct file *filp, char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+@@ -633,7 +634,7 @@ done:
+ * '*ppos' from user-space at the address 'buf'.
+ * The return value is the number of bytes actually transferred.
+ */
+-static hfs_rwret_t hdr_write(struct file *filp, const char *buf,
++static hfs_rwret_t hdr_write(struct file *filp, const char __user *buf,
+ hfs_rwarg_t count, loff_t *ppos)
+ {
+ struct inode *inode = filp->f_dentry->d_inode;
+--- linux-2.6.0-test6/fs/hfs/super.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/fs/hfs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -31,6 +31,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/parser.h>
+ #include <linux/smp_lock.h>
+ #include <linux/vfs.h>
+
+@@ -211,6 +212,60 @@ static int hfs_statfs(struct super_block
+ return 0;
+ }
+
++enum {
++ Opt_version, Opt_uid, Opt_gid, Opt_umask, Opt_part,
++ Opt_type, Opt_creator, Opt_quiet, Opt_afpd,
++ Opt_names_netatalk, Opt_names_trivial, Opt_names_alpha, Opt_names_latin,
++ Opt_names_7bit, Opt_names_8bit, Opt_names_cap,
++ Opt_fork_netatalk, Opt_fork_single, Opt_fork_double, Opt_fork_cap,
++ Opt_case_lower, Opt_case_asis,
++ Opt_conv_binary, Opt_conv_text, Opt_conv_auto,
++};
++
++static match_table_t tokens = {
++ {Opt_version, "version=%u"},
++ {Opt_uid, "uid=%u"},
++ {Opt_gid, "gid=%u"},
++ {Opt_umask, "umask=%o"},
++ {Opt_part, "part=%u"},
++ {Opt_type, "type=%s"},
++ {Opt_creator, "creator=%s"},
++ {Opt_quiet, "quiet"},
++ {Opt_afpd, "afpd"},
++ {Opt_names_netatalk, "names=netatalk"},
++ {Opt_names_trivial, "names=trivial"},
++ {Opt_names_alpha, "names=alpha"},
++ {Opt_names_latin, "names=latin"},
++ {Opt_names_7bit, "names=7bit"},
++ {Opt_names_8bit, "names=8bit"},
++ {Opt_names_cap, "names=cap"},
++ {Opt_names_netatalk, "names=n"},
++ {Opt_names_trivial, "names=t"},
++ {Opt_names_alpha, "names=a"},
++ {Opt_names_latin, "names=l"},
++ {Opt_names_7bit, "names=7"},
++ {Opt_names_8bit, "names=8"},
++ {Opt_names_cap, "names=c"},
++ {Opt_fork_netatalk, "fork=netatalk"},
++ {Opt_fork_single, "fork=single"},
++ {Opt_fork_double, "fork=double"},
++ {Opt_fork_cap, "fork=cap"},
++ {Opt_fork_netatalk, "fork=n"},
++ {Opt_fork_single, "fork=s"},
++ {Opt_fork_double, "fork=d"},
++ {Opt_fork_cap, "fork=c"},
++ {Opt_case_lower, "case=lower"},
++ {Opt_case_asis, "case=asis"},
++ {Opt_case_lower, "case=l"},
++ {Opt_case_asis, "case=a"},
++ {Opt_conv_binary, "conv=binary"},
++ {Opt_conv_text, "conv=text"},
++ {Opt_conv_auto, "conv=auto"},
++ {Opt_conv_binary, "conv=b"},
++ {Opt_conv_text, "conv=t"},
++ {Opt_conv_auto, "conv=a"},
++};
++
+ /*
+ * parse_options()
+ *
+@@ -219,8 +274,10 @@ static int hfs_statfs(struct super_block
+ */
+ static int parse_options(char *options, struct hfs_sb_info *hsb, int *part)
+ {
+- char *this_char, *value;
++ char *p;
+ char names, fork;
++ substring_t args[MAX_OPT_ARGS];
++ int option;
+
+ /* initialize the sb with defaults */
+ memset(hsb, 0, sizeof(*hsb));
+@@ -243,117 +300,109 @@ static int parse_options(char *options,
+ if (!options) {
+ goto done;
+ }
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++ while ((p = strsep(&options,",")) != NULL) {
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char,'=')) != NULL) {
+- *value++ = 0;
+- }
+- /* Numeric-valued options */
+- if (!strcmp(this_char, "version")) {
+- if (!value || !*value) {
+- return 0;
+- }
+- hsb->s_version = simple_strtoul(value,&value,0);
+- if (*value) {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"uid")) {
+- if (!value || !*value) {
+- return 0;
+- }
+- hsb->s_uid = simple_strtoul(value,&value,0);
+- if (*value) {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"gid")) {
+- if (!value || !*value) {
+- return 0;
+- }
+- hsb->s_gid = simple_strtoul(value,&value,0);
+- if (*value) {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"umask")) {
+- if (!value || !*value) {
+- return 0;
+- }
+- hsb->s_umask = simple_strtoul(value,&value,8);
+- if (*value) {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"part")) {
+- if (!value || !*value) {
+- return 0;
+- }
+- *part = simple_strtoul(value,&value,0);
+- if (*value) {
+- return 0;
+- }
+- /* String-valued options */
+- } else if (!strcmp(this_char,"type") && value) {
+- if (strlen(value) != 4) {
+- return 0;
+- }
+- hsb->s_type = hfs_get_nl(value);
+- } else if (!strcmp(this_char,"creator") && value) {
+- if (strlen(value) != 4) {
+- return 0;
+- }
+- hsb->s_creator = hfs_get_nl(value);
+- /* Boolean-valued options */
+- } else if (!strcmp(this_char,"quiet")) {
+- if (value) {
+- return 0;
+- }
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ /* Numeric-valued options */
++ case Opt_version:
++ if (match_int(&args[0], &option))
++ return 0;
++ hsb->s_version = option;
++ break;
++ case Opt_uid:
++ if (match_int(&args[0], &option))
++ return 0;
++ hsb->s_uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(&args[0], &option))
++ return 0;
++ hsb->s_gid = option;
++ break;
++ case Opt_umask:
++ if (match_octal(&args[0], &option))
++ return 0;
++ hsb->s_umask = option;
++ break;
++ case Opt_part:
++ if (match_int(&args[0], &option))
++ return 0;
++ *part = option;
++ break;
++ /* String-valued options */
++ case Opt_type:
++ if (strlen(args[0].from) != 4) {
++ return 0;
++ }
++ hsb->s_type = hfs_get_nl(args[0].from);
++ break;
++ case Opt_creator:
++ if (strlen(args[0].from) != 4) {
++ return 0;
++ }
++ hsb->s_creator = hfs_get_nl(args[0].from);
++ break;
++ /* Boolean-valued options */
++ case Opt_quiet:
+ hsb->s_quiet = 1;
+- } else if (!strcmp(this_char,"afpd")) {
+- if (value) {
+- return 0;
+- }
++ break;
++ case Opt_afpd:
+ hsb->s_afpd = 1;
+- /* Multiple choice options */
+- } else if (!strcmp(this_char,"names") && value) {
+- if ((*value && !value[1] && strchr("ntal78c",*value)) ||
+- !strcmp(value,"netatalk") ||
+- !strcmp(value,"trivial") ||
+- !strcmp(value,"alpha") ||
+- !strcmp(value,"latin") ||
+- !strcmp(value,"7bit") ||
+- !strcmp(value,"8bit") ||
+- !strcmp(value,"cap")) {
+- names = *value;
+- } else {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"fork") && value) {
+- if ((*value && !value[1] && strchr("nsdc",*value)) ||
+- !strcmp(value,"netatalk") ||
+- !strcmp(value,"single") ||
+- !strcmp(value,"double") ||
+- !strcmp(value,"cap")) {
+- fork = *value;
+- } else {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"case") && value) {
+- if ((*value && !value[1] && strchr("la",*value)) ||
+- !strcmp(value,"lower") ||
+- !strcmp(value,"asis")) {
+- hsb->s_lowercase = (*value == 'l');
+- } else {
+- return 0;
+- }
+- } else if (!strcmp(this_char,"conv") && value) {
+- if ((*value && !value[1] && strchr("bta",*value)) ||
+- !strcmp(value,"binary") ||
+- !strcmp(value,"text") ||
+- !strcmp(value,"auto")) {
+- hsb->s_conv = *value;
+- } else {
+- return 0;
+- }
+- } else {
++ break;
++ /* Multiple choice options */
++ case Opt_names_netatalk:
++ names = 'n';
++ break;
++ case Opt_names_trivial:
++ names = 't';
++ break;
++ case Opt_names_alpha:
++ names = 'a';
++ break;
++ case Opt_names_latin:
++ names = 'l';
++ break;
++ case Opt_names_7bit:
++ names = '7';
++ break;
++ case Opt_names_8bit:
++ names = '8';
++ break;
++ case Opt_names_cap:
++ names = 'c';
++ break;
++ case Opt_fork_netatalk:
++ fork = 'n';
++ break;
++ case Opt_fork_single:
++ fork = 's';
++ break;
++ case Opt_fork_double:
++ fork = 'd';
++ break;
++ case Opt_fork_cap:
++ fork = 'c';
++ break;
++ case Opt_case_lower:
++ hsb->s_lowercase = 1;
++ break;
++ case Opt_case_asis:
++ hsb->s_lowercase = 0;
++ break;
++ case Opt_conv_binary:
++ hsb->s_conv = 'b';
++ break;
++ case Opt_conv_text:
++ hsb->s_conv = 't';
++ break;
++ case Opt_conv_auto:
++ hsb->s_conv = 'a';
++ break;
++ default:
+ return 0;
+ }
+ }
+--- linux-2.6.0-test6/fs/hpfs/file.c 2003-06-14 12:18:35.000000000 -0700
++++ 25/fs/hpfs/file.c 2003-10-05 00:33:24.000000000 -0700
+@@ -124,7 +124,8 @@ struct address_space_operations hpfs_aop
+ .bmap = _hpfs_bmap
+ };
+
+-ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
++ssize_t hpfs_file_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
+ {
+ ssize_t retval;
+
+--- linux-2.6.0-test6/fs/hpfs/hpfs_fn.h 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/hpfs/hpfs_fn.h 2003-10-05 00:33:24.000000000 -0700
+@@ -249,7 +249,7 @@ int hpfs_file_fsync(struct file *, struc
+ secno hpfs_bmap(struct inode *, unsigned);
+ void hpfs_truncate(struct inode *);
+ int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create);
+-ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos);
++ssize_t hpfs_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
+
+ /* inode.c */
+
+--- linux-2.6.0-test6/fs/hpfs/super.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/fs/hpfs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -10,6 +10,7 @@
+ #include <linux/string.h>
+ #include "hpfs_fn.h"
+ #include <linux/module.h>
++#include <linux/parser.h>
+ #include <linux/init.h>
+ #include <linux/vfs.h>
+
+@@ -219,15 +220,52 @@ static struct super_operations hpfs_sops
+
+ /*
+ * A tiny parser for option strings, stolen from dosfs.
+- *
+ * Stolen again from read-only hpfs.
++ * And updated for table-driven option parsing.
+ */
+
++enum {
++ Opt_help, Opt_uid, Opt_gid, Opt_umask, Opt_case_lower, Opt_case_asis,
++ Opt_conv_binary, Opt_conv_text, Opt_conv_auto,
++ Opt_check_none, Opt_check_normal, Opt_check_strict,
++ Opt_err_cont, Opt_err_ro, Opt_err_panic,
++ Opt_eas_no, Opt_eas_ro, Opt_eas_rw,
++ Opt_chkdsk_no, Opt_chkdsk_errors, Opt_chkdsk_always,
++ Opt_timeshift, Opt_err,
++};
++
++static match_table_t tokens = {
++ {Opt_help, "help"},
++ {Opt_uid, "uid=%u"},
++ {Opt_gid, "gid=%u"},
++ {Opt_umask, "umask=%o"},
++ {Opt_case_lower, "case=lower"},
++ {Opt_case_asis, "case=asis"},
++ {Opt_conv_binary, "conv=binary"},
++ {Opt_conv_text, "conv=text"},
++ {Opt_conv_auto, "conv=auto"},
++ {Opt_check_none, "check=none"},
++ {Opt_check_normal, "check=normal"},
++ {Opt_check_strict, "check=strict"},
++ {Opt_err_cont, "errors=continue"},
++ {Opt_err_ro, "errors=remount-ro"},
++ {Opt_err_panic, "errors=panic"},
++ {Opt_eas_no, "eas=no"},
++ {Opt_eas_ro, "eas=ro"},
++ {Opt_eas_rw, "eas=rw"},
++ {Opt_chkdsk_no, "chkdsk=no"},
++ {Opt_chkdsk_errors, "chkdsk=errors"},
++ {Opt_chkdsk_always, "chkdsk=always"},
++ {Opt_timeshift, "timeshift=%d"},
++ {Opt_err, NULL},
++};
++
+ int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
+ int *lowercase, int *conv, int *eas, int *chk, int *errs,
+ int *chkdsk, int *timeshift)
+ {
+- char *p, *rhs;
++ char *p;
++ int option;
+
+ if (!opts)
+ return 1;
+@@ -235,34 +273,85 @@ int parse_opts(char *opts, uid_t *uid, g
+ /*printk("Parsing opts: '%s'\n",opts);*/
+
+ while ((p = strsep(&opts, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
+ if (!*p)
+ continue;
+- if ((rhs = strchr(p, '=')) != 0)
+- *rhs++ = '\0';
+- if (!strcmp(p, "help")) return 2;
+- if (!strcmp(p, "uid")) {
+- if (!rhs || !*rhs)
+- return 0;
+- *uid = simple_strtoul(rhs, &rhs, 0);
+- if (*rhs)
+- return 0;
+- }
+- else if (!strcmp(p, "gid")) {
+- if (!rhs || !*rhs)
+- return 0;
+- *gid = simple_strtoul(rhs, &rhs, 0);
+- if (*rhs)
+- return 0;
+- }
+- else if (!strcmp(p, "umask")) {
+- if (!rhs || !*rhs)
+- return 0;
+- *umask = simple_strtoul(rhs, &rhs, 8);
+- if (*rhs)
+- return 0;
+- }
+- else if (!strcmp(p, "timeshift")) {
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_help:
++ return 2;
++ case Opt_uid:
++ if (match_int(args, &option))
++ return 0;
++ *uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(args, &option))
++ return 0;
++ *gid = option;
++ break;
++ case Opt_umask:
++ if (match_octal(args, &option))
++ return 0;
++ *umask = option;
++ break;
++ case Opt_case_lower:
++ *lowercase = 1;
++ break;
++ case Opt_case_asis:
++ *lowercase = 0;
++ break;
++ case Opt_conv_binary:
++ *conv = CONV_BINARY;
++ break;
++ case Opt_conv_text:
++ *conv = CONV_TEXT;
++ break;
++ case Opt_conv_auto:
++ *conv = CONV_AUTO;
++ break;
++ case Opt_check_none:
++ *chk = 0;
++ break;
++ case Opt_check_normal:
++ *chk = 1;
++ break;
++ case Opt_check_strict:
++ *chk = 2;
++ break;
++ case Opt_err_cont:
++ *errs = 0;
++ break;
++ case Opt_err_ro:
++ *errs = 1;
++ break;
++ case Opt_err_panic:
++ *errs = 2;
++ break;
++ case Opt_eas_no:
++ *eas = 0;
++ break;
++ case Opt_eas_ro:
++ *eas = 1;
++ break;
++ case Opt_eas_rw:
++ *eas = 2;
++ break;
++ case Opt_chkdsk_no:
++ *chkdsk = 0;
++ break;
++ case Opt_chkdsk_errors:
++ *chkdsk = 1;
++ break;
++ case Opt_chkdsk_always:
++ *chkdsk = 2;
++ break;
++ case Opt_timeshift:
++ {
+ int m = 1;
++ char *rhs = args[0].from;
+ if (!rhs || !*rhs)
+ return 0;
+ if (*rhs == '-') m = -1;
+@@ -270,79 +359,11 @@ int parse_opts(char *opts, uid_t *uid, g
+ *timeshift = simple_strtoul(rhs, &rhs, 0) * m;
+ if (*rhs)
+ return 0;
++ break;
+ }
+- else if (!strcmp(p, "case")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "lower"))
+- *lowercase = 1;
+- else if (!strcmp(rhs, "asis"))
+- *lowercase = 0;
+- else
+- return 0;
+- }
+- else if (!strcmp(p, "conv")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "binary"))
+- *conv = CONV_BINARY;
+- else if (!strcmp(rhs, "text"))
+- *conv = CONV_TEXT;
+- else if (!strcmp(rhs, "auto"))
+- *conv = CONV_AUTO;
+- else
+- return 0;
+- }
+- else if (!strcmp(p, "check")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "none"))
+- *chk = 0;
+- else if (!strcmp(rhs, "normal"))
+- *chk = 1;
+- else if (!strcmp(rhs, "strict"))
+- *chk = 2;
+- else
+- return 0;
+- }
+- else if (!strcmp(p, "errors")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "continue"))
+- *errs = 0;
+- else if (!strcmp(rhs, "remount-ro"))
+- *errs = 1;
+- else if (!strcmp(rhs, "panic"))
+- *errs = 2;
+- else
+- return 0;
+- }
+- else if (!strcmp(p, "eas")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "no"))
+- *eas = 0;
+- else if (!strcmp(rhs, "ro"))
+- *eas = 1;
+- else if (!strcmp(rhs, "rw"))
+- *eas = 2;
+- else
+- return 0;
+- }
+- else if (!strcmp(p, "chkdsk")) {
+- if (!rhs || !*rhs)
+- return 0;
+- if (!strcmp(rhs, "no"))
+- *chkdsk = 0;
+- else if (!strcmp(rhs, "errors"))
+- *chkdsk = 1;
+- else if (!strcmp(rhs, "always"))
+- *chkdsk = 2;
+- else
+- return 0;
+- }
+- else
++ default:
+ return 0;
++ }
+ }
+ return 1;
+ }
+--- linux-2.6.0-test6/fs/hugetlbfs/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/hugetlbfs/inode.c 2003-10-05 00:37:03.000000000 -0700
+@@ -165,7 +165,7 @@ void truncate_hugepages(struct address_s
+ pagevec_init(&pvec, 0);
+ next = start;
+ while (1) {
+- if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
++ if (!pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
+ if (next == start)
+ break;
+ next = start;
+@@ -176,9 +176,6 @@ void truncate_hugepages(struct address_s
+ struct page *page = pvec.pages[i];
+
+ lock_page(page);
+- if (page->index > next)
+- next = page->index;
+- ++next;
+ truncate_huge_page(page);
+ unlock_page(page);
+ hugetlb_put_quota(mapping);
+@@ -648,11 +645,6 @@ hugetlbfs_fill_super(struct super_block
+ struct hugetlbfs_config config;
+ struct hugetlbfs_sb_info *sbinfo;
+
+- sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL);
+- if (!sbinfo)
+- return -ENOMEM;
+- sb->s_fs_info = sbinfo;
+-
+ config.nr_blocks = -1; /* No limit on size by default */
+ config.nr_inodes = -1; /* No limit on number of inodes by default */
+ config.uid = current->fsuid;
+@@ -663,6 +655,10 @@ hugetlbfs_fill_super(struct super_block
+ if (ret)
+ return ret;
+
++ sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL);
++ if (!sbinfo)
++ return -ENOMEM;
++ sb->s_fs_info = sbinfo;
+ spin_lock_init(&sbinfo->stat_lock);
+ sbinfo->max_blocks = config.nr_blocks;
+ sbinfo->free_blocks = config.nr_blocks;
+@@ -675,15 +671,18 @@ hugetlbfs_fill_super(struct super_block
+ inode = hugetlbfs_get_inode(sb, config.uid, config.gid,
+ S_IFDIR | config.mode, 0);
+ if (!inode)
+- return -ENOMEM;
++ goto out_free;
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+- return -ENOMEM;
++ goto out_free;
+ }
+ sb->s_root = root;
+ return 0;
++out_free:
++ kfree(sbinfo);
++ return -ENOMEM;
+ }
+
+ int hugetlb_get_quota(struct address_space *mapping)
+@@ -772,6 +771,7 @@ struct file *hugetlb_zero_setup(size_t s
+ inode->i_nlink = 0;
+ file->f_vfsmnt = mntget(hugetlbfs_vfsmount);
+ file->f_dentry = dentry;
++ file->f_mapping = inode->i_mapping;
+ file->f_op = &hugetlbfs_file_operations;
+ file->f_mode = FMODE_WRITE | FMODE_READ;
+ return file;
+--- linux-2.6.0-test6/fs/inode.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/inode.c 2003-10-05 00:36:52.000000000 -0700
+@@ -183,6 +183,7 @@ void inode_init_once(struct inode *inode
+ INIT_LIST_HEAD(&inode->i_dentry);
+ INIT_LIST_HEAD(&inode->i_devices);
+ sema_init(&inode->i_sem, 1);
++ init_rwsem(&inode->i_alloc_sem);
+ INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
+ spin_lock_init(&inode->i_data.page_lock);
+ init_MUTEX(&inode->i_data.i_shared_sem);
+@@ -195,6 +196,8 @@ void inode_init_once(struct inode *inode
+ i_size_ordered_init(inode);
+ }
+
++EXPORT_SYMBOL(inode_init_once);
++
+ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+ {
+ struct inode * inode = (struct inode *) foo;
+@@ -229,7 +232,6 @@ void __iget(struct inode * inode)
+ * that the inode is no longer useful. We just
+ * terminate it with extreme prejudice.
+ */
+-
+ void clear_inode(struct inode *inode)
+ {
+ invalidate_inode_buffers(inode);
+@@ -251,7 +253,12 @@ void clear_inode(struct inode *inode)
+ inode->i_state = I_CLEAR;
+ }
+
++EXPORT_SYMBOL(clear_inode);
++
+ /*
++ * dispose_list - dispose of the contents of a local list
++ * @head: the head of the list to free
++ *
+ * Dispose-list gets a local list with local inodes in it, so it doesn't
+ * need to worry about list corruption and SMP locks.
+ */
+@@ -327,7 +334,6 @@ static int invalidate_list(struct list_h
+ * fails because there are busy inodes then a non zero value is returned.
+ * If the discard is successful all the inodes have been discarded.
+ */
+-
+ int invalidate_inodes(struct super_block * sb)
+ {
+ int busy;
+@@ -346,6 +352,8 @@ int invalidate_inodes(struct super_block
+
+ return busy;
+ }
++
++EXPORT_SYMBOL(invalidate_inodes);
+
+ int __invalidate_device(struct block_device *bdev, int do_sync)
+ {
+@@ -372,6 +380,8 @@ int __invalidate_device(struct block_dev
+ return res;
+ }
+
++EXPORT_SYMBOL(__invalidate_device);
++
+ static int can_unuse(struct inode *inode)
+ {
+ if (inode->i_state)
+@@ -532,7 +542,6 @@ repeat:
+ *
+ * Allocates a new inode for given superblock.
+ */
+-
+ struct inode *new_inode(struct super_block *sb)
+ {
+ static unsigned long last_ino;
+@@ -552,6 +561,8 @@ struct inode *new_inode(struct super_blo
+ return inode;
+ }
+
++EXPORT_SYMBOL(new_inode);
++
+ void unlock_new_inode(struct inode *inode)
+ {
+ /*
+@@ -565,6 +576,7 @@ void unlock_new_inode(struct inode *inod
+ inode->i_state &= ~(I_LOCK|I_NEW);
+ wake_up_inode(inode);
+ }
++
+ EXPORT_SYMBOL(unlock_new_inode);
+
+ /*
+@@ -685,7 +697,6 @@ static inline unsigned long hash(struct
+ * With a large number of inodes live on the file system this function
+ * currently becomes quite slow.
+ */
+-
+ ino_t iunique(struct super_block *sb, ino_t max_reserved)
+ {
+ static ino_t counter;
+@@ -709,6 +720,8 @@ retry:
+
+ }
+
++EXPORT_SYMBOL(iunique);
++
+ struct inode *igrab(struct inode *inode)
+ {
+ spin_lock(&inode_lock);
+@@ -725,14 +738,16 @@ struct inode *igrab(struct inode *inode)
+ return inode;
+ }
+
++EXPORT_SYMBOL(igrab);
++
+ /**
+ * ifind - internal function, you want ilookup5() or iget5().
+ * @sb: super block of file system to search
+- * @hashval: hash value (usually inode number) to search for
++ * @head: the head of the list to search
+ * @test: callback used for comparisons between inodes
+ * @data: opaque data pointer to pass to @test
+ *
+- * ifind() searches for the inode specified by @hashval and @data in the inode
++ * ifind() searches for the inode specified by @data in the inode
+ * cache. This is a generalized version of ifind_fast() for file systems where
+ * the inode number is not sufficient for unique identification of an inode.
+ *
+@@ -764,6 +779,7 @@ static inline struct inode *ifind(struct
+ /**
+ * ifind_fast - internal function, you want ilookup() or iget().
+ * @sb: super block of file system to search
++ * @head: head of the list to search
+ * @ino: inode number to search for
+ *
+ * ifind_fast() searches for the inode @ino in the inode cache. This is for
+@@ -818,6 +834,7 @@ struct inode *ilookup5(struct super_bloc
+
+ return ifind(sb, head, test, data);
+ }
++
+ EXPORT_SYMBOL(ilookup5);
+
+ /**
+@@ -840,6 +857,7 @@ struct inode *ilookup(struct super_block
+
+ return ifind_fast(sb, head, ino);
+ }
++
+ EXPORT_SYMBOL(ilookup);
+
+ /**
+@@ -880,6 +898,7 @@ struct inode *iget5_locked(struct super_
+ */
+ return get_new_inode(sb, head, test, set, data);
+ }
++
+ EXPORT_SYMBOL(iget5_locked);
+
+ /**
+@@ -913,6 +932,7 @@ struct inode *iget_locked(struct super_b
+ */
+ return get_new_inode_fast(sb, head, ino);
+ }
++
+ EXPORT_SYMBOL(iget_locked);
+
+ /**
+@@ -923,7 +943,6 @@ EXPORT_SYMBOL(iget_locked);
+ *
+ * Add an inode to the inode hash for this superblock.
+ */
+-
+ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
+ {
+ struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval);
+@@ -932,13 +951,14 @@ void __insert_inode_hash(struct inode *i
+ spin_unlock(&inode_lock);
+ }
+
++EXPORT_SYMBOL(__insert_inode_hash);
++
+ /**
+ * remove_inode_hash - remove an inode from the hash
+ * @inode: inode to unhash
+ *
+ * Remove an inode from the superblock.
+ */
+-
+ void remove_inode_hash(struct inode *inode)
+ {
+ spin_lock(&inode_lock);
+@@ -946,6 +966,8 @@ void remove_inode_hash(struct inode *ino
+ spin_unlock(&inode_lock);
+ }
+
++EXPORT_SYMBOL(remove_inode_hash);
++
+ /*
+ * Tell the filesystem that this inode is no longer of any interest and should
+ * be completely destroyed.
+@@ -988,6 +1010,7 @@ void generic_delete_inode(struct inode *
+ BUG();
+ destroy_inode(inode);
+ }
++
+ EXPORT_SYMBOL(generic_delete_inode);
+
+ static void generic_forget_inode(struct inode *inode)
+@@ -1059,7 +1082,6 @@ static inline void iput_final(struct ino
+ * Puts an inode, dropping its usage count. If the inode use count hits
+ * zero the inode is also then freed and may be destroyed.
+ */
+-
+ void iput(struct inode *inode)
+ {
+ if (inode) {
+@@ -1076,6 +1098,8 @@ void iput(struct inode *inode)
+ }
+ }
+
++EXPORT_SYMBOL(iput);
++
+ /**
+ * bmap - find a block number in a file
+ * @inode: inode of file
+@@ -1087,7 +1111,6 @@ void iput(struct inode *inode)
+ * disk block relative to the disk start that holds that block of the
+ * file.
+ */
+-
+ sector_t bmap(struct inode * inode, sector_t block)
+ {
+ sector_t res = 0;
+@@ -1096,6 +1119,8 @@ sector_t bmap(struct inode * inode, sect
+ return res;
+ }
+
++EXPORT_SYMBOL(bmap);
++
+ /*
+ * Return true if the filesystem which backs this inode considers the two
+ * passed timespecs to be sufficiently different to warrant flushing the
+@@ -1117,7 +1142,6 @@ static int inode_times_differ(struct ino
+ * This function automatically handles read only file systems and media,
+ * as well as the "noatime" flag and inode specific "noatime" markers.
+ */
+-
+ void update_atime(struct inode *inode)
+ {
+ struct timespec now;
+@@ -1139,6 +1163,8 @@ void update_atime(struct inode *inode)
+ }
+ }
+
++EXPORT_SYMBOL(update_atime);
++
+ /**
+ * inode_update_time - update mtime and ctime time
+ * @inode: inode accessed
+@@ -1170,6 +1196,7 @@ void inode_update_time(struct inode *ino
+ if (sync_it)
+ mark_inode_dirty_sync(inode);
+ }
++
+ EXPORT_SYMBOL(inode_update_time);
+
+ int inode_needs_sync(struct inode *inode)
+@@ -1180,6 +1207,7 @@ int inode_needs_sync(struct inode *inode
+ return 1;
+ return 0;
+ }
++
+ EXPORT_SYMBOL(inode_needs_sync);
+
+ /*
+@@ -1375,3 +1403,5 @@ void init_special_inode(struct inode *in
+ printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
+ mode);
+ }
++
++EXPORT_SYMBOL(init_special_inode);
+--- linux-2.6.0-test6/fs/intermezzo/file.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/intermezzo/file.c 2003-10-05 00:34:01.000000000 -0700
+@@ -337,7 +337,7 @@ static void presto_apply_write_policy(st
+ unlock_kernel();
+ return;
+ }
+- error = presto_journal_close(&rec, fset, file,
++ error = presto_journal_close(&rec, fset, fdata,
+ file->f_dentry,
+ &fdata->fd_version,
+ &new_file_ver);
+--- linux-2.6.0-test6/fs/intermezzo/intermezzo_fs.h 2003-07-10 18:50:31.000000000 -0700
++++ 25/fs/intermezzo/intermezzo_fs.h 2003-10-05 00:34:01.000000000 -0700
+@@ -603,7 +603,7 @@ int presto_journal_rename(struct rec_inf
+ int presto_journal_open(struct rec_info *, struct presto_file_set *,
+ struct dentry *, struct presto_version *old_ver);
+ int presto_journal_close(struct rec_info *rec, struct presto_file_set *,
+- struct file *, struct dentry *,
++ struct presto_file_data *, struct dentry *,
+ struct presto_version *old_file_ver,
+ struct presto_version *new_file_ver);
+ int presto_write_lml_close(struct rec_info *rec,
+--- linux-2.6.0-test6/fs/intermezzo/journal.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/intermezzo/journal.c 2003-10-05 00:34:01.000000000 -0700
+@@ -2104,12 +2104,11 @@ int presto_journal_unlink(struct rec_inf
+
+ int
+ presto_journal_close(struct rec_info *rec, struct presto_file_set *fset,
+- struct file *file, struct dentry *dentry,
++ struct presto_file_data *fd, struct dentry *dentry,
+ struct presto_version *old_file_ver,
+ struct presto_version *new_file_ver)
+ {
+ int opcode = KML_OPCODE_CLOSE;
+- struct presto_file_data *fd;
+ char *buffer, *path, *logrecord, record[316];
+ struct dentry *root;
+ int error, size, i;
+@@ -2138,7 +2137,6 @@ presto_journal_close(struct rec_info *re
+
+ root = fset->fset_dentry;
+
+- fd = (struct presto_file_data *)file->private_data;
+ if (fd) {
+ open_ngroups = fd->fd_ngroups;
+ for (i = 0; i < fd->fd_ngroups; i++)
+--- linux-2.6.0-test6/fs/intermezzo/presto.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/intermezzo/presto.c 2003-10-05 00:34:01.000000000 -0700
+@@ -260,11 +260,8 @@ int lento_cancel_lml(char *path,
+
+
+ if (info->flags & LENTO_FL_WRITE_KML) {
+- struct file file;
+- file.private_data = NULL;
+- file.f_dentry = dentry;
+ presto_getversion(&new_ver, dentry->d_inode);
+- error = presto_journal_close(&rec, fset, &file, dentry,
++ error = presto_journal_close(&rec, fset, NULL, dentry,
+ &new_ver);
+ if ( error ) {
+ EXIT;
+--- linux-2.6.0-test6/fs/intermezzo/vfs.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/intermezzo/vfs.c 2003-10-05 00:34:03.000000000 -0700
+@@ -322,7 +322,7 @@ int presto_do_close(struct presto_file_s
+ }
+
+ if (fdata->fd_info.flags & LENTO_FL_KML)
+- rc = presto_journal_close(&rec, fset, file, file->f_dentry,
++ rc = presto_journal_close(&rec, fset, fdata, file->f_dentry,
+ &fdata->fd_version,
+ &fdata->fd_info.remote_version);
+ if (rc) {
+@@ -432,14 +432,11 @@ int presto_do_setattr(struct presto_file
+
+ if ( presto_do_kml(info, dentry) ) {
+ if ((iattr->ia_valid & ATTR_SIZE) && (old_size != inode->i_size)) {
+- struct file file;
+ /* Journal a close whenever we see a potential truncate
+ * At the receiving end, lento should explicitly remove
+ * ATTR_SIZE from the list of valid attributes */
+ presto_getversion(&new_ver, inode);
+- file.private_data = NULL;
+- file.f_dentry = dentry;
+- error = presto_journal_close(&rec, fset, &file, dentry,
++ error = presto_journal_close(&rec, fset, NULL, dentry,
+ &old_ver, &new_ver);
+ }
+
+@@ -2087,7 +2084,9 @@ static struct file *presto_filp_dopen(st
+ }
+ }
+
++ /* XXX: where the fuck is ->f_vfsmnt? */
+ f->f_dentry = dentry;
++ f->f_mapping = dentry->d_inode->i_mapping;
+ f->f_pos = 0;
+ //f->f_reada = 0;
+ f->f_op = NULL;
+--- linux-2.6.0-test6/fs/ioctl.c 2003-07-13 21:44:35.000000000 -0700
++++ 25/fs/ioctl.c 2003-10-05 00:34:08.000000000 -0700
+@@ -22,7 +22,7 @@ static int file_ioctl(struct file *filp,
+ switch (cmd) {
+ case FIBMAP:
+ {
+- struct address_space *mapping = inode->i_mapping;
++ struct address_space *mapping = filp->f_mapping;
+ int res;
+ /* do we support this mess? */
+ if (!mapping->a_ops->bmap)
+--- linux-2.6.0-test6/fs/isofs/inode.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/isofs/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -29,6 +29,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
++#include <linux/parser.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+
+@@ -328,9 +329,52 @@ isofs_dentry_cmpi_ms(struct dentry *dent
+ }
+ #endif
+
++enum {
++ Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
++ Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
++ Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
++ Opt_nocompress,
++};
++
++static match_table_t tokens = {
++ {Opt_norock, "norock"},
++ {Opt_nojoliet, "nojoliet"},
++ {Opt_unhide, "unhide"},
++ {Opt_cruft, "cruft"},
++ {Opt_utf8, "utf8"},
++ {Opt_iocharset, "iocharset=%s"},
++ {Opt_map_a, "map=acorn"},
++ {Opt_map_a, "map=a"},
++ {Opt_map_n, "map=normal"},
++ {Opt_map_n, "map=n"},
++ {Opt_map_o, "map=off"},
++ {Opt_map_o, "map=o"},
++ {Opt_session, "session=%u"},
++ {Opt_sb, "sbsector=%u"},
++ {Opt_check_r, "check=relaxed"},
++ {Opt_check_r, "check=r"},
++ {Opt_check_s, "check=strict"},
++ {Opt_check_s, "check=s"},
++ {Opt_uid, "uid=%u"},
++ {Opt_gid, "gid=%u"},
++ {Opt_mode, "mode=%u"},
++ {Opt_block, "block=%u"},
++ {Opt_ignore, "conv=binary"},
++ {Opt_ignore, "conv=b"},
++ {Opt_ignore, "conv=text"},
++ {Opt_ignore, "conv=t"},
++ {Opt_ignore, "conv=mtext"},
++ {Opt_ignore, "conv=m"},
++ {Opt_ignore, "conv=auto"},
++ {Opt_ignore, "conv=a"},
++ {Opt_nocompress, "nocompress"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options, struct iso9660_options * popt)
+ {
+- char *this_char,*value;
++ char *p;
++ int option;
+
+ popt->map = 'n';
+ popt->rock = 'y';
+@@ -350,112 +394,101 @@ static int parse_options(char *options,
+ popt->utf8 = 0;
+ popt->session=-1;
+ popt->sbsector=-1;
+- if (!options) return 1;
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++ if (!options)
++ return 1;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ substring_t args[MAX_OPT_ARGS];
++ unsigned n;
++
++ if (!*p)
+ continue;
+- if (strncmp(this_char,"norock",6) == 0) {
+- popt->rock = 'n';
+- continue;
+- }
+- if (strncmp(this_char,"nojoliet",8) == 0) {
+- popt->joliet = 'n';
+- continue;
+- }
+- if (strncmp(this_char,"unhide",6) == 0) {
+- popt->unhide = 'y';
+- continue;
+- }
+- if (strncmp(this_char,"cruft",5) == 0) {
+- popt->cruft = 'y';
+- continue;
+- }
+- if (strncmp(this_char,"utf8",4) == 0) {
+- popt->utf8 = 1;
+- continue;
+- }
+- if (strncmp(this_char,"nocompress",10) == 0) {
+- popt->nocompress = 1;
+- continue;
+- }
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_norock:
++ popt->rock = 'n';
++ break;
++ case Opt_nojoliet:
++ popt->joliet = 'n';
++ break;
++ case Opt_unhide:
++ popt->unhide = 'y';
++ break;
++ case Opt_cruft:
++ popt->cruft = 'y';
++ break;
++ case Opt_utf8:
++ popt->utf8 = 1;
++ break;
+ #ifdef CONFIG_JOLIET
+- if (!strcmp(this_char,"iocharset") && value) {
+- popt->iocharset = value;
+- while (*value && *value != ',')
+- value++;
+- if (value == popt->iocharset)
+- return 0;
+- *value = 0;
+- } else
++ case Opt_iocharset:
++ popt->iocharset = match_strdup(&args[0]);
++ break;
+ #endif
+- if (!strcmp(this_char,"map") && value) {
+- if (value[0] && !value[1] && strchr("ano",*value))
+- popt->map = *value;
+- else if (!strcmp(value,"off")) popt->map = 'o';
+- else if (!strcmp(value,"normal")) popt->map = 'n';
+- else if (!strcmp(value,"acorn")) popt->map = 'a';
+- else return 0;
+- }
+- if (!strcmp(this_char,"session") && value) {
+- char * vpnt = value;
+- unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
+- if(ivalue < 0 || ivalue >99) return 0;
+- popt->session=ivalue+1;
+- }
+- if (!strcmp(this_char,"sbsector") && value) {
+- char * vpnt = value;
+- unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
+- if(ivalue < 0 || ivalue >660*512) return 0;
+- popt->sbsector=ivalue;
+- }
+- else if (!strcmp(this_char,"check") && value) {
+- if (value[0] && !value[1] && strchr("rs",*value))
+- popt->check = *value;
+- else if (!strcmp(value,"relaxed")) popt->check = 'r';
+- else if (!strcmp(value,"strict")) popt->check = 's';
+- else return 0;
+- }
+- else if (!strcmp(this_char,"conv") && value) {
+- /* no conversion is done anymore;
+- we still accept the same mount options,
+- but ignore them */
+- if (value[0] && !value[1] && strchr("btma",*value)) ;
+- else if (!strcmp(value,"binary")) ;
+- else if (!strcmp(value,"text")) ;
+- else if (!strcmp(value,"mtext")) ;
+- else if (!strcmp(value,"auto")) ;
+- else return 0;
+- }
+- else if (value &&
+- (!strcmp(this_char,"block") ||
+- !strcmp(this_char,"mode") ||
+- !strcmp(this_char,"uid") ||
+- !strcmp(this_char,"gid"))) {
+- char * vpnt = value;
+- unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);
+- if (*vpnt) return 0;
+- switch(*this_char) {
+- case 'b':
+- if ( ivalue != 512
+- && ivalue != 1024
+- && ivalue != 2048) return 0;
+- popt->blocksize = ivalue;
+- break;
+- case 'u':
+- popt->uid = ivalue;
+- break;
+- case 'g':
+- popt->gid = ivalue;
+- break;
+- case 'm':
+- popt->mode = ivalue;
+- break;
+- }
++ case Opt_map_a:
++ popt->map = 'a';
++ break;
++ case Opt_map_o:
++ popt->map = 'o';
++ break;
++ case Opt_map_n:
++ popt->map = 'n';
++ break;
++ case Opt_session:
++ if (match_int(&args[0], &option))
++ return 0;
++ n = option;
++ if (n > 99)
++ return 0;
++ popt->session = n + 1;
++ break;
++ case Opt_sb:
++ if (match_int(&args[0], &option))
++ return 0;
++ n = option;
++ if (n > 660 * 512)
++ return 0;
++ popt->sbsector = n;
++ break;
++ case Opt_check_r:
++ popt->check = 'r';
++ break;
++ case Opt_check_s:
++ popt->check = 's';
++ break;
++ case Opt_ignore:
++ break;
++ case Opt_uid:
++ if (match_int(&args[0], &option))
++ return 0;
++ popt->uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(&args[0], &option))
++ return 0;
++ popt->gid = option;
++ break;
++ case Opt_mode:
++ if (match_int(&args[0], &option))
++ return 0;
++ popt->mode = option;
++ break;
++ case Opt_block:
++ if (match_int(&args[0], &option))
++ return 0;
++ n = option;
++ if (n != 512 && n != 1024 && n != 2048)
++ return 0;
++ popt->blocksize = n;
++ break;
++ case Opt_nocompress:
++ popt->nocompress = 1;
++ break;
++ default:
++ return 0;
+ }
+- else return 1;
+ }
+ return 1;
+ }
+@@ -842,6 +875,9 @@ root_found:
+ if (opt.check == 'r') table++;
+ s->s_root->d_op = &isofs_dentry_ops[table];
+
++ if (opt.iocharset)
++ kfree(opt.iocharset);
++
+ return 0;
+
+ /*
+@@ -879,6 +915,8 @@ out_unknown_format:
+ out_freebh:
+ brelse(bh);
+ out_freesbi:
++ if (opt.iocharset)
++ kfree(opt.iocharset);
+ kfree(sbi);
+ s->s_fs_info = NULL;
+ return -EINVAL;
+--- linux-2.6.0-test6/fs/jbd/journal.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/jbd/journal.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1800,7 +1800,7 @@ int read_jbd_debug(char *page, char **st
+ return ret;
+ }
+
+-int write_jbd_debug(struct file *file, const char *buffer,
++int write_jbd_debug(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+ {
+ char buf[32];
+--- linux-2.6.0-test6/fs/jffs/intrep.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/jffs/intrep.c 2003-10-05 00:34:48.000000000 -0700
+@@ -3337,18 +3337,16 @@ jffs_garbage_collect_thread(void *ptr)
+ int result = 0;
+ D1(int i = 1);
+
++ daemonize("jffs_gcd");
++
+ c->gc_task = current;
+
+ lock_kernel();
+- exit_mm(c->gc_task);
+-
+- set_special_pids(1, 1);
+ init_completion(&c->gc_thread_comp); /* barrier */
+ spin_lock_irq(¤t->sighand->siglock);
+ siginitsetinv (¤t->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+- strcpy(current->comm, "jffs_gcd");
+
+ D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
+
+--- linux-2.6.0-test6/fs/jfs/inode.c 2003-09-08 13:58:58.000000000 -0700
++++ 25/fs/jfs/inode.c 2003-10-05 00:34:07.000000000 -0700
+@@ -302,7 +302,7 @@ static int jfs_direct_IO(int rw, struct
+ loff_t offset, unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ offset, nr_segs, jfs_get_blocks, NULL);
+--- linux-2.6.0-test6/fs/jfs/jfs_debug.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/fs/jfs/jfs_debug.c 2003-10-05 00:33:24.000000000 -0700
+@@ -81,7 +81,7 @@ static int loglevel_read(char *page, cha
+ return len;
+ }
+
+-static int loglevel_write(struct file *file, const char *buffer,
++static int loglevel_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+ {
+ char c;
+--- linux-2.6.0-test6/fs/jfs/jfs_imap.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/jfs/jfs_imap.c 2003-10-05 00:33:24.000000000 -0700
+@@ -838,7 +838,7 @@ int diWrite(tid_t tid, struct inode *ip)
+ */
+ if (S_ISDIR(ip->i_mode)
+ && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
+- bcopy(&ip->i_DASD, &dp->di_DASD, sizeof(struct dasd));
++ memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
+ #endif /* _JFS_FASTDASD */
+
+ /* release the buffer holding the updated on-disk inode.
+--- linux-2.6.0-test6/fs/jfs/super.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/jfs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -20,6 +20,7 @@
+ #include <linux/fs.h>
+ #include <linux/config.h>
+ #include <linux/module.h>
++#include <linux/parser.h>
+ #include <linux/completion.h>
+ #include <linux/vfs.h>
+ #include <asm/uaccess.h>
+@@ -164,59 +165,82 @@ static void jfs_put_super(struct super_b
+ kfree(sbi);
+ }
+
++enum {
++ Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
++ Opt_ignore, Opt_err,
++};
++
++static match_table_t tokens = {
++ {Opt_integrity, "integrity"},
++ {Opt_nointegrity, "nointegrity"},
++ {Opt_iocharset, "iocharset=%s"},
++ {Opt_resize, "resize=%u"},
++ {Opt_ignore, "noquota"},
++ {Opt_ignore, "quota"},
++ {Opt_ignore, "usrquota"},
++ {Opt_ignore, "grpquota"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
+ int *flag)
+ {
+ void *nls_map = NULL;
+- char *this_char;
+- char *value;
++ char *p;
+ struct jfs_sb_info *sbi = JFS_SBI(sb);
+
+ *newLVSize = 0;
+
+ if (!options)
+ return 1;
+- while ((this_char = strsep(&options, ",")) != NULL) {
+- if (!*this_char)
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char, '=')) != NULL)
+- *value++ = 0;
+- if (!strcmp(this_char, "integrity")) {
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_integrity:
+ *flag &= ~JFS_NOINTEGRITY;
+- } else if (!strcmp(this_char, "nointegrity")) {
++ break;
++ case Opt_nointegrity:
+ *flag |= JFS_NOINTEGRITY;
+- } else if (!strcmp(this_char, "iocharset")) {
+- if (!value || !*value)
+- goto needs_arg;
++ break;
++ case Opt_ignore:
++ /* Silently ignore the quota options */
++ /* Don't do anything ;-) */
++ break;
++ case Opt_iocharset:
+ if (nls_map) /* specified iocharset twice! */
+ unload_nls(nls_map);
+- nls_map = load_nls(value);
++ nls_map = load_nls(args[0].from);
+ if (!nls_map) {
+ printk(KERN_ERR "JFS: charset not found\n");
+ goto cleanup;
+ }
+- } else if (!strcmp(this_char, "resize")) {
+- if (!value || !*value) {
++ break;
++ case Opt_resize:
++ {
++ char *resize = args[0].from;
++ if (!resize || !*resize) {
+ *newLVSize = sb->s_bdev->bd_inode->i_size >>
+ sb->s_blocksize_bits;
+ if (*newLVSize == 0)
+ printk(KERN_ERR
+- "JFS: Cannot determine volume size\n");
++ "JFS: Cannot determine volume size\n");
+ } else
+- *newLVSize = simple_strtoull(value, &value, 0);
+-
+- /* Silently ignore the quota options */
+- } else if (!strcmp(this_char, "grpquota")
+- || !strcmp(this_char, "noquota")
+- || !strcmp(this_char, "quota")
+- || !strcmp(this_char, "usrquota"))
+- /* Don't do anything ;-) */ ;
+- else {
+- printk("jfs: Unrecognized mount option %s\n",
+- this_char);
++ *newLVSize = simple_strtoull(resize, &resize, 0);
++ break;
++ }
++ default:
++ printk("jfs: Unrecognized mount option \"%s\" "
++ " or missing value\n", p);
+ goto cleanup;
+ }
+ }
++
+ if (nls_map) {
+ /* Discard old (if remount) */
+ if (sbi->nls_tab)
+@@ -224,8 +248,7 @@ static int parse_options(char *options,
+ sbi->nls_tab = nls_map;
+ }
+ return 1;
+-needs_arg:
+- printk(KERN_ERR "JFS: %s needs an argument\n", this_char);
++
+ cleanup:
+ if (nls_map)
+ unload_nls(nls_map);
+--- linux-2.6.0-test6/fs/jfs/symlink.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/fs/jfs/symlink.c 2003-10-05 00:33:24.000000000 -0700
+@@ -26,7 +26,7 @@ static int jfs_follow_link(struct dentry
+ return vfs_follow_link(nd, s);
+ }
+
+-static int jfs_readlink(struct dentry *dentry, char *buffer, int buflen)
++static int jfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+ {
+ char *s = JFS_IP(dentry->d_inode)->i_inline;
+ return vfs_readlink(dentry, buffer, buflen, s);
+--- linux-2.6.0-test6/fs/Kconfig 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/Kconfig 2003-10-05 00:36:47.000000000 -0700
+@@ -874,6 +874,7 @@ config TMPFS
+
+ config HUGETLBFS
+ bool "HugeTLB file system support"
++ depends X86 || IA64 || PPC64 || SPARC64 || X86_64 || BROKEN
+
+ config HUGETLB_PAGE
+ def_bool HUGETLBFS
+@@ -1254,6 +1255,8 @@ menu "Network File Systems"
+ config NFS_FS
+ tristate "NFS file system support"
+ depends on INET
++ select LOCKD
++ select SUNRPC
+ help
+ If you are connected to some other (usually local) Unix computer
+ (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
+@@ -1306,9 +1309,36 @@ config NFS_V4
+
+ If unsure, say N.
+
++config NFS_DIRECTIO
++ bool
++ depends on NFS_FS
++ default y
++ help
++ This option enables applications to perform uncached I/O on files
++ in NFS file systems using the O_DIRECT open() flag. When O_DIRECT
++ is set for a file, its data is not cached in the system's page
++ cache. Data is moved to and from user-level application buffers
++ directly. Unlike local disk-based file systems, NFS O_DIRECT has
++ no alignment restrictions.
++
++ Unless your program is designed to use O_DIRECT properly, you are
++ much better off allowing the NFS client to manage data caching for
++ you. Misusing O_DIRECT can cause poor server performance or network
++ storms. This kernel build option defaults OFF to avoid exposing
++ system administrators unwittingly to a potentially hazardous
++ feature.
++
++ For more details on NFS O_DIRECT, see fs/nfs/direct.c.
++
++ If unsure, say N. This reduces the size of the NFS client, and
++ causes open() to return EINVAL if a file residing in NFS is
++ opened with the O_DIRECT flag.
++
+ config NFSD
+ tristate "NFS server support"
+ depends on INET
++ select LOCKD
++ select SUNRPC
+ help
+ If you want your Linux box to act as an NFS *server*, so that other
+ computers on your local network which support NFS can access certain
+@@ -1371,8 +1401,6 @@ config ROOT_NFS
+
+ config LOCKD
+ tristate
+- default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
+- default y if NFS_FS=y || NFSD=y
+
+ config LOCKD_V4
+ bool
+@@ -1385,8 +1413,6 @@ config EXPORTFS
+
+ config SUNRPC
+ tristate
+- default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m)
+- default y if NFS_FS=y || NFSD=y
+
+ config SUNRPC_GSS
+ tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)"
+@@ -1565,6 +1591,7 @@ config AFS_FS
+ # for fs/nls/Config.in
+ tristate "Andrew File System support (AFS) (Experimental)"
+ depends on INET && EXPERIMENTAL
++ select RXRPC
+ help
+ If you say Y here, you will get an experimental Andrew File System
+ driver. It currently only supports unsecured read-only AFS access.
+@@ -1575,8 +1602,6 @@ config AFS_FS
+
+ config RXRPC
+ tristate
+- default m if AFS_FS=m
+- default y if AFS_FS=y
+
+ endmenu
+
+--- linux-2.6.0-test6/fs/libfs.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/libfs.c 2003-10-05 00:33:24.000000000 -0700
+@@ -429,3 +429,26 @@ void simple_release_fs(struct vfsmount *
+ spin_unlock(&pin_fs_lock);
+ mntput(mnt);
+ }
++
++EXPORT_SYMBOL(dcache_dir_close);
++EXPORT_SYMBOL(dcache_dir_lseek);
++EXPORT_SYMBOL(dcache_dir_open);
++EXPORT_SYMBOL(dcache_readdir);
++EXPORT_SYMBOL(generic_read_dir);
++EXPORT_SYMBOL(simple_commit_write);
++EXPORT_SYMBOL(simple_dir_inode_operations);
++EXPORT_SYMBOL(simple_dir_operations);
++EXPORT_SYMBOL(simple_empty);
++EXPORT_SYMBOL(simple_fill_super);
++EXPORT_SYMBOL(simple_getattr);
++EXPORT_SYMBOL(simple_link);
++EXPORT_SYMBOL(simple_lookup);
++EXPORT_SYMBOL(simple_pin_fs);
++EXPORT_SYMBOL(simple_prepare_write);
++EXPORT_SYMBOL(simple_readpage);
++EXPORT_SYMBOL(simple_release_fs);
++EXPORT_SYMBOL(simple_rename);
++EXPORT_SYMBOL(simple_rmdir);
++EXPORT_SYMBOL(simple_statfs);
++EXPORT_SYMBOL(simple_sync_file);
++EXPORT_SYMBOL(simple_unlink);
+--- linux-2.6.0-test6/fs/locks.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/locks.c 2003-10-05 00:36:10.000000000 -0700
+@@ -928,10 +928,10 @@ int locks_mandatory_locked(struct inode
+ * locks_mandatory_area - Check for a conflicting lock
+ * @read_write: %FLOCK_VERIFY_WRITE for exclusive access, %FLOCK_VERIFY_READ
+ * for shared
+- * @inode: the file to check
+- * @file: how the file was opened (if it was)
+- * @offset: start of area to check
+- * @count: length of area to check
++ * @inode: the file to check
++ * @filp: how the file was opened (if it was)
++ * @offset: start of area to check
++ * @count: length of area to check
+ *
+ * Searches the inode's list of locks to find any POSIX locks which conflict.
+ * This function is called from locks_verify_area() and
+@@ -1119,6 +1119,7 @@ out:
+ /**
+ * lease_get_mtime
+ * @inode: the inode
++ * @time: pointer to a timespec which will contain the last modified time
+ *
+ * This is to force NFS clients to flush their caches for files with
+ * exclusive leases. The justification is that if someone has an
+@@ -1434,7 +1435,7 @@ int fcntl_setlk(struct file *filp, unsig
+ */
+ if (IS_MANDLOCK(inode) &&
+ (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
+- struct address_space *mapping = inode->i_mapping;
++ struct address_space *mapping = filp->f_mapping;
+
+ if (!list_empty(&mapping->i_mmap_shared)) {
+ error = -EAGAIN;
+@@ -1572,7 +1573,7 @@ int fcntl_setlk64(struct file *filp, uns
+ */
+ if (IS_MANDLOCK(inode) &&
+ (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
+- struct address_space *mapping = inode->i_mapping;
++ struct address_space *mapping = filp->f_mapping;
+
+ if (!list_empty(&mapping->i_mmap_shared)) {
+ error = -EAGAIN;
+@@ -1726,6 +1727,7 @@ posix_block_lock(struct file_lock *block
+
+ /**
+ * posix_unblock_lock - stop waiting for a file lock
++ * @filp: how the file was opened
+ * @waiter: the lock which was waiting
+ *
+ * lockd needs to block waiting for locks.
+--- linux-2.6.0-test6/fs/namei.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/namei.c 2003-10-05 00:33:24.000000000 -0700
+@@ -15,6 +15,7 @@
+ */
+
+ #include <linux/init.h>
++#include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/fs.h>
+ #include <linux/namei.h>
+@@ -218,7 +219,7 @@ int permission(struct inode * inode,int
+ if (retval)
+ return retval;
+
+- return security_inode_permission(inode, mask);
++ return security_inode_permission(inode, mask, nd);
+ }
+
+ /*
+@@ -302,7 +303,8 @@ static struct dentry * cached_lookup(str
+ * short-cut DAC fails, then call permission() to do more
+ * complete permission check.
+ */
+-static inline int exec_permission_lite(struct inode *inode)
++static inline int exec_permission_lite(struct inode *inode,
++ struct nameidata *nd)
+ {
+ umode_t mode = inode->i_mode;
+
+@@ -325,7 +327,7 @@ static inline int exec_permission_lite(s
+
+ return -EACCES;
+ ok:
+- return security_inode_permission(inode, MAY_EXEC);
++ return security_inode_permission(inode, MAY_EXEC, nd);
+ }
+
+ /*
+@@ -584,7 +586,7 @@ int link_path_walk(const char * name, st
+ struct qstr this;
+ unsigned int c;
+
+- err = exec_permission_lite(inode);
++ err = exec_permission_lite(inode, nd);
+ if (err == -EAGAIN) {
+ err = permission(inode, MAY_EXEC, nd);
+ }
+@@ -2275,3 +2277,33 @@ struct inode_operations page_symlink_ino
+ .readlink = page_readlink,
+ .follow_link = page_follow_link,
+ };
++
++EXPORT_SYMBOL(__user_walk);
++EXPORT_SYMBOL(follow_down);
++EXPORT_SYMBOL(follow_up);
++EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
++EXPORT_SYMBOL(getname);
++EXPORT_SYMBOL(lock_rename);
++EXPORT_SYMBOL(lookup_create);
++EXPORT_SYMBOL(lookup_hash);
++EXPORT_SYMBOL(lookup_one_len);
++EXPORT_SYMBOL(page_follow_link);
++EXPORT_SYMBOL(page_readlink);
++EXPORT_SYMBOL(page_symlink);
++EXPORT_SYMBOL(page_symlink_inode_operations);
++EXPORT_SYMBOL(path_lookup);
++EXPORT_SYMBOL(path_release);
++EXPORT_SYMBOL(path_walk);
++EXPORT_SYMBOL(permission);
++EXPORT_SYMBOL(unlock_rename);
++EXPORT_SYMBOL(vfs_create);
++EXPORT_SYMBOL(vfs_follow_link);
++EXPORT_SYMBOL(vfs_link);
++EXPORT_SYMBOL(vfs_mkdir);
++EXPORT_SYMBOL(vfs_mknod);
++EXPORT_SYMBOL(vfs_permission);
++EXPORT_SYMBOL(vfs_readlink);
++EXPORT_SYMBOL(vfs_rename);
++EXPORT_SYMBOL(vfs_rmdir);
++EXPORT_SYMBOL(vfs_symlink);
++EXPORT_SYMBOL(vfs_unlink);
+--- linux-2.6.0-test6/fs/nfs/direct.c 2003-06-26 22:07:25.000000000 -0700
++++ 25/fs/nfs/direct.c 2003-10-05 00:36:46.000000000 -0700
+@@ -1,7 +1,7 @@
+ /*
+ * linux/fs/nfs/direct.c
+ *
+- * Copyright (C) 2001 by Chuck Lever <cel@netapp.com>
++ * Copyright (C) 2003 by Chuck Lever <cel@netapp.com>
+ *
+ * High-performance uncached I/O for the Linux NFS client
+ *
+@@ -26,19 +26,23 @@
+ * also supports uncaching whole NFS partitions with "-o forcedirectio,"
+ * an undocumented mount option.
+ *
+- * Designed by Jeff Kimmel, Chuck Lever, and Trond Myklebust.
++ * Designed by Jeff Kimmel, Chuck Lever, and Trond Myklebust, with
++ * help from Andrew Morton.
+ *
+ * 18 Dec 2001 Initial implementation for 2.4 --cel
+ * 08 Jul 2002 Version for 2.4.19, with bug fixes --trondmy
+- * 24 Sep 2002 Rewrite to use asynchronous RPCs, port to 2.5 --cel
++ * 08 Jun 2003 Port to 2.5 APIs --cel
+ *
+ */
+
+ #include <linux/config.h>
++#include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
++#include <linux/smp_lock.h>
+ #include <linux/file.h>
+-#include <linux/errno.h>
++#include <linux/pagemap.h>
++
+ #include <linux/nfs_fs.h>
+ #include <linux/nfs_page.h>
+ #include <linux/sunrpc/clnt.h>
+@@ -46,35 +50,41 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+
+-#define NFSDBG_FACILITY (NFSDBG_PAGECACHE | NFSDBG_VFS)
++#define NFSDBG_FACILITY NFSDBG_VFS
+ #define VERF_SIZE (2 * sizeof(__u32))
++#define MAX_DIRECTIO_SIZE (4096UL << PAGE_SHIFT)
+
+
+ /**
+- * nfs_get_user_pages - find and set up page representing user buffer
+- * addr: user-space address of target buffer
+- * size: total size in bytes of target buffer
+- * @pages: returned array of page struct pointers underlying target buffer
+- * write: whether or not buffer is target of a write operation
++ * nfs_get_user_pages - find and set up pages underlying user's buffer
++ * rw: direction (read or write)
++ * user_addr: starting address of this segment of user's buffer
++ * count: size of this segment
++ * @pages: returned array of page struct pointers underlying user's buffer
+ */
+ static inline int
+-nfs_get_user_pages(unsigned long addr, size_t size,
+- struct page ***pages, int rw)
++nfs_get_user_pages(int rw, unsigned long user_addr, size_t size,
++ struct page ***pages)
+ {
+ int result = -ENOMEM;
+- unsigned page_count = (unsigned) size >> PAGE_SHIFT;
+- unsigned array_size = (page_count * sizeof(struct page *)) + 2U;
++ unsigned long page_count;
++ size_t array_size;
++
++ /* set an arbitrary limit to prevent arithmetic overflow */
++ if (size > MAX_DIRECTIO_SIZE)
++ return -EFBIG;
+
+- *pages = (struct page **) kmalloc(array_size, GFP_KERNEL);
++ page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ page_count -= user_addr >> PAGE_SHIFT;
++
++ array_size = (page_count * sizeof(struct page *));
++ *pages = kmalloc(array_size, GFP_KERNEL);
+ if (*pages) {
+ down_read(¤t->mm->mmap_sem);
+- result = get_user_pages(current, current->mm, addr,
+- page_count, (rw == WRITE), 0,
++ result = get_user_pages(current, current->mm, user_addr,
++ page_count, (rw == READ), 0,
+ *pages, NULL);
+ up_read(¤t->mm->mmap_sem);
+- if (result < 0)
+- printk(KERN_ERR "%s: get_user_pages result %d\n",
+- __FUNCTION__, result);
+ }
+ return result;
+ }
+@@ -84,176 +94,349 @@ nfs_get_user_pages(unsigned long addr, s
+ * @pages: array of page struct pointers underlying target buffer
+ */
+ static inline void
+-nfs_free_user_pages(struct page **pages, unsigned count)
++nfs_free_user_pages(struct page **pages)
+ {
+- unsigned page = 0;
++ kfree(pages);
++}
+
+- while (count--)
+- page_cache_release(pages[page++]);
++/**
++ * nfs_direct_read_seg - Read in one iov segment. Generate separate
++ * read RPCs for each "rsize" bytes.
++ * @inode: target inode
++ * @cred: user's credential
++ * user_addr: starting address of this segment of user's buffer
++ * count: size of this segment
++ * file_offset: offset in file to begin the operation
++ * @pages: array of addresses of page structs defining user's buffer
++ * nr_pages: size of pages array
++ */
++static int
++nfs_direct_read_seg(struct inode *inode, struct rpc_cred *cred,
++ unsigned long user_addr, size_t count, loff_t file_offset,
++ struct page **pages, int nr_pages)
++{
++ const unsigned int rsize = NFS_SERVER(inode)->rsize;
++ int tot_bytes = 0;
++ int curpage = 0;
++ struct nfs_read_data rdata = {
++ .flags = 0,
++ .cred = cred,
++ .inode = inode,
++ .args = {
++ .fh = NFS_FH(inode),
++ },
++ .res = {
++ .fattr = &rdata.fattr,
++ },
++ };
++
++ do {
++ int request, result;
++
++ request = count;
++ if (count > rsize)
++ request = rsize;
++ rdata.args.count = request,
++ rdata.args.pgbase = user_addr & ~PAGE_MASK;
++ rdata.args.offset = file_offset;
++ rdata.args.pages = &pages[curpage];
++
++ dprintk("NFS: direct read: c=%u o=%Ld ua=%lu, pb=%u, cp=%u\n",
++ rdata.args.count, (long long) rdata.args.offset,
++ user_addr, rdata.args.pgbase, curpage);
++
++ lock_kernel();
++ result = NFS_PROTO(inode)->read(&rdata);
++ unlock_kernel();
++
++ if (result < 0) {
++ if (result == -EISDIR)
++ result = -EINVAL;
++ return result;
++ }
+
+- kfree(pages);
++ tot_bytes += result;
++ count -= result;
++ file_offset += result;
++ user_addr += result;
++
++ if (rdata.res.eof)
++ break;
++
++ curpage += (rdata.args.pgbase + result) >> PAGE_SHIFT;
++ } while (count);
++
++ /* XXX: should we zero the rest of the user's buffer if we
++ * hit eof? */
++
++ return tot_bytes;
+ }
+
+ /**
+- * nfs_iov2pagelist - convert an array of iovecs to a list of page requests
+- * @inode: inode of target file
+- * @cred: credentials of user who requested I/O
++ * nfs_direct_read - For each iov segment, map the user's buffer
++ * then generate read RPCs.
++ * @inode: target inode
++ * @cred: user's credential
+ * @iov: array of vectors that define I/O buffer
+- * offset: where in file to begin the read
++ * file_offset: offset in file to begin the operation
+ * nr_segs: size of iovec array
+- * @requests: append new page requests to this list head
++ *
++ * generic_file_direct_IO has already pushed out any non-direct
++ * writes so that this read will see them when we read from the
++ * server.
+ */
+ static int
+-nfs_iov2pagelist(int rw, const struct inode *inode,
+- const struct rpc_cred *cred,
+- const struct iovec *iov, loff_t offset,
+- unsigned long nr_segs, struct list_head *requests)
++nfs_direct_read(struct inode *inode, struct rpc_cred *cred,
++ const struct iovec *iov, loff_t file_offset,
++ unsigned long nr_segs)
+ {
+- unsigned seg;
+ int tot_bytes = 0;
+- struct page **pages;
++ unsigned long seg = 0;
+
+- /* for each iovec in the array... */
+- for (seg = 0; seg < nr_segs; seg++) {
+- const unsigned long user_addr =
+- (unsigned long) iov[seg].iov_base;
+- size_t bytes = iov[seg].iov_len;
+- unsigned int pg_offset = (user_addr & ~PAGE_MASK);
+- int page_count, page = 0;
+-
+- page_count = nfs_get_user_pages(user_addr, bytes, &pages, rw);
+- if (page_count < 0) {
+- nfs_release_list(requests);
+- return page_count;
++ while ((seg < nr_segs) && (tot_bytes >= 0)) {
++ int result, page_count;
++ struct page **pages;
++ const struct iovec *vec = &iov[seg++];
++ unsigned long user_addr = (unsigned long) vec->iov_base;
++ size_t size = vec->iov_len;
++
++ page_count = nfs_get_user_pages(READ, user_addr, size, &pages);
++ if (page_count < 0) {
++ nfs_free_user_pages(pages);
++ return page_count;
++ }
++
++ result = nfs_direct_read_seg(inode, cred, user_addr, size,
++ file_offset, pages, page_count);
++ if (result < 0)
++ tot_bytes = result;
++ else {
++ tot_bytes += result;
++ file_offset += result;
+ }
+
+- /* ...build as many page requests as required */
+- while (bytes > 0) {
+- struct nfs_page *new;
+- const unsigned int pg_bytes = (bytes > PAGE_SIZE) ?
+- PAGE_SIZE : bytes;
+-
+- new = nfs_create_request((struct rpc_cred *) cred,
+- (struct inode *) inode,
+- pages[page],
+- pg_offset, pg_bytes);
+- if (IS_ERR(new)) {
+- nfs_free_user_pages(pages, page_count);
+- nfs_release_list(requests);
+- return PTR_ERR(new);
+- }
+- new->wb_index = offset;
+- nfs_list_add_request(new, requests);
+-
+- /* after the first page */
+- pg_offset = 0;
+- offset += PAGE_SIZE;
+- tot_bytes += pg_bytes;
+- bytes -= pg_bytes;
+- page++;
++ nfs_free_user_pages(pages);
++ }
++
++ return tot_bytes;
++}
++
++/**
++ * nfs_direct_write_seg - Write out one iov segment. Generate separate
++ * write RPCs for each "wsize" bytes, then commit.
++ * @inode: target inode
++ * @cred: user's credential
++ * user_addr: starting address of this segment of user's buffer
++ * count: size of this segment
++ * file_offset: offset in file to begin the operation
++ * @pages: array of addresses of page structs defining user's buffer
++ * nr_pages: size of pages array
++ */
++static int
++nfs_direct_write_seg(struct inode *inode, struct rpc_cred *cred,
++ unsigned long user_addr, size_t count, loff_t file_offset,
++ struct page **pages, int nr_pages)
++{
++ const unsigned int wsize = NFS_SERVER(inode)->wsize;
++ loff_t save_offset = file_offset;
++ size_t save_count = count;
++ int need_commit = 0;
++ int tot_bytes = 0;
++ int curpage = 0;
++ struct nfs_writeverf first_verf;
++ struct nfs_write_data wdata = {
++ .cred = cred,
++ .inode = inode,
++ .args = {
++ .fh = NFS_FH(inode),
++ },
++ .res = {
++ .fattr = &wdata.fattr,
++ .verf = &wdata.verf,
++ },
++ };
++
++ wdata.args.stable = NFS_UNSTABLE;
++ if (IS_SYNC(inode) || NFS_PROTO(inode)->version == 2 || count <= wsize)
++ wdata.args.stable = NFS_FILE_SYNC;
++
++retry:
++ do {
++ int request, result;
++
++ request = count;
++ if (count > wsize)
++ request = wsize;
++ wdata.args.count = request,
++ wdata.args.pgbase = user_addr & ~PAGE_MASK;
++ wdata.args.offset = file_offset;
++ wdata.args.pages = &pages[curpage];
++
++ dprintk("NFS: direct write: c=%u o=%Ld ua=%lu, pb=%u, cp=%u\n",
++ wdata.args.count, (long long) wdata.args.offset,
++ user_addr, wdata.args.pgbase, curpage);
++
++ lock_kernel();
++ result = NFS_PROTO(inode)->write(&wdata);
++ unlock_kernel();
++
++ if (result < 0)
++ return result;
++
++ if (!tot_bytes)
++ memcpy(&first_verf.verifier, &wdata.verf.verifier,
++ VERF_SIZE);
++ if (wdata.verf.committed != NFS_FILE_SYNC) {
++ need_commit = 1;
++ if (memcmp(&first_verf.verifier,
++ &wdata.verf.verifier, VERF_SIZE))
++ goto sync_retry;
+ }
+
+- /* don't release pages here -- I/O completion will do that */
+- nfs_free_user_pages(pages, 0);
++ tot_bytes += result;
++ count -= result;
++ file_offset += result;
++ user_addr += result;
++
++ curpage += (wdata.args.pgbase + result) >> PAGE_SHIFT;
++ } while (count);
++
++ /*
++ * Commit data written so far, even in the event of an error
++ */
++ if (need_commit) {
++ int result;
++
++ wdata.args.count = tot_bytes;
++ wdata.args.offset = save_offset;
++
++ lock_kernel();
++ result = NFS_PROTO(inode)->commit(&wdata);
++ unlock_kernel();
++
++ if (result < 0)
++ goto sync_retry;
++ if (memcmp(&first_verf.verifier, &wdata.verf.verifier,
++ VERF_SIZE))
++ goto sync_retry;
+ }
+
+ return tot_bytes;
++
++sync_retry:
++ wdata.args.stable = NFS_FILE_SYNC;
++ file_offset = save_offset;
++ count = save_count;
++ goto retry;
+ }
+
+ /**
+- * do_nfs_direct_IO - Read or write data without caching
+- * @inode: inode of target file
+- * @cred: credentials of user who requested I/O
++ * nfs_direct_write - For each iov segment, map the user's buffer
++ * then generate write and commit RPCs.
++ * @inode: target inode
++ * @cred: user's credential
+ * @iov: array of vectors that define I/O buffer
+- * offset: where in file to begin the read
++ * file_offset: offset in file to begin the operation
+ * nr_segs: size of iovec array
+ *
+- * Break the passed-in iovec into a series of page-sized or smaller
+- * requests, where each page is mapped for direct user-land I/O.
+- *
+- * For each of these pages, create an NFS page request and
+- * append it to an automatic list of page requests.
+- *
+- * When all page requests have been queued, start the I/O on the
+- * whole list. The underlying routines coalesce the pages on the
+- * list into a bunch of asynchronous "r/wsize" network requests.
+- *
+- * I/O completion automatically unmaps and releases the pages.
++ * Upon return, generic_file_direct_IO invalidates any cached pages
++ * that non-direct readers might access, so they will pick up these
++ * writes immediately.
+ */
+ static int
+-do_nfs_direct_IO(int rw, const struct inode *inode,
+- const struct rpc_cred *cred, const struct iovec *iov,
+- loff_t offset, unsigned long nr_segs)
++nfs_direct_write(struct inode *inode, struct rpc_cred *cred,
++ const struct iovec *iov, loff_t file_offset,
++ unsigned long nr_segs)
+ {
+- LIST_HEAD(requests);
+- int result, tot_bytes;
++ int tot_bytes = 0;
++ unsigned long seg = 0;
+
+- result = nfs_iov2pagelist(rw, inode, cred, iov, offset, nr_segs,
+- &requests);
+- if (result < 0)
+- return result;
+- tot_bytes = result;
++ while ((seg < nr_segs) && (tot_bytes >= 0)) {
++ int result, page_count;
++ struct page **pages;
++ const struct iovec *vec = &iov[seg++];
++ unsigned long user_addr = (unsigned long) vec->iov_base;
++ size_t size = vec->iov_len;
++
++ page_count = nfs_get_user_pages(WRITE, user_addr, size, &pages);
++ if (page_count < 0) {
++ nfs_free_user_pages(pages);
++ return page_count;
++ }
+
+- switch (rw) {
+- case READ:
+- if (IS_SYNC(inode) || (NFS_SERVER(inode)->rsize < PAGE_SIZE)) {
+- result = nfs_direct_read_sync(inode, cred, iov, offset, nr_segs);
+- break;
++ result = nfs_direct_write_seg(inode, cred, user_addr, size,
++ file_offset, pages, page_count);
++ if (result < 0)
++ tot_bytes = result;
++ else {
++ tot_bytes += result;
++ file_offset += result;
+ }
+- result = nfs_pagein_list(&requests, NFS_SERVER(inode)->rpages);
+- nfs_wait_for_reads(&requests);
+- break;
+- case WRITE:
+- if (IS_SYNC(inode) || (NFS_SERVER(inode)->wsize < PAGE_SIZE))
+- result = nfs_direct_write_sync(inode, cred, iov, offset, nr_segs);
+- else
+- result = nfs_flush_list(&requests,
+- NFS_SERVER(inode)->wpages, FLUSH_WAIT);
+
+- /* invalidate cache so non-direct readers pick up changes */
+- invalidate_inode_pages((struct inode *) inode);
+- break;
+- default:
+- result = -EINVAL;
+- break;
++ nfs_free_user_pages(pages);
+ }
+
+- if (result < 0)
+- return result;
+ return tot_bytes;
+ }
+
+ /**
+ * nfs_direct_IO - NFS address space operation for direct I/O
+ * rw: direction (read or write)
+- * @file: file struct of target file
++ * @iocb: target I/O control block
+ * @iov: array of vectors that define I/O buffer
+- * offset: offset in file to begin the operation
++ * file_offset: offset in file to begin the operation
+ * nr_segs: size of iovec array
+ *
++ * Usually a file system implements direct I/O by calling out to
++ * blockdev_direct_IO. The NFS client doesn't have a backing block
++ * device, so we do everything by hand instead.
++ *
+ * The inode's i_sem is no longer held by the VFS layer before it calls
+ * this function to do a write.
+ */
+ int
+ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+- loff_t offset, unsigned long nr_segs)
++ loff_t file_offset, unsigned long nr_segs)
+ {
+- /* None of this works yet, so prevent it from compiling. */
+-#if 0
+- int result;
++ int result = -EINVAL;
++ struct file *file = iocb->ki_filp;
+ struct dentry *dentry = file->f_dentry;
+- const struct inode *inode = dentry->d_inode->i_mapping->host;
+- const struct rpc_cred *cred = nfs_file_cred(file);
+-#endif
+-
+- dfprintk(VFS, "NFS: direct_IO(%s) (%s/%s) off/no(%Lu/%lu)\n",
+- ((rw == READ) ? "READ" : "WRITE"),
+- dentry->d_parent->d_name.name,
+- dentry->d_name.name, offset, nr_segs);
++ struct inode *inode = dentry->d_inode;
++ struct rpc_cred *cred;
++
++ /*
++ * No support for async yet
++ */
++ if (!is_sync_kiocb(iocb))
++ goto out;
++
++ cred = get_rpccred(nfs_file_cred(file));
++ if (!cred)
++ cred = get_rpccred(NFS_I(inode)->mm_cred);
++
++ switch (rw) {
++ case READ:
++ dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
++ dentry->d_name.name, file_offset, nr_segs);
++
++ result = nfs_direct_read(inode, cred, iov,
++ file_offset, nr_segs);
++ break;
++ case WRITE:
++ dprintk("NFS: direct_IO(write) (%s) off/no(%Lu/%lu)\n",
++ dentry->d_name.name, file_offset, nr_segs);
+
+- result = do_nfs_direct_IO(rw, inode, cred, iov, offset, nr_segs);
++ result = nfs_direct_write(inode, cred, iov,
++ file_offset, nr_segs);
++ break;
++ default:
++ break;
++ }
+
+- dfprintk(VFS, "NFS: direct_IO result = %d\n", result);
++ if (cred)
++ put_rpccred(cred);
+
++out:
++ dprintk("NFS: direct_IO result=%d\n", result);
+ return result;
+ }
+--- linux-2.6.0-test6/fs/nfsd/nfsctl.c 2003-07-02 14:53:16.000000000 -0700
++++ 25/fs/nfsd/nfsctl.c 2003-10-05 00:33:24.000000000 -0700
+@@ -429,6 +429,7 @@ static struct file_system_type nfsd_fs_t
+
+ static int __init init_nfsd(void)
+ {
++ int retval;
+ printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
+
+ nfsd_stat_init(); /* Statistics */
+@@ -441,8 +442,16 @@ static int __init init_nfsd(void)
+ if (entry)
+ entry->proc_fops = &exports_operations;
+ }
+- register_filesystem(&nfsd_fs_type);
+- return 0;
++ retval = register_filesystem(&nfsd_fs_type);
++ if (retval) {
++ nfsd_export_shutdown();
++ nfsd_cache_shutdown();
++ remove_proc_entry("fs/nfs/exports", NULL);
++ remove_proc_entry("fs/nfs", NULL);
++ nfsd_stat_shutdown();
++ nfsd_lockd_shutdown();
++ }
++ return retval;
+ }
+
+ static void __exit exit_nfsd(void)
+--- linux-2.6.0-test6/fs/nfs/file.c 2003-07-10 18:50:32.000000000 -0700
++++ 25/fs/nfs/file.c 2003-10-05 00:34:08.000000000 -0700
+@@ -262,7 +262,7 @@ out_swapfile:
+ int
+ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+ {
+- struct inode * inode = filp->f_dentry->d_inode;
++ struct inode * inode = filp->f_mapping->host;
+ int status = 0;
+ int status2;
+
+@@ -305,13 +305,13 @@ nfs_lock(struct file *filp, int cmd, str
+ * Flush all pending writes before doing anything
+ * with locks..
+ */
+- status = filemap_fdatawrite(inode->i_mapping);
++ status = filemap_fdatawrite(filp->f_mapping);
+ down(&inode->i_sem);
+ status2 = nfs_wb_all(inode);
+ if (!status)
+ status = status2;
+ up(&inode->i_sem);
+- status2 = filemap_fdatawait(inode->i_mapping);
++ status2 = filemap_fdatawait(filp->f_mapping);
+ if (!status)
+ status = status2;
+ if (status < 0)
+@@ -331,11 +331,11 @@ nfs_lock(struct file *filp, int cmd, str
+ */
+ out_ok:
+ if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
+- filemap_fdatawrite(inode->i_mapping);
++ filemap_fdatawrite(filp->f_mapping);
+ down(&inode->i_sem);
+ nfs_wb_all(inode); /* we may have slept */
+ up(&inode->i_sem);
+- filemap_fdatawait(inode->i_mapping);
++ filemap_fdatawait(filp->f_mapping);
+ nfs_zap_caches(inode);
+ }
+ return status;
+--- linux-2.6.0-test6/fs/nfs/nfs3proc.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/nfs/nfs3proc.c 2003-10-05 00:36:45.000000000 -0700
+@@ -225,81 +225,74 @@ nfs3_proc_readlink(struct inode *inode,
+ }
+
+ static int
+-nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int flags,
+- unsigned int base, unsigned int count, struct page *page,
+- int *eofp)
+-{
+- u64 offset = page_offset(page) + base;
+- struct nfs_readargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .pgbase = base,
+- .pages = &page
+- };
+- struct nfs_readres res = {
+- .fattr = fattr,
+- .count = count,
+- };
++nfs3_proc_read(struct nfs_read_data *rdata)
++{
++ int flags = rdata->flags;
++ struct inode * inode = rdata->inode;
++ struct nfs_fattr * fattr = rdata->res.fattr;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_READ],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred
++ .rpc_argp = &rdata->args,
++ .rpc_resp = &rdata->res,
++ .rpc_cred = rdata->cred,
+ };
+ int status;
+
+- dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
++ (long long) rdata->args.offset);
+ fattr->valid = 0;
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
+ if (status >= 0)
+ nfs_refresh_inode(inode, fattr);
+ dprintk("NFS reply read: %d\n", status);
+- *eofp = res.eof;
+ return status;
+ }
+
+ static int
+-nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int flags,
+- unsigned int base, unsigned int count,
+- struct page *page, struct nfs_writeverf *verf)
++nfs3_proc_write(struct nfs_write_data *wdata)
+ {
+- u64 offset = page_offset(page) + base;
+- struct nfs_writeargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .stable = NFS_FILE_SYNC,
+- .pgbase = base,
+- .pages = &page
+- };
+- struct nfs_writeres res = {
+- .fattr = fattr,
+- .verf = verf,
+- };
++ int rpcflags = wdata->flags;
++ struct inode * inode = wdata->inode;
++ struct nfs_fattr * fattr = wdata->res.fattr;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[NFS3PROC_WRITE],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred
++ .rpc_argp = &wdata->args,
++ .rpc_resp = &wdata->res,
++ .rpc_cred = wdata->cred,
+ };
+- int status, rpcflags = 0;
++ int status;
+
+- dprintk("NFS call write %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
++ (long long) wdata->args.offset);
+ fattr->valid = 0;
+- if (flags & NFS_RW_SWAP)
+- rpcflags |= NFS_RPC_SWAPFLAGS;
+- arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
+-
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
+-
+ if (status >= 0)
+ nfs3_write_refresh_inode(inode, fattr);
++ dprintk("NFS reply write: %d\n", status);
++ return status < 0? status : wdata->res.count;
++}
+
+- dprintk("NFS reply read: %d\n", status);
+- return status < 0? status : res.count;
++static int
++nfs3_proc_commit(struct nfs_write_data *cdata)
++{
++ struct inode * inode = cdata->inode;
++ struct nfs_fattr * fattr = cdata->res.fattr;
++ struct rpc_message msg = {
++ .rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT],
++ .rpc_argp = &cdata->args,
++ .rpc_resp = &cdata->res,
++ .rpc_cred = cdata->cred,
++ };
++ int status;
++
++ dprintk("NFS call commit %d @ %Ld\n", cdata->args.count,
++ (long long) cdata->args.offset);
++ fattr->valid = 0;
++ status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
++ if (status >= 0)
++ nfs3_write_refresh_inode(inode, fattr);
++ dprintk("NFS reply commit: %d\n", status);
++ return status;
+ }
+
+ /*
+@@ -863,6 +856,7 @@ struct nfs_rpc_ops nfs_v3_clientops = {
+ .readlink = nfs3_proc_readlink,
+ .read = nfs3_proc_read,
+ .write = nfs3_proc_write,
++ .commit = nfs3_proc_commit,
+ .create = nfs3_proc_create,
+ .remove = nfs3_proc_remove,
+ .unlink_setup = nfs3_proc_unlink_setup,
+--- linux-2.6.0-test6/fs/nfs/nfs4proc.c 2003-06-26 22:07:25.000000000 -0700
++++ 25/fs/nfs/nfs4proc.c 2003-10-05 00:36:45.000000000 -0700
+@@ -1012,45 +1012,36 @@ nfs4_proc_readlink(struct inode *inode,
+ }
+
+ static int
+-nfs4_proc_read(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int flags,
+- unsigned int base, unsigned int count,
+- struct page *page, int *eofp)
++nfs4_proc_read(struct nfs_read_data *rdata)
+ {
++ int flags = rdata->flags;
++ struct inode *inode = rdata->inode;
++ struct nfs_fattr *fattr = rdata->res.fattr;
++ nfs4_stateid *stateid = &rdata->args.stateid;
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs4_shareowner *sp;
+- uint64_t offset = page_offset(page) + base;
+- struct nfs_readargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .pgbase = base,
+- .pages = &page,
+- };
+- struct nfs_readres res = {
+- .fattr = fattr,
+- .count = count,
+- };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred,
++ .rpc_argp = &rdata->args,
++ .rpc_resp = &rdata->res,
++ .rpc_cred = rdata->cred,
+ };
+ unsigned long timestamp = jiffies;
+ int status;
+
+- dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
++ (long long) rdata->args.offset);
++
+ /*
+- * Try first to use O_RDONLY, then O_RDWR stateid.
+- */
++ * Try first to use O_RDONLY, then O_RDWR stateid.
++ */
+ sp = nfs4_get_inode_share(inode, O_RDONLY);
+ if (!sp)
+ sp = nfs4_get_inode_share(inode, O_RDWR);
+ if (sp)
+- memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid));
++ memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
+ else
+- memcpy(arg.stateid, zero_stateid, sizeof(nfs4_stateid));
++ memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
+
+ fattr->valid = 0;
+ status = rpc_call_sync(server->client, &msg, flags);
+@@ -1061,56 +1052,82 @@ nfs4_proc_read(struct inode *inode, stru
+ nfs_zap_caches(inode);
+ }
+ dprintk("NFS reply read: %d\n", status);
+- *eofp = res.eof;
+ return status;
+ }
+
+ static int
+-nfs4_proc_write(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int flags,
+- unsigned int base, unsigned int count,
+- struct page *page, struct nfs_writeverf *verf)
++nfs4_proc_write(struct nfs_write_data *wdata)
+ {
++ int rpcflags = wdata->flags;
++ struct inode *inode = wdata->inode;
++ struct nfs_fattr *fattr = wdata->res.fattr;
++ nfs4_stateid *stateid = &wdata->args.stateid;
+ struct nfs_server *server = NFS_SERVER(inode);
+- struct nfs4_shareowner *sp;
+- uint64_t offset = page_offset(page) + base;
+- struct nfs_writeargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE,
+- .pgbase = base,
+- .pages = &page,
+- };
+- struct nfs_writeres res = {
+- .fattr = fattr,
+- .count = count,
+- .verf = verf,
+- };
++ struct nfs4_shareowner *sp;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred,
++ .rpc_argp = &wdata->args,
++ .rpc_resp = &wdata->res,
++ .rpc_cred = wdata->cred,
++ };
++ int status;
++
++ dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
++ (long long) wdata->args.offset);
++
++ /*
++ * Try first to use O_WRONLY, then O_RDWR stateid.
++ */
++ sp = nfs4_get_inode_share(inode, O_WRONLY);
++ if (!sp)
++ sp = nfs4_get_inode_share(inode, O_RDWR);
++
++ if (sp)
++ memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
++ else
++ memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
++
++ fattr->valid = 0;
++ status = rpc_call_sync(server->client, &msg, rpcflags);
++ dprintk("NFS reply write: %d\n", status);
++ return status;
++}
++
++static int
++nfs4_proc_commit(struct nfs_write_data *cdata)
++{
++ struct inode *inode = cdata->inode;
++ struct nfs_fattr *fattr = cdata->res.fattr;
++ nfs4_stateid *stateid = &cdata->args.stateid;
++ struct nfs_server *server = NFS_SERVER(inode);
++ struct nfs4_shareowner *sp;
++ struct rpc_message msg = {
++ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
++ .rpc_argp = &cdata->args,
++ .rpc_resp = &cdata->res,
++ .rpc_cred = cdata->cred,
+ };
+- int rpcflags = (flags & NFS_RW_SWAP) ? NFS_RPC_SWAPFLAGS : 0;
++ int status;
+
+- dprintk("NFS call write %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call commit %d @ %Ld\n", cdata->args.count,
++ (long long) cdata->args.offset);
+
+ /*
+- * Try first to use O_WRONLY, then O_RDWR stateid.
+- */
++ * Try first to use O_WRONLY, then O_RDWR stateid.
++ */
+ sp = nfs4_get_inode_share(inode, O_WRONLY);
+ if (!sp)
+ sp = nfs4_get_inode_share(inode, O_RDWR);
+
+ if (sp)
+- memcpy(arg.stateid,sp->so_stateid, sizeof(nfs4_stateid));
++ memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
+ else
+- memcpy(arg.stateid, zero_stateid, sizeof(nfs4_stateid));
++ memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
+
+ fattr->valid = 0;
+- return rpc_call_sync(server->client, &msg, rpcflags);
++ status = rpc_call_sync(server->client, &msg, 0);
++ dprintk("NFS reply commit: %d\n", status);
++ return status;
+ }
+
+ /*
+@@ -1752,7 +1769,7 @@ struct nfs_rpc_ops nfs_v4_clientops = {
+ .readlink = nfs4_proc_readlink,
+ .read = nfs4_proc_read,
+ .write = nfs4_proc_write,
+- .commit = NULL,
++ .commit = nfs4_proc_commit,
+ .create = nfs4_proc_create,
+ .remove = nfs4_proc_remove,
+ .unlink_setup = nfs4_proc_unlink_setup,
+--- linux-2.6.0-test6/fs/nfs/pagelist.c 2003-06-26 22:07:25.000000000 -0700
++++ 25/fs/nfs/pagelist.c 2003-10-05 00:36:43.000000000 -0700
+@@ -154,26 +154,6 @@ nfs_release_request(struct nfs_page *req
+ }
+
+ /**
+- * nfs_release_list - cleanly dispose of an unattached list of page requests
+- * @list: list of doomed page requests
+- */
+-void
+-nfs_release_list(struct list_head *list)
+-{
+- while (!list_empty(list)) {
+- struct nfs_page *req = nfs_list_entry(list);
+-
+- nfs_list_remove_request(req);
+-
+- page_cache_release(req->wb_page);
+-
+- /* Release struct file or cached credential */
+- nfs_clear_request(req);
+- nfs_page_free(req);
+- }
+-}
+-
+-/**
+ * nfs_list_add_request - Insert a request into a sorted list
+ * @req: request
+ * @head: head of list into which to insert the request.
+@@ -222,37 +202,6 @@ nfs_wait_on_request(struct nfs_page *req
+ }
+
+ /**
+- * nfs_wait_for_reads - wait for outstanding requests to complete
+- * @head: list of page requests to wait for
+- */
+-int
+-nfs_wait_for_reads(struct list_head *head)
+-{
+- struct list_head *p = head->next;
+- unsigned int res = 0;
+-
+- while (p != head) {
+- struct nfs_page *req = nfs_list_entry(p);
+- int error;
+-
+- if (!NFS_WBACK_BUSY(req))
+- continue;
+-
+- req->wb_count++;
+- error = nfs_wait_on_request(req);
+- if (error < 0)
+- return error;
+- nfs_list_remove_request(req);
+- nfs_clear_request(req);
+- nfs_page_free(req);
+-
+- p = head->next;
+- res++;
+- }
+- return res;
+-}
+-
+-/**
+ * nfs_coalesce_requests - Split coalesced requests out from a list.
+ * @head: source list
+ * @dst: destination list
+--- linux-2.6.0-test6/fs/nfs/proc.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/nfs/proc.c 2003-10-05 00:36:44.000000000 -0700
+@@ -149,82 +149,62 @@ nfs_proc_readlink(struct inode *inode, s
+ }
+
+ static int
+-nfs_proc_read(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int flags,
+- unsigned int base, unsigned int count, struct page *page,
+- int *eofp)
+-{
+- u64 offset = page_offset(page) + base;
+- struct nfs_readargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .pgbase = base,
+- .pages = &page
+- };
+- struct nfs_readres res = {
+- .fattr = fattr,
+- .count = count
+- };
++nfs_proc_read(struct nfs_read_data *rdata)
++{
++ int flags = rdata->flags;
++ struct inode * inode = rdata->inode;
++ struct nfs_fattr * fattr = rdata->res.fattr;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_READ],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred
++ .rpc_argp = &rdata->args,
++ .rpc_resp = &rdata->res,
++ .rpc_cred = rdata->cred,
+ };
+ int status;
+
+- dprintk("NFS call read %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call read %d @ %Ld\n", rdata->args.count,
++ (long long) rdata->args.offset);
+ fattr->valid = 0;
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
+-
+- if (status >= 0)
++ if (status >= 0) {
+ nfs_refresh_inode(inode, fattr);
++ /* NFSv2 reads don't return an eof flag, so we make
++ * up a value here. XDR has already set eof to 0. */
++ if (status < rdata->args.count)
++ rdata->res.eof = 1;
++ }
+ dprintk("NFS reply read: %d\n", status);
+- *eofp = res.eof;
+ return status;
+ }
+
+ static int
+-nfs_proc_write(struct inode *inode, struct rpc_cred *cred,
+- struct nfs_fattr *fattr, int how,
+- unsigned int base, unsigned int count,
+- struct page *page, struct nfs_writeverf *verf)
++nfs_proc_write(struct nfs_write_data *wdata)
+ {
+- u64 offset = page_offset(page) + base;
+- struct nfs_writeargs arg = {
+- .fh = NFS_FH(inode),
+- .offset = offset,
+- .count = count,
+- .stable = NFS_FILE_SYNC,
+- .pgbase = base,
+- .pages = &page
+- };
+- struct nfs_writeres res = {
+- .fattr = fattr,
+- .verf = verf,
+- .count = count
+- };
++ int flags = wdata->flags;
++ struct inode * inode = wdata->inode;
++ struct nfs_fattr * fattr = wdata->res.fattr;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[NFSPROC_WRITE],
+- .rpc_argp = &arg,
+- .rpc_resp = &res,
+- .rpc_cred = cred
++ .rpc_argp = &wdata->args,
++ .rpc_resp = &wdata->res,
++ .rpc_cred = wdata->cred
+ };
+- int status, flags = 0;
++ int status;
+
+- dprintk("NFS call write %d @ %Ld\n", count, (long long)offset);
++ dprintk("NFS call write %d @ %Ld\n", wdata->args.count,
++ (long long) wdata->args.offset);
+ fattr->valid = 0;
+- if (how & NFS_RW_SWAP)
+- flags |= NFS_RPC_SWAPFLAGS;
+ status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
+-
+- if (status >= 0)
++ if (status >= 0) {
+ nfs_write_refresh_inode(inode, fattr);
+-
++ /* NFSv2 writes don't return a byte count or write
++ * verifier, so we make up values here. Note that
++ * v2 writes are always NFS_FILE_SYNC writes. */
++ wdata->res.count = wdata->args.count;
++ wdata->verf.committed = NFS_FILE_SYNC;
++ }
+ dprintk("NFS reply write: %d\n", status);
+- verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */
+- return status < 0? status : count;
++ return status < 0? status : wdata->res.count;
+ }
+
+ static int
+--- linux-2.6.0-test6/fs/nfs/read.c 2003-06-26 22:07:25.000000000 -0700
++++ 25/fs/nfs/read.c 2003-10-05 00:36:44.000000000 -0700
+@@ -69,19 +69,28 @@ void nfs_readdata_release(struct rpc_tas
+ static int
+ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
+ {
+- struct rpc_cred *cred = NULL;
+- struct nfs_fattr fattr;
+- unsigned int offset = 0;
+ unsigned int rsize = NFS_SERVER(inode)->rsize;
+ unsigned int count = PAGE_CACHE_SIZE;
+ int result;
+- int flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
+- int eof;
++ struct nfs_read_data rdata = {
++ .flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0),
++ .cred = NULL,
++ .inode = inode,
++ .args = {
++ .fh = NFS_FH(inode),
++ .pages = &page,
++ .pgbase = 0UL,
++ .count = rsize,
++ },
++ .res = {
++ .fattr = &rdata.fattr,
++ }
++ };
+
+ dprintk("NFS: nfs_readpage_sync(%p)\n", page);
+
+ if (file)
+- cred = nfs_file_cred(file);
++ rdata.cred = nfs_file_cred(file);
+
+ /*
+ * This works now because the socket layer never tries to DMA
+@@ -89,17 +98,19 @@ nfs_readpage_sync(struct file *file, str
+ */
+ do {
+ if (count < rsize)
+- rsize = count;
++ rdata.args.count = count;
++ rdata.res.count = rdata.args.count;
++ rdata.args.offset = page_offset(page) + rdata.args.pgbase;
+
+ dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n",
+ NFS_SERVER(inode)->hostname,
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
+- (unsigned long long)offset, rsize);
++ (unsigned long long)rdata.args.pgbase,
++ rdata.args.count);
+
+ lock_kernel();
+- result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
+- offset, rsize, page, &eof);
++ result = NFS_PROTO(inode)->read(&rdata);
+ unlock_kernel();
+
+ /*
+@@ -111,14 +122,15 @@ nfs_readpage_sync(struct file *file, str
+ result = -EINVAL;
+ goto io_error;
+ }
+- count -= result;
+- offset += result;
+- if (result < rsize) /* NFSv2ism */
++ count -= result;
++ rdata.args.pgbase += result;
++
++ if (rdata.res.eof)
+ break;
+ } while (count);
+
+ if (count)
+- memclear_highpage_flush(page, offset, count);
++ memclear_highpage_flush(page, rdata.args.pgbase, count);
+ SetPageUptodate(page);
+ if (PageError(page))
+ ClearPageError(page);
+--- linux-2.6.0-test6/fs/nfs/write.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/nfs/write.c 2003-10-05 00:36:44.000000000 -0700
+@@ -132,66 +132,73 @@ static int
+ nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
+ unsigned int offset, unsigned int count)
+ {
+- struct rpc_cred *cred = NULL;
+- loff_t base;
+ unsigned int wsize = NFS_SERVER(inode)->wsize;
+- int result, refresh = 0, written = 0, flags;
+- u8 *buffer;
+- struct nfs_fattr fattr;
+- struct nfs_writeverf verf;
+-
++ int result, written = 0;
++ int swapfile = IS_SWAPFILE(inode);
++ struct nfs_write_data wdata = {
++ .flags = swapfile ? NFS_RPC_SWAPFLAGS : 0,
++ .cred = NULL,
++ .inode = inode,
++ .args = {
++ .fh = NFS_FH(inode),
++ .pages = &page,
++ .stable = NFS_FILE_SYNC,
++ .pgbase = offset,
++ .count = wsize,
++ },
++ .res = {
++ .fattr = &wdata.fattr,
++ .verf = &wdata.verf,
++ },
++ };
+
+ if (file)
+- cred = get_rpccred(nfs_file_cred(file));
+- if (!cred)
+- cred = get_rpccred(NFS_I(inode)->mm_cred);
++ wdata.cred = get_rpccred(nfs_file_cred(file));
++ if (!wdata.cred)
++ wdata.cred = get_rpccred(NFS_I(inode)->mm_cred);
+
+ dprintk("NFS: nfs_writepage_sync(%s/%Ld %d@%Ld)\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode),
+ count, (long long)(page_offset(page) + offset));
+
+- base = page_offset(page) + offset;
+-
+- flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC;
+-
+ do {
+- if (count < wsize && !IS_SWAPFILE(inode))
+- wsize = count;
++ if (count < wsize && !swapfile)
++ wdata.args.count = count;
++ wdata.args.offset = page_offset(page) + wdata.args.pgbase;
+
+- result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
+- offset, wsize, page, &verf);
++ result = NFS_PROTO(inode)->write(&wdata);
+
+ if (result < 0) {
+ /* Must mark the page invalid after I/O error */
+ ClearPageUptodate(page);
+ goto io_error;
+ }
+- if (result != wsize)
+- printk("NFS: short write, wsize=%u, result=%d\n",
+- wsize, result);
+- refresh = 1;
+- buffer += wsize;
+- base += wsize;
+- offset += wsize;
+- written += wsize;
+- count -= wsize;
++ if (result < wdata.args.count)
++ printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n",
++ wdata.args.count, result);
++
++ wdata.args.offset += result;
++ wdata.args.pgbase += result;
++ written += result;
++ count -= result;
++
+ /*
+ * If we've extended the file, update the inode
+ * now so we don't invalidate the cache.
+ */
+- if (base > i_size_read(inode))
+- i_size_write(inode, base);
++ if (wdata.args.offset > i_size_read(inode))
++ i_size_write(inode, wdata.args.offset);
+ } while (count);
+
+ if (PageError(page))
+ ClearPageError(page);
+
+ io_error:
+- if (cred)
+- put_rpccred(cred);
++ if (wdata.cred)
++ put_rpccred(wdata.cred);
+
+- return written? written : result;
++ return written ? written : result;
+ }
+
+ static int
+--- linux-2.6.0-test6/fs/open.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/open.c 2003-10-05 00:36:52.000000000 -0700
+@@ -190,7 +190,9 @@ int do_truncate(struct dentry *dentry, l
+ newattrs.ia_size = length;
+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ down(&dentry->d_inode->i_sem);
++ down_write(&dentry->d_inode->i_alloc_sem);
+ err = notify_change(dentry, &newattrs);
++ up_write(&dentry->d_inode->i_alloc_sem);
+ up(&dentry->d_inode->i_sem);
+ return err;
+ }
+@@ -772,7 +774,8 @@ struct file *dentry_open(struct dentry *
+ goto cleanup_file;
+ }
+
+- file_ra_state_init(&f->f_ra, inode->i_mapping);
++ f->f_mapping = inode->i_mapping;
++ file_ra_state_init(&f->f_ra, f->f_mapping);
+ f->f_dentry = dentry;
+ f->f_vfsmnt = mnt;
+ f->f_pos = 0;
+@@ -788,8 +791,8 @@ struct file *dentry_open(struct dentry *
+
+ /* NB: we're sure to have correct a_ops only after f_op->open */
+ if (f->f_flags & O_DIRECT) {
+- if (!inode->i_mapping || !inode->i_mapping->a_ops ||
+- !inode->i_mapping->a_ops->direct_IO) {
++ if (!f->f_mapping || !f->f_mapping->a_ops ||
++ !f->f_mapping->a_ops->direct_IO) {
+ fput(f);
+ f = ERR_PTR(-EINVAL);
+ }
+@@ -1019,7 +1022,7 @@ out_unlock:
+ asmlinkage long sys_vhangup(void)
+ {
+ if (capable(CAP_SYS_TTY_CONFIG)) {
+- tty_vhangup(current->tty);
++ tty_vhangup(process_tty(current));
+ return 0;
+ }
+ return -EPERM;
+--- linux-2.6.0-test6/fs/pipe.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/pipe.c 2003-10-05 00:34:03.000000000 -0700
+@@ -580,6 +580,7 @@ int do_pipe(int *fd)
+ d_add(dentry, inode);
+ f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
+ f1->f_dentry = f2->f_dentry = dget(dentry);
++ f1->f_mapping = f2->f_mapping = inode->i_mapping;
+
+ /* read file */
+ f1->f_pos = f2->f_pos = 0;
+--- linux-2.6.0-test6/fs/proc/array.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/proc/array.c 2003-10-05 00:36:15.000000000 -0700
+@@ -304,9 +304,9 @@ int proc_pid_stat(struct task_struct *ta
+ mm = task->mm;
+ if(mm)
+ mm = mmgrab(mm);
+- if (task->tty) {
+- tty_pgrp = task->tty->pgrp;
+- tty_nr = new_encode_dev(tty_devnum(task->tty));
++ if (process_tty(task)) {
++ tty_pgrp = process_tty(task)->pgrp;
++ tty_nr = new_encode_dev(tty_devnum(process_tty(task)));
+ }
+ task_unlock(task);
+ if (mm) {
+@@ -345,7 +345,7 @@ int proc_pid_stat(struct task_struct *ta
+ state,
+ ppid,
+ process_group(task),
+- task->session,
++ process_session(task),
+ tty_nr,
+ tty_pgrp,
+ task->flags,
+--- linux-2.6.0-test6/fs/proc/base.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/proc/base.c 2003-10-05 00:36:09.000000000 -0700
+@@ -53,6 +53,7 @@ enum pid_directory_inos {
+ PROC_TGID_EXE,
+ PROC_TGID_FD,
+ PROC_TGID_ENVIRON,
++ PROC_TGID_AUXV,
+ PROC_TGID_CMDLINE,
+ PROC_TGID_STAT,
+ PROC_TGID_STATM,
+@@ -75,6 +76,7 @@ enum pid_directory_inos {
+ PROC_TID_EXE,
+ PROC_TID_FD,
+ PROC_TID_ENVIRON,
++ PROC_TID_AUXV,
+ PROC_TID_CMDLINE,
+ PROC_TID_STAT,
+ PROC_TID_STATM,
+@@ -104,6 +106,7 @@ static struct pid_entry tgid_base_stuff[
+ E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO),
+ E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
+ E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
++ E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
+ E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
+ E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
+@@ -125,6 +128,7 @@ static struct pid_entry tgid_base_stuff[
+ static struct pid_entry tid_base_stuff[] = {
+ E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
+ E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
++ E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
+ E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
+ E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
+@@ -322,6 +326,25 @@ out:
+ return res;
+ }
+
++static int proc_pid_auxv(struct task_struct *task, char *buffer)
++{
++ int res = 0;
++ struct mm_struct *mm = get_task_mm(task);
++ if (mm) {
++ unsigned int nwords = 0;
++ do
++ nwords += 2;
++ while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
++ res = nwords * sizeof(mm->saved_auxv[0]);
++ if (res > PAGE_SIZE)
++ res = PAGE_SIZE;
++ memcpy(buffer, mm->saved_auxv, res);
++ mmput(mm);
++ }
++ return res;
++}
++
++
+ #ifdef CONFIG_KALLSYMS
+ /*
+ * Provides a wchan file via kallsyms in a proper one-value-per-file format.
+@@ -1271,6 +1294,11 @@ static struct dentry *proc_pident_lookup
+ inode->i_fop = &proc_info_file_operations;
+ ei->op.proc_read = proc_pid_environ;
+ break;
++ case PROC_TID_AUXV:
++ case PROC_TGID_AUXV:
++ inode->i_fop = &proc_info_file_operations;
++ ei->op.proc_read = proc_pid_auxv;
++ break;
+ case PROC_TID_STATUS:
+ case PROC_TGID_STATUS:
+ inode->i_fop = &proc_info_file_operations;
+--- linux-2.6.0-test6/fs/proc/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/proc/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -14,6 +14,7 @@
+ #include <linux/limits.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
++#include <linux/parser.h>
+ #include <linux/smp_lock.h>
+
+ #include <asm/system.h>
+@@ -135,34 +136,47 @@ static struct super_operations proc_sops
+ .statfs = simple_statfs,
+ };
+
++enum {
++ Opt_uid, Opt_gid, Opt_err
++};
++
++static match_table_t tokens = {
++ {Opt_uid, "uid=%u"},
++ {Opt_gid, "gid=%u"},
++ {Opt_err, NULL}
++};
++
+ static int parse_options(char *options,uid_t *uid,gid_t *gid)
+ {
+- char *this_char,*value;
++ char *p;
++ int option;
+
+ *uid = current->uid;
+ *gid = current->gid;
+ if (!options)
+ return 1;
+- while ((this_char = strsep(&options,",")) != NULL) {
+- if (!*this_char)
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr(this_char,'=')) != NULL)
+- *value++ = 0;
+- if (!strcmp(this_char,"uid")) {
+- if (!value || !*value)
+- return 0;
+- *uid = simple_strtoul(value,&value,0);
+- if (*value)
+- return 0;
+- }
+- else if (!strcmp(this_char,"gid")) {
+- if (!value || !*value)
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_uid:
++ if (match_int(args, &option))
+ return 0;
+- *gid = simple_strtoul(value,&value,0);
+- if (*value)
++ *uid = option;
++ break;
++ case Opt_gid:
++ if (match_int(args, &option))
+ return 0;
++ *gid = option;
++ break;
++ default:
++ return 0;
+ }
+- else return 1;
+ }
+ return 1;
+ }
+--- linux-2.6.0-test6/fs/proc/proc_misc.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/proc/proc_misc.c 2003-10-05 00:36:40.000000000 -0700
+@@ -638,6 +638,36 @@ static void create_seq_entry(char *name,
+ entry->proc_fops = f;
+ }
+
++#ifdef CONFIG_LOCKMETER
++extern ssize_t get_lockmeter_info(char *, size_t, loff_t *);
++extern ssize_t put_lockmeter_info(const char *, size_t);
++extern int get_lockmeter_info_size(void);
++
++/*
++ * This function accesses lock metering information.
++ */
++static ssize_t read_lockmeter(struct file *file, char *buf,
++ size_t count, loff_t *ppos)
++{
++ return get_lockmeter_info(buf, count, ppos);
++}
++
++/*
++ * Writing to /proc/lockmeter resets the counters
++ */
++static ssize_t write_lockmeter(struct file * file, const char * buf,
++ size_t count, loff_t *ppos)
++{
++ return put_lockmeter_info(buf, count);
++}
++
++static struct file_operations proc_lockmeter_operations = {
++ NULL, /* lseek */
++ read: read_lockmeter,
++ write: write_lockmeter,
++};
++#endif /* CONFIG_LOCKMETER */
++
+ void __init proc_misc_init(void)
+ {
+ struct proc_dir_entry *entry;
+@@ -705,6 +735,13 @@ void __init proc_misc_init(void)
+ if (entry)
+ entry->proc_fops = &proc_sysrq_trigger_operations;
+ #endif
++#ifdef CONFIG_LOCKMETER
++ entry = create_proc_entry("lockmeter", S_IWUSR | S_IRUGO, NULL);
++ if (entry) {
++ entry->proc_fops = &proc_lockmeter_operations;
++ entry->size = get_lockmeter_info_size();
++ }
++#endif
+ #ifdef CONFIG_PPC32
+ {
+ extern struct file_operations ppc_htab_operations;
+--- linux-2.6.0-test6/fs/read_write.c 2003-07-13 21:44:35.000000000 -0700
++++ 25/fs/read_write.c 2003-10-05 00:34:07.000000000 -0700
+@@ -26,7 +26,7 @@ struct file_operations generic_ro_fops =
+ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
+ {
+ long long retval;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+
+ down(&inode->i_sem);
+ switch (origin) {
+--- linux-2.6.0-test6/fs/reiserfs/file.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/reiserfs/file.c 2003-10-05 00:34:11.000000000 -0700
+@@ -1052,7 +1052,7 @@ ssize_t reiserfs_file_write( struct file
+ /* Check if we can write to specified region of file, file
+ is not overly big and this kind of stuff. Adjust pos and
+ count, if needed */
+- res = generic_write_checks(inode, file, &pos, &count, 0);
++ res = generic_write_checks(file, &pos, &count, 0);
+ if (res)
+ goto out;
+
+@@ -1179,7 +1179,7 @@ ssize_t reiserfs_file_write( struct file
+ }
+
+ if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
+- res = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA);
++ res = generic_osync_inode(inode, file->f_mapping, OSYNC_METADATA|OSYNC_DATA);
+
+ up(&inode->i_sem);
+ return (already_written != 0)?already_written:res;
+--- linux-2.6.0-test6/fs/reiserfs/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/reiserfs/inode.c 2003-10-05 00:34:07.000000000 -0700
+@@ -2375,7 +2375,7 @@ static int reiserfs_direct_IO(int rw, st
+ loff_t offset, unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ offset, nr_segs, reiserfs_get_blocks_direct_io, NULL);
+--- linux-2.6.0-test6/fs/reiserfs/journal.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/reiserfs/journal.c 2003-10-05 00:34:11.000000000 -0700
+@@ -1937,18 +1937,13 @@ static int journal_init_dev( struct supe
+
+ journal -> j_dev_file = filp_open( jdev_name, 0, 0 );
+ if( !IS_ERR( journal -> j_dev_file ) ) {
+- struct inode *jdev_inode;
+-
+- jdev_inode = journal -> j_dev_file -> f_dentry -> d_inode;
+- journal -> j_dev_bd = jdev_inode -> i_bdev;
++ struct inode *jdev_inode = journal->j_dev_file->f_mapping->host;
+ if( !S_ISBLK( jdev_inode -> i_mode ) ) {
+ printk( "journal_init_dev: '%s' is not a block device\n", jdev_name );
+ result = -ENOTBLK;
+- } else if( jdev_inode -> i_bdev == NULL ) {
+- printk( "journal_init_dev: bdev uninitialized for '%s'\n", jdev_name );
+- result = -ENOMEM;
+ } else {
+ /* ok */
++ journal->j_dev_bd = I_BDEV(jdev_inode);
+ set_blocksize(journal->j_dev_bd, super->s_blocksize);
+ }
+ } else {
+--- linux-2.6.0-test6/fs/seq_file.c 2003-06-14 12:18:28.000000000 -0700
++++ 25/fs/seq_file.c 2003-10-05 00:33:24.000000000 -0700
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/fs.h>
++#include <linux/module.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+
+@@ -37,6 +38,8 @@ int seq_open(struct file *file, struct s
+ return 0;
+ }
+
++EXPORT_SYMBOL(seq_open);
++
+ /**
+ * seq_read - ->read() method for sequential files.
+ * @file, @buf, @size, @ppos: see file_operations method
+@@ -144,6 +147,8 @@ Efault:
+ goto Done;
+ }
+
++EXPORT_SYMBOL(seq_read);
++
+ static int traverse(struct seq_file *m, loff_t offset)
+ {
+ loff_t pos = 0;
+@@ -228,6 +233,8 @@ loff_t seq_lseek(struct file *file, loff
+ return retval;
+ }
+
++EXPORT_SYMBOL(seq_lseek);
++
+ /**
+ * seq_release - free the structures associated with sequential file.
+ * @file: file in question
+@@ -244,6 +251,8 @@ int seq_release(struct inode *inode, str
+ return 0;
+ }
+
++EXPORT_SYMBOL(seq_release);
++
+ /**
+ * seq_escape - print string into buffer, escaping some characters
+ * @m: target buffer
+@@ -279,6 +288,8 @@ int seq_escape(struct seq_file *m, const
+ return 0;
+ }
+
++EXPORT_SYMBOL(seq_escape);
++
+ int seq_printf(struct seq_file *m, const char *f, ...)
+ {
+ va_list args;
+@@ -297,9 +308,11 @@ int seq_printf(struct seq_file *m, const
+ return -1;
+ }
+
++EXPORT_SYMBOL(seq_printf);
++
+ int seq_path(struct seq_file *m,
+- struct vfsmount *mnt, struct dentry *dentry,
+- char *esc)
++ struct vfsmount *mnt, struct dentry *dentry,
++ char *esc)
+ {
+ if (m->count < m->size) {
+ char *s = m->buf + m->count;
+@@ -328,6 +341,8 @@ int seq_path(struct seq_file *m,
+ return -1;
+ }
+
++EXPORT_SYMBOL(seq_path);
++
+ static void *single_start(struct seq_file *p, loff_t *pos)
+ {
+ return NULL + (*pos == 0);
+@@ -343,7 +358,8 @@ static void single_stop(struct seq_file
+ {
+ }
+
+-int single_open(struct file *file, int (*show)(struct seq_file *, void*), void *data)
++int single_open(struct file *file, int (*show)(struct seq_file *, void *),
++ void *data)
+ {
+ struct seq_operations *op = kmalloc(sizeof(*op), GFP_KERNEL);
+ int res = -ENOMEM;
+@@ -362,6 +378,8 @@ int single_open(struct file *file, int (
+ return res;
+ }
+
++EXPORT_SYMBOL(single_open);
++
+ int single_release(struct inode *inode, struct file *file)
+ {
+ struct seq_operations *op = ((struct seq_file *)file->private_data)->op;
+@@ -370,6 +388,8 @@ int single_release(struct inode *inode,
+ return res;
+ }
+
++EXPORT_SYMBOL(single_release);
++
+ int seq_release_private(struct inode *inode, struct file *file)
+ {
+ struct seq_file *seq = file->private_data;
+@@ -379,3 +399,4 @@ int seq_release_private(struct inode *in
+ return seq_release(inode, file);
+ }
+
++EXPORT_SYMBOL(seq_release_private);
+--- linux-2.6.0-test6/fs/smbfs/inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/smbfs/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -551,8 +551,8 @@ int smb_fill_super(struct super_block *s
+ if (ver == SMB_MOUNT_OLDVERSION) {
+ mnt->version = oldmnt->version;
+
+- mnt->uid = low2highuid(oldmnt->uid);
+- mnt->gid = low2highuid(oldmnt->gid);
++ mnt->uid = OLD_TO_NEW_UID(oldmnt->uid);
++ mnt->gid = OLD_TO_NEW_GID(oldmnt->gid);
+
+ mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+ mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
+--- linux-2.6.0-test6/fs/super.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/super.c 2003-10-05 00:36:10.000000000 -0700
+@@ -21,6 +21,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/smp_lock.h>
+ #include <linux/acct.h>
+@@ -134,9 +135,11 @@ void deactivate_super(struct super_block
+ }
+ }
+
++EXPORT_SYMBOL(deactivate_super);
++
+ /**
+- * grab_super - acquire an active reference
+- * @s - reference we are trying to make active
++ * grab_super - acquire an active reference
++ * @s: reference we are trying to make active
+ *
+ * Tries to acquire an active reference. grab_super() is used when we
+ * had just found a superblock in super_blocks or fs_type->fs_supers
+@@ -214,6 +217,8 @@ void generic_shutdown_super(struct super
+ up_write(&sb->s_umount);
+ }
+
++EXPORT_SYMBOL(generic_shutdown_super);
++
+ /**
+ * sget - find or create a superblock
+ * @type: filesystem type superblock should belong to
+@@ -226,13 +231,10 @@ struct super_block *sget(struct file_sys
+ int (*set)(struct super_block *,void *),
+ void *data)
+ {
+- struct super_block *s = alloc_super();
++ struct super_block *s = NULL;
+ struct list_head *p;
+ int err;
+
+- if (!s)
+- return ERR_PTR(-ENOMEM);
+-
+ retry:
+ spin_lock(&sb_lock);
+ if (test) list_for_each(p, &type->fs_supers) {
+@@ -242,9 +244,18 @@ retry:
+ continue;
+ if (!grab_super(old))
+ goto retry;
+- destroy_super(s);
++ if (s)
++ destroy_super(s);
+ return old;
+ }
++ if (!s) {
++ spin_unlock(&sb_lock);
++ s = alloc_super();
++ if (!s)
++ return ERR_PTR(-ENOMEM);
++ goto retry;
++ }
++
+ err = set(s, data);
+ if (err) {
+ spin_unlock(&sb_lock);
+@@ -259,12 +270,16 @@ retry:
+ return s;
+ }
+
++EXPORT_SYMBOL(sget);
++
+ void drop_super(struct super_block *sb)
+ {
+ up_read(&sb->s_umount);
+ put_super(sb);
+ }
+
++EXPORT_SYMBOL(drop_super);
++
+ static inline void write_super(struct super_block *sb)
+ {
+ lock_super(sb);
+@@ -353,8 +368,8 @@ restart:
+ }
+
+ /**
+- * get_super - get the superblock of a device
+- * @dev: device to get the superblock for
++ * get_super - get the superblock of a device
++ * @bdev: device to get the superblock for
+ *
+ * Scans the superblock list and finds the superblock of the file system
+ * mounted on the device given. %NULL is returned if no match is found.
+@@ -382,6 +397,8 @@ rescan:
+ spin_unlock(&sb_lock);
+ return NULL;
+ }
++
++EXPORT_SYMBOL(get_super);
+
+ struct super_block * user_get_super(dev_t dev)
+ {
+@@ -405,6 +422,8 @@ rescan:
+ return NULL;
+ }
+
++EXPORT_SYMBOL(user_get_super);
++
+ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf)
+ {
+ struct super_block *s;
+@@ -442,10 +461,11 @@ static void mark_files_ro(struct super_b
+ }
+
+ /**
+- * do_remount_sb - asks filesystem to change mount options.
++ * do_remount_sb - asks filesystem to change mount options.
+ * @sb: superblock in question
+ * @flags: numeric part of options
+ * @data: the rest of options
++ * @force: whether or not to force the change
+ *
+ * Alters the mount options of a mounted file system.
+ */
+@@ -534,6 +554,8 @@ int set_anon_super(struct super_block *s
+ return 0;
+ }
+
++EXPORT_SYMBOL(set_anon_super);
++
+ void kill_anon_super(struct super_block *sb)
+ {
+ int slot = MINOR(sb->s_dev);
+@@ -543,6 +565,8 @@ void kill_anon_super(struct super_block
+ spin_unlock(&unnamed_dev_lock);
+ }
+
++EXPORT_SYMBOL(kill_anon_super);
++
+ void kill_litter_super(struct super_block *sb)
+ {
+ if (sb->s_root)
+@@ -550,6 +574,8 @@ void kill_litter_super(struct super_bloc
+ kill_anon_super(sb);
+ }
+
++EXPORT_SYMBOL(kill_litter_super);
++
+ static int set_bdev_super(struct super_block *s, void *data)
+ {
+ s->s_bdev = data;
+@@ -608,6 +634,8 @@ out:
+ return s;
+ }
+
++EXPORT_SYMBOL(get_sb_bdev);
++
+ void kill_block_super(struct super_block *sb)
+ {
+ struct block_device *bdev = sb->s_bdev;
+@@ -616,6 +644,8 @@ void kill_block_super(struct super_block
+ close_bdev_excl(bdev, BDEV_FS);
+ }
+
++EXPORT_SYMBOL(kill_block_super);
++
+ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+ int flags, void *data,
+ int (*fill_super)(struct super_block *, void *, int))
+@@ -638,6 +668,8 @@ struct super_block *get_sb_nodev(struct
+ return s;
+ }
+
++EXPORT_SYMBOL(get_sb_nodev);
++
+ static int compare_single(struct super_block *s, void *p)
+ {
+ return 1;
+@@ -667,6 +699,8 @@ struct super_block *get_sb_single(struct
+ return s;
+ }
+
++EXPORT_SYMBOL(get_sb_single);
++
+ struct vfsmount *
+ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+ {
+@@ -709,3 +743,5 @@ struct vfsmount *kern_mount(struct file_
+ {
+ return do_kern_mount(type->name, 0, type->name, NULL);
+ }
++
++EXPORT_SYMBOL(kern_mount);
+--- linux-2.6.0-test6/fs/sysfs/dir.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/sysfs/dir.c 2003-10-05 00:34:36.000000000 -0700
+@@ -82,8 +82,16 @@ static void remove_dir(struct dentry * d
+ {
+ struct dentry * parent = dget(d->d_parent);
+ down(&parent->d_inode->i_sem);
+- d_delete(d);
+- simple_rmdir(parent->d_inode,d);
++ /*
++ * It is possible that parent has already been removed, in which
++ * case directory is already unhashed and dput.
++ * Note that this won't update parent->d_inode->i_nlink; OTOH
++ * parent should already be dead
++ */
++ if (!d_unhashed(d)) {
++ d_delete(d);
++ simple_rmdir(parent->d_inode,d);
++ }
+
+ pr_debug(" o %s removing done (%d)\n",d->d_name.name,
+ atomic_read(&d->d_count));
+--- linux-2.6.0-test6/fs/udf/inode.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/fs/udf/inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -127,6 +127,7 @@ no_delete:
+ void udf_clear_inode(struct inode *inode)
+ {
+ kfree(UDF_I_DATA(inode));
++ UDF_I_DATA(inode) = NULL;
+ }
+
+ void udf_discard_prealloc(struct inode * inode)
+--- linux-2.6.0-test6/fs/udf/super.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/fs/udf/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -50,6 +50,7 @@
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/parser.h>
+ #include <linux/stat.h>
+ #include <linux/cdrom.h>
+ #include <linux/nls.h>
+@@ -132,8 +133,10 @@ static void init_once(void * foo, kmem_c
+ struct udf_inode_info *ei = (struct udf_inode_info *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+- SLAB_CTOR_CONSTRUCTOR)
++ SLAB_CTOR_CONSTRUCTOR) {
++ ei->i_ext.i_data = NULL;
+ inode_init_once(&ei->vfs_inode);
++ }
+ }
+
+ static int init_inodecache(void)
+@@ -225,7 +228,7 @@ module_exit(exit_udf_fs)
+ * gid= Set the default group.
+ * umask= Set the default umask.
+ * uid= Set the default user.
+- * bs= Set the block size.
++ * bs= Set the block size.
+ * unhide Show otherwise hidden files.
+ * undelete Show deleted files in lists.
+ * adinicb Embed data in the inode (default)
+@@ -259,18 +262,53 @@ module_exit(exit_udf_fs)
+ * uopts Pointer to mount options variable.
+ *
+ * POST-CONDITIONS
+- * <return> 0 Mount options parsed okay.
+- * <return> -1 Error parsing mount options.
++ * <return> 1 Mount options parsed okay.
++ * <return> 0 Error parsing mount options.
+ *
+ * HISTORY
+ * July 1, 1997 - Andrew E. Mileski
+ * Written, tested, and released.
+ */
+
++enum {
++ Opt_novrs, Opt_nostrict, Opt_bs, Opt_unhide, Opt_undelete,
++ Opt_noadinicb, Opt_adinicb, Opt_shortad, Opt_longad,
++ Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock,
++ Opt_anchor, Opt_volume, Opt_partition, Opt_fileset,
++ Opt_rootdir, Opt_utf8, Opt_iocharset,
++ Opt_err
++};
++
++static match_table_t tokens = {
++ {Opt_novrs, "novrs"},
++ {Opt_nostrict, "nostrict"},
++ {Opt_bs, "bs=%u"},
++ {Opt_unhide, "unhide"},
++ {Opt_undelete, "undelete"},
++ {Opt_noadinicb, "noadinicb"},
++ {Opt_adinicb, "adinicb"},
++ {Opt_shortad, "shortad"},
++ {Opt_longad, "longad"},
++ {Opt_gid, "gid=%u"},
++ {Opt_uid, "uid=%u"},
++ {Opt_umask, "umask=%o"},
++ {Opt_session, "session=%u"},
++ {Opt_lastblock, "lastblock=%u"},
++ {Opt_anchor, "anchor=%u"},
++ {Opt_volume, "volume=%u"},
++ {Opt_partition, "partition=%u"},
++ {Opt_fileset, "fileset=%u"},
++ {Opt_rootdir, "rootdir=%u"},
++ {Opt_utf8, "utf8"},
++ {Opt_iocharset, "iocharset=%s"},
++ {Opt_err, NULL}
++};
++
+ static int
+ udf_parse_options(char *options, struct udf_options *uopt)
+ {
+- char *opt, *val;
++ char *p;
++ int option;
+
+ uopt->novrs = 0;
+ uopt->blocksize = 2048;
+@@ -286,71 +324,106 @@ udf_parse_options(char *options, struct
+ if (!options)
+ return 1;
+
+- while ((opt = strsep(&options, ",")) != NULL)
+- {
+- if (!*opt)
++ while ((p = strsep(&options, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- /* Make "opt=val" into two strings */
+- val = strchr(opt, '=');
+- if (val)
+- *(val++) = 0;
+- if (!strcmp(opt, "novrs") && !val)
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_novrs:
+ uopt->novrs = 1;
+- else if (!strcmp(opt, "bs") && val)
+- uopt->blocksize = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "unhide") && !val)
++ break;
++ case Opt_bs:
++ if (match_int(&args[0], &option))
++ return 0;
++ uopt->blocksize = option;
++ break;
++ case Opt_unhide:
+ uopt->flags |= (1 << UDF_FLAG_UNHIDE);
+- else if (!strcmp(opt, "undelete") && !val)
++ break;
++ case Opt_undelete:
+ uopt->flags |= (1 << UDF_FLAG_UNDELETE);
+- else if (!strcmp(opt, "noadinicb") && !val)
++ break;
++ case Opt_noadinicb:
+ uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
+- else if (!strcmp(opt, "adinicb") && !val)
++ break;
++ case Opt_adinicb:
+ uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
+- else if (!strcmp(opt, "shortad") && !val)
++ break;
++ case Opt_shortad:
+ uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
+- else if (!strcmp(opt, "longad") && !val)
++ break;
++ case Opt_longad:
+ uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
+- else if (!strcmp(opt, "gid") && val)
+- uopt->gid = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "umask") && val)
+- uopt->umask = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "nostrict") && !val)
++ break;
++ case Opt_gid:
++ if (match_int(args, &option))
++ return 0;
++ uopt->gid = option;
++ break;
++ case Opt_uid:
++ if (match_int(args, &option))
++ return 0;
++ uopt->uid = option;
++ break;
++ case Opt_umask:
++ if (match_octal(args, &option))
++ return 0;
++ uopt->umask = option;
++ break;
++ case Opt_nostrict:
+ uopt->flags &= ~(1 << UDF_FLAG_STRICT);
+- else if (!strcmp(opt, "uid") && val)
+- uopt->uid = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "session") && val)
+- uopt->session = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "lastblock") && val)
+- uopt->lastblock = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "anchor") && val)
+- uopt->anchor = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "volume") && val)
+- uopt->volume = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "partition") && val)
+- uopt->partition = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "fileset") && val)
+- uopt->fileset = simple_strtoul(val, NULL, 0);
+- else if (!strcmp(opt, "rootdir") && val)
+- uopt->rootdir = simple_strtoul(val, NULL, 0);
++ break;
++ case Opt_session:
++ if (match_int(args, &option))
++ return 0;
++ uopt->session = option;
++ break;
++ case Opt_lastblock:
++ if (match_int(args, &option))
++ return 0;
++ uopt->lastblock = option;
++ break;
++ case Opt_anchor:
++ if (match_int(args, &option))
++ return 0;
++ uopt->anchor = option;
++ break;
++ case Opt_volume:
++ if (match_int(args, &option))
++ return 0;
++ uopt->volume = option;
++ break;
++ case Opt_partition:
++ if (match_int(args, &option))
++ return 0;
++ uopt->partition = option;
++ break;
++ case Opt_fileset:
++ if (match_int(args, &option))
++ return 0;
++ uopt->fileset = option;
++ break;
++ case Opt_rootdir:
++ if (match_int(args, &option))
++ return 0;
++ uopt->rootdir = option;
++ break;
++ case Opt_utf8:
++ uopt->flags |= (1 << UDF_FLAG_UTF8);
++ break;
+ #ifdef CONFIG_NLS
+- else if (!strcmp(opt, "iocharset") && val)
+- {
+- uopt->nls_map = load_nls(val);
++ case Opt_iocharset:
++ uopt->nls_map = load_nls(args[0].from);
+ uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
+- }
++ break;
+ #endif
+- else if (!strcmp(opt, "utf8") && !val)
+- uopt->flags |= (1 << UDF_FLAG_UTF8);
+- else if (val)
+- {
+- printk(KERN_ERR "udf: bad mount option \"%s=%s\"\n",
+- opt, val);
+- return 0;
+- }
+- else
+- {
+- printk(KERN_ERR "udf: bad mount option \"%s\"\n",
+- opt);
++ default:
++ printk(KERN_ERR "udf: bad mount option \"%s\" "
++ "or missing value\n",
++ p);
+ return 0;
+ }
+ }
+--- linux-2.6.0-test6/fs/ufs/super.c 2003-06-22 12:04:44.000000000 -0700
++++ 25/fs/ufs/super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -79,6 +79,7 @@
+ #include <linux/string.h>
+ #include <linux/blkdev.h>
+ #include <linux/init.h>
++#include <linux/parser.h>
+ #include <linux/smp_lock.h>
+ #include <linux/buffer_head.h>
+ #include <linux/vfs.h>
+@@ -250,64 +251,99 @@ void ufs_warning (struct super_block * s
+ sb->s_id, function, error_buf);
+ }
+
++enum {
++ Opt_type_old, Opt_type_sunx86, Opt_type_sun, Opt_type_44bsd,
++ Opt_type_hp, Opt_type_nextstepcd, Opt_type_nextstep,
++ Opt_type_openstep, Opt_onerror_panic, Opt_onerror_lock,
++ Opt_onerror_umount, Opt_onerror_repair, Opt_err
++};
++
++static match_table_t tokens = {
++ {Opt_type_old, "ufstype=old"},
++ {Opt_type_sunx86, "ufstype=sunx86"},
++ {Opt_type_sun, "ufstype=sun"},
++ {Opt_type_44bsd, "ufstype=44bsd"},
++ {Opt_type_hp, "ufstype=hp"},
++ {Opt_type_nextstepcd, "ufstype=nextstep-cd"},
++ {Opt_type_nextstep, "ufstype=nextstep"},
++ {Opt_type_openstep, "ufstype=openstep"},
++ {Opt_onerror_panic, "onerror=panic"},
++ {Opt_onerror_lock, "onerror=lock"},
++ {Opt_onerror_umount, "onerror=umount"},
++ {Opt_onerror_repair, "onerror=repair"},
++ {Opt_err, NULL}
++};
++
+ static int ufs_parse_options (char * options, unsigned * mount_options)
+ {
+- char * this_char;
+- char * value;
++ char * p;
+
+ UFSD(("ENTER\n"))
+
+ if (!options)
+ return 1;
+
+- while ((this_char = strsep (&options, ",")) != NULL) {
+- if (!*this_char)
++ while ((p = strsep(&options, ",")) != NULL) {
++ substring_t args[MAX_OPT_ARGS];
++ int token;
++ if (!*p)
+ continue;
+- if ((value = strchr (this_char, '=')) != NULL)
+- *value++ = 0;
+- if (!strcmp (this_char, "ufstype")) {
++
++ token = match_token(p, tokens, args);
++ switch (token) {
++ case Opt_type_old:
+ ufs_clear_opt (*mount_options, UFSTYPE);
+- if (!strcmp (value, "old"))
+- ufs_set_opt (*mount_options, UFSTYPE_OLD);
+- else if (!strcmp (value, "sun"))
+- ufs_set_opt (*mount_options, UFSTYPE_SUN);
+- else if (!strcmp (value, "44bsd"))
+- ufs_set_opt (*mount_options, UFSTYPE_44BSD);
+- else if (!strcmp (value, "nextstep"))
+- ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP);
+- else if (!strcmp (value, "nextstep-cd"))
+- ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD);
+- else if (!strcmp (value, "openstep"))
+- ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
+- else if (!strcmp (value, "sunx86"))
+- ufs_set_opt (*mount_options, UFSTYPE_SUNx86);
+- else if (!strcmp (value, "hp"))
+- ufs_set_opt (*mount_options, UFSTYPE_HP);
+- else {
+- printk ("UFS-fs: Invalid type option: %s\n", value);
+- return 0;
+- }
+- }
+- else if (!strcmp (this_char, "onerror")) {
++ ufs_set_opt (*mount_options, UFSTYPE_OLD);
++ break;
++ case Opt_type_sunx86:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_SUNx86);
++ break;
++ case Opt_type_sun:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_SUN);
++ break;
++ case Opt_type_44bsd:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_44BSD);
++ break;
++ case Opt_type_hp:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_HP);
++ break;
++ case Opt_type_nextstepcd:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD);
++ break;
++ case Opt_type_nextstep:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP);
++ break;
++ case Opt_type_openstep:
++ ufs_clear_opt (*mount_options, UFSTYPE);
++ ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
++ break;
++ case Opt_onerror_panic:
+ ufs_clear_opt (*mount_options, ONERROR);
+- if (!strcmp (value, "panic"))
+- ufs_set_opt (*mount_options, ONERROR_PANIC);
+- else if (!strcmp (value, "lock"))
+- ufs_set_opt (*mount_options, ONERROR_LOCK);
+- else if (!strcmp (value, "umount"))
+- ufs_set_opt (*mount_options, ONERROR_UMOUNT);
+- else if (!strcmp (value, "repair")) {
+- printk("UFS-fs: Unable to do repair on error, "
+- "will lock lock instead \n");
+- ufs_set_opt (*mount_options, ONERROR_REPAIR);
+- }
+- else {
+- printk ("UFS-fs: Invalid action onerror: %s\n", value);
+- return 0;
+- }
+- }
+- else {
+- printk("UFS-fs: Invalid option: %s\n", this_char);
++ ufs_set_opt (*mount_options, ONERROR_PANIC);
++ break;
++ case Opt_onerror_lock:
++ ufs_clear_opt (*mount_options, ONERROR);
++ ufs_set_opt (*mount_options, ONERROR_LOCK);
++ break;
++ case Opt_onerror_umount:
++ ufs_clear_opt (*mount_options, ONERROR);
++ ufs_set_opt (*mount_options, ONERROR_UMOUNT);
++ break;
++ case Opt_onerror_repair:
++ printk("UFS-fs: Unable to do repair on error, "
++ "will lock lock instead\n");
++ ufs_clear_opt (*mount_options, ONERROR);
++ ufs_set_opt (*mount_options, ONERROR_REPAIR);
++ break;
++ default:
++ printk("UFS-fs: Invalid option: \"%s\" "
++ "or missing value\n", p);
+ return 0;
+ }
+ }
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_aops.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_aops.c 2003-10-05 00:36:53.000000000 -0700
+@@ -461,7 +461,8 @@ map_unwritten(
+ struct page *page;
+
+ tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT;
+- tloff = min(tlast, start_page->index + pb->pb_page_count - 1);
++ tloff = (mp->pbm_offset + mp->pbm_bsize) >> PAGE_CACHE_SHIFT;
++ tloff = min(tlast, tloff);
+ for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
+ page = probe_unwritten_page(mapping, tindex, mp, pb,
+ PAGE_CACHE_SIZE, &bs, bbits);
+@@ -973,7 +974,7 @@ linvfs_direct_IO(
+ unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ page_buf_bmap_t pbmap;
+ int maps = 1;
+@@ -983,7 +984,7 @@ linvfs_direct_IO(
+ if (error)
+ return -error;
+
+- return blockdev_direct_IO(rw, iocb, inode,
++ return blockdev_direct_IO_no_locking(rw, iocb, inode,
+ pbmap.pbm_target->pbr_bdev,
+ iov, offset, nr_segs,
+ linvfs_get_blocks_direct,
+@@ -1041,6 +1042,8 @@ count_page_state(
+ do {
+ if (buffer_uptodate(bh) && !buffer_mapped(bh))
+ (*unmapped) = 1;
++ else if (buffer_unwritten(bh) && !buffer_delay(bh))
++ clear_buffer_unwritten(bh);
+ else if (buffer_unwritten(bh))
+ (*unwritten) = 1;
+ else if (buffer_delay(bh))
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_file.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/xfs/linux/xfs_file.c 2003-10-05 00:34:07.000000000 -0700
+@@ -86,7 +86,7 @@ linvfs_write(
+ {
+ struct iovec iov = {(void *)buf, count};
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ int error;
+ int direct = file->f_flags & O_DIRECT;
+@@ -111,7 +111,7 @@ linvfs_readv(
+ unsigned long nr_segs,
+ loff_t *ppos)
+ {
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ struct kiocb kiocb;
+ int error;
+@@ -133,7 +133,7 @@ linvfs_writev(
+ unsigned long nr_segs,
+ loff_t *ppos)
+ {
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
++ struct inode *inode = file->f_mapping->host;
+ vnode_t *vp = LINVFS_GET_VP(inode);
+ struct kiocb kiocb;
+ int error;
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_iops.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_iops.c 2003-10-05 00:33:24.000000000 -0700
+@@ -386,6 +386,7 @@ linvfs_readlink(
+ uio.uio_segflg = UIO_USERSPACE;
+ uio.uio_resid = size;
+ uio.uio_iovcnt = 1;
++ uio.uio_fmode = 0;
+
+ VOP_READLINK(vp, &uio, NULL, error);
+ if (error)
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_lrw.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_lrw.c 2003-10-05 00:33:24.000000000 -0700
+@@ -218,7 +218,7 @@ xfs_read(
+ int error;
+ vrwlock_t locktype = VRWLOCK_READ;
+
+- error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offset, size,
++ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, size,
+ FILP_DELAY_FLAG(file), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+@@ -278,7 +278,7 @@ xfs_sendfile(
+ vrwlock_t locktype = VRWLOCK_READ;
+ int error;
+
+- error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offset, count,
++ error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), *offset, count,
+ FILP_DELAY_FLAG(filp), &locktype);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+@@ -612,7 +612,7 @@ start:
+ loff_t savedsize = *offset;
+
+ xfs_iunlock(xip, XFS_ILOCK_EXCL);
+- error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, bdp,
++ error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
+ *offset, size,
+ FILP_DELAY_FLAG(file), &locktype);
+ if (error) {
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_stats.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_stats.c 2003-10-05 00:33:24.000000000 -0700
+@@ -33,7 +33,7 @@
+ #include "xfs.h"
+ #include <linux/proc_fs.h>
+
+-struct xfsstats xfsstats;
++DEFINE_PER_CPU(struct xfsstats, xfsstats);
+
+ STATIC int
+ xfs_read_xfsstats(
+@@ -44,7 +44,11 @@ xfs_read_xfsstats(
+ int *eof,
+ void *data)
+ {
+- int i, j, len;
++ int c, i, j, len, val;
++ __uint64_t xs_xstrat_bytes = 0;
++ __uint64_t xs_write_bytes = 0;
++ __uint64_t xs_read_bytes = 0;
++
+ static struct xstats_entry {
+ char *desc;
+ int endpoint;
+@@ -65,21 +69,32 @@ xfs_read_xfsstats(
+ { "vnodes", XFSSTAT_END_VNODE_OPS },
+ };
+
++ /* Loop over all stats groups */
+ for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
+ len += sprintf(buffer + len, xstats[i].desc);
+ /* inner loop does each group */
+ while (j < xstats[i].endpoint) {
+- len += sprintf(buffer + len, " %u",
+- *(((__u32*)&xfsstats) + j));
++ val = 0;
++ /* sum over all cpus */
++ for (c = 0; c < NR_CPUS; c++) {
++ if (!cpu_possible(c)) continue;
++ val += *(((__u32*)&per_cpu(xfsstats, c) + j));
++ }
++ len += sprintf(buffer + len, " %u", val);
+ j++;
+ }
+ buffer[len++] = '\n';
+ }
+ /* extra precision counters */
++ for (i = 0; i < NR_CPUS; i++) {
++ if (!cpu_possible(i)) continue;
++ xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
++ xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
++ xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
++ }
++
+ len += sprintf(buffer + len, "xpc %Lu %Lu %Lu\n",
+- xfsstats.xs_xstrat_bytes,
+- xfsstats.xs_write_bytes,
+- xfsstats.xs_read_bytes);
++ xs_xstrat_bytes, xs_write_bytes, xs_read_bytes);
+ len += sprintf(buffer + len, "debug %u\n",
+ #if defined(XFSDEBUG)
+ 1);
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_stats.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_stats.h 2003-10-05 00:33:24.000000000 -0700
+@@ -35,6 +35,8 @@
+
+ #if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF)
+
++#include <linux/percpu.h>
++
+ /*
+ * XFS global statistics
+ */
+@@ -126,11 +128,13 @@ struct xfsstats {
+ __uint64_t xs_read_bytes;
+ };
+
+-extern struct xfsstats xfsstats;
++DECLARE_PER_CPU(struct xfsstats, xfsstats);
+
+-# define XFS_STATS_INC(count) ( xfsstats.count++ )
+-# define XFS_STATS_DEC(count) ( xfsstats.count-- )
+-# define XFS_STATS_ADD(count, inc) ( xfsstats.count += (inc) )
++/* We don't disable preempt, not too worried about poking the
++ * wrong cpu's stat for now */
++#define XFS_STATS_INC(count) (__get_cpu_var(xfsstats).count++)
++#define XFS_STATS_DEC(count) (__get_cpu_var(xfsstats).count--)
++#define XFS_STATS_ADD(count, inc) (__get_cpu_var(xfsstats).count += (inc))
+
+ extern void xfs_init_procfs(void);
+ extern void xfs_cleanup_procfs(void);
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_super.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_super.c 2003-10-05 00:33:24.000000000 -0700
+@@ -315,8 +315,8 @@ xfs_setsize_buftarg(
+
+ if (set_blocksize(btp->pbr_bdev, sectorsize)) {
+ printk(KERN_WARNING
+- "XFS: Cannot set_blocksize to %u on device %u:%u\n",
+- sectorsize, MAJOR(btp->pbr_dev), MINOR(btp->pbr_dev));
++ "XFS: Cannot set_blocksize to %u on device %s\n",
++ sectorsize, XFS_BUFTARG_NAME(btp));
+ }
+ }
+
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_sysctl.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_sysctl.c 2003-10-05 00:33:24.000000000 -0700
+@@ -48,17 +48,23 @@ xfs_stats_clear_proc_handler(
+ void *buffer,
+ size_t *lenp)
+ {
+- int ret, *valp = ctl->data;
++ int c, ret, *valp = ctl->data;
+ __uint32_t vn_active;
+
+ ret = proc_doulongvec_minmax(ctl, write, filp, buffer, lenp);
+
+ if (!ret && write && *valp) {
+ printk("XFS Clearing xfsstats\n");
+- /* save vn_active, it's a universal truth! */
+- vn_active = xfsstats.vn_active;
+- memset(&xfsstats, 0, sizeof(xfsstats));
+- xfsstats.vn_active = vn_active;
++ for (c = 0; c < NR_CPUS; c++) {
++ if (!cpu_possible(c)) continue;
++ preempt_disable();
++ /* save vn_active, it's a universal truth! */
++ vn_active = per_cpu(xfsstats, c).vn_active;
++ memset(&per_cpu(xfsstats, c), 0,
++ sizeof(struct xfsstats));
++ per_cpu(xfsstats, c).vn_active = vn_active;
++ preempt_enable();
++ }
+ xfs_stats_clear = 0;
+ }
+
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_vnode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/linux/xfs_vnode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -200,7 +200,7 @@ vn_revalidate(
+ vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address);
+ ASSERT(vp->v_fbhv != NULL);
+
+- va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT;
++ va.va_mask = XFS_AT_STAT|XFS_AT_XFLAGS;
+ VOP_GETATTR(vp, &va, 0, NULL, error);
+ if (!error) {
+ inode = LINVFS_GET_IP(vp);
+--- linux-2.6.0-test6/fs/xfs/linux/xfs_vnode.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/xfs/linux/xfs_vnode.h 2003-10-05 00:33:24.000000000 -0700
+@@ -28,6 +28,37 @@
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
++ *
++ * Portions Copyright (c) 1989, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
+ */
+ #ifndef __XFS_VNODE_H__
+ #define __XFS_VNODE_H__
+@@ -39,19 +70,9 @@ struct page_buf_bmap_s;
+ struct attrlist_cursor_kern;
+
+ /*
+- * Vnode types (unrelated to on-disk inodes). VNON means no type.
++ * Vnode types. VNON means no type.
+ */
+-typedef enum vtype {
+- VNON = 0,
+- VREG = 1,
+- VDIR = 2,
+- VBLK = 3,
+- VCHR = 4,
+- VLNK = 5,
+- VFIFO = 6,
+- VBAD = 7,
+- VSOCK = 8
+-} vtype_t;
++enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VFIFO, VBAD, VSOCK };
+
+ typedef xfs_ino_t vnumber_t;
+ typedef struct dentry vname_t;
+@@ -115,14 +136,15 @@ typedef enum {
+ #define LINVFS_GET_IP(vp) (&(vp)->v_inode)
+
+ /*
+- * Conversion between vnode types/modes and encoded type/mode as
+- * seen by stat(2) and mknod(2).
++ * Convert between vnode types and inode formats (since POSIX.1
++ * defines mode word of stat structure in terms of inode formats).
+ */
+-extern enum vtype iftovt_tab[];
+-extern ushort vttoif_tab[];
+-#define IFTOVT(M) (iftovt_tab[((M) & S_IFMT) >> 12])
+-#define VTTOIF(T) (vttoif_tab[(int)(T)])
+-#define MAKEIMODE(T, M) (VTTOIF(T) | ((M) & ~S_IFMT))
++extern enum vtype iftovt_tab[];
++extern u_short vttoif_tab[];
++#define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12])
++#define VTTOIF(indx) (vttoif_tab[(int)(indx)])
++#define MAKEIMODE(indx, mode) (int)(VTTOIF(indx) | (mode))
++
+
+ /*
+ * Vnode flags.
+@@ -370,31 +392,29 @@ typedef struct vnodeops {
+
+ /*
+ * Vnode attributes. va_mask indicates those attributes the caller
+- * wants to set (setattr) or extract (getattr).
++ * wants to set or extract.
+ */
+ typedef struct vattr {
+- int va_mask; /* bit-mask of attributes */
+- vtype_t va_type; /* vnode type (for create) */
+- mode_t va_mode; /* file access mode */
++ int va_mask; /* bit-mask of attributes present */
++ enum vtype va_type; /* vnode type (for create) */
++ mode_t va_mode; /* file access mode and type */
++ nlink_t va_nlink; /* number of references to file */
+ uid_t va_uid; /* owner user id */
+ gid_t va_gid; /* owner group id */
+- xfs_dev_t va_fsid; /* file system id (dev for now) */
+- xfs_ino_t va_nodeid; /* node id */
+- nlink_t va_nlink; /* number of references to file */
++ xfs_ino_t va_nodeid; /* file id */
+ xfs_off_t va_size; /* file size in bytes */
+- timespec_t va_atime; /* time of last access */
+- timespec_t va_mtime; /* time of last modification */
+- timespec_t va_ctime; /* time file ``created'' */
+- xfs_dev_t va_rdev; /* device the file represents */
+- u_long va_blksize; /* fundamental block size */
+- __int64_t va_nblocks; /* # of blocks allocated */
+- u_long va_vcode; /* version code */
++ u_long va_blocksize; /* blocksize preferred for i/o */
++ struct timespec va_atime; /* time of last access */
++ struct timespec va_mtime; /* time of last modification */
++ struct timespec va_ctime; /* time file changed */
++ u_int va_gen; /* generation number of file */
++ xfs_dev_t va_rdev; /* device the special file represents */
++ __int64_t va_nblocks; /* number of blocks allocated */
+ u_long va_xflags; /* random extended file flags */
+ u_long va_extsize; /* file extent size */
+ u_long va_nextents; /* number of extents in file */
+ u_long va_anextents; /* number of attr extents in file */
+ int va_projid; /* project id */
+- u_int va_gencount; /* object generation count */
+ } vattr_t;
+
+ /*
+@@ -450,11 +470,17 @@ typedef struct vattr {
+ XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
+ XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
+
+-#define VREAD 00400
+-#define VWRITE 00200
+-#define VEXEC 00100
+-#define VSGID 02000 /* set group id on execution */
+-#define MODEMASK 07777 /* mode bits plus permission bits */
++/*
++ * Modes.
++ */
++#define VSUID S_ISUID /* set user id on execution */
++#define VSGID S_ISGID /* set group id on execution */
++#define VSVTX S_ISVTX /* save swapped text even after use */
++#define VREAD S_IRUSR /* read, write, execute permissions */
++#define VWRITE S_IWUSR
++#define VEXEC S_IXUSR
++
++#define MODEMASK S_IALLUGO /* mode bits plus permission bits */
+
+ /*
+ * Check whether mandatory file locking is enabled.
+@@ -569,13 +595,9 @@ static __inline__ void vn_flagclr(struct
+ * Flags to VOP_SETATTR/VOP_GETATTR.
+ */
+ #define ATTR_UTIME 0x01 /* non-default utime(2) request */
+-#define ATTR_EXEC 0x02 /* invocation from exec(2) */
+-#define ATTR_COMM 0x04 /* yield common vp attributes */
+ #define ATTR_DMI 0x08 /* invocation from a DMI function */
+ #define ATTR_LAZY 0x80 /* set/get attributes lazily */
+ #define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
+-#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */
+-#define ATTR_NOSIZETOK 0x400 /* Don't get the DVN_SIZE_READ token */
+
+ /*
+ * Flags to VOP_FSYNC and VOP_RECLAIM.
+--- linux-2.6.0-test6/fs/xfs/pagebuf/page_buf.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/pagebuf/page_buf.c 2003-10-05 00:33:24.000000000 -0700
+@@ -141,7 +141,7 @@ pagebuf_param_t pb_params = {
+ * Pagebuf statistics variables
+ */
+
+-struct pbstats pbstats;
++DEFINE_PER_CPU(struct pbstats, pbstats);
+
+ /*
+ * Pagebuf allocation / freeing.
+@@ -293,7 +293,7 @@ _pagebuf_initialize(
+ atomic_set(&pb->pb_pin_count, 0);
+ init_waitqueue_head(&pb->pb_waiters);
+
+- PB_STATS_INC(pbstats.pb_create);
++ PB_STATS_INC(pb_create);
+ PB_TRACE(pb, PB_TRACE_REC(get), target);
+ }
+
+@@ -485,7 +485,7 @@ _pagebuf_lookup_pages(
+ page = find_or_create_page(aspace, index, gfp_mask);
+ if (!page) {
+ if (--retry_count > 0) {
+- PB_STATS_INC(pbstats.pb_page_retries);
++ PB_STATS_INC(pb_page_retries);
+ pagebuf_daemon_wakeup(1);
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(10);
+@@ -495,7 +495,7 @@ _pagebuf_lookup_pages(
+ all_mapped = 0;
+ continue;
+ }
+- PB_STATS_INC(pbstats.pb_page_found);
++ PB_STATS_INC(pb_page_found);
+ mark_page_accessed(page);
+ pb->pb_pages[pi] = page;
+ } else {
+@@ -645,7 +645,7 @@ _pagebuf_find( /* find buffer for blo
+ h->pb_count++;
+ list_add(&new_pb->pb_hash_list, &h->pb_hash);
+ } else {
+- PB_STATS_INC(pbstats.pb_miss_locked);
++ PB_STATS_INC(pb_miss_locked);
+ }
+
+ spin_unlock(&h->pb_hash_lock);
+@@ -665,7 +665,7 @@ found:
+ /* wait for buffer ownership */
+ PB_TRACE(pb, PB_TRACE_REC(get_lk), 0);
+ pagebuf_lock(pb);
+- PB_STATS_INC(pbstats.pb_get_locked_waited);
++ PB_STATS_INC(pb_get_locked_waited);
+ } else {
+ /* We asked for a trylock and failed, no need
+ * to look at file offset and length here, we
+@@ -675,7 +675,7 @@ found:
+ */
+
+ pagebuf_rele(pb);
+- PB_STATS_INC(pbstats.pb_busy_locked);
++ PB_STATS_INC(pb_busy_locked);
+ return (NULL);
+ }
+ } else {
+@@ -691,7 +691,7 @@ found:
+ _PBF_ADDR_ALLOCATED | \
+ _PBF_MEM_ALLOCATED;
+ PB_TRACE(pb, PB_TRACE_REC(got_lk), 0);
+- PB_STATS_INC(pbstats.pb_get_locked);
++ PB_STATS_INC(pb_get_locked);
+ return (pb);
+ }
+
+@@ -747,7 +747,7 @@ pagebuf_get( /* allocate a buffer */
+ return (NULL);
+ }
+
+- PB_STATS_INC(pbstats.pb_get);
++ PB_STATS_INC(pb_get);
+
+ /* fill in any missing pages */
+ error = _pagebuf_lookup_pages(pb, pb->pb_target->pbr_mapping, flags);
+@@ -766,7 +766,7 @@ pagebuf_get( /* allocate a buffer */
+ if (flags & PBF_READ) {
+ if (PBF_NOT_DONE(pb)) {
+ PB_TRACE(pb, PB_TRACE_REC(get_read), flags);
+- PB_STATS_INC(pbstats.pb_get_read);
++ PB_STATS_INC(pb_get_read);
+ pagebuf_iostart(pb, flags);
+ } else if (flags & PBF_ASYNC) {
+ /*
+@@ -1677,6 +1677,9 @@ pagebuf_daemon(
+ break;
+ }
+
++ pb->pb_flags &= ~PBF_DELWRI;
++ pb->pb_flags |= PBF_WRITE;
++
+ list_del(&pb->pb_list);
+ list_add(&pb->pb_list, &tmp);
+
+@@ -1688,8 +1691,6 @@ pagebuf_daemon(
+ while (!list_empty(&tmp)) {
+ pb = list_entry(tmp.next, page_buf_t, pb_list);
+ list_del_init(&pb->pb_list);
+- pb->pb_flags &= ~PBF_DELWRI;
+- pb->pb_flags |= PBF_WRITE;
+
+ pagebuf_iostrategy(pb);
+ }
+@@ -1720,6 +1721,7 @@ pagebuf_delwri_flush(
+ int flush_cnt = 0;
+
+ pagebuf_runall_queues(pagebuf_dataio_workqueue);
++ pagebuf_runall_queues(pagebuf_logio_workqueue);
+
+ spin_lock(&pbd_delwrite_lock);
+ INIT_LIST_HEAD(&tmp);
+@@ -1742,47 +1744,32 @@ pagebuf_delwri_flush(
+ continue;
+ }
+
+- if (flags & PBDF_TRYLOCK) {
+- if (!pagebuf_cond_lock(pb)) {
+- pincount++;
+- continue;
+- }
+- }
+-
+- list_del_init(&pb->pb_list);
+- if (flags & PBDF_WAIT) {
+- list_add(&pb->pb_list, &tmp);
+- pb->pb_flags &= ~PBF_ASYNC;
+- }
+-
+- spin_unlock(&pbd_delwrite_lock);
+-
+- if ((flags & PBDF_TRYLOCK) == 0) {
+- pagebuf_lock(pb);
+- }
+-
+ pb->pb_flags &= ~PBF_DELWRI;
+ pb->pb_flags |= PBF_WRITE;
++ list_move(&pb->pb_list, &tmp);
++ }
++ /* ok found all the items that can be worked on
++ * drop the lock and process the private list */
++ spin_unlock(&pbd_delwrite_lock);
++
++ list_for_each_safe(curr, next, &tmp) {
++ pb = list_entry(curr, page_buf_t, pb_list);
++
++ if (flags & PBDF_WAIT)
++ pb->pb_flags &= ~PBF_ASYNC;
++ else
++ list_del_init(curr);
+
++ pagebuf_lock(pb);
+ pagebuf_iostrategy(pb);
+ if (++flush_cnt > 32) {
+ blk_run_queues();
+ flush_cnt = 0;
+ }
+-
+- spin_lock(&pbd_delwrite_lock);
+ }
+
+- spin_unlock(&pbd_delwrite_lock);
+-
+ blk_run_queues();
+
+- if (pinptr)
+- *pinptr = pincount;
+-
+- if ((flags & PBDF_WAIT) == 0)
+- return;
+-
+ while (!list_empty(&tmp)) {
+ pb = list_entry(tmp.next, page_buf_t, pb_list);
+
+@@ -1792,6 +1779,9 @@ pagebuf_delwri_flush(
+ pagebuf_unlock(pb);
+ pagebuf_rele(pb);
+ }
++
++ if (pinptr)
++ *pinptr = pincount;
+ }
+
+ STATIC int
+@@ -1846,14 +1836,18 @@ pb_stats_clear_handler(
+ void *buffer,
+ size_t *lenp)
+ {
+- int ret;
++ int c, ret;
+ int *valp = ctl->data;
+
+ ret = proc_doulongvec_minmax(ctl, write, filp, buffer, lenp);
+
+ if (!ret && write && *valp) {
+ printk("XFS Clearing pbstats\n");
+- memset(&pbstats, 0, sizeof(pbstats));
++ for (c = 0; c < NR_CPUS; c++) {
++ if (!cpu_possible(c)) continue;
++ memset(&per_cpu(pbstats, c), 0,
++ sizeof(struct pbstats));
++ }
+ pb_params.stats_clear.val = 0;
+ }
+
+@@ -1907,13 +1901,17 @@ pagebuf_readstats(
+ int *eof,
+ void *data)
+ {
+- int i, len;
++ int c, i, len, val;
+
+ len = 0;
+ len += sprintf(buffer + len, "pagebuf");
+- for (i = 0; i < sizeof(pbstats) / sizeof(u_int32_t); i++) {
+- len += sprintf(buffer + len, " %u",
+- *(((u_int32_t*)&pbstats) + i));
++ for (i = 0; i < sizeof(struct pbstats) / sizeof(u_int32_t); i++) {
++ val = 0;
++ for (c = 0 ; c < NR_CPUS; c++) {
++ if (!cpu_possible(c)) continue;
++ val += *(((u_int32_t*)&per_cpu(pbstats, c) + i));
++ }
++ len += sprintf(buffer + len, " %u", val);
+ }
+ buffer[len++] = '\n';
+
+--- linux-2.6.0-test6/fs/xfs/pagebuf/page_buf.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/xfs/pagebuf/page_buf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -136,9 +136,6 @@ typedef enum page_buf_flags_e { /* pb_f
+ #define PBF_NOT_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) != 0)
+ #define PBF_DONE(pb) (((pb)->pb_flags & (PBF_PARTIAL|PBF_NONE)) == 0)
+
+-#define PBR_SECTOR_ONLY 1 /* only use sector size buffer heads */
+-#define PBR_ALIGNED_ONLY 2 /* only use aligned I/O */
+-
+ typedef struct pb_target {
+ dev_t pbr_dev;
+ struct block_device *pbr_bdev;
+@@ -371,7 +368,6 @@ extern int pagebuf_ispin( /* check if b
+ /* Delayed Write Buffer Routines */
+
+ #define PBDF_WAIT 0x01
+-#define PBDF_TRYLOCK 0x02
+ extern void pagebuf_delwri_flush(
+ pb_target_t *,
+ unsigned long,
+--- linux-2.6.0-test6/fs/xfs/pagebuf/page_buf_internal.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/pagebuf/page_buf_internal.h 2003-10-05 00:33:24.000000000 -0700
+@@ -37,6 +37,7 @@
+ #ifndef __PAGE_BUF_PRIVATE_H__
+ #define __PAGE_BUF_PRIVATE_H__
+
++#include <linux/percpu.h>
+ #include "page_buf.h"
+
+ #define _PAGE_BUF_INTERNAL_
+@@ -120,9 +121,11 @@ struct pbstats {
+ u_int32_t pb_get_read;
+ };
+
+-extern struct pbstats pbstats;
++DECLARE_PER_CPU(struct pbstats, pbstats);
+
+-#define PB_STATS_INC(count) ( count ++ )
++/* We don't disable preempt, not too worried about poking the
++ * wrong cpu's stat for now */
++#define PB_STATS_INC(count) (__get_cpu_var(pbstats).count++)
+
+ #ifndef STATIC
+ # define STATIC static
+--- linux-2.6.0-test6/fs/xfs/quota/xfs_dquot.c 2003-06-14 12:18:09.000000000 -0700
++++ 25/fs/xfs/quota/xfs_dquot.c 2003-10-05 00:33:24.000000000 -0700
+@@ -87,9 +87,9 @@
+ STATIC void xfs_qm_dqflush_done(xfs_buf_t *, xfs_dq_logitem_t *);
+
+ #ifdef DEBUG
+-dev_t xfs_dqerror_dev = 0;
+-int xfs_do_dqerror = 0;
+-int xfs_dqreq_num = 0;
++xfs_buftarg_t *xfs_dqerror_target;
++int xfs_do_dqerror;
++int xfs_dqreq_num;
+ int xfs_dqerror_mod = 33;
+ #endif
+
+@@ -911,7 +911,7 @@ xfs_qm_dqget(
+
+ #ifdef DEBUG
+ if (xfs_do_dqerror) {
+- if ((xfs_dqerror_dev == mp->m_dev) &&
++ if ((xfs_dqerror_target == mp->m_ddev_targp) &&
+ (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) {
+ cmn_err(CE_DEBUG, "Returning error in dqget");
+ return (EIO);
+--- linux-2.6.0-test6/fs/xfs/quota/xfs_qm.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/fs/xfs/quota/xfs_qm.h 2003-10-05 00:33:24.000000000 -0700
+@@ -165,9 +165,9 @@ typedef struct xfs_dquot_acct {
+ * Users are allowed to have a usage exceeding their softlimit for
+ * a period this long.
+ */
+-#define XFS_QM_BTIMELIMIT DQ_BTIMELIMIT
+-#define XFS_QM_RTBTIMELIMIT DQ_BTIMELIMIT
+-#define XFS_QM_ITIMELIMIT DQ_FTIMELIMIT
++#define XFS_QM_BTIMELIMIT (7 * 24*60*60) /* 1 week */
++#define XFS_QM_RTBTIMELIMIT (7 * 24*60*60) /* 1 week */
++#define XFS_QM_ITIMELIMIT (7 * 24*60*60) /* 1 week */
+
+ #define XFS_QM_BWARNLIMIT 5
+ #define XFS_QM_IWARNLIMIT 5
+--- linux-2.6.0-test6/fs/xfs/support/move.c 2003-06-14 12:18:22.000000000 -0700
++++ 25/fs/xfs/support/move.c 2003-10-05 00:33:24.000000000 -0700
+@@ -38,57 +38,37 @@
+ #include "debug.h"
+ #include "move.h"
+
+-/*
+- * Move "n" bytes at byte address "cp"; "rw" indicates the direction
+- * of the move, and the I/O parameters are provided in "uio", which is
+- * update to reflect the data which was moved. Returns 0 on success or
+- * a non-zero errno on failure.
++/* Read from kernel buffer at src to user/kernel buffer defined
++ * by the uio structure. Advance the pointer in the uio struct
++ * as we go.
+ */
+ int
+-uiomove(void *cp, size_t n, enum uio_rw rw, struct uio *uio)
++uio_read(caddr_t src, size_t len, struct uio *uio)
+ {
+- register struct iovec *iov;
++ struct iovec *iov;
+ u_int cnt;
+ int error;
+
+- while (n > 0 && uio->uio_resid) {
++ if (len > 0 && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = (u_int)iov->iov_len;
+- if (cnt == 0) {
+- uio->uio_iov++;
+- uio->uio_iovcnt--;
+- continue;
+- }
+- if (cnt > n)
+- cnt = (u_int)n;
+- switch (uio->uio_segflg) {
+- case UIO_USERSPACE:
+- if (rw == UIO_READ)
+- error = copy_to_user(iov->iov_base, cp, cnt);
+- else
+- error = copy_from_user(cp, iov->iov_base, cnt);
++ if (cnt == 0)
++ return 0;
++ if (cnt > len)
++ cnt = (u_int)len;
++ if (uio->uio_segflg == UIO_USERSPACE) {
++ error = copy_to_user(iov->iov_base, src, cnt);
+ if (error)
+ return EFAULT;
+- break;
+-
+-
+- case UIO_SYSSPACE:
+- if (rw == UIO_READ)
+- memcpy(iov->iov_base, cp, cnt);
+- else
+- memcpy(cp, iov->iov_base, cnt);
+- break;
+-
+- default:
++ } else if (uio->uio_segflg == UIO_SYSSPACE) {
++ memcpy(iov->iov_base, src, cnt);
++ } else {
+ ASSERT(0);
+- break;
+ }
+ iov->iov_base = (void *)((char *)iov->iov_base + cnt);
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+- cp = (void *)((char *)cp + cnt);
+- n -= cnt;
+ }
+ return 0;
+ }
+--- linux-2.6.0-test6/fs/xfs/support/move.h 2003-06-14 12:18:20.000000000 -0700
++++ 25/fs/xfs/support/move.h 2003-10-05 00:33:24.000000000 -0700
+@@ -48,11 +48,6 @@ typedef struct uio {
+ } uio_t;
+
+ /*
+- * I/O direction.
+- */
+-typedef enum uio_rw { UIO_READ, UIO_WRITE } uio_rw_t;
+-
+-/*
+ * Segment flag values.
+ */
+ typedef enum uio_seg {
+@@ -60,7 +55,6 @@ typedef enum uio_seg {
+ UIO_SYSSPACE, /* uio_iov describes system space */
+ } uio_seg_t;
+
+-
+-extern int uiomove (void *, size_t, uio_rw_t, uio_t *);
++extern int uio_read (caddr_t, size_t, uio_t *);
+
+ #endif /* __XFS_SUPPORT_MOVE_H__ */
+--- linux-2.6.0-test6/fs/xfs/xfs_attr_fetch.c 2003-06-14 12:18:25.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,100 +0,0 @@
+-/*
+- * Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it would be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+- *
+- * Further, this software is distributed without any warranty that it is
+- * free of the rightful claim of any third person regarding infringement
+- * or the like. Any license provided herein, whether implied or
+- * otherwise, applies only to this software file. Patent licenses, if
+- * any, provided herein do not apply to combinations of this program with
+- * other software, or any other product whatsoever.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write the Free Software Foundation, Inc., 59
+- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+- *
+- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+- * Mountain View, CA 94043, or:
+- *
+- * http://www.sgi.com
+- *
+- * For further information regarding this notice, see:
+- *
+- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+- */
+-
+-#include "xfs.h"
+-
+-#include "xfs_macros.h"
+-#include "xfs_types.h"
+-#include "xfs_inum.h"
+-#include "xfs_log.h"
+-#include "xfs_trans.h"
+-#include "xfs_sb.h"
+-#include "xfs_ag.h"
+-#include "xfs_dir.h"
+-#include "xfs_dir2.h"
+-#include "xfs_dmapi.h"
+-#include "xfs_mount.h"
+-#include "xfs_alloc_btree.h"
+-#include "xfs_bmap_btree.h"
+-#include "xfs_ialloc_btree.h"
+-#include "xfs_itable.h"
+-#include "xfs_btree.h"
+-#include "xfs_ialloc.h"
+-#include "xfs_alloc.h"
+-#include "xfs_attr_sf.h"
+-#include "xfs_dir_sf.h"
+-#include "xfs_dir2_sf.h"
+-#include "xfs_dinode.h"
+-#include "xfs_inode_item.h"
+-#include "xfs_inode.h"
+-#include "xfs_bmap.h"
+-#include "xfs_da_btree.h"
+-#include "xfs_attr.h"
+-#include "xfs_attr_leaf.h"
+-
+-int
+-xfs_attr_fetch(xfs_inode_t *ip, char *name, char *value, int valuelen)
+-{
+- xfs_da_args_t args;
+- int error;
+-
+- if (XFS_IFORK_Q(ip) == 0)
+- return ENOATTR;
+- /*
+- * Do the argument setup for the xfs_attr routines.
+- */
+- memset((char *)&args, 0, sizeof(args));
+- args.dp = ip;
+- args.flags = ATTR_ROOT;
+- args.whichfork = XFS_ATTR_FORK;
+- args.name = name;
+- args.namelen = strlen(name);
+- args.value = value;
+- args.valuelen = valuelen;
+- args.hashval = xfs_da_hashname(args.name, args.namelen);
+- args.oknoent = 1;
+-
+- /*
+- * Decide on what work routines to call based on the inode size.
+- */
+- if (args.dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
+- error = xfs_attr_shortform_getvalue(&args);
+- else if (xfs_bmap_one_block(args.dp, XFS_ATTR_FORK))
+- error = xfs_attr_leaf_get(&args);
+- else
+- error = xfs_attr_node_get(&args);
+-
+- if (error == EEXIST)
+- error = 0;
+-
+- return(error);
+-}
+--- linux-2.6.0-test6/fs/xfs/xfs_bmap.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_bmap.c 2003-10-05 00:33:24.000000000 -0700
+@@ -5553,7 +5553,7 @@ xfs_getbmap(
+ && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)
+ && whichfork == XFS_DATA_FORK) {
+
+- error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, 0, 0, 0, NULL);
++ error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
+ if (error)
+ return XFS_ERROR(error);
+ }
+--- linux-2.6.0-test6/fs/xfs/xfs_buf.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/fs/xfs/xfs_buf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -194,7 +194,10 @@ extern inline xfs_caddr_t xfs_buf_offset
+ (bp)->pb_target = (target)
+
+ #define XFS_BUF_TARGET(bp) ((bp)->pb_target)
+-#define XFS_BUF_TARGET_DEV(bp) ((bp)->pb_target->pbr_dev)
++
++#define XFS_BUFTARG_NAME(target) \
++ ({ char __b[BDEVNAME_SIZE]; bdevname((target->pbr_bdev), __b); __b; })
++
+ #define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
+ #define XFS_BUF_SET_VTYPE(bp, type)
+ #define XFS_BUF_SET_REF(bp, ref)
+--- linux-2.6.0-test6/fs/xfs/xfs_buf_item.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/fs/xfs/xfs_buf_item.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1007,7 +1007,7 @@ xfs_buf_iodone_callbacks(
+ {
+ xfs_log_item_t *lip;
+ static ulong lasttime;
+- static dev_t lastdev;
++ static xfs_buftarg_t *lasttarg;
+ xfs_mount_t *mp;
+
+ ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
+@@ -1045,15 +1045,15 @@ xfs_buf_iodone_callbacks(
+ return;
+ }
+
+- if ((XFS_BUF_TARGET_DEV(bp) != lastdev) ||
++ if ((XFS_BUF_TARGET(bp) != lasttarg) ||
+ (time_after(jiffies, (lasttime + 5*HZ)))) {
+ lasttime = jiffies;
+ prdev("XFS write error in file system meta-data "
+ "block 0x%Lx in %s",
+- XFS_BUF_TARGET_DEV(bp),
++ XFS_BUF_TARGET(bp),
+ XFS_BUF_ADDR(bp), mp->m_fsname);
+ }
+- lastdev = XFS_BUF_TARGET_DEV(bp);
++ lasttarg = XFS_BUF_TARGET(bp);
+
+ if (XFS_BUF_ISASYNC(bp)) {
+ /*
+--- linux-2.6.0-test6/fs/xfs/xfs_da_btree.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_da_btree.c 2003-10-05 00:33:24.000000000 -0700
+@@ -2450,7 +2450,7 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bp
+ dabuf->dirty = 0;
+ #ifdef XFS_DABUF_DEBUG
+ dabuf->ra = ra;
+- dabuf->dev = XFS_BUF_TARGET_DEV(bps[0]);
++ dabuf->target = XFS_BUF_TARGET(bps[0]);
+ dabuf->blkno = XFS_BUF_ADDR(bps[0]);
+ #endif
+ if (nbuf == 1) {
+@@ -2480,7 +2480,7 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bp
+ s = mutex_spinlock(&xfs_dabuf_global_lock);
+ for (p = xfs_dabuf_global_list; p; p = p->next) {
+ ASSERT(p->blkno != dabuf->blkno ||
+- p->dev != dabuf->dev);
++ p->target != dabuf->target);
+ }
+ dabuf->prev = NULL;
+ if (xfs_dabuf_global_list)
+--- linux-2.6.0-test6/fs/xfs/xfs_da_btree.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_da_btree.h 2003-10-05 00:33:24.000000000 -0700
+@@ -212,7 +212,7 @@ typedef struct xfs_dabuf {
+ inst_t *ra; /* return address of caller to make */
+ struct xfs_dabuf *next; /* next in global chain */
+ struct xfs_dabuf *prev; /* previous in global chain */
+- dev_t dev; /* device for buffer */
++ struct xfs_buftarg *target; /* device for buffer */
+ xfs_daddr_t blkno; /* daddr first in bps[0] */
+ #endif
+ struct xfs_buf *bps[1]; /* actually nbuf of these */
+--- linux-2.6.0-test6/fs/xfs/xfs_dinode.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_dinode.h 2003-10-05 00:33:24.000000000 -0700
+@@ -439,25 +439,21 @@ void xfs_dfork_next_set(xfs_dinode_t *di
+ /*
+ * File types (mode field)
+ */
+-#define IFMT 0170000 /* type of file */
+-#define IFIFO 0010000 /* named pipe (fifo) */
+-#define IFCHR 0020000 /* character special */
+-#define IFDIR 0040000 /* directory */
+-#define IFBLK 0060000 /* block special */
+-#define IFREG 0100000 /* regular */
+-#define IFLNK 0120000 /* symbolic link */
+-#define IFSOCK 0140000 /* socket */
+-#define IFMNT 0160000 /* mount point */
++#define IFMT S_IFMT
++#define IFSOCK S_IFSOCK
++#define IFLNK S_IFLNK
++#define IFREG S_IFREG
++#define IFBLK S_IFBLK
++#define IFDIR S_IFDIR
++#define IFCHR S_IFCHR
++#define IFIFO S_IFIFO
+
+-/*
+- * File execution and access modes.
+- */
+-#define ISUID 04000 /* set user id on execution */
+-#define ISGID 02000 /* set group id on execution */
+-#define ISVTX 01000 /* sticky directory */
+-#define IREAD 0400 /* read, write, execute permissions */
+-#define IWRITE 0200
+-#define IEXEC 0100
++#define ISUID S_ISUID
++#define ISGID S_ISGID
++#define ISVTX S_ISVTX
++#define IREAD S_IRUSR
++#define IWRITE S_IWUSR
++#define IEXEC S_IXUSR
+
+ #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BUF_TO_DINODE)
+ xfs_dinode_t *xfs_buf_to_dinode(struct xfs_buf *bp);
+--- linux-2.6.0-test6/fs/xfs/xfs_dir2.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_dir2.c 2003-10-05 00:33:24.000000000 -0700
+@@ -773,7 +773,7 @@ xfs_dir2_put_dirent64_uio(
+ idbp->d_off = pa->cook;
+ idbp->d_name[namelen] = '\0';
+ memcpy(idbp->d_name, pa->name, namelen);
+- rval = uiomove((caddr_t)idbp, reclen, UIO_READ, uio);
++ rval = uio_read((caddr_t)idbp, reclen, uio);
+ pa->done = (rval == 0);
+ return rval;
+ }
+--- linux-2.6.0-test6/fs/xfs/xfs_dir_leaf.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_dir_leaf.c 2003-10-05 00:33:24.000000000 -0700
+@@ -2225,7 +2225,7 @@ xfs_dir_put_dirent64_uio(xfs_dir_put_arg
+ idbp->d_off = pa->cook.o;
+ idbp->d_name[namelen] = '\0';
+ memcpy(idbp->d_name, pa->name, namelen);
+- retval = uiomove((caddr_t)idbp, reclen, UIO_READ, uio);
++ retval = uio_read((caddr_t)idbp, reclen, uio);
+ pa->done = (retval == 0);
+ return retval;
+ }
+--- linux-2.6.0-test6/fs/xfs/xfs_error.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_error.c 2003-10-05 00:33:24.000000000 -0700
+@@ -329,6 +329,7 @@ xfs_corruption_error(
+ int linenum,
+ inst_t *ra)
+ {
+- xfs_hex_dump(p, 16);
++ if (level <= xfs_error_level)
++ xfs_hex_dump(p, 16);
+ xfs_error_report(tag, level, mp, fname, linenum, ra);
+ }
+--- linux-2.6.0-test6/fs/xfs/xfs_error.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_error.h 2003-10-05 00:33:24.000000000 -0700
+@@ -32,8 +32,8 @@
+ #ifndef __XFS_ERROR_H__
+ #define __XFS_ERROR_H__
+
+-#define prdev(fmt,dev,args...) \
+- printk("XFS: device %u:%u- " fmt "\n", MAJOR(dev), MINOR(dev), ## args)
++#define prdev(fmt,targ,args...) \
++ printk("XFS: device %s- " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
+
+ #define XFS_ERECOVER 1 /* Failure to recover log */
+ #define XFS_ELOGSTAT 2 /* Failure to stat log in user space */
+--- linux-2.6.0-test6/fs/xfs/xfs_fs.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_fs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -392,22 +392,17 @@ typedef struct xfs_fsop_attrmulti_handle
+ } xfs_fsop_attrmulti_handlereq_t;
+
+ /*
+- * File system identifier. Should be unique (at least per machine).
++ * per machine unique filesystem identifier types.
+ */
+-typedef struct {
+- __u32 val[2]; /* file system id type */
+-} xfs_fsid_t;
++typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */
++
+
+-/*
+- * File identifier. Should be unique per filesystem on a single machine.
+- * This is typically called by a stateless file server in order to generate
+- * "file handles".
+- */
+ #ifndef HAVE_FID
+ #define MAXFIDSZ 46
++
+ typedef struct fid {
+ __u16 fid_len; /* length of data in bytes */
+- unsigned char fid_data[MAXFIDSZ]; /* data (variable length) */
++ unsigned char fid_data[MAXFIDSZ]; /* data (fid_len worth) */
+ } fid_t;
+ #endif
+
+--- linux-2.6.0-test6/fs/xfs/xfsidbg.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfsidbg.c 2003-10-05 00:33:24.000000000 -0700
+@@ -3739,9 +3739,9 @@ xfsidbg_xdabuf(xfs_dabuf_t *dabuf)
+ kdb_printf(" %d:0x%p", i, dabuf->bps[i]);
+ kdb_printf("\n");
+ #ifdef XFS_DABUF_DEBUG
+- kdb_printf(" ra 0x%x prev 0x%x next 0x%x dev %u:%u blkno 0x%x\n",
++ kdb_printf(" ra 0x%x prev 0x%x next 0x%x dev %s blkno 0x%x\n",
+ dabuf->ra, dabuf->prev, dabuf->next,
+- MAJOR(dabuf->dev), MINOR(dabuf->dev), dabuf->blkno);
++ XFS_BUFTARG_NAME(dabuf->dev), dabuf->blkno);
+ #endif
+ }
+
+@@ -4269,9 +4269,8 @@ xfsidbg_xlog(xlog_t *log)
+ xfsidbg_get_cstate(log->l_covered_state));
+ kdb_printf("flags: ");
+ printflags(log->l_flags, t_flags,"log");
+- kdb_printf(" dev: %u:%u logBBstart: %lld logsize: %d logBBsize: %d\n",
+- MAJOR(log->l_dev), MINOR(log->l_dev),
+- (long long) log->l_logBBstart,
++ kdb_printf(" dev: %s logBBstart: %lld logsize: %d logBBsize: %d\n",
++ XFS_BUFTARG_NAME(log->l_targ), (long long) log->l_logBBstart,
+ log->l_logsize,log->l_logBBsize);
+ kdb_printf("curr_cycle: %d prev_cycle: %d curr_block: %d prev_block: %d\n",
+ log->l_curr_cycle, log->l_prev_cycle, log->l_curr_block,
+@@ -4646,14 +4645,14 @@ xfsidbg_xmount(xfs_mount_t *mp)
+ XFS_MTOVFS(mp), mp->m_tid, &mp->m_ail_lock, &mp->m_ail);
+ kdb_printf("ail_gen 0x%x &sb 0x%p\n",
+ mp->m_ail_gen, &mp->m_sb);
+- kdb_printf("sb_lock 0x%p sb_bp 0x%p dev %u:%u logdev %u:%u rtdev %u:%u\n",
++ kdb_printf("sb_lock 0x%p sb_bp 0x%p dev %s logdev %s rtdev %s\n",
+ &mp->m_sb_lock, mp->m_sb_bp,
+- mp->m_ddev_targp ? MAJOR(mp->m_ddev_targp->pbr_dev) : 0,
+- mp->m_ddev_targp ? MINOR(mp->m_ddev_targp->pbr_dev) : 0,
+- mp->m_logdev_targp ? MAJOR(mp->m_logdev_targp->pbr_dev) : 0,
+- mp->m_logdev_targp ? MINOR(mp->m_logdev_targp->pbr_dev) : 0,
+- mp->m_rtdev_targp ? MAJOR(mp->m_rtdev_targp->pbr_dev) : 0,
+- mp->m_rtdev_targp ? MINOR(mp->m_rtdev_targp->pbr_dev) : 0);
++ mp->m_ddev_targp ?
++ XFS_BUFTARG_NAME(mp->m_ddev_targp) : "none",
++ mp->m_logdev_targp ?
++ XFS_BUFTARG_NAME(mp->m_logdev_targp) : "none",
++ mp->m_rtdev_targp ?
++ XFS_BUFTARG_NAME(mp->m_rtdev_targp) : "none");
+ kdb_printf("bsize %d agfrotor %d agirotor %d ihash 0x%p ihsize %d\n",
+ mp->m_bsize, mp->m_agfrotor, mp->m_agirotor,
+ mp->m_ihash, mp->m_ihsize);
+@@ -4824,9 +4823,8 @@ xfsidbg_xnode(xfs_inode_t *ip)
+ ip->i_mnext,
+ ip->i_mprev,
+ XFS_ITOV_NULL(ip));
+- kdb_printf("dev %u:%u ino %s\n",
+- MAJOR(ip->i_mount->m_dev),
+- MINOR(ip->i_mount->m_dev),
++ kdb_printf("dev %s ino %s\n",
++ XFS_BUFTARG_NAME(ip->i_mount->m_ddev_targp),
+ xfs_fmtino(ip->i_ino, ip->i_mount));
+ kdb_printf("blkno 0x%llx len 0x%x boffset 0x%x\n",
+ (long long) ip->i_blkno,
+--- linux-2.6.0-test6/fs/xfs/xfs_inode.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -408,8 +408,9 @@ xfs_itobp(
+ if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
+ XFS_RANDOM_ITOBP_INOTOBP))) {
+ #ifdef DEBUG
+- prdev("bad inode magic/vsn daddr 0x%llx #%d (magic=%x)",
+- mp->m_dev, (unsigned long long)imap.im_blkno, i,
++ prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)",
++ mp->m_ddev_targp,
++ (unsigned long long)imap.im_blkno, i,
+ INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
+ #endif
+ XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
+--- linux-2.6.0-test6/fs/xfs/xfs_log.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_log.c 2003-10-05 00:33:24.000000000 -0700
+@@ -65,7 +65,7 @@ STATIC int xlog_bdstrat_cb(struct xfs_b
+ STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket,
+ xlog_in_core_t **, xfs_lsn_t *);
+ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp,
+- dev_t log_dev,
++ xfs_buftarg_t *log_target,
+ xfs_daddr_t blk_offset,
+ int num_bblks);
+ STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
+@@ -155,7 +155,7 @@ int xlog_error_mod = 33;
+ */
+ #if defined(XLOG_NOLOG) || defined(DEBUG)
+ int xlog_debug = 1;
+-dev_t xlog_devt = 0;
++xfs_buftarg_t *xlog_target;
+ #endif
+
+ #if defined(XFS_LOG_TRACE)
+@@ -274,7 +274,7 @@ xfs_log_done(xfs_mount_t *mp,
+ xfs_lsn_t lsn = 0;
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return 0;
+ #endif
+
+@@ -339,7 +339,7 @@ xfs_log_force(xfs_mount_t *mp,
+ xlog_t *log = mp->m_log;
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return 0;
+ #endif
+
+@@ -378,7 +378,7 @@ xfs_log_notify(xfs_mount_t *mp, /* mo
+ int abortflg, spl;
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return 0;
+ #endif
+ cb->cb_next = 0;
+@@ -436,7 +436,7 @@ xfs_log_reserve(xfs_mount_t *mp,
+ int retval;
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return 0;
+ #endif
+ retval = 0;
+@@ -472,7 +472,7 @@ xfs_log_reserve(xfs_mount_t *mp,
+ * Mount a log filesystem
+ *
+ * mp - ubiquitous xfs mount point structure
+- * log_dev - device number of on-disk log device
++ * log_target - buftarg of on-disk log device
+ * blk_offset - Start block # where block size is 512 bytes (BBSIZE)
+ * num_bblocks - Number of BBSIZE blocks in on-disk log
+ *
+@@ -480,7 +480,7 @@ xfs_log_reserve(xfs_mount_t *mp,
+ */
+ int
+ xfs_log_mount(xfs_mount_t *mp,
+- dev_t log_dev,
++ xfs_buftarg_t *log_target,
+ xfs_daddr_t blk_offset,
+ int num_bblks)
+ {
+@@ -493,12 +493,11 @@ xfs_log_mount(xfs_mount_t *mp,
+ ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
+ }
+
+- mp->m_log = xlog_alloc_log(mp, log_dev, blk_offset, num_bblks);
++ mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug) {
+- cmn_err(CE_NOTE, "log dev: %u:%u",
+- MAJOR(log_dev), MINOR(log_dev));
++ if (!xlog_debug) {
++ cmn_err(CE_NOTE, "log dev: %s", XFS_BUFTARG_NAME(log_target));
+ return 0;
+ }
+ #endif
+@@ -606,7 +605,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
+ } magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (! xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return 0;
+ #endif
+
+@@ -734,9 +733,9 @@ xfs_log_write(xfs_mount_t * mp,
+ {
+ int error;
+ xlog_t *log = mp->m_log;
+-#if defined(DEBUG) || defined(XLOG_NOLOG)
+
+- if (! xlog_debug && xlog_devt == log->l_dev) {
++#if defined(DEBUG) || defined(XLOG_NOLOG)
++ if (!xlog_debug && xlog_target == log->l_targ) {
+ *start_lsn = 0;
+ return 0;
+ }
+@@ -761,7 +760,7 @@ xfs_log_move_tail(xfs_mount_t *mp,
+ SPLDECL(s);
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+- if (!xlog_debug && xlog_devt == log->l_dev)
++ if (!xlog_debug && xlog_target == log->l_targ)
+ return;
+ #endif
+ /* XXXsup tmp */
+@@ -1059,14 +1058,14 @@ xlog_get_iclog_buffer_size(xfs_mount_t *
+ /*
+ * When logbufs == 0, someone has disabled the log from the FSTAB
+ * file. This is not a documented feature. We need to set xlog_debug
+- * to zero (this deactivates the log) and set xlog_devt to the
++ * to zero (this deactivates the log) and set xlog_target to the
+ * appropriate dev_t. Only one filesystem may be affected as such
+ * since this is just a performance hack to test what we might be able
+ * to get if the log were not present.
+ */
+ if (mp->m_logbufs == 0) {
+ xlog_debug = 0;
+- xlog_devt = log->l_dev;
++ xlog_target = log->l_targ;
+ log->l_iclog_bufs = XLOG_MIN_ICLOGS;
+ } else
+ #endif
+@@ -1089,8 +1088,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t *
+
+ #if defined(DEBUG) || defined(XLOG_NOLOG)
+ /* We are reactivating a filesystem after it was active */
+- if (log->l_dev == xlog_devt) {
+- xlog_devt = 1;
++ if (log->l_targ == xlog_target) {
++ xlog_target = 1; /* XXX(hch): WTF? */
+ xlog_debug = 1;
+ }
+ #endif
+@@ -1176,7 +1175,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t *
+ */
+ STATIC xlog_t *
+ xlog_alloc_log(xfs_mount_t *mp,
+- dev_t log_dev,
++ xfs_buftarg_t *log_target,
+ xfs_daddr_t blk_offset,
+ int num_bblks)
+ {
+@@ -1191,7 +1190,7 @@ xlog_alloc_log(xfs_mount_t *mp,
+ log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
+
+ log->l_mp = mp;
+- log->l_dev = log_dev;
++ log->l_targ = log_target;
+ log->l_logsize = BBTOB(num_bblks);
+ log->l_logBBstart = blk_offset;
+ log->l_logBBsize = num_bblks;
+--- linux-2.6.0-test6/fs/xfs/xfs_log.h 2003-06-14 12:18:52.000000000 -0700
++++ 25/fs/xfs/xfs_log.h 2003-10-05 00:33:24.000000000 -0700
+@@ -153,10 +153,10 @@ xfs_lsn_t xfs_log_done(struct xfs_mount
+ int xfs_log_force(struct xfs_mount *mp,
+ xfs_lsn_t lsn,
+ uint flags);
+-int xfs_log_mount(struct xfs_mount *mp,
+- dev_t log_dev,
+- xfs_daddr_t start_block,
+- int num_bblocks);
++int xfs_log_mount(struct xfs_mount *mp,
++ struct xfs_buftarg *log_target,
++ xfs_daddr_t start_block,
++ int num_bblocks);
+ int xfs_log_mount_finish(struct xfs_mount *mp, int);
+ void xfs_log_move_tail(struct xfs_mount *mp,
+ xfs_lsn_t tail_lsn);
+--- linux-2.6.0-test6/fs/xfs/xfs_log_priv.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/xfs/xfs_log_priv.h 2003-10-05 00:33:24.000000000 -0700
+@@ -504,7 +504,7 @@ typedef struct log {
+ struct xfs_mount *l_mp; /* mount point */
+ struct xfs_buf *l_xbuf; /* extra buffer for log
+ * wrapping */
+- dev_t l_dev; /* dev_t of log */
++ struct xfs_buftarg *l_targ; /* buftarg of log */
+ xfs_daddr_t l_logBBstart; /* start block of log */
+ int l_logsize; /* size of log in bytes */
+ int l_logBBsize; /* size of log in BB chunks */
+--- linux-2.6.0-test6/fs/xfs/xfs_log_recover.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_log_recover.c 2003-10-05 00:33:24.000000000 -0700
+@@ -2179,8 +2179,8 @@ xlog_recover_do_buffer_trans(
+ break;
+ default:
+ xfs_fs_cmn_err(CE_ALERT, log->l_mp,
+- "xfs_log_recover: unknown buffer type 0x%x, dev %u:%u",
+- buf_f->blf_type, MAJOR(log->l_dev), MINOR(log->l_dev));
++ "xfs_log_recover: unknown buffer type 0x%x, dev %s",
++ buf_f->blf_type, XFS_BUFTARG_NAME(log->l_targ));
+ XFS_ERROR_REPORT("xlog_recover_do_buffer_trans",
+ XFS_ERRLEVEL_LOW, log->l_mp);
+ return XFS_ERROR(EFSCORRUPTED);
+@@ -3889,9 +3889,8 @@ xlog_recover(
+ }
+
+ cmn_err(CE_NOTE,
+- "Starting XFS recovery on filesystem: %s (dev: %d/%d)",
+- log->l_mp->m_fsname, MAJOR(log->l_dev),
+- MINOR(log->l_dev));
++ "Starting XFS recovery on filesystem: %s (dev: %s)",
++ log->l_mp->m_fsname, XFS_BUFTARG_NAME(log->l_targ));
+
+ error = xlog_do_recover(log, head_blk, tail_blk);
+ log->l_flags |= XLOG_RECOVERY_NEEDED;
+@@ -3939,10 +3938,8 @@ xlog_recover_finish(
+ xlog_recover_check_summary(log);
+
+ cmn_err(CE_NOTE,
+- "Ending XFS recovery on filesystem: %s (dev: %d/%d)",
+- log->l_mp->m_fsname, MAJOR(log->l_dev),
+- MINOR(log->l_dev));
+-
++ "Ending XFS recovery on filesystem: %s (dev: %s)",
++ log->l_mp->m_fsname, XFS_BUFTARG_NAME(log->l_targ));
+ log->l_flags &= ~XLOG_RECOVERY_NEEDED;
+ } else {
+ cmn_err(CE_DEBUG,
+--- linux-2.6.0-test6/fs/xfs/xfs_mount.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_mount.c 2003-10-05 00:33:24.000000000 -0700
+@@ -285,9 +285,9 @@ xfs_mount_validate_sb(
+ #if !XFS_BIG_BLKNOS
+ if (unlikely(
+ (sbp->sb_dblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
+- > INT_MAX ||
++ > UINT_MAX ||
+ (sbp->sb_rblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
+- > INT_MAX)) {
++ > UINT_MAX)) {
+ cmn_err(CE_WARN,
+ "XFS: File system is too large to be mounted on this system.");
+ return XFS_ERROR(E2BIG);
+@@ -949,7 +949,7 @@ xfs_mountfs(
+ * log's mount-time initialization. Perform 1st part recovery if needed
+ */
+ if (likely(sbp->sb_logblocks > 0)) { /* check for volume case */
+- error = xfs_log_mount(mp, mp->m_logdev_targp->pbr_dev,
++ error = xfs_log_mount(mp, mp->m_logdev_targp,
+ XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
+ XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
+ if (error) {
+@@ -980,7 +980,7 @@ xfs_mountfs(
+ if (unlikely((rip->i_d.di_mode & IFMT) != IFDIR)) {
+ cmn_err(CE_WARN, "XFS: corrupted root inode");
+ prdev("Root inode %llu is not a directory",
+- mp->m_dev, (unsigned long long)rip->i_ino);
++ mp->m_ddev_targp, (unsigned long long)rip->i_ino);
+ xfs_iunlock(rip, XFS_ILOCK_EXCL);
+ XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
+ mp);
+--- linux-2.6.0-test6/fs/xfs/xfs_mount.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_mount.h 2003-10-05 00:33:24.000000000 -0700
+@@ -91,10 +91,10 @@ struct xfs_bmap_free;
+ * Prototypes and functions for the Data Migration subsystem.
+ */
+
+-typedef int (*xfs_send_data_t)(int, struct bhv_desc *,
++typedef int (*xfs_send_data_t)(int, struct vnode *,
+ xfs_off_t, size_t, int, vrwlock_t *);
+ typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint);
+-typedef int (*xfs_send_destroy_t)(struct bhv_desc *, dm_right_t);
++typedef int (*xfs_send_destroy_t)(struct vnode *, dm_right_t);
+ typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct vnode *,
+ dm_right_t, struct vnode *, dm_right_t,
+ char *, char *, mode_t, int, int);
+@@ -109,12 +109,12 @@ typedef struct xfs_dmops {
+ xfs_send_unmount_t xfs_send_unmount;
+ } xfs_dmops_t;
+
+-#define XFS_SEND_DATA(mp, ev,bdp,off,len,fl,lock) \
+- (*(mp)->m_dm_ops.xfs_send_data)(ev,bdp,off,len,fl,lock)
++#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
++ (*(mp)->m_dm_ops.xfs_send_data)(ev,vp,off,len,fl,lock)
+ #define XFS_SEND_MMAP(mp, vma,fl) \
+ (*(mp)->m_dm_ops.xfs_send_mmap)(vma,fl)
+-#define XFS_SEND_DESTROY(mp, bdp,right) \
+- (*(mp)->m_dm_ops.xfs_send_destroy)(bdp,right)
++#define XFS_SEND_DESTROY(mp, vp,right) \
++ (*(mp)->m_dm_ops.xfs_send_destroy)(vp,right)
+ #define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+ (*(mp)->m_dm_ops.xfs_send_namesp)(ev,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+ #define XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \
+--- linux-2.6.0-test6/fs/xfs/xfs_rw.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_rw.c 2003-10-05 00:33:24.000000000 -0700
+@@ -260,11 +260,10 @@ xfs_ioerror_alert(
+ xfs_daddr_t blkno)
+ {
+ cmn_err(CE_ALERT,
+- "I/O error in filesystem (\"%s\") meta-data dev %u:%u block 0x%llx"
++ "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
+ " (\"%s\") error %d buf count %u",
+ (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
+- MAJOR(XFS_BUF_TARGET_DEV(bp)),
+- MINOR(XFS_BUF_TARGET_DEV(bp)),
++ XFS_BUFTARG_NAME(bp->pb_target),
+ (__uint64_t)blkno,
+ func,
+ XFS_BUF_GETERROR(bp),
+--- linux-2.6.0-test6/fs/xfs/xfs_trans_buf.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/fs/xfs/xfs_trans_buf.c 2003-10-05 00:33:24.000000000 -0700
+@@ -264,7 +264,7 @@ xfs_trans_getsb(xfs_trans_t *tp,
+ }
+
+ #ifdef DEBUG
+-dev_t xfs_error_dev = 0;
++xfs_buftarg_t *xfs_error_target;
+ int xfs_do_error;
+ int xfs_req_num;
+ int xfs_error_mod = 33;
+@@ -322,7 +322,7 @@ xfs_trans_read_buf(
+ }
+ #ifdef DEBUG
+ if (xfs_do_error && (bp != NULL)) {
+- if (xfs_error_dev == target->pbr_dev) {
++ if (xfs_error_target == target) {
+ if (((xfs_req_num++) % xfs_error_mod) == 0) {
+ xfs_buf_relse(bp);
+ printk("Returning error!\n");
+@@ -425,7 +425,7 @@ xfs_trans_read_buf(
+ }
+ #ifdef DEBUG
+ if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) {
+- if (xfs_error_dev == target->pbr_dev) {
++ if (xfs_error_target == target) {
+ if (((xfs_req_num++) % xfs_error_mod) == 0) {
+ xfs_force_shutdown(tp->t_mountp,
+ XFS_METADATA_IO_ERROR);
+--- linux-2.6.0-test6/fs/xfs/xfs_trans.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/fs/xfs/xfs_trans.h 2003-10-05 00:33:24.000000000 -0700
+@@ -995,7 +995,6 @@ void xfs_trans_dquot_buf(xfs_trans_t *,
+ void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
+ int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
+ xfs_ino_t , uint, struct xfs_inode **);
+-void xfs_trans_iput(xfs_trans_t *, struct xfs_inode *, uint);
+ void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
+ void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
+ void xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
+--- linux-2.6.0-test6/fs/xfs/xfs_trans_inode.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/fs/xfs/xfs_trans_inode.c 2003-10-05 00:33:24.000000000 -0700
+@@ -188,106 +188,6 @@ xfs_trans_iget(
+
+
+ /*
+- * Release the inode ip which was previously acquired with xfs_trans_iget()
+- * or added with xfs_trans_ijoin(). This will decrement the lock
+- * recursion count of the inode item. If the count goes to less than 0,
+- * the inode will be unlocked and disassociated from the transaction.
+- *
+- * If the inode has been modified within the transaction, it will not be
+- * unlocked until the transaction commits.
+- */
+-void
+-xfs_trans_iput(
+- xfs_trans_t *tp,
+- xfs_inode_t *ip,
+- uint lock_flags)
+-{
+- xfs_inode_log_item_t *iip;
+- xfs_log_item_desc_t *lidp;
+-
+- /*
+- * If the transaction pointer is NULL, just call xfs_iput().
+- */
+- if (tp == NULL) {
+- xfs_iput(ip, lock_flags);
+- }
+-
+- ASSERT(ip->i_transp == tp);
+- iip = ip->i_itemp;
+- ASSERT(iip != NULL);
+-
+- /*
+- * Find the item descriptor pointing to this inode's
+- * log item. It must be there.
+- */
+- lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)iip);
+- ASSERT(lidp != NULL);
+- ASSERT(lidp->lid_item == (xfs_log_item_t*)iip);
+-
+- /*
+- * Be consistent about the bookkeeping for the inode's
+- * io lock, but it doesn't mean much really.
+- */
+- ASSERT((iip->ili_flags & XFS_ILI_IOLOCKED_ANY) != XFS_ILI_IOLOCKED_ANY);
+- if (lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) {
+- ASSERT(iip->ili_flags & XFS_ILI_IOLOCKED_ANY);
+- ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
+- (iip->ili_flags & XFS_ILI_IOLOCKED_EXCL));
+- ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
+- (iip->ili_flags &
+- (XFS_ILI_IOLOCKED_EXCL | XFS_ILI_IOLOCKED_SHARED)));
+- if (iip->ili_iolock_recur > 0) {
+- iip->ili_iolock_recur--;
+- }
+- }
+-
+- /*
+- * If the release is just for a recursive lock on the inode lock,
+- * then decrement the count and return. We can assert that
+- * the caller is dropping an EXCL lock on the inode, because
+- * inode must be locked EXCL within transactions.
+- */
+- ASSERT(lock_flags & XFS_ILOCK_EXCL);
+- if (iip->ili_ilock_recur > 0) {
+- iip->ili_ilock_recur--;
+- return;
+- }
+- ASSERT(iip->ili_iolock_recur == 0);
+-
+- /*
+- * If the inode was dirtied within this transaction, it cannot
+- * be released until the transaction commits.
+- */
+- if (lidp->lid_flags & XFS_LID_DIRTY) {
+- return;
+- }
+-
+- xfs_trans_free_item(tp, lidp);
+-
+- /*
+- * Clear the hold and iolocked flags in the inode log item.
+- * We wouldn't want the next user of the inode to
+- * get confused. Assert that if the iolocked flag is set
+- * in the item then we are unlocking it in the call to xfs_iput()
+- * below.
+- */
+- ASSERT((!(iip->ili_flags & XFS_ILI_IOLOCKED_ANY)) ||
+- (lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)));
+- if (iip->ili_flags & (XFS_ILI_HOLD | XFS_ILI_IOLOCKED_ANY)) {
+- iip->ili_flags &= ~(XFS_ILI_HOLD | XFS_ILI_IOLOCKED_ANY);
+- }
+-
+- /*
+- * Unlike xfs_brelse() the inode log item cannot be
+- * freed, because it is embedded within the inode.
+- * All we have to do is release the inode.
+- */
+- xfs_iput(ip, lock_flags);
+- return;
+-}
+-
+-
+-/*
+ * Add the locked inode to the transaction.
+ * The inode must be locked, and it cannot be associated with any
+ * transaction. The caller must specify the locks already held
+--- linux-2.6.0-test6/fs/xfs/xfs_types.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_types.h 2003-10-05 00:33:24.000000000 -0700
+@@ -83,7 +83,7 @@ typedef __uint64_t __psunsigned_t;
+ * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well
+ * as requiring XFS_BIG_BLKNOS to be set.
+ */
+-#if defined(CONFIG_LBD) || (defined(HAVE_SECTOR_T) && (BITS_PER_LONG == 64))
++#if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
+ # define XFS_BIG_BLKNOS 1
+ # if BITS_PER_LONG == 64
+ # define XFS_BIG_INUMS 1
+--- linux-2.6.0-test6/fs/xfs/xfs_vfsops.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_vfsops.c 2003-10-05 00:33:24.000000000 -0700
+@@ -1776,7 +1776,6 @@ xfs_showargs(
+ };
+ struct proc_xfs_info *xfs_infop;
+ struct xfs_mount *mp = XFS_BHVTOM(bhv);
+- char b[BDEVNAME_SIZE];
+
+ for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
+ if (mp->m_flags & xfs_infop->flag)
+@@ -1792,14 +1791,13 @@ xfs_showargs(
+ if (mp->m_logbsize > 0)
+ seq_printf(m, "," MNTOPT_LOGBSIZE "=%d", mp->m_logbsize);
+
+- if (mp->m_ddev_targp->pbr_dev != mp->m_logdev_targp->pbr_dev)
++ if (mp->m_ddev_targp != mp->m_logdev_targp)
+ seq_printf(m, "," MNTOPT_LOGDEV "=%s",
+- bdevname(mp->m_logdev_targp->pbr_bdev, b));
++ XFS_BUFTARG_NAME(mp->m_logdev_targp));
+
+- if (mp->m_rtdev_targp &&
+- mp->m_ddev_targp->pbr_dev != mp->m_rtdev_targp->pbr_dev)
++ if (mp->m_rtdev_targp && mp->m_ddev_targp != mp->m_rtdev_targp)
+ seq_printf(m, "," MNTOPT_RTDEV "=%s",
+- bdevname(mp->m_rtdev_targp->pbr_bdev, b));
++ XFS_BUFTARG_NAME(mp->m_rtdev_targp));
+
+ if (mp->m_dalign > 0)
+ seq_printf(m, "," MNTOPT_SUNIT "=%d",
+--- linux-2.6.0-test6/fs/xfs/xfs_vnodeops.c 2003-09-27 18:57:46.000000000 -0700
++++ 25/fs/xfs/xfs_vnodeops.c 2003-10-05 00:33:24.000000000 -0700
+@@ -144,14 +144,11 @@ xfs_getattr(
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+
+ vap->va_size = ip->i_d.di_size;
+- if (vap->va_mask == XFS_AT_SIZE) {
+- if (!(flags & ATTR_LAZY))
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+- return 0;
+- }
++ if (vap->va_mask == XFS_AT_SIZE)
++ goto all_done;
++
+ vap->va_nblocks =
+ XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
+- vap->va_fsid = mp->m_dev;
+ vap->va_nodeid = ip->i_ino;
+ #if XFS_BIG_INUMS
+ vap->va_nodeid += mp->m_inoadd;
+@@ -163,11 +160,8 @@ xfs_getattr(
+ */
+ if ((vap->va_mask &
+ ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|
+- XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0) {
+- if (!(flags & ATTR_LAZY))
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+- return 0;
+- }
++ XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0)
++ goto all_done;
+
+ /*
+ * Copy from in-core inode.
+@@ -194,7 +188,7 @@ xfs_getattr(
+ * stripe size through is not a good
+ * idea for now.
+ */
+- vap->va_blksize = mp->m_swidth ?
++ vap->va_blocksize = mp->m_swidth ?
+ /*
+ * If the underlying volume is a stripe, then
+ * return the stripe width in bytes as the
+@@ -211,7 +205,7 @@ xfs_getattr(
+ mp->m_writeio_log));
+
+ #else
+- vap->va_blksize =
++ vap->va_blocksize =
+ /*
+ * Return the largest of the preferred buffer
+ * sizes since doing small I/Os into larger
+@@ -229,13 +223,13 @@ xfs_getattr(
+ * realtime extent size or the realtime volume's
+ * extent size.
+ */
+- vap->va_blksize = ip->i_d.di_extsize ?
++ vap->va_blocksize = ip->i_d.di_extsize ?
+ (ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
+ (mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
+ }
+ } else {
+ vap->va_rdev = ip->i_df.if_u2.if_rdev;
+- vap->va_blksize = BLKDEV_IOSIZE;
++ vap->va_blocksize = BLKDEV_IOSIZE;
+ }
+
+ vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec;
+@@ -251,46 +245,53 @@ xfs_getattr(
+ */
+ if ((vap->va_mask &
+ (XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
+- XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0) {
+- if (!(flags & ATTR_LAZY))
+- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+- return 0;
+- }
++ XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
++ goto all_done;
++
+ /*
+ * convert di_flags to xflags
+ */
+- vap->va_xflags =
+- ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
+- XFS_XFLAG_REALTIME : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) ?
+- XFS_XFLAG_PREALLOC : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) ?
+- XFS_XFLAG_IMMUTABLE : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_APPEND) ?
+- XFS_XFLAG_APPEND : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_SYNC) ?
+- XFS_XFLAG_SYNC : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_NOATIME) ?
+- XFS_XFLAG_NOATIME : 0) |
+- ((ip->i_d.di_flags & XFS_DIFLAG_NODUMP) ?
+- XFS_XFLAG_NODUMP: 0) |
+- (XFS_IFORK_Q(ip) ?
+- XFS_XFLAG_HASATTR : 0);
++ vap->va_xflags = 0;
++ if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
++ vap->va_xflags |= XFS_XFLAG_REALTIME;
++ if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC)
++ vap->va_xflags |= XFS_XFLAG_PREALLOC;
++ if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
++ vap->va_xflags |= XFS_XFLAG_IMMUTABLE;
++ if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
++ vap->va_xflags |= XFS_XFLAG_APPEND;
++ if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
++ vap->va_xflags |= XFS_XFLAG_SYNC;
++ if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
++ vap->va_xflags |= XFS_XFLAG_NOATIME;
++ if (ip->i_d.di_flags & XFS_DIFLAG_NODUMP)
++ vap->va_xflags |= XFS_XFLAG_NODUMP;
++ if (XFS_IFORK_Q(ip))
++ vap->va_xflags |= XFS_XFLAG_HASATTR;
++ /*
++ * Exit for inode revalidate. See if any of the rest of
++ * the fields to be filled in are needed.
++ */
++ if ((vap->va_mask &
++ (XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
++ XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
++ goto all_done;
++
+ vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
+ vap->va_nextents =
+ (ip->i_df.if_flags & XFS_IFEXTENTS) ?
+ ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) :
+ ip->i_d.di_nextents;
+- if (ip->i_afp != NULL)
++ if (ip->i_afp)
+ vap->va_anextents =
+ (ip->i_afp->if_flags & XFS_IFEXTENTS) ?
+ ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) :
+ ip->i_d.di_anextents;
+ else
+ vap->va_anextents = 0;
+- vap->va_gencount = ip->i_d.di_gen;
+- vap->va_vcode = 0L;
++ vap->va_gen = ip->i_d.di_gen;
+
++ all_done:
+ if (!(flags & ATTR_LAZY))
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ return 0;
+@@ -415,7 +416,7 @@ xfs_setattr(
+ } else {
+ if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) &&
+ !(flags & ATTR_DMI)) {
+- code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, bdp,
++ code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
+ vap->va_size, 0, AT_DELAY_FLAG(flags), NULL);
+ if (code) {
+ lock_flags = 0;
+@@ -1042,7 +1043,7 @@ xfs_readlink(
+ pathlen = (int)ip->i_d.di_size;
+
+ if (ip->i_df.if_flags & XFS_IFINLINE) {
+- error = uiomove(ip->i_df.if_u1.if_data, pathlen, UIO_READ, uiop);
++ error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
+ }
+ else {
+ /*
+@@ -1073,8 +1074,7 @@ xfs_readlink(
+ byte_cnt = pathlen;
+ pathlen -= byte_cnt;
+
+- error = uiomove(XFS_BUF_PTR(bp), byte_cnt,
+- UIO_READ, uiop);
++ error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
+ xfs_buf_relse (bp);
+ }
+
+@@ -1729,7 +1729,7 @@ xfs_inactive(
+
+ if (ip->i_d.di_nlink == 0 &&
+ DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_DESTROY)) {
+- (void) XFS_SEND_DESTROY(mp, bdp, DM_RIGHT_NULL);
++ (void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL);
+ }
+
+ error = 0;
+@@ -4163,7 +4163,7 @@ xfs_alloc_file_space(
+ end_dmi_offset = offset+len;
+ if (end_dmi_offset > ip->i_d.di_size)
+ end_dmi_offset = ip->i_d.di_size;
+- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOBHV(ip),
++ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+ offset, end_dmi_offset - offset,
+ 0, NULL);
+ if (error)
+@@ -4410,7 +4410,7 @@ xfs_free_file_space(
+ DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
+ if (end_dmi_offset > ip->i_d.di_size)
+ end_dmi_offset = ip->i_d.di_size;
+- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOBHV(ip),
++ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+ offset, end_dmi_offset - offset,
+ AT_DELAY_FLAG(attr_flags), NULL);
+ if (error)
+--- linux-2.6.0-test6/include/acpi/acconfig.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/acpi/acconfig.h 2003-10-05 00:33:24.000000000 -0700
+@@ -64,7 +64,7 @@
+
+ /* Version string */
+
+-#define ACPI_CA_VERSION 0x20030813
++#define ACPI_CA_VERSION 0x20030918
+
+ /* Maximum objects in the various object caches */
+
+--- linux-2.6.0-test6/include/acpi/acdisasm.h 2003-06-14 12:18:22.000000000 -0700
++++ 25/include/acpi/acdisasm.h 2003-10-05 00:33:24.000000000 -0700
+@@ -152,10 +152,6 @@ void
+ acpi_dm_decode_internal_object (
+ union acpi_operand_object *obj_desc);
+
+-void
+-acpi_dm_decode_node (
+- struct acpi_namespace_node *node);
+-
+ u32
+ acpi_dm_block_type (
+ union acpi_parse_object *op);
+--- linux-2.6.0-test6/include/acpi/acstruct.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/acpi/acstruct.h 2003-10-05 00:33:24.000000000 -0700
+@@ -91,11 +91,12 @@ struct acpi_walk_state
+ struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
+ union acpi_operand_object **caller_return_desc;
+ union acpi_generic_state *control_state; /* List of control states (nested IFs) */
++ struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
+ struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
+ struct acpi_namespace_node *method_call_node; /* Called method Node*/
+ union acpi_parse_object *method_call_op; /* method_call Op if running a method */
+ union acpi_operand_object *method_desc; /* Method descriptor if running a method */
+- struct acpi_namespace_node *method_node; /* Method Node if running a method */
++ struct acpi_namespace_node *method_node; /* Method node if running a method. */
+ union acpi_parse_object *op; /* Current parser op */
+ union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS+1]; /* Operands passed to the interpreter (+1 for NULL terminator) */
+ const struct acpi_opcode_info *op_info; /* Info on current opcode */
+--- linux-2.6.0-test6/include/asm-alpha/cacheflush.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/include/asm-alpha/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -10,6 +10,8 @@
+ #define flush_cache_range(vma, start, end) do { } while (0)
+ #define flush_cache_page(vma, vmaddr) do { } while (0)
+ #define flush_dcache_page(page) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
+
+ /* Note that the following two definitions are _highly_ dependent
+ on the contexts in which they are used in the kernel. I personally
+@@ -60,4 +62,11 @@ extern void flush_icache_user_range(stru
+ #define flush_icache_page(vma, page) \
+ flush_icache_user_range((vma), (page), 0, 0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ #endif /* _ALPHA_CACHEFLUSH_H */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-alpha/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,90 @@
++/*
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.h by Jack Steiner (steiner@sgi.com)
++ *
++ * Modified by Peter Rival (frival@zk3.dec.com)
++ */
++
++#ifndef _ALPHA_LOCKMETER_H
++#define _ALPHA_LOCKMETER_H
++
++#include <asm/hwrpb.h>
++#define CPU_CYCLE_FREQUENCY hwrpb->cycle_freq
++
++#define get_cycles64() get_cycles()
++
++#define THIS_CPU_NUMBER smp_processor_id()
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
++#define local_irq_save(x) \
++ __save_and_cli(x)
++#define local_irq_restore(x) \
++ __restore_flags(x)
++#endif /* Linux version 2.2.x */
++
++#define SPINLOCK_MAGIC_INIT /**/
++
++/*
++ * Macros to cache and retrieve an index value inside of a lock
++ * these macros assume that there are less than 65536 simultaneous
++ * (read mode) holders of a rwlock.
++ * We also assume that the hash table has less than 32767 entries.
++ * the high order bit is used for write locking a rw_lock
++ * Note: although these defines and macros are the same as what is being used
++ * in include/asm-i386/lockmeter.h, they are present here to easily
++ * allow an alternate Alpha implementation.
++ */
++/*
++ * instrumented spinlock structure -- never used to allocate storage
++ * only used in macros below to overlay a spinlock_t
++ */
++typedef struct inst_spinlock_s {
++ /* remember, Alpha is little endian */
++ unsigned short lock;
++ unsigned short index;
++} inst_spinlock_t;
++#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv
++#define GET_INDEX(lock_ptr) ((inst_spinlock_t *)(lock_ptr))->index
++
++/*
++ * macros to cache and retrieve an index value in a read/write lock
++ * as well as the cpu where a reader busy period started
++ * we use the 2nd word (the debug word) for this, so require the
++ * debug word to be present
++ */
++/*
++ * instrumented rwlock structure -- never used to allocate storage
++ * only used in macros below to overlay a rwlock_t
++ */
++typedef struct inst_rwlock_s {
++ volatile int lock;
++ unsigned short index;
++ unsigned short cpu;
++} inst_rwlock_t;
++#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
++#define GET_RWINDEX(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->index
++#define PUT_RW_CPU(rwlock_ptr,cpuv) ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
++#define GET_RW_CPU(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->cpu
++
++/*
++ * return true if rwlock is write locked
++ * (note that other lock attempts can cause the lock value to be negative)
++ */
++#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) (((inst_rwlock_t *)rwlock_ptr)->lock & 1)
++#define IABS(x) ((x) > 0 ? (x) : -(x))
++
++#define RWLOCK_READERS(rwlock_ptr) rwlock_readers(rwlock_ptr)
++extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
++{
++ int tmp = (int) ((inst_rwlock_t *)rwlock_ptr)->lock;
++ /* readers subtract 2, so we have to: */
++ /* - andnot off a possible writer (bit 0) */
++ /* - get the absolute value */
++ /* - divide by 2 (right shift by one) */
++ /* to find the number of readers */
++ if (tmp == 0) return(0);
++ else return(IABS(tmp & ~1)>>1);
++}
++
++#endif /* _ALPHA_LOCKMETER_H */
+--- linux-2.6.0-test6/include/asm-alpha/numnodes.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/include/asm-alpha/numnodes.h 2003-10-05 00:34:38.000000000 -0700
+@@ -1,6 +1,7 @@
+ #ifndef _ASM_MAX_NUMNODES_H
+ #define _ASM_MAX_NUMNODES_H
+
+-#define MAX_NUMNODES 128 /* Marvel */
++/* Max 128 Nodes - Marvel */
++#define NODES_SHIFT 7
+
+ #endif /* _ASM_MAX_NUMNODES_H */
+--- linux-2.6.0-test6/include/asm-alpha/pgtable.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/include/asm-alpha/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -49,7 +49,6 @@
+ #else
+ #define VMALLOC_START (-2*PGDIR_SIZE)
+ #endif
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (-PGDIR_SIZE)
+
+ /*
+--- linux-2.6.0-test6/include/asm-alpha/spinlock.h 2003-06-26 22:07:25.000000000 -0700
++++ 25/include/asm-alpha/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -6,6 +6,10 @@
+ #include <linux/kernel.h>
+ #include <asm/current.h>
+
++#ifdef CONFIG_LOCKMETER
++#undef DEBUG_SPINLOCK
++#undef DEBUG_RWLOCK
++#endif
+
+ /*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+@@ -95,9 +99,18 @@ static inline int _raw_spin_trylock(spin
+
+ typedef struct {
+ volatile int write_lock:1, read_counter:31;
++#ifdef CONFIG_LOCKMETER
++ /* required for LOCKMETER since all bits in lock are used */
++ /* need this storage for CPU and lock INDEX ............. */
++ unsigned magic;
++#endif
+ } /*__attribute__((aligned(32)))*/ rwlock_t;
+
++#ifdef CONFIG_LOCKMETER
++#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0 }
++#else
+ #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
++#endif
+
+ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+ #define rwlock_is_locked(x) (*(volatile int *)(x) != 0)
+@@ -169,4 +182,41 @@ static inline void _raw_read_unlock(rwlo
+ : "m" (*lock) : "memory");
+ }
+
++#ifdef CONFIG_LOCKMETER
++static inline int _raw_write_trylock(rwlock_t *lock)
++{
++ long temp,result;
++
++ __asm__ __volatile__(
++ " ldl_l %1,%0\n"
++ " mov $31,%2\n"
++ " bne %1,1f\n"
++ " or $31,1,%2\n"
++ " stl_c %2,%0\n"
++ "1: mb\n"
++ : "=m" (*(volatile int *)lock), "=&r" (temp), "=&r" (result)
++ : "m" (*(volatile int *)lock)
++ );
++
++ return (result);
++}
++
++static inline int _raw_read_trylock(rwlock_t *lock)
++{
++ unsigned long temp,result;
++
++ __asm__ __volatile__(
++ " ldl_l %1,%0\n"
++ " mov $31,%2\n"
++ " blbs %1,1f\n"
++ " subl %1,2,%2\n"
++ " stl_c %2,%0\n"
++ "1: mb\n"
++ : "=m" (*(volatile int *)lock), "=&r" (temp), "=&r" (result)
++ : "m" (*(volatile int *)lock)
++ );
++ return (result);
++}
++#endif /* CONFIG_LOCKMETER */
++
+ #endif /* _ALPHA_SPINLOCK_H */
+--- linux-2.6.0-test6/include/asm-arm26/cacheflush.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-arm26/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -25,6 +25,8 @@
+ #define flush_cache_range(vma,start,end) do { } while (0)
+ #define flush_cache_page(vma,vmaddr) do { } while (0)
+ #define flush_page_to_ram(page) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
+
+ #define invalidate_dcache_range(start,end) do { } while (0)
+ #define clean_dcache_range(start,end) do { } while (0)
+@@ -37,6 +39,11 @@
+ #define flush_icache_range(start,end) do { } while (0)
+ #define flush_icache_page(vma,page) do { } while (0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ /* DAG: ARM3 will flush cache on MEMC updates anyway? so don't bother */
+ /* IM : Yes, it will, but only if setup to do so (we do this). */
+ #define clean_cache_area(_start,_size) do { } while (0)
+--- linux-2.6.0-test6/include/asm-arm26/pgtable.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/asm-arm26/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -173,7 +173,6 @@ extern struct page *empty_zero_page;
+ * area for the same reason. ;) FIXME: surely 1 page not 4k ?
+ */
+ #define VMALLOC_START 0x01a00000
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END 0x01c00000
+
+ /* Is pmd_page supposed to return a pointer to a page in some arches? ours seems to
+--- linux-2.6.0-test6/include/asm-arm/arch-adifcc/vmalloc.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/include/asm-arm/arch-adifcc/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (0xe8000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-anakin/vmalloc.h 2003-06-14 12:18:04.000000000 -0700
++++ 25/include/asm-arm/arch-anakin/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -19,8 +19,7 @@
+ * linux/arch/arm/kernel/traps.c)
+ */
+ #define VMALLOC_ARCH_OFFSET (8 * 1024 * 1024)
+-#define VMALLOC_VMADDR(a) ((unsigned int) (a))
+-#define VMALLOC_START ((VMALLOC_VMADDR(high_memory) + VMALLOC_ARCH_OFFSET) & ~(VMALLOC_ARCH_OFFSET - 1))
++#define VMALLOC_START (((unsigned long) (high_memory) + VMALLOC_ARCH_OFFSET) & ~(VMALLOC_ARCH_OFFSET - 1))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-cl7500/vmalloc.h 2003-06-14 12:18:32.000000000 -0700
++++ 25/include/asm-arm/arch-cl7500/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x1c000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-clps711x/memory.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/include/asm-arm/arch-clps711x/memory.h 2003-10-05 00:34:40.000000000 -0700
+@@ -109,8 +109,6 @@
+ * node 3: 0xd8000000 - 0xdfffffff
+ */
+
+-#define NR_NODES 4
+-
+ /*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+--- linux-2.6.0-test6/include/asm-arm/arch-clps711x/vmalloc.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/include/asm-arm/arch-clps711x/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-ebsa110/vmalloc.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/asm-arm/arch-ebsa110/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -18,7 +18,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x1f000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-ebsa285/vmalloc.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/include/asm-arm/arch-ebsa285/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -18,7 +18,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+ #ifdef CONFIG_ARCH_FOOTBRIDGE
+ #define VMALLOC_END (PAGE_OFFSET + 0x30000000)
+--- linux-2.6.0-test6/include/asm-arm/arch-epxa10db/vmalloc.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/include/asm-arm/arch-epxa10db/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-integrator/irqs.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-arm/arch-integrator/irqs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -19,116 +19,39 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-/* Use the integrator definitions */
+-#include <asm/arch/platform.h>
+-
+-/*
+- * IRQ interrupts definitions are the same the INT definitions
+- * held within platform.h
+- */
+-#define IRQ_SOFTINT INT_SOFTINT
+-#define IRQ_UARTINT0 INT_UARTINT0
+-#define IRQ_UARTINT1 INT_UARTINT1
+-#define IRQ_KMIINT0 INT_KMIINT0
+-#define IRQ_KMIINT1 INT_KMIINT1
+-#define IRQ_TIMERINT0 INT_TIMERINT0
+-#define IRQ_TIMERINT1 INT_TIMERINT1
+-#define IRQ_TIMERINT2 INT_TIMERINT2
+-#define IRQ_RTCINT INT_RTCINT
+-#define IRQ_EXPINT0 INT_EXPINT0
+-#define IRQ_EXPINT1 INT_EXPINT1
+-#define IRQ_EXPINT2 INT_EXPINT2
+-#define IRQ_EXPINT3 INT_EXPINT3
+-#define IRQ_PCIINT0 INT_PCIINT0
+-#define IRQ_PCIINT1 INT_PCIINT1
+-#define IRQ_PCIINT2 INT_PCIINT2
+-#define IRQ_PCIINT3 INT_PCIINT3
+-#define IRQ_V3INT INT_V3INT
+-#define IRQ_CPINT0 INT_CPINT0
+-#define IRQ_CPINT1 INT_CPINT1
+-#define IRQ_LBUSTIMEOUT INT_LBUSTIMEOUT
+-#define IRQ_APCINT INT_APCINT
+-
+-#define IRQMASK_SOFTINT INTMASK_SOFTINT
+-#define IRQMASK_UARTINT0 INTMASK_UARTINT0
+-#define IRQMASK_UARTINT1 INTMASK_UARTINT1
+-#define IRQMASK_KMIINT0 INTMASK_KMIINT0
+-#define IRQMASK_KMIINT1 INTMASK_KMIINT1
+-#define IRQMASK_TIMERINT0 INTMASK_TIMERINT0
+-#define IRQMASK_TIMERINT1 INTMASK_TIMERINT1
+-#define IRQMASK_TIMERINT2 INTMASK_TIMERINT2
+-#define IRQMASK_RTCINT INTMASK_RTCINT
+-#define IRQMASK_EXPINT0 INTMASK_EXPINT0
+-#define IRQMASK_EXPINT1 INTMASK_EXPINT1
+-#define IRQMASK_EXPINT2 INTMASK_EXPINT2
+-#define IRQMASK_EXPINT3 INTMASK_EXPINT3
+-#define IRQMASK_PCIINT0 INTMASK_PCIINT0
+-#define IRQMASK_PCIINT1 INTMASK_PCIINT1
+-#define IRQMASK_PCIINT2 INTMASK_PCIINT2
+-#define IRQMASK_PCIINT3 INTMASK_PCIINT3
+-#define IRQMASK_V3INT INTMASK_V3INT
+-#define IRQMASK_CPINT0 INTMASK_CPINT0
+-#define IRQMASK_CPINT1 INTMASK_CPINT1
+-#define IRQMASK_LBUSTIMEOUT INTMASK_LBUSTIMEOUT
+-#define IRQMASK_APCINT INTMASK_APCINT
+-
+ /*
+- * FIQ interrupts definitions are the same the INT definitions.
++ * Interrupt numbers
+ */
+-#define FIQ_SOFTINT INT_SOFTINT
+-#define FIQ_UARTINT0 INT_UARTINT0
+-#define FIQ_UARTINT1 INT_UARTINT1
+-#define FIQ_KMIINT0 INT_KMIINT0
+-#define FIQ_KMIINT1 INT_KMIINT1
+-#define FIQ_TIMERINT0 INT_TIMERINT0
+-#define FIQ_TIMERINT1 INT_TIMERINT1
+-#define FIQ_TIMERINT2 INT_TIMERINT2
+-#define FIQ_RTCINT INT_RTCINT
+-#define FIQ_EXPINT0 INT_EXPINT0
+-#define FIQ_EXPINT1 INT_EXPINT1
+-#define FIQ_EXPINT2 INT_EXPINT2
+-#define FIQ_EXPINT3 INT_EXPINT3
+-#define FIQ_PCIINT0 INT_PCIINT0
+-#define FIQ_PCIINT1 INT_PCIINT1
+-#define FIQ_PCIINT2 INT_PCIINT2
+-#define FIQ_PCIINT3 INT_PCIINT3
+-#define FIQ_V3INT INT_V3INT
+-#define FIQ_CPINT0 INT_CPINT0
+-#define FIQ_CPINT1 INT_CPINT1
+-#define FIQ_LBUSTIMEOUT INT_LBUSTIMEOUT
+-#define FIQ_APCINT INT_APCINT
+-
+-#define FIQMASK_SOFTINT INTMASK_SOFTINT
+-#define FIQMASK_UARTINT0 INTMASK_UARTINT0
+-#define FIQMASK_UARTINT1 INTMASK_UARTINT1
+-#define FIQMASK_KMIINT0 INTMASK_KMIINT0
+-#define FIQMASK_KMIINT1 INTMASK_KMIINT1
+-#define FIQMASK_TIMERINT0 INTMASK_TIMERINT0
+-#define FIQMASK_TIMERINT1 INTMASK_TIMERINT1
+-#define FIQMASK_TIMERINT2 INTMASK_TIMERINT2
+-#define FIQMASK_RTCINT INTMASK_RTCINT
+-#define FIQMASK_EXPINT0 INTMASK_EXPINT0
+-#define FIQMASK_EXPINT1 INTMASK_EXPINT1
+-#define FIQMASK_EXPINT2 INTMASK_EXPINT2
+-#define FIQMASK_EXPINT3 INTMASK_EXPINT3
+-#define FIQMASK_PCIINT0 INTMASK_PCIINT0
+-#define FIQMASK_PCIINT1 INTMASK_PCIINT1
+-#define FIQMASK_PCIINT2 INTMASK_PCIINT2
+-#define FIQMASK_PCIINT3 INTMASK_PCIINT3
+-#define FIQMASK_V3INT INTMASK_V3INT
+-#define FIQMASK_CPINT0 INTMASK_CPINT0
+-#define FIQMASK_CPINT1 INTMASK_CPINT1
+-#define FIQMASK_LBUSTIMEOUT INTMASK_LBUSTIMEOUT
+-#define FIQMASK_APCINT INTMASK_APCINT
+-
+-/*
+- * Misc. interrupt definitions
+- */
+-#define IRQ_KEYBDINT INT_KMIINT0
+-#define IRQ_MOUSEINT INT_KMIINT1
+-
+-#define IRQMASK_KEYBDINT INTMASK_KMIINT0
+-#define IRQMASK_MOUSEINT INTMASK_KMIINT1
++#define IRQ_PIC_START 0
++#define IRQ_SOFTINT 0
++#define IRQ_UARTINT0 1
++#define IRQ_UARTINT1 2
++#define IRQ_KMIINT0 3
++#define IRQ_KMIINT1 4
++#define IRQ_TIMERINT0 5
++#define IRQ_TIMERINT1 6
++#define IRQ_TIMERINT2 7
++#define IRQ_RTCINT 8
++#define IRQ_AP_EXPINT0 9
++#define IRQ_AP_EXPINT1 10
++#define IRQ_AP_EXPINT2 11
++#define IRQ_AP_EXPINT3 12
++#define IRQ_AP_PCIINT0 13
++#define IRQ_AP_PCIINT1 14
++#define IRQ_AP_PCIINT2 15
++#define IRQ_AP_PCIINT3 16
++#define IRQ_AP_V3INT 17
++#define IRQ_AP_CPINT0 18
++#define IRQ_AP_CPINT1 19
++#define IRQ_AP_LBUSTIMEOUT 20
++#define IRQ_AP_APCINT 21
++#define IRQ_PIC_END 31
++
++#define IRQ_CIC_START 32
++#define IRQ_CM_SOFTINT 32
++#define IRQ_CM_COMMRX 33
++#define IRQ_CM_COMMTX 34
++#define IRQ_CIC_END 34
+
+-#define NR_IRQS (MAXIRQNUM + 1)
++#define NR_IRQS 47
+
+--- linux-2.6.0-test6/include/asm-arm/arch-integrator/platform.h 2003-06-14 12:18:22.000000000 -0700
++++ 25/include/asm-arm/arch-integrator/platform.h 2003-10-05 00:33:24.000000000 -0700
+@@ -386,85 +386,6 @@
+ *
+ */
+
+-/*
+- * As the interrupt bit definitions for FIQ/IRQ there is a common
+- * set of definitions prefixed INT/INTMASK. The FIQ/IRQ definitions
+- * have been left to maintain backwards compatible.
+- *
+- */
+-
+-/*
+- * Interrupt numbers
+- *
+- */
+-#define INT_SOFTINT 0
+-#define INT_UARTINT0 1
+-#define INT_UARTINT1 2
+-#define INT_KMIINT0 3
+-#define INT_KMIINT1 4
+-#define INT_TIMERINT0 5
+-#define INT_TIMERINT1 6
+-#define INT_TIMERINT2 7
+-#define INT_RTCINT 8
+-#define INT_EXPINT0 9
+-#define INT_EXPINT1 10
+-#define INT_EXPINT2 11
+-#define INT_EXPINT3 12
+-#define INT_PCIINT0 13
+-#define INT_PCIINT1 14
+-#define INT_PCIINT2 15
+-#define INT_PCIINT3 16
+-#define INT_V3INT 17
+-#define INT_CPINT0 18
+-#define INT_CPINT1 19
+-#define INT_LBUSTIMEOUT 20
+-#define INT_APCINT 21
+-#define INT_CM_SOFTINT 24
+-#define INT_CM_COMMRX 25
+-#define INT_CM_COMMTX 26
+-
+-/*
+- * Interrupt bit positions
+- *
+- */
+-#define INTMASK_SOFTINT (1 << INT_SOFTINT)
+-#define INTMASK_UARTINT0 (1 << INT_UARTINT0)
+-#define INTMASK_UARTINT1 (1 << INT_UARTINT1)
+-#define INTMASK_KMIINT0 (1 << INT_KMIINT0)
+-#define INTMASK_KMIINT1 (1 << INT_KMIINT1)
+-#define INTMASK_TIMERINT0 (1 << INT_TIMERINT0)
+-#define INTMASK_TIMERINT1 (1 << INT_TIMERINT1)
+-#define INTMASK_TIMERINT2 (1 << INT_TIMERINT2)
+-#define INTMASK_RTCINT (1 << INT_RTCINT)
+-#define INTMASK_EXPINT0 (1 << INT_EXPINT0)
+-#define INTMASK_EXPINT1 (1 << INT_EXPINT1)
+-#define INTMASK_EXPINT2 (1 << INT_EXPINT2)
+-#define INTMASK_EXPINT3 (1 << INT_EXPINT3)
+-#define INTMASK_PCIINT0 (1 << INT_PCIINT0)
+-#define INTMASK_PCIINT1 (1 << INT_PCIINT1)
+-#define INTMASK_PCIINT2 (1 << INT_PCIINT2)
+-#define INTMASK_PCIINT3 (1 << INT_PCIINT3)
+-#define INTMASK_V3INT (1 << INT_V3INT)
+-#define INTMASK_CPINT0 (1 << INT_CPINT0)
+-#define INTMASK_CPINT1 (1 << INT_CPINT1)
+-#define INTMASK_LBUSTIMEOUT (1 << INT_LBUSTIMEOUT)
+-#define INTMASK_APCINT (1 << INT_APCINT)
+-#define INTMASK_CM_SOFTINT (1 << INT_CM_SOFTINT)
+-#define INTMASK_CM_COMMRX (1 << INT_CM_COMMRX)
+-#define INTMASK_CM_COMMTX (1 << INT_CM_COMMTX)
+-
+-/*
+- * INTEGRATOR_CM_INT0 - Interrupt number of first CM interrupt
+- * INTEGRATOR_SC_VALID_INT - Mask of valid system controller interrupts
+- *
+- */
+-#define INTEGRATOR_CM_INT0 INT_CM_SOFTINT
+-#define INTEGRATOR_SC_VALID_INT 0x003FFFFF
+-
+-#define MAXIRQNUM 31
+-#define MAXFIQNUM 31
+-#define MAXSWINUM 31
+-
+ /* ------------------------------------------------------------------------
+ * LED's - The header LED is not accessible via the uHAL API
+ * ------------------------------------------------------------------------
+--- linux-2.6.0-test6/include/asm-arm/arch-integrator/time.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-arm/arch-integrator/time.h 2003-10-05 00:33:24.000000000 -0700
+@@ -86,7 +86,7 @@ static unsigned long integrator_gettimeo
+ /*
+ * Interrupt pending? If so, we've reloaded once already.
+ */
+- if (status & IRQMASK_TIMERINT1)
++ if (status & (1 << IRQ_TIMERINT1))
+ ticks1 += TIMER_RELOAD;
+
+ /*
+--- linux-2.6.0-test6/include/asm-arm/arch-integrator/vmalloc.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-arm/arch-integrator/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -28,7 +28,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-iop3xx/vmalloc.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/include/asm-arm/arch-iop3xx/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (0xe8000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-l7200/vmalloc.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/include/asm-arm/arch-l7200/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-nexuspci/vmalloc.h 2003-06-14 12:18:21.000000000 -0700
++++ 25/include/asm-arm/arch-nexuspci/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x20000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-pxa/irqs.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/include/asm-arm/arch-pxa/irqs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,7 +13,7 @@
+ #include <linux/config.h>
+
+ #define PXA_IRQ_SKIP 7 /* The first 7 IRQs are not yet used */
+-#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
++#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
+
+ #define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error */
+ #define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
+@@ -47,7 +47,7 @@
+
+ #define IRQ_TO_GPIO_2_80(i) \
+ ((i) - PXA_IRQ(32) + 2)
+-#define IRQ_TO_GPIO(i) ((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) : IRQ_GPIO(0)))
++#define IRQ_TO_GPIO(i) ((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
+
+ /*
+ * The next 16 interrupts are for board specific purposes. Since
+@@ -131,8 +131,10 @@
+ #define LUBBOCK_IRQ(x) (IRQ_BOARD_START + (x))
+ #define LUBBOCK_SD_IRQ LUBBOCK_IRQ(0)
+ #define LUBBOCK_SA1111_IRQ LUBBOCK_IRQ(1)
+-#define LUBBOCK_USB_IRQ LUBBOCK_IRQ(2)
++#define LUBBOCK_USB_IRQ LUBBOCK_IRQ(2) /* usb connect */
+ #define LUBBOCK_ETH_IRQ LUBBOCK_IRQ(3)
+ #define LUBBOCK_UCB1400_IRQ LUBBOCK_IRQ(4)
+ #define LUBBOCK_BB_IRQ LUBBOCK_IRQ(5)
++#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
++#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
+
+--- linux-2.6.0-test6/include/asm-arm/arch-pxa/lubbock.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/include/asm-arm/arch-pxa/lubbock.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,8 @@
+
+ #define LUBBOCK_FPGA_PHYS PXA_CS2_PHYS
+ #define LUBBOCK_FPGA_VIRT (0xf0000000) /* phys 0x08000000 */
+-#define LUBBOCK_ETH_BASE (0xf1000000) /* phys 0x0c000000 */
++#define LUBBOCK_ETH_PHYS PXA_CS3_PHYS
++#define LUBBOCK_ETH_VIRT (0xf1000000)
+
+ #define LUB_P2V(x) ((x) - LUBBOCK_FPGA_PHYS + LUBBOCK_FPGA_VIRT)
+ #define LUB_V2P(x) ((x) - LUBBOCK_FPGA_VIRT + LUBBOCK_FPGA_PHYS)
+--- linux-2.6.0-test6/include/asm-arm/arch-pxa/vmalloc.h 2003-06-14 12:18:21.000000000 -0700
++++ 25/include/asm-arm/arch-pxa/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -19,7 +19,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (0xe8000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-rpc/vmalloc.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/include/asm-arm/arch-rpc/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -18,7 +18,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x1c000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-sa1100/memory.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/include/asm-arm/arch-sa1100/memory.h 2003-10-05 00:34:40.000000000 -0700
+@@ -74,8 +74,6 @@
+ * node 3: 0xd8000000 - 0xdfffffff
+ */
+
+-#define NR_NODES 4
+-
+ /*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+--- linux-2.6.0-test6/include/asm-arm/arch-sa1100/vmalloc.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-arm/arch-sa1100/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (0xe8000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-shark/vmalloc.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/include/asm-arm/arch-shark/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/arch-tbox/vmalloc.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/include/asm-arm/arch-tbox/vmalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -12,7 +12,6 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+ #define MODULE_START (PAGE_OFFSET - 16*1048576)
+--- linux-2.6.0-test6/include/asm-arm/cacheflush.h 2003-09-27 18:57:46.000000000 -0700
++++ 25/include/asm-arm/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -207,6 +207,15 @@ extern void dmac_inv_range(unsigned long
+ extern void dmac_clean_range(unsigned long, unsigned long);
+ extern void dmac_flush_range(unsigned long, unsigned long);
+
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ #endif
+
+ /*
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-arm/mach/flash.h 2003-10-05 00:33:24.000000000 -0700
+@@ -0,0 +1,19 @@
++/*
++ * linux/include/asm-arm/mach/flash.h
++ *
++ * Copyright (C) 2003 Russell King, All Rights Reserved.
++ */
++#ifndef ASMARM_MACH_FLASH_H
++#define ASMAMR_MACH_FLASH_H
++
++struct mtd_partition;
++
++struct flash_platform_data {
++ const char *map_name;
++ int width;
++ int (*init)(void);
++ void (*exit)(void);
++ void (*set_vpp)(int on);
++};
++
++#endif
+--- linux-2.6.0-test6/include/asm-arm/memory.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/asm-arm/memory.h 2003-10-05 00:34:41.000000000 -0700
+@@ -84,24 +84,24 @@ static inline void *phys_to_virt(unsigne
+
+ #define PHYS_TO_NID(addr) (0)
+
+-#else
++#else /* CONFIG_DISCONTIGMEM */
++
+ /*
+ * This is more complex. We have a set of mem_map arrays spread
+ * around in memory.
+ */
++#include <linux/numa.h>
++
+ #define page_to_pfn(page) \
+ (( (page) - page_zone(page)->zone_mem_map) \
+ + page_zone(page)->zone_start_pfn)
+-
+ #define pfn_to_page(pfn) \
+ (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
+-
+-#define pfn_valid(pfn) (PFN_TO_NID(pfn) < NR_NODES)
++#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES)
+
+ #define virt_to_page(kaddr) \
+ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+-
+-#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < NR_NODES)
++#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
+
+ /*
+ * Common discontigmem stuff.
+@@ -109,7 +109,7 @@ static inline void *phys_to_virt(unsigne
+ */
+ #define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT)
+
+-#endif
++#endif /* !CONFIG_DISCONTIGMEM */
+
+ /*
+ * For BIO. "will die". Kill me when bio_to_phys() and bvec_to_phys() die.
+--- linux-2.6.0-test6/include/asm-arm/numnodes.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/asm-arm/numnodes.h 2003-10-05 00:34:40.000000000 -0700
+@@ -10,8 +10,7 @@
+ #ifndef __ASM_ARM_NUMNODES_H
+ #define __ASM_ARM_NUMNODES_H
+
+-#include <asm/memory.h>
+-
+-#define MAX_NUMNODES NR_NODES
++/* Max 4 Nodes */
++#define NODES_SHIFT 2
+
+ #endif
+--- linux-2.6.0-test6/include/asm-arm/unistd.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/asm-arm/unistd.h 2003-10-05 00:33:24.000000000 -0700
+@@ -32,7 +32,7 @@
+ #define __NR_write (__NR_SYSCALL_BASE+ 4)
+ #define __NR_open (__NR_SYSCALL_BASE+ 5)
+ #define __NR_close (__NR_SYSCALL_BASE+ 6)
+-#define __NR_waitpid (__NR_SYSCALL_BASE+ 7) /* removed */
++ /* 7 was sys_waitpid */
+ #define __NR_creat (__NR_SYSCALL_BASE+ 8)
+ #define __NR_link (__NR_SYSCALL_BASE+ 9)
+ #define __NR_unlink (__NR_SYSCALL_BASE+ 10)
+@@ -42,7 +42,7 @@
+ #define __NR_mknod (__NR_SYSCALL_BASE+ 14)
+ #define __NR_chmod (__NR_SYSCALL_BASE+ 15)
+ #define __NR_lchown (__NR_SYSCALL_BASE+ 16)
+-#define __NR_break (__NR_SYSCALL_BASE+ 17) /* removed */
++ /* 17 was sys_break */
+ /* 18 was sys_stat */
+ #define __NR_lseek (__NR_SYSCALL_BASE+ 19)
+ #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
+@@ -53,14 +53,14 @@
+ #define __NR_stime (__NR_SYSCALL_BASE+ 25)
+ #define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
+ #define __NR_alarm (__NR_SYSCALL_BASE+ 27)
+-
++ /* 28 was sys_fstat */
+ #define __NR_pause (__NR_SYSCALL_BASE+ 29)
+ #define __NR_utime (__NR_SYSCALL_BASE+ 30)
+-#define __NR_stty (__NR_SYSCALL_BASE+ 31) /* removed */
+-#define __NR_gtty (__NR_SYSCALL_BASE+ 32) /* removed */
++ /* 31 was sys_stty */
++ /* 32 was sys_gtty */
+ #define __NR_access (__NR_SYSCALL_BASE+ 33)
+ #define __NR_nice (__NR_SYSCALL_BASE+ 34)
+-#define __NR_ftime (__NR_SYSCALL_BASE+ 35) /* removed */
++ /* 35 was sys_ftime */
+ #define __NR_sync (__NR_SYSCALL_BASE+ 36)
+ #define __NR_kill (__NR_SYSCALL_BASE+ 37)
+ #define __NR_rename (__NR_SYSCALL_BASE+ 38)
+@@ -69,21 +69,21 @@
+ #define __NR_dup (__NR_SYSCALL_BASE+ 41)
+ #define __NR_pipe (__NR_SYSCALL_BASE+ 42)
+ #define __NR_times (__NR_SYSCALL_BASE+ 43)
+-#define __NR_prof (__NR_SYSCALL_BASE+ 44) /* removed */
++ /* 44 was sys_prof */
+ #define __NR_brk (__NR_SYSCALL_BASE+ 45)
+ #define __NR_setgid (__NR_SYSCALL_BASE+ 46)
+ #define __NR_getgid (__NR_SYSCALL_BASE+ 47)
+-#define __NR_signal (__NR_SYSCALL_BASE+ 48) /* removed */
++ /* 48 was sys_signal */
+ #define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
+ #define __NR_getegid (__NR_SYSCALL_BASE+ 50)
+ #define __NR_acct (__NR_SYSCALL_BASE+ 51)
+ #define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
+-#define __NR_lock (__NR_SYSCALL_BASE+ 53) /* removed */
++ /* 53 was sys_lock */
+ #define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
+ #define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
+-#define __NR_mpx (__NR_SYSCALL_BASE+ 56) /* removed */
++ /* 56 was sys_mpx */
+ #define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
+-#define __NR_ulimit (__NR_SYSCALL_BASE+ 58) /* removed */
++ /* 58 was sys_ulimit */
+ /* 59 was sys_olduname */
+ #define __NR_umask (__NR_SYSCALL_BASE+ 60)
+ #define __NR_chroot (__NR_SYSCALL_BASE+ 61)
+@@ -93,8 +93,8 @@
+ #define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
+ #define __NR_setsid (__NR_SYSCALL_BASE+ 66)
+ #define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
+-#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68) /* removed */
+-#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69) /* removed */
++ /* 68 was sys_sgetmask */
++ /* 69 was sys_ssetmask */
+ #define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
+ #define __NR_setregid (__NR_SYSCALL_BASE+ 71)
+ #define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
+@@ -123,10 +123,10 @@
+ #define __NR_fchown (__NR_SYSCALL_BASE+ 95)
+ #define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
+ #define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
+-#define __NR_profil (__NR_SYSCALL_BASE+ 98) /* removed */
++ /* 98 was sys_profil */
+ #define __NR_statfs (__NR_SYSCALL_BASE+ 99)
+ #define __NR_fstatfs (__NR_SYSCALL_BASE+100)
+-#define __NR_ioperm (__NR_SYSCALL_BASE+101)
++ /* 101 was sys_ioperm */
+ #define __NR_socketcall (__NR_SYSCALL_BASE+102)
+ #define __NR_syslog (__NR_SYSCALL_BASE+103)
+ #define __NR_setitimer (__NR_SYSCALL_BASE+104)
+@@ -137,7 +137,7 @@
+ /* 109 was sys_uname */
+ /* 110 was sys_iopl */
+ #define __NR_vhangup (__NR_SYSCALL_BASE+111)
+-#define __NR_idle (__NR_SYSCALL_BASE+112)
++ /* 112 was sys_idle */
+ #define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
+ #define __NR_wait4 (__NR_SYSCALL_BASE+114)
+ #define __NR_swapoff (__NR_SYSCALL_BASE+115)
+@@ -148,21 +148,21 @@
+ #define __NR_clone (__NR_SYSCALL_BASE+120)
+ #define __NR_setdomainname (__NR_SYSCALL_BASE+121)
+ #define __NR_uname (__NR_SYSCALL_BASE+122)
+-#define __NR_modify_ldt (__NR_SYSCALL_BASE+123)
++ /* 123 was sys_modify_ldt */
+ #define __NR_adjtimex (__NR_SYSCALL_BASE+124)
+ #define __NR_mprotect (__NR_SYSCALL_BASE+125)
+ #define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
+-#define __NR_create_module (__NR_SYSCALL_BASE+127) /* removed */
++ /* 127 was sys_create_module */
+ #define __NR_init_module (__NR_SYSCALL_BASE+128)
+ #define __NR_delete_module (__NR_SYSCALL_BASE+129)
+-#define __NR_get_kernel_syms (__NR_SYSCALL_BASE+130) /* removed */
++ /* 130 was sys_get_kernel_syms */
+ #define __NR_quotactl (__NR_SYSCALL_BASE+131)
+ #define __NR_getpgid (__NR_SYSCALL_BASE+132)
+ #define __NR_fchdir (__NR_SYSCALL_BASE+133)
+ #define __NR_bdflush (__NR_SYSCALL_BASE+134)
+ #define __NR_sysfs (__NR_SYSCALL_BASE+135)
+ #define __NR_personality (__NR_SYSCALL_BASE+136)
+-#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */
++ /* 137 was sys_afs_syscall */
+ #define __NR_setfsuid (__NR_SYSCALL_BASE+138)
+ #define __NR_setfsgid (__NR_SYSCALL_BASE+139)
+ #define __NR__llseek (__NR_SYSCALL_BASE+140)
+@@ -191,8 +191,8 @@
+ #define __NR_mremap (__NR_SYSCALL_BASE+163)
+ #define __NR_setresuid (__NR_SYSCALL_BASE+164)
+ #define __NR_getresuid (__NR_SYSCALL_BASE+165)
+-#define __NR_vm86 (__NR_SYSCALL_BASE+166) /* removed */
+-#define __NR_query_module (__NR_SYSCALL_BASE+167) /* removed */
++ /* 166 was sys_vm86 */
++ /* 167 was sys_query_module */
+ #define __NR_poll (__NR_SYSCALL_BASE+168)
+ #define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
+ #define __NR_setresgid (__NR_SYSCALL_BASE+170)
+--- linux-2.6.0-test6/include/asm-cris/arch-v10/pgtable.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/asm-cris/arch-v10/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,11 +7,9 @@
+
+ #ifdef CONFIG_CRIS_LOW_MAP
+ #define VMALLOC_START KSEG_7
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END KSEG_8
+ #else
+ #define VMALLOC_START KSEG_D
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END KSEG_E
+ #endif
+
+--- linux-2.6.0-test6/include/asm-cris/cacheflush.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/asm-cris/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -16,6 +16,13 @@
+ #define flush_icache_range(start, end) do { } while (0)
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ void global_flush_tlb(void);
+ int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+--- linux-2.6.0-test6/include/asm-h8300/cacheflush.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/asm-h8300/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -11,7 +11,6 @@
+ */
+
+ #define flush_cache_all()
+-#define flush_cache_all()
+ #define flush_cache_mm(mm)
+ #define flush_cache_range(vma,a,b)
+ #define flush_cache_page(vma,p)
+@@ -20,6 +19,8 @@
+ #define flush_icache()
+ #define flush_icache_page(vma,page)
+ #define flush_icache_range(start,len)
++#define flush_cache_vmap(start, end)
++#define flush_cache_vunmap(start, end)
+ #define cache_push_v(vaddr,len)
+ #define cache_push(paddr,len)
+ #define cache_clear(paddr,len)
+@@ -28,4 +29,9 @@
+
+ #define flush_icache_user_range(vma,page,addr,len)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ #endif /* _ASM_H8300_CACHEFLUSH_H */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-i386/atomic_kmap.h 2003-10-05 00:36:48.000000000 -0700
+@@ -0,0 +1,95 @@
++/*
++ * atomic_kmap.h: temporary virtual kernel memory mappings
++ *
++ * Copyright (C) 2003 Ingo Molnar <mingo@redhat.com>
++ */
++
++#ifndef _ASM_ATOMIC_KMAP_H
++#define _ASM_ATOMIC_KMAP_H
++
++#ifdef __KERNEL__
++
++#include <linux/config.h>
++#include <asm/tlbflush.h>
++
++#ifdef CONFIG_DEBUG_HIGHMEM
++#define HIGHMEM_DEBUG 1
++#else
++#define HIGHMEM_DEBUG 0
++#endif
++
++extern pte_t *kmap_pte;
++#define kmap_prot PAGE_KERNEL
++
++#define PKMAP_BASE (0xff000000UL)
++#define NR_SHARED_PMDS ((0xffffffff-PKMAP_BASE+1)/PMD_SIZE)
++
++static inline unsigned long __kmap_atomic_vaddr(enum km_type type)
++{
++ enum fixed_addresses idx;
++
++ idx = type + KM_TYPE_NR*smp_processor_id();
++ return __fix_to_virt(FIX_KMAP_BEGIN + idx);
++}
++
++static inline void *__kmap_atomic_noflush(struct page *page, enum km_type type)
++{
++ enum fixed_addresses idx;
++ unsigned long vaddr;
++
++ idx = type + KM_TYPE_NR*smp_processor_id();
++ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++ /*
++ * NOTE: entries that rely on some secondary TLB-flush
++ * effect must not be global:
++ */
++ set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
++
++ return (void*) vaddr;
++}
++
++static inline void *__kmap_atomic(struct page *page, enum km_type type)
++{
++ enum fixed_addresses idx;
++ unsigned long vaddr;
++
++ idx = type + KM_TYPE_NR*smp_processor_id();
++ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++#if HIGHMEM_DEBUG
++ BUG_ON(!pte_none(*(kmap_pte-idx)));
++#else
++ /*
++ * Performance optimization - do not flush if the new
++ * pte is the same as the old one:
++ */
++ if (pte_val(*(kmap_pte-idx)) == pte_val(mk_pte(page, kmap_prot)))
++ return (void *) vaddr;
++#endif
++ set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
++ __flush_tlb_one(vaddr);
++
++ return (void*) vaddr;
++}
++
++static inline void __kunmap_atomic(void *kvaddr, enum km_type type)
++{
++#if HIGHMEM_DEBUG
++ unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
++ enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
++
++ BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
++ /*
++ * force other mappings to Oops if they'll try to access
++ * this pte without first remap it
++ */
++ pte_clear(kmap_pte-idx);
++ __flush_tlb_one(vaddr);
++#endif
++}
++
++#define __kunmap_atomic_type(type) \
++ __kunmap_atomic((void *)__kmap_atomic_vaddr(type), (type))
++
++#endif /* __KERNEL__ */
++
++#endif /* _ASM_ATOMIC_KMAP_H */
+--- linux-2.6.0-test6/include/asm-i386/bugs.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/asm-i386/bugs.h 2003-10-05 00:33:38.000000000 -0700
+@@ -1,11 +1,11 @@
+ /*
+ * include/asm-i386/bugs.h
+ *
+- * Copyright (C) 1994 Linus Torvalds
++ * Copyright (C) 1994 Linus Torvalds
+ *
+ * Cyrix stuff, June 1998 by:
+ * - Rafael R. Reilova (moved everything from head.S),
+- * <rreilova@ececs.uc.edu>
++ * <rreilova@ececs.uc.edu>
+ * - Channing Corn (tests & fixes),
+ * - Andrew D. Balsa (code cleanup).
+ *
+@@ -25,7 +25,20 @@
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/msr.h>
+-
++#ifdef CONFIG_KGDB
++/*
++ * Provied the command line "gdb" initial break
++ */
++int __init kgdb_initial_break(char * str)
++{
++ if (*str == '\0'){
++ breakpoint();
++ return 1;
++ }
++ return 0;
++}
++__setup("gdb",kgdb_initial_break);
++#endif
+ static int __init no_halt(char *s)
+ {
+ boot_cpu_data.hlt_works_ok = 0;
+@@ -140,7 +153,7 @@ static void __init check_popad(void)
+ : "ecx", "edi" );
+ /* If this fails, it means that any user program may lock the CPU hard. Too bad. */
+ if (res != 12345678) printk( "Buggy.\n" );
+- else printk( "OK.\n" );
++ else printk( "OK.\n" );
+ #endif
+ }
+
+--- linux-2.6.0-test6/include/asm-i386/cacheflush.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/asm-i386/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,6 +13,13 @@
+ #define flush_icache_range(start, end) do { } while (0)
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ void global_flush_tlb(void);
+ int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+--- linux-2.6.0-test6/include/asm-i386/checksum.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-i386/checksum.h 2003-10-05 00:36:48.000000000 -0700
+@@ -25,7 +25,7 @@ asmlinkage unsigned int csum_partial(con
+ * better 64-bit) boundary
+ */
+
+-asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
++asmlinkage unsigned int direct_csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+ int *src_err_ptr, int *dst_err_ptr);
+
+ /*
+@@ -39,14 +39,19 @@ static __inline__
+ unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
+ int len, int sum)
+ {
+- return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
++ /*
++ * The direct function is OK for kernel-space => kernel-space copies:
++ */
++ return direct_csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+ }
+
+ static __inline__
+ unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+ {
+- return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
++ if (copy_from_user(dst, src, len))
++ *err_ptr = -EFAULT;
++ return csum_partial(dst, len, sum);
+ }
+
+ /*
+@@ -171,11 +176,26 @@ static __inline__ unsigned short int csu
+ * Copy and checksum to user
+ */
+ #define HAVE_CSUM_COPY_USER
+-static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
++static __inline__ unsigned int direct_csum_and_copy_to_user(const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+ {
+ if (access_ok(VERIFY_WRITE, dst, len))
+- return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
++ return direct_csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
++
++ if (len)
++ *err_ptr = -EFAULT;
++
++ return -1; /* invalid checksum */
++}
++
++static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
++ int len, int sum, int *err_ptr)
++{
++ if (access_ok(VERIFY_WRITE, dst, len)) {
++ if (copy_to_user(dst, src, len))
++ *err_ptr = -EFAULT;
++ return csum_partial(src, len, sum);
++ }
+
+ if (len)
+ *err_ptr = -EFAULT;
+--- linux-2.6.0-test6/include/asm-i386/desc.h 2003-06-14 12:17:55.000000000 -0700
++++ 25/include/asm-i386/desc.h 2003-10-05 00:36:48.000000000 -0700
+@@ -21,6 +21,13 @@ struct Xgt_desc_struct {
+
+ extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
+
++extern void trap_init_virtual_IDT(void);
++extern void trap_init_virtual_GDT(void);
++
++asmlinkage int system_call(void);
++asmlinkage void lcall7(void);
++asmlinkage void lcall27(void);
++
+ #define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
+ #define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
+
+@@ -30,6 +37,7 @@ extern struct Xgt_desc_struct idt_descr,
+ */
+ extern struct desc_struct default_ldt[];
+ extern void set_intr_gate(unsigned int irq, void * addr);
++extern void set_trap_gate(unsigned int n, void *addr);
+
+ #define _set_tssldt_desc(n,addr,limit,type) \
+ __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
+@@ -90,31 +98,8 @@ static inline void load_TLS(struct threa
+ #undef C
+ }
+
+-static inline void clear_LDT(void)
+-{
+- int cpu = get_cpu();
+-
+- set_ldt_desc(cpu, &default_ldt[0], 5);
+- load_LDT_desc();
+- put_cpu();
+-}
+-
+-/*
+- * load one particular LDT into the current CPU
+- */
+-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
+-{
+- void *segments = pc->ldt;
+- int count = pc->size;
+-
+- if (likely(!count)) {
+- segments = &default_ldt[0];
+- count = 5;
+- }
+-
+- set_ldt_desc(cpu, segments, count);
+- load_LDT_desc();
+-}
++extern struct page *default_ldt_page;
++extern void load_LDT_nolock(mm_context_t *pc, int cpu);
+
+ static inline void load_LDT(mm_context_t *pc)
+ {
+@@ -123,6 +108,6 @@ static inline void load_LDT(mm_context_t
+ put_cpu();
+ }
+
+-#endif /* !__ASSEMBLY__ */
+
++#endif /* !__ASSEMBLY__ */
+ #endif
+--- linux-2.6.0-test6/include/asm-i386/elf.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/include/asm-i386/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -127,11 +127,6 @@ extern int dump_task_extended_fpu (struc
+ #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+ #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
+
+-#ifdef CONFIG_SMP
+-extern void dump_smp_unlazy_fpu(void);
+-#define ELF_CORE_SYNC dump_smp_unlazy_fpu
+-#endif
+-
+ #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
+ #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
+ #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
+@@ -162,7 +157,10 @@ do { \
+ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
+ struct elf_phdr phdr = vsyscall_phdrs[i]; \
+ if (phdr.p_type == PT_LOAD) { \
++ BUG_ON(ofs != 0); \
+ ofs = phdr.p_offset = offset; \
++ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
++ phdr.p_filesz = phdr.p_memsz; \
+ offset += phdr.p_filesz; \
+ } \
+ else \
+@@ -180,7 +178,7 @@ do { \
+ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
+ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+ DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
+- vsyscall_phdrs[i].p_filesz); \
++ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ } \
+ } while (0)
+
+--- linux-2.6.0-test6/include/asm-i386/fixmap.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-i386/fixmap.h 2003-10-05 00:36:48.000000000 -0700
+@@ -18,17 +18,15 @@
+ #include <asm/acpi.h>
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
+-#ifdef CONFIG_HIGHMEM
+ #include <linux/threads.h>
+ #include <asm/kmap_types.h>
+-#endif
+
+ /*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+- * in the boot process. We allocate these special addresses
+- * from the end of virtual memory (0xfffff000) backwards.
++ * in the boot process. We allocate these special addresses
++ * from the end of virtual memory (0xffffe000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+@@ -41,11 +39,20 @@
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
++
++/*
++ * on UP currently we will have no trace of the fixmap mechanizm,
++ * no page table allocations, etc. This might change in the
++ * future, say framebuffers for the console driver(s) could be
++ * fix-mapped?
++ */
+ enum fixed_addresses {
+ FIX_HOLE,
+ FIX_VSYSCALL,
+ #ifdef CONFIG_X86_LOCAL_APIC
+ FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */
++#else
++ FIX_VSTACK_HOLE_1,
+ #endif
+ #ifdef CONFIG_X86_IO_APIC
+ FIX_IO_APIC_BASE_0,
+@@ -57,16 +64,21 @@ enum fixed_addresses {
+ FIX_LI_PCIA, /* Lithium PCI Bridge A */
+ FIX_LI_PCIB, /* Lithium PCI Bridge B */
+ #endif
+-#ifdef CONFIG_X86_F00F_BUG
+- FIX_F00F_IDT, /* Virtual mapping for IDT */
+-#endif
++ FIX_IDT,
++ FIX_GDT_1,
++ FIX_GDT_0,
++ FIX_TSS_3,
++ FIX_TSS_2,
++ FIX_TSS_1,
++ FIX_TSS_0,
++ FIX_ENTRY_TRAMPOLINE_1,
++ FIX_ENTRY_TRAMPOLINE_0,
+ #ifdef CONFIG_X86_CYCLONE_TIMER
+ FIX_CYCLONE_TIMER, /*cyclone timer register*/
++ FIX_VSTACK_HOLE_2,
+ #endif
+-#ifdef CONFIG_HIGHMEM
+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+-#endif
+ #ifdef CONFIG_ACPI_BOOT
+ FIX_ACPI_BEGIN,
+ FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
+@@ -95,12 +107,15 @@ extern void __set_fixmap (enum fixed_add
+ __set_fixmap(idx, 0, __pgprot(0))
+
+ /*
+- * used by vmalloc.c.
++ * used by vmalloc.c and various other places.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
++ *
++ * IMPORTANT: dont change FIXADDR_TOP without adjusting KM_VSTACK0
++ * and KM_VSTACK1 so that the virtual stack is 8K aligned.
+ */
+-#define FIXADDR_TOP (0xfffff000UL)
++#define FIXADDR_TOP (0xffffe000UL)
+ #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
+ #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
+
+--- linux-2.6.0-test6/include/asm-i386/highmem.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-i386/highmem.h 2003-10-05 00:36:48.000000000 -0700
+@@ -25,26 +25,19 @@
+ #include <linux/threads.h>
+ #include <asm/kmap_types.h>
+ #include <asm/tlbflush.h>
++#include <asm/atomic_kmap.h>
+
+ /* declarations for highmem.c */
+ extern unsigned long highstart_pfn, highend_pfn;
+
+-extern pte_t *kmap_pte;
+-extern pgprot_t kmap_prot;
+ extern pte_t *pkmap_page_table;
+-
+-extern void kmap_init(void);
++extern void kmap_init(void) __init;
+
+ /*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+-#if NR_CPUS <= 32
+-#define PKMAP_BASE (0xff800000UL)
+-#else
+-#define PKMAP_BASE (0xff600000UL)
+-#endif
+ #ifdef CONFIG_X86_PAE
+ #define LAST_PKMAP 512
+ #else
+@@ -63,6 +56,8 @@ void *kmap_atomic(struct page *page, enu
+ void kunmap_atomic(void *kvaddr, enum km_type type);
+ struct page *kmap_atomic_to_page(void *ptr);
+
++#define flush_cache_kmaps() do { } while (0)
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_HIGHMEM_H */
+--- linux-2.6.0-test6/include/asm-i386/hw_irq.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-i386/hw_irq.h 2003-10-05 00:36:27.000000000 -0700
+@@ -25,8 +25,9 @@
+ * Interrupt entry/exit code at both C and assembly level
+ */
+
+-extern int irq_vector[NR_IRQS];
+-#define IO_APIC_VECTOR(irq) irq_vector[irq]
++extern u8 *irq_vector;
++#define IO_APIC_VECTOR(irq) ((int)irq_vector[(irq)])
++extern int nr_irqs;
+
+ extern void (*interrupt[NR_IRQS])(void);
+
+@@ -41,6 +42,7 @@ asmlinkage void apic_timer_interrupt(voi
+ asmlinkage void error_interrupt(void);
+ asmlinkage void spurious_interrupt(void);
+ asmlinkage void thermal_interrupt(struct pt_regs);
++#define platform_legacy_irq(irq) ((irq) < 16)
+ #endif
+
+ void mask_irq(unsigned int irq);
+--- linux-2.6.0-test6/include/asm-i386/io_apic.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-i386/io_apic.h 2003-10-05 00:36:21.000000000 -0700
+@@ -13,6 +13,46 @@
+
+ #ifdef CONFIG_X86_IO_APIC
+
++#ifdef CONFIG_PCI_USE_VECTOR
++static inline int use_pci_vector(void) {return 1;}
++static inline void disable_edge_ioapic_vector(unsigned int vector) { }
++static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
++static inline void end_edge_ioapic_vector (unsigned int vector) { }
++#define startup_level_ioapic startup_level_ioapic_vector
++#define shutdown_level_ioapic mask_IO_APIC_vector
++#define enable_level_ioapic unmask_IO_APIC_vector
++#define disable_level_ioapic mask_IO_APIC_vector
++#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector
++#define end_level_ioapic end_level_ioapic_vector
++#define set_ioapic_affinity set_ioapic_affinity_vector
++
++#define startup_edge_ioapic startup_edge_ioapic_vector
++#define shutdown_edge_ioapic disable_edge_ioapic_vector
++#define enable_edge_ioapic unmask_IO_APIC_vector
++#define disable_edge_ioapic disable_edge_ioapic_vector
++#define ack_edge_ioapic ack_edge_ioapic_vector
++#define end_edge_ioapic end_edge_ioapic_vector
++#else
++static inline int use_pci_vector(void) {return 0;}
++static inline void disable_edge_ioapic_irq(unsigned int irq) { }
++static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
++static inline void end_edge_ioapic_irq (unsigned int irq) { }
++#define startup_level_ioapic startup_level_ioapic_irq
++#define shutdown_level_ioapic mask_IO_APIC_irq
++#define enable_level_ioapic unmask_IO_APIC_irq
++#define disable_level_ioapic mask_IO_APIC_irq
++#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
++#define end_level_ioapic end_level_ioapic_irq
++#define set_ioapic_affinity set_ioapic_affinity_irq
++
++#define startup_edge_ioapic startup_edge_ioapic_irq
++#define shutdown_edge_ioapic disable_edge_ioapic_irq
++#define enable_edge_ioapic unmask_IO_APIC_irq
++#define disable_edge_ioapic disable_edge_ioapic_irq
++#define ack_edge_ioapic ack_edge_ioapic_irq
++#define end_edge_ioapic end_edge_ioapic_irq
++#endif
++
+ #define APIC_MISMATCH_DEBUG
+
+ #define IO_APIC_BASE(idx) \
+@@ -177,4 +217,6 @@ extern int io_apic_set_pci_routing (int
+ #define io_apic_assign_pci_irqs 0
+ #endif
+
++extern int assign_irq_vector(int irq);
++
+ #endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-i386/kgdb.h 2003-10-05 00:33:50.000000000 -0700
+@@ -0,0 +1,76 @@
++#ifndef __KGDB
++#define __KGDB
++
++/*
++ * This file should not include ANY others. This makes it usable
++ * most anywhere without the fear of include order or inclusion.
++ * Make it so!
++ *
++ * This file may be included all the time. It is only active if
++ * CONFIG_KGDB is defined, otherwise it stubs out all the macros
++ * and entry points.
++ */
++#if defined(CONFIG_KGDB) && !defined(__ASSEMBLY__)
++
++extern void breakpoint(void);
++#define INIT_KGDB_INTS kgdb_enable_ints()
++
++#ifndef BREAKPOINT
++#define BREAKPOINT asm(" int $3")
++#endif
++
++struct sk_buff;
++
++extern int kgdb_eth;
++extern unsigned kgdb_remoteip;
++extern unsigned short kgdb_listenport;
++extern unsigned short kgdb_sendport;
++extern unsigned char kgdb_remotemac[6];
++extern unsigned char kgdb_localmac[6];
++extern int kgdb_eth_need_breakpoint[];
++
++extern int kgdb_tty_hook(void);
++extern int kgdb_eth_hook(void);
++extern int gdb_net_interrupt(struct sk_buff *skb);
++
++/*
++ * GDB debug stub (or any debug stub) can point the 'linux_debug_hook'
++ * pointer to its routine and it will be entered as the first thing
++ * when a trap occurs.
++ *
++ * Return values are, at present, undefined.
++ *
++ * The debug hook routine does not necessarily return to its caller.
++ * It has the register image and thus may choose to resume execution
++ * anywhere it pleases.
++ */
++struct pt_regs;
++struct sk_buff;
++
++extern int kgdb_handle_exception(int trapno,
++ int signo, int err_code, struct pt_regs *regs);
++extern int in_kgdb(struct pt_regs *regs);
++extern int kgdb_net_interrupt(struct sk_buff *skb);
++
++#ifdef CONFIG_KGDB_TS
++void kgdb_tstamp(int line, char *source, int data0, int data1);
++/*
++ * This is the time stamp function. The macro adds the source info and
++ * does a cast on the data to allow most any 32-bit value.
++ */
++
++#define kgdb_ts(data0,data1) kgdb_tstamp(__LINE__,__FILE__,(int)data0,(int)data1)
++#else
++#define kgdb_ts(data0,data1)
++#endif
++#else /* CONFIG_KGDB && ! __ASSEMBLY__ ,stubs follow... */
++#ifndef BREAKPOINT
++#define BREAKPOINT
++#endif
++#define kgdb_ts(data0,data1)
++#define in_kgdb
++#define kgdb_handle_exception
++#define breakpoint
++#define INIT_KGDB_INTS
++#endif
++#endif /* __KGDB */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-i386/kgdb_local.h 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,102 @@
++#ifndef __KGDB_LOCAL
++#define ___KGDB_LOCAL
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/serial.h>
++#include <linux/serialP.h>
++#include <linux/spinlock.h>
++#include <asm/processor.h>
++#include <asm/msr.h>
++#include <asm/kgdb.h>
++
++#define PORT 0x3f8
++#ifdef CONFIG_KGDB_PORT
++#undef PORT
++#define PORT CONFIG_KGDB_PORT
++#endif
++#define IRQ 4
++#ifdef CONFIG_KGDB_IRQ
++#undef IRQ
++#define IRQ CONFIG_KGDB_IRQ
++#endif
++#define SB_CLOCK 1843200
++#define SB_BASE (SB_CLOCK/16)
++#define SB_BAUD9600 SB_BASE/9600
++#define SB_BAUD192 SB_BASE/19200
++#define SB_BAUD384 SB_BASE/38400
++#define SB_BAUD576 SB_BASE/57600
++#define SB_BAUD1152 SB_BASE/115200
++#ifdef CONFIG_KGDB_9600BAUD
++#define SB_BAUD SB_BAUD9600
++#endif
++#ifdef CONFIG_KGDB_19200BAUD
++#define SB_BAUD SB_BAUD192
++#endif
++#ifdef CONFIG_KGDB_38400BAUD
++#define SB_BAUD SB_BAUD384
++#endif
++#ifdef CONFIG_KGDB_57600BAUD
++#define SB_BAUD SB_BAUD576
++#endif
++#ifdef CONFIG_KGDB_115200BAUD
++#define SB_BAUD SB_BAUD1152
++#endif
++#ifndef SB_BAUD
++#define SB_BAUD SB_BAUD1152 /* Start with this if not given */
++#endif
++
++#ifndef CONFIG_X86_TSC
++#undef rdtsc
++#define rdtsc(a,b) if (a++ > 10000){a = 0; b++;}
++#undef rdtscll
++#define rdtscll(s) s++
++#endif
++
++#ifdef _raw_read_unlock /* must use a name that is "define"ed, not an inline */
++#undef spin_lock
++#undef spin_trylock
++#undef spin_unlock
++#define spin_lock _raw_spin_lock
++#define spin_trylock _raw_spin_trylock
++#define spin_unlock _raw_spin_unlock
++#else
++#endif
++#undef spin_unlock_wait
++#define spin_unlock_wait(x) do { cpu_relax(); barrier();} \
++ while(spin_is_locked(x))
++
++#define SB_IER 1
++#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
++
++#define FLAGS 0
++#define SB_STATE { \
++ magic: SSTATE_MAGIC, \
++ baud_base: SB_BASE, \
++ port: PORT, \
++ irq: IRQ, \
++ flags: FLAGS, \
++ custom_divisor:SB_BAUD}
++#define SB_INFO { \
++ magic: SERIAL_MAGIC, \
++ port: PORT,0,FLAGS, \
++ state: &state, \
++ tty: (struct tty_struct *)&state, \
++ IER: SB_IER, \
++ MCR: SB_MCR}
++extern void putDebugChar(int);
++/* RTAI support needs us to really stop/start interrupts */
++
++#define kgdb_sti() __asm__ __volatile__("sti": : :"memory")
++#define kgdb_cli() __asm__ __volatile__("cli": : :"memory")
++#define kgdb_local_save_flags(x) __asm__ __volatile__(\
++ "pushfl ; popl %0":"=g" (x): /* no input */)
++#define kgdb_local_irq_restore(x) __asm__ __volatile__(\
++ "pushl %0 ; popfl": \
++ /* no output */ :"g" (x):"memory", "cc")
++#define kgdb_local_irq_save(x) kgdb_local_save_flags(x); kgdb_cli()
++
++#ifdef CONFIG_SERIAL
++extern void shutdown_for_kgdb(struct async_struct *info);
++#endif
++#define INIT_KDEBUG putDebugChar("+");
++#endif /* __KGDB_LOCAL */
+--- linux-2.6.0-test6/include/asm-i386/kmap_types.h 2003-06-14 12:18:28.000000000 -0700
++++ 25/include/asm-i386/kmap_types.h 2003-10-05 00:36:48.000000000 -0700
+@@ -3,30 +3,36 @@
+
+ #include <linux/config.h>
+
+-#ifdef CONFIG_DEBUG_HIGHMEM
+-# define D(n) __KM_FENCE_##n ,
+-#else
+-# define D(n)
+-#endif
+-
+ enum km_type {
+-D(0) KM_BOUNCE_READ,
+-D(1) KM_SKB_SUNRPC_DATA,
+-D(2) KM_SKB_DATA_SOFTIRQ,
+-D(3) KM_USER0,
+-D(4) KM_USER1,
+-D(5) KM_BIO_SRC_IRQ,
+-D(6) KM_BIO_DST_IRQ,
+-D(7) KM_PTE0,
+-D(8) KM_PTE1,
+-D(9) KM_PTE2,
+-D(10) KM_IRQ0,
+-D(11) KM_IRQ1,
+-D(12) KM_SOFTIRQ0,
+-D(13) KM_SOFTIRQ1,
+-D(14) KM_TYPE_NR
+-};
+-
+-#undef D
++ /*
++ * IMPORTANT: don't move these 3 entries, and only add entries in
++ * pairs: the 4G/4G virtual stack must be 8K aligned on each cpu.
++ */
++ KM_BOUNCE_READ,
++ KM_VSTACK1,
++ KM_VSTACK0,
+
++ KM_LDT_PAGE15,
++ KM_LDT_PAGE0 = KM_LDT_PAGE15 + 16-1,
++ KM_USER_COPY,
++ KM_VSTACK_HOLE,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_PTE2,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ /*
++ * Add new entries in pairs:
++ * the 4G/4G virtual stack must be 8K aligned on each cpu.
++ */
++ KM_TYPE_NR
++};
+ #endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-i386/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,127 @@
++/*
++ * Copyright (C) 1999,2000 Silicon Graphics, Inc.
++ *
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.h by Jack Steiner (steiner@sgi.com)
++ *
++ * Modified by Ray Bryant (raybry@us.ibm.com)
++ * Changes Copyright (C) 2000 IBM, Inc.
++ * Added save of index in spinlock_t to improve efficiency
++ * of "hold" time reporting for spinlocks.
++ * Added support for hold time statistics for read and write
++ * locks.
++ * Moved machine dependent code here from include/lockmeter.h.
++ *
++ */
++
++#ifndef _I386_LOCKMETER_H
++#define _I386_LOCKMETER_H
++
++#include <asm/spinlock.h>
++#include <asm/rwlock.h>
++
++#include <linux/version.h>
++
++#ifdef __KERNEL__
++extern unsigned long cpu_khz;
++#define CPU_CYCLE_FREQUENCY (cpu_khz * 1000)
++#else
++#define CPU_CYCLE_FREQUENCY 450000000
++#endif
++
++#define THIS_CPU_NUMBER smp_processor_id()
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
++#define local_irq_save(x) \
++ __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
++
++#define local_irq_restore(x) \
++ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
++#endif /* Linux version 2.2.x */
++
++/*
++ * macros to cache and retrieve an index value inside of a spin lock
++ * these macros assume that there are less than 65536 simultaneous
++ * (read mode) holders of a rwlock. Not normally a problem!!
++ * we also assume that the hash table has less than 65535 entries.
++ */
++/*
++ * instrumented spinlock structure -- never used to allocate storage
++ * only used in macros below to overlay a spinlock_t
++ */
++typedef struct inst_spinlock_s {
++ /* remember, Intel is little endian */
++ unsigned short lock;
++ unsigned short index;
++} inst_spinlock_t;
++#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv
++#define GET_INDEX(lock_ptr) ((inst_spinlock_t *)(lock_ptr))->index
++
++/*
++ * macros to cache and retrieve an index value in a read/write lock
++ * as well as the cpu where a reader busy period started
++ * we use the 2nd word (the debug word) for this, so require the
++ * debug word to be present
++ */
++/*
++ * instrumented rwlock structure -- never used to allocate storage
++ * only used in macros below to overlay a rwlock_t
++ */
++typedef struct inst_rwlock_s {
++ volatile int lock;
++ unsigned short index;
++ unsigned short cpu;
++} inst_rwlock_t;
++#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
++#define GET_RWINDEX(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->index
++#define PUT_RW_CPU(rwlock_ptr,cpuv) ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
++#define GET_RW_CPU(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->cpu
++
++/*
++ * return the number of readers for a rwlock_t
++ */
++#define RWLOCK_READERS(rwlock_ptr) rwlock_readers(rwlock_ptr)
++
++extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
++{
++ int tmp = (int) rwlock_ptr->lock;
++ /* read and write lock attempts may cause the lock value to temporarily */
++ /* be negative. Until it is >= 0 we know nothing (i. e. can't tell if */
++ /* is -1 because it was write locked and somebody tried to read lock it */
++ /* or if it is -1 because it was read locked and somebody tried to write*/
++ /* lock it. ........................................................... */
++ do {
++ tmp = (int) rwlock_ptr->lock;
++ } while (tmp < 0);
++ if (tmp == 0) return(0);
++ else return(RW_LOCK_BIAS-tmp);
++}
++
++/*
++ * return true if rwlock is write locked
++ * (note that other lock attempts can cause the lock value to be negative)
++ */
++#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->lock <= 0)
++#define IABS(x) ((x) > 0 ? (x) : -(x))
++#define RWLOCK_IS_READ_LOCKED(rwlock_ptr) ((IABS((rwlock_ptr)->lock) % RW_LOCK_BIAS) != 0)
++
++/* this is a lot of typing just to get gcc to emit "rdtsc" */
++static inline long long get_cycles64 (void)
++{
++#ifndef CONFIG_X86_TSC
++ #error this code requires CONFIG_X86_TSC
++#else
++ union longlong_u {
++ long long intlong;
++ struct intint_s {
++ uint32_t eax;
++ uint32_t edx;
++ } intint;
++ } longlong;
++
++ rdtsc(longlong.intint.eax,longlong.intint.edx);
++ return longlong.intlong;
++#endif
++}
++
++#endif /* _I386_LOCKMETER_H */
+--- linux-2.6.0-test6/include/asm-i386/mach-default/irq_vectors.h 2003-06-14 12:18:04.000000000 -0700
++++ 25/include/asm-i386/mach-default/irq_vectors.h 2003-10-05 00:36:20.000000000 -0700
+@@ -76,11 +76,21 @@
+ * Since vectors 0x00-0x1f are used/reserved for the CPU,
+ * the usable vector space is 0x20-0xff (224 vectors)
+ */
++/*
++ * The maximum number of vectors supported by i386 processors
++ * is limited to 256. For processors other than i386, NR_VECTORS
++ * should be changed accordingly.
++ */
++#define NR_VECTORS 256
++#ifdef CONFIG_PCI_USE_VECTOR
++#define NR_IRQS FIRST_SYSTEM_VECTOR
++#else
+ #ifdef CONFIG_X86_IO_APIC
+ #define NR_IRQS 224
+ #else
+ #define NR_IRQS 16
+ #endif
++#endif
+
+ #define FPU_IRQ 13
+
+--- linux-2.6.0-test6/include/asm-i386/mman.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/mman.h 2003-10-05 00:33:24.000000000 -0700
+@@ -8,8 +8,6 @@
+ #define PROT_NONE 0x0 /* page can not be accessed */
+ #define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+ #define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
+-#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+-#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
+
+ #define MAP_SHARED 0x01 /* Share changes */
+ #define MAP_PRIVATE 0x02 /* Changes are private */
+--- linux-2.6.0-test6/include/asm-i386/mmu_context.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-i386/mmu_context.h 2003-10-05 00:36:48.000000000 -0700
+@@ -29,6 +29,10 @@ static inline void switch_mm(struct mm_s
+ {
+ int cpu = smp_processor_id();
+
++#ifdef CONFIG_X86_SWITCH_PAGETABLES
++ if (tsk->mm)
++ tsk->thread_info->user_pgd = (void *)__pa(tsk->mm->pgd);
++#endif
+ if (likely(prev != next)) {
+ /* stop flush ipis for the previous mm */
+ cpu_clear(cpu, prev->cpu_vm_mask);
+@@ -39,12 +43,14 @@ static inline void switch_mm(struct mm_s
+ cpu_set(cpu, next->cpu_vm_mask);
+
+ /* Re-load page tables */
++#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
+ load_cr3(next->pgd);
++#endif
+
+ /*
+ * load the LDT, if the LDT is different:
+ */
+- if (unlikely(prev->context.ldt != next->context.ldt))
++ if (unlikely(prev->context.size + next->context.size))
+ load_LDT_nolock(&next->context, cpu);
+ }
+ #ifdef CONFIG_SMP
+@@ -56,7 +62,9 @@ static inline void switch_mm(struct mm_s
+ /* We were in lazy tlb mode and leave_mm disabled
+ * tlb flush IPI delivery. We must reload %cr3.
+ */
++#if !defined(CONFIG_X86_SWITCH_PAGETABLES)
+ load_cr3(next->pgd);
++#endif
+ load_LDT_nolock(&next->context, cpu);
+ }
+ }
+@@ -67,6 +75,6 @@ static inline void switch_mm(struct mm_s
+ asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
+
+ #define activate_mm(prev, next) \
+- switch_mm((prev),(next),NULL)
++ switch_mm((prev),(next),current)
+
+ #endif
+--- linux-2.6.0-test6/include/asm-i386/mmu.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/include/asm-i386/mmu.h 2003-10-05 00:36:48.000000000 -0700
+@@ -8,10 +8,13 @@
+ *
+ * cpu_vm_mask is used to optimize ldt flushing.
+ */
++
++#define MAX_LDT_PAGES 16
++
+ typedef struct {
+ int size;
+ struct semaphore sem;
+- void *ldt;
++ struct page *ldt_pages[MAX_LDT_PAGES];
+ } mm_context_t;
+
+ #endif
+--- linux-2.6.0-test6/include/asm-i386/numaq.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/numaq.h 2003-10-05 00:34:38.000000000 -0700
+@@ -28,7 +28,6 @@
+
+ #ifdef CONFIG_X86_NUMAQ
+
+-#define MAX_NUMNODES 16
+ extern int get_memcfg_numaq(void);
+
+ /*
+--- linux-2.6.0-test6/include/asm-i386/numnodes.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/numnodes.h 2003-10-05 00:34:38.000000000 -0700
+@@ -4,11 +4,15 @@
+ #include <linux/config.h>
+
+ #ifdef CONFIG_X86_NUMAQ
+-#include <asm/numaq.h>
+-#elif CONFIG_ACPI_SRAT
+-#include <asm/srat.h>
+-#else
+-#define MAX_NUMNODES 1
++
++/* Max 16 Nodes */
++#define NODES_SHIFT 4
++
++#elif defined(CONFIG_ACPI_SRAT)
++
++/* Max 8 Nodes */
++#define NODES_SHIFT 3
++
+ #endif /* CONFIG_X86_NUMAQ */
+
+ #endif /* _ASM_MAX_NUMNODES_H */
+--- linux-2.6.0-test6/include/asm-i386/page.h 2003-06-26 22:07:25.000000000 -0700
++++ 25/include/asm-i386/page.h 2003-10-05 00:36:48.000000000 -0700
+@@ -1,6 +1,8 @@
+ #ifndef _I386_PAGE_H
+ #define _I386_PAGE_H
+
++#include <linux/config.h>
++
+ /* PAGE_SHIFT determines the page size */
+ #define PAGE_SHIFT 12
+ #define PAGE_SIZE (1UL << PAGE_SHIFT)
+@@ -9,11 +11,10 @@
+ #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
+ #define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
+
+-#ifdef __KERNEL__
+-#ifndef __ASSEMBLY__
+-
+ #include <linux/config.h>
+
++#ifdef __KERNEL__
++#ifndef __ASSEMBLY__
+ #ifdef CONFIG_X86_USE_3DNOW
+
+ #include <asm/mmx.h>
+@@ -88,8 +89,19 @@ typedef struct { unsigned long pgprot; }
+ *
+ * If you want more physical memory than this then see the CONFIG_HIGHMEM4G
+ * and CONFIG_HIGHMEM64G options in the kernel configuration.
++ *
++ * Note: on PAE the kernel must never go below 32 MB, we use the
++ * first 8 entries of the 2-level boot pgd for PAE magic.
+ */
+
++#ifdef CONFIG_X86_4G_VM_LAYOUT
++#define __PAGE_OFFSET (0x02000000)
++#define TASK_SIZE (0xff000000)
++#else
++#define __PAGE_OFFSET (0xc0000000)
++#define TASK_SIZE (0xc0000000)
++#endif
++
+ /*
+ * This much address space is reserved for vmalloc() and iomap()
+ * as well as fixmap mappings.
+@@ -114,16 +126,10 @@ static __inline__ int get_order(unsigned
+
+ #endif /* __ASSEMBLY__ */
+
+-#ifdef __ASSEMBLY__
+-#define __PAGE_OFFSET (0xC0000000)
+-#else
+-#define __PAGE_OFFSET (0xC0000000UL)
+-#endif
+-
+-
+ #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
+ #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
+-#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
++#define __MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
++#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
+ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
+ #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
+ #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+--- linux-2.6.0-test6/include/asm-i386/pgtable.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/include/asm-i386/pgtable.h 2003-10-05 00:36:48.000000000 -0700
+@@ -32,16 +32,17 @@
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+ extern unsigned long empty_zero_page[1024];
+ extern pgd_t swapper_pg_dir[1024];
+-extern kmem_cache_t *pgd_cache;
+-extern kmem_cache_t *pmd_cache;
++extern kmem_cache_t *pgd_cache, *pmd_cache, *kpmd_cache;
+ extern spinlock_t pgd_lock;
+ extern struct list_head pgd_list;
+
+ void pmd_ctor(void *, kmem_cache_t *, unsigned long);
++void kpmd_ctor(void *, kmem_cache_t *, unsigned long);
+ void pgd_ctor(void *, kmem_cache_t *, unsigned long);
+ void pgd_dtor(void *, kmem_cache_t *, unsigned long);
+ void pgtable_cache_init(void);
+ void paging_init(void);
++void setup_identity_mappings(pgd_t *pgd_base, unsigned long start, unsigned long end);
+
+ #endif /* !__ASSEMBLY__ */
+
+@@ -51,6 +52,11 @@ void paging_init(void);
+ * newer 3-level PAE-mode page tables.
+ */
+ #ifndef __ASSEMBLY__
++
++extern void set_system_gate(unsigned int n, void *addr);
++extern void init_entry_mappings(void);
++extern void entry_trampoline_setup(void);
++
+ #ifdef CONFIG_X86_PAE
+ # include <asm/pgtable-3level.h>
+ #else
+@@ -63,7 +69,12 @@ void paging_init(void);
+ #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+ #define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+-#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
++#if defined(CONFIG_X86_PAE) && defined(CONFIG_X86_4G_VM_LAYOUT)
++# define USER_PTRS_PER_PGD 4
++#else
++# define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) + ((TASK_SIZE % PGDIR_SIZE) + PGDIR_SIZE-1)/PGDIR_SIZE)
++#endif
++
+ #define FIRST_USER_PGD_NR 0
+
+ #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+@@ -85,7 +96,6 @@ void paging_init(void);
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
+ ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #ifdef CONFIG_HIGHMEM
+ # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
+ #else
+@@ -234,6 +244,7 @@ static inline void ptep_mkdirty(pte_t *p
+
+ #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+ #define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
++#define mk_pte_phys(physpage, pgprot) pfn_pte((physpage) >> PAGE_SHIFT, pgprot)
+
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+--- linux-2.6.0-test6/include/asm-i386/processor.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/processor.h 2003-10-05 00:36:49.000000000 -0700
+@@ -291,11 +291,6 @@ extern unsigned int machine_submodel_id;
+ extern unsigned int BIOS_revision;
+ extern unsigned int mca_pentium_flag;
+
+-/*
+- * User space process size: 3GB (default).
+- */
+-#define TASK_SIZE (PAGE_OFFSET)
+-
+ /* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+@@ -406,6 +401,7 @@ struct tss_struct {
+ struct thread_struct {
+ /* cached TLS descriptors. */
+ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
++ void *stack_page0, *stack_page1;
+ unsigned long esp0;
+ unsigned long eip;
+ unsigned long esp;
+@@ -491,6 +487,13 @@ extern void prepare_to_copy(struct task_
+ */
+ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
++#ifdef CONFIG_X86_HIGH_ENTRY
++#define virtual_esp0(tsk) \
++ ((unsigned long)(tsk)->thread_info->virtual_stack + ((tsk)->thread.esp0 - (unsigned long)(tsk)->thread_info->real_stack))
++#else
++# define virtual_esp0(tsk) ((tsk)->thread.esp0)
++#endif
++
+ extern unsigned long thread_saved_pc(struct task_struct *tsk);
+ void show_trace(struct task_struct *task, unsigned long *stack);
+
+@@ -585,12 +588,12 @@ static inline void rep_nop(void)
+
+ /* Prefetch instructions for Pentium III and AMD Athlon */
+ /* It's not worth to care about 3dnow! prefetches for the K6
+- because they are microcoded there and very slow. */
++ because they are microcoded there and very slow.
++ However we don't do prefetches for pre XP Athlons currently
++ That should be fixed. */
+ #define ARCH_HAS_PREFETCH
+ extern inline void prefetch(const void *x)
+ {
+- if (cpu_data[0].x86_vendor == X86_VENDOR_AMD)
+- return; /* Some athlons fault if the address is bad */
+ alternative_input(ASM_NOP4,
+ "prefetchnta (%1)",
+ X86_FEATURE_XMM,
+--- linux-2.6.0-test6/include/asm-i386/rwlock.h 2003-06-26 22:07:25.000000000 -0700
++++ 25/include/asm-i386/rwlock.h 2003-10-05 00:34:17.000000000 -0700
+@@ -20,28 +20,52 @@
+ #define RW_LOCK_BIAS 0x01000000
+ #define RW_LOCK_BIAS_STR "0x01000000"
+
+-#define __build_read_lock_ptr(rw, helper) \
+- asm volatile(LOCK "subl $1,(%0)\n\t" \
+- "js 2f\n" \
+- "1:\n" \
+- LOCK_SECTION_START("") \
+- "2:\tcall " helper "\n\t" \
+- "jmp 1b\n" \
+- LOCK_SECTION_END \
+- ::"a" (rw) : "memory")
+-
+-#define __build_read_lock_const(rw, helper) \
+- asm volatile(LOCK "subl $1,%0\n\t" \
+- "js 2f\n" \
+- "1:\n" \
+- LOCK_SECTION_START("") \
+- "2:\tpushl %%eax\n\t" \
+- "leal %0,%%eax\n\t" \
+- "call " helper "\n\t" \
+- "popl %%eax\n\t" \
+- "jmp 1b\n" \
+- LOCK_SECTION_END \
+- :"=m" (*(volatile int *)rw) : : "memory")
++#ifdef CONFIG_SPINLINE
++
++ #define __build_read_lock_ptr(rw, helper) \
++ asm volatile(LOCK "subl $1,(%0)\n\t" \
++ "jns 1f\n\t" \
++ "call " helper "\n\t" \
++ "1:\t" \
++ ::"a" (rw) : "memory")
++
++ #define __build_read_lock_const(rw, helper) \
++ asm volatile(LOCK "subl $1,%0\n\t" \
++ "jns 1f\n\t" \
++ "pushl %%eax\n\t" \
++ "leal %0,%%eax\n\t" \
++ "call " helper "\n\t" \
++ "popl %%eax\n\t" \
++ "1:\t" \
++ :"=m" (*(volatile int *)rw) : : "memory")
++
++#else /* !CONFIG_SPINLINE */
++
++ #define __build_read_lock_ptr(rw, helper) \
++ asm volatile(LOCK "subl $1,(%0)\n\t" \
++ "js 2f\n" \
++ "1:\n" \
++ LOCK_SECTION_START("") \
++ "2:\tcall " helper "\n\t" \
++ "jmp 1b\n" \
++ LOCK_SECTION_END \
++ ::"a" (rw) : "memory")
++
++ #define __build_read_lock_const(rw, helper) \
++ asm volatile(LOCK "subl $1,%0\n\t" \
++ "js 2f\n" \
++ "1:\n" \
++ LOCK_SECTION_START("") \
++ "2:\tpushl %%eax\n\t" \
++ "leal %0,%%eax\n\t" \
++ "call " helper "\n\t" \
++ "popl %%eax\n\t" \
++ "jmp 1b\n" \
++ LOCK_SECTION_END \
++ :"=m" (*(volatile int *)rw) : : "memory")
++
++#endif /* CONFIG_SPINLINE */
++
+
+ #define __build_read_lock(rw, helper) do { \
+ if (__builtin_constant_p(rw)) \
+@@ -50,28 +74,51 @@
+ __build_read_lock_ptr(rw, helper); \
+ } while (0)
+
+-#define __build_write_lock_ptr(rw, helper) \
+- asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+- "jnz 2f\n" \
+- "1:\n" \
+- LOCK_SECTION_START("") \
+- "2:\tcall " helper "\n\t" \
+- "jmp 1b\n" \
+- LOCK_SECTION_END \
+- ::"a" (rw) : "memory")
+-
+-#define __build_write_lock_const(rw, helper) \
+- asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+- "jnz 2f\n" \
+- "1:\n" \
+- LOCK_SECTION_START("") \
+- "2:\tpushl %%eax\n\t" \
+- "leal %0,%%eax\n\t" \
+- "call " helper "\n\t" \
+- "popl %%eax\n\t" \
+- "jmp 1b\n" \
+- LOCK_SECTION_END \
+- :"=m" (*(volatile int *)rw) : : "memory")
++#ifdef CONFIG_SPINLINE
++
++ #define __build_write_lock_ptr(rw, helper) \
++ asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
++ "jz 1f\n\t" \
++ "call " helper "\n\t" \
++ "1:\n" \
++ ::"a" (rw) : "memory")
++
++ #define __build_write_lock_const(rw, helper) \
++ asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
++ "jz 1f\n\t" \
++ "pushl %%eax\n\t" \
++ "leal %0,%%eax\n\t" \
++ "call " helper "\n\t" \
++ "popl %%eax\n\t" \
++ "1:\n" \
++ :"=m" (*(volatile int *)rw) : : "memory")
++
++#else /* !CONFIG_SPINLINE */
++
++ #define __build_write_lock_ptr(rw, helper) \
++ asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
++ "jnz 2f\n" \
++ "1:\n" \
++ LOCK_SECTION_START("") \
++ "2:\tcall " helper "\n\t" \
++ "jmp 1b\n" \
++ LOCK_SECTION_END \
++ ::"a" (rw) : "memory")
++
++ #define __build_write_lock_const(rw, helper) \
++ asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
++ "jnz 2f\n" \
++ "1:\n" \
++ LOCK_SECTION_START("") \
++ "2:\tpushl %%eax\n\t" \
++ "leal %0,%%eax\n\t" \
++ "call " helper "\n\t" \
++ "popl %%eax\n\t" \
++ "jmp 1b\n" \
++ LOCK_SECTION_END \
++ :"=m" (*(volatile int *)rw) : : "memory")
++
++#endif /* CONFIG_SPINLINE */
+
+ #define __build_write_lock(rw, helper) do { \
+ if (__builtin_constant_p(rw)) \
+--- linux-2.6.0-test6/include/asm-i386/setup.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/setup.h 2003-10-05 00:36:22.000000000 -0700
+@@ -29,6 +29,11 @@
+ #define IST_INFO (*(struct ist_info *) (PARAM+0x60))
+ #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
+ #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
++#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
++#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
++#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
++#define EFI_MEMMAP ((efi_memory_desc_t *) *((unsigned long *)(PARAM+0x1d0)))
++#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
+ #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
+ #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
+ #define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
+--- linux-2.6.0-test6/include/asm-i386/spinlock.h 2003-06-26 22:07:25.000000000 -0700
++++ 25/include/asm-i386/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -43,18 +43,35 @@ typedef struct {
+ #define spin_is_locked(x) (*(volatile signed char *)(&(x)->lock) <= 0)
+ #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
+
+-#define spin_lock_string \
+- "\n1:\t" \
+- "lock ; decb %0\n\t" \
+- "js 2f\n" \
+- LOCK_SECTION_START("") \
+- "2:\t" \
+- "rep;nop\n\t" \
+- "cmpb $0,%0\n\t" \
+- "jle 2b\n\t" \
+- "jmp 1b\n" \
+- LOCK_SECTION_END
++#ifdef CONFIG_SPINLINE
+
++ #define spin_lock_string \
++ "\n1:\t" \
++ "lock ; decb %0\n\t" \
++ "js 2f\n" \
++ "jmp 3f\n" \
++ "2:\t" \
++ "rep;nop\n\t" \
++ "cmpb $0,%0\n\t" \
++ "jle 2b\n\t" \
++ "jmp 1b\n" \
++ "3:\t"
++
++#else /* !CONFIG_SPINLINE */
++
++ #define spin_lock_string \
++ "\n1:\t" \
++ "lock ; decb %0\n\t" \
++ "js 2f\n" \
++ LOCK_SECTION_START("") \
++ "2:\t" \
++ "rep;nop\n\t" \
++ "cmpb $0,%0\n\t" \
++ "jle 2b\n\t" \
++ "jmp 1b\n" \
++ LOCK_SECTION_END
++
++#endif /* CONFIG_SPINLINE */
+ /*
+ * This works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE)
+@@ -138,6 +155,11 @@ here:
+ */
+ typedef struct {
+ volatile unsigned int lock;
++#ifdef CONFIG_LOCKMETER
++ /* required for LOCKMETER since all bits in lock are used */
++ /* and we need this storage for CPU and lock INDEX */
++ unsigned lockmeter_magic;
++#endif
+ #ifdef CONFIG_DEBUG_SPINLOCK
+ unsigned magic;
+ #endif
+@@ -145,11 +167,19 @@ typedef struct {
+
+ #define RWLOCK_MAGIC 0xdeaf1eed
+
++#ifdef CONFIG_LOCKMETER
++#ifdef CONFIG_DEBUG_SPINLOCK
++#define RWLOCK_MAGIC_INIT , 0, RWLOCK_MAGIC
++#else
++#define RWLOCK_MAGIC_INIT , 0
++#endif
++#else /* !CONFIG_LOCKMETER */
+ #ifdef CONFIG_DEBUG_SPINLOCK
+ #define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
+ #else
+ #define RWLOCK_MAGIC_INIT /* */
+ #endif
++#endif /* !CONFIG_LOCKMETER */
+
+ #define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
+
+@@ -196,4 +226,58 @@ static inline int _raw_write_trylock(rwl
+ return 0;
+ }
+
++#ifdef CONFIG_LOCKMETER
++static inline int _raw_read_trylock(rwlock_t *lock)
++{
++/* FIXME -- replace with assembler */
++ atomic_t *count = (atomic_t *)lock;
++ atomic_dec(count);
++ if (count->counter > 0)
++ return 1;
++ atomic_inc(count);
++ return 0;
++}
++#endif
++
++#if defined(CONFIG_LOCKMETER) && defined(CONFIG_HAVE_DEC_LOCK)
++extern void _metered_spin_lock (spinlock_t *lock);
++extern void _metered_spin_unlock(spinlock_t *lock);
++
++/*
++ * Matches what is in arch/i386/lib/dec_and_lock.c, except this one is
++ * "static inline" so that the spin_lock(), if actually invoked, is charged
++ * against the real caller, not against the catch-all atomic_dec_and_lock
++ */
++static inline int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
++{
++ int counter;
++ int newcount;
++
++repeat:
++ counter = atomic_read(atomic);
++ newcount = counter-1;
++
++ if (!newcount)
++ goto slow_path;
++
++ asm volatile("lock; cmpxchgl %1,%2"
++ :"=a" (newcount)
++ :"r" (newcount), "m" (atomic->counter), "0" (counter));
++
++ /* If the above failed, "eax" will have changed */
++ if (newcount != counter)
++ goto repeat;
++ return 0;
++
++slow_path:
++ _metered_spin_lock(lock);
++ if (atomic_dec_and_test(atomic))
++ return 1;
++ _metered_spin_unlock(lock);
++ return 0;
++}
++
++#define ATOMIC_DEC_AND_LOCK
++#endif
++
+ #endif /* __ASM_SPINLOCK_H */
+--- linux-2.6.0-test6/include/asm-i386/srat.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/srat.h 2003-10-05 00:34:38.000000000 -0700
+@@ -31,7 +31,6 @@
+ #error CONFIG_ACPI_SRAT not defined, and srat.h header has been included
+ #endif
+
+-#define MAX_NUMNODES 8
+ extern int get_memcfg_from_srat(void);
+ extern unsigned long *get_zholes_size(int);
+
+--- linux-2.6.0-test6/include/asm-i386/string.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-i386/string.h 2003-10-05 00:36:48.000000000 -0700
+@@ -56,6 +56,29 @@ __asm__ __volatile__(
+ return dest;
+ }
+
++/*
++ * This is a more generic variant of strncpy_count() suitable for
++ * implementing string-access routines with all sorts of return
++ * code semantics. It's used by mm/usercopy.c.
++ */
++static inline size_t strncpy_count(char * dest,const char *src,size_t count)
++{
++ __asm__ __volatile__(
++
++ "1:\tdecl %0\n\t"
++ "js 2f\n\t"
++ "lodsb\n\t"
++ "stosb\n\t"
++ "testb %%al,%%al\n\t"
++ "jne 1b\n\t"
++ "2:"
++ "incl %0"
++ : "=c" (count)
++ :"S" (src),"D" (dest),"0" (count) : "memory");
++
++ return count;
++}
++
+ #define __HAVE_ARCH_STRCAT
+ static inline char * strcat(char * dest,const char * src)
+ {
+--- linux-2.6.0-test6/include/asm-i386/thread_info.h 2003-07-27 12:14:40.000000000 -0700
++++ 25/include/asm-i386/thread_info.h 2003-10-05 00:36:48.000000000 -0700
+@@ -33,23 +33,12 @@ struct thread_info {
+ 0-0xBFFFFFFF for user-thead
+ 0-0xFFFFFFFF for kernel-thread
+ */
+- struct restart_block restart_block;
++ void *real_stack, *virtual_stack, *user_pgd;
+
++ struct restart_block restart_block;
+ __u8 supervisor_stack[0];
+ };
+
+-#else /* !__ASSEMBLY__ */
+-
+-/* offsets into the thread_info struct for assembly code access */
+-#define TI_TASK 0x00000000
+-#define TI_EXEC_DOMAIN 0x00000004
+-#define TI_FLAGS 0x00000008
+-#define TI_STATUS 0x0000000C
+-#define TI_CPU 0x00000010
+-#define TI_PRE_COUNT 0x00000014
+-#define TI_ADDR_LIMIT 0x00000018
+-#define TI_RESTART_BLOCK 0x000001C
+-
+ #endif
+
+ #define PREEMPT_ACTIVE 0x4000000
+@@ -61,7 +50,7 @@ struct thread_info {
+ */
+ #ifndef __ASSEMBLY__
+
+-#define INIT_THREAD_INFO(tsk) \
++#define INIT_THREAD_INFO(tsk, thread_info) \
+ { \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+@@ -72,6 +61,7 @@ struct thread_info {
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
++ .real_stack = &thread_info, \
+ }
+
+ #define init_thread_info (init_thread_union.thread_info)
+@@ -113,6 +103,7 @@ static inline struct thread_info *curren
+ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
+ #define TIF_IRET 5 /* return with iret */
++#define TIF_DB7 6 /* has debug registers */
+ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+@@ -121,6 +112,7 @@ static inline struct thread_info *curren
+ #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+ #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+ #define _TIF_IRET (1<<TIF_IRET)
++#define _TIF_DB7 (1<<TIF_DB7)
+ #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+ #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
+--- linux-2.6.0-test6/include/asm-i386/tlbflush.h 2003-06-14 12:18:35.000000000 -0700
++++ 25/include/asm-i386/tlbflush.h 2003-10-05 00:36:48.000000000 -0700
+@@ -85,22 +85,28 @@ extern unsigned long pgkern_mask;
+
+ static inline void flush_tlb_mm(struct mm_struct *mm)
+ {
++#ifndef CONFIG_X86_SWITCH_PAGETABLES
+ if (mm == current->active_mm)
+ __flush_tlb();
++#endif
+ }
+
+ static inline void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr)
+ {
++#ifndef CONFIG_X86_SWITCH_PAGETABLES
+ if (vma->vm_mm == current->active_mm)
+ __flush_tlb_one(addr);
++#endif
+ }
+
+ static inline void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
++#ifndef CONFIG_X86_SWITCH_PAGETABLES
+ if (vma->vm_mm == current->active_mm)
+ __flush_tlb();
++#endif
+ }
+
+ #else
+@@ -111,11 +117,10 @@ static inline void flush_tlb_range(struc
+ __flush_tlb()
+
+ extern void flush_tlb_all(void);
+-extern void flush_tlb_current_task(void);
+ extern void flush_tlb_mm(struct mm_struct *);
+ extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+-#define flush_tlb() flush_tlb_current_task()
++#define flush_tlb() flush_tlb_all()
+
+ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
+ {
+--- linux-2.6.0-test6/include/asm-i386/uaccess.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-i386/uaccess.h 2003-10-05 00:36:48.000000000 -0700
+@@ -26,7 +26,7 @@
+
+
+ #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL)
+-#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
++#define USER_DS MAKE_MM_SEG(TASK_SIZE)
+
+ #define get_ds() (KERNEL_DS)
+ #define get_fs() (current_thread_info()->addr_limit)
+@@ -149,6 +149,45 @@ extern void __get_user_4(void);
+ :"=a" (ret),"=d" (x) \
+ :"0" (ptr))
+
++extern int get_user_size(unsigned int size, void *val, const void *ptr);
++extern int put_user_size(unsigned int size, const void *val, void *ptr);
++extern int zero_user_size(unsigned int size, void *ptr);
++extern int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr);
++extern int strlen_fromuser_size(unsigned int size, const void *ptr);
++
++
++# define indirect_get_user(x,ptr) \
++({ int __ret_gu,__val_gu; \
++ __typeof__(ptr) __ptr_gu = (ptr); \
++ __ret_gu = get_user_size(sizeof(*__ptr_gu), &__val_gu,__ptr_gu) ? -EFAULT : 0;\
++ (x) = (__typeof__(*__ptr_gu))__val_gu; \
++ __ret_gu; \
++})
++#define indirect_put_user(x,ptr) \
++({ \
++ __typeof__(*(ptr)) *__ptr_pu = (ptr), __x_pu = (x); \
++ put_user_size(sizeof(*__ptr_pu), &__x_pu, __ptr_pu) ? -EFAULT : 0; \
++})
++#define __indirect_put_user indirect_put_user
++#define __indirect_get_user indirect_get_user
++
++#define indirect_copy_from_user(to,from,n) get_user_size(n,to,from)
++#define indirect_copy_to_user(to,from,n) put_user_size(n,from,to)
++
++#define __indirect_copy_from_user indirect_copy_from_user
++#define __indirect_copy_to_user indirect_copy_to_user
++
++#define indirect_strncpy_from_user(dst, src, count) \
++ copy_str_fromuser_size(count, dst, src)
++
++extern int strlen_fromuser_size(unsigned int size, const void *ptr);
++#define indirect_strnlen_user(str, n) strlen_fromuser_size(n, str)
++#define indirect_strlen_user(str) indirect_strnlen_user(str, ~0UL >> 1)
++
++extern int zero_user_size(unsigned int size, void *ptr);
++
++#define indirect_clear_user(mem, len) zero_user_size(len, mem)
++#define __indirect_clear_user clear_user
+
+ /* Careful: we have to cast the result to the type of the pointer for sign reasons */
+ /**
+@@ -168,7 +207,7 @@ extern void __get_user_4(void);
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+-#define get_user(x,ptr) \
++#define direct_get_user(x,ptr) \
+ ({ int __ret_gu,__val_gu; \
+ switch(sizeof (*(ptr))) { \
+ case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
+@@ -198,7 +237,7 @@ extern void __put_user_bad(void);
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+-#define put_user(x,ptr) \
++#define direct_put_user(x,ptr) \
+ __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+
+@@ -222,7 +261,7 @@ extern void __put_user_bad(void);
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+-#define __get_user(x,ptr) \
++#define __direct_get_user(x,ptr) \
+ __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+
+@@ -245,7 +284,7 @@ extern void __put_user_bad(void);
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+-#define __put_user(x,ptr) \
++#define __direct_put_user(x,ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+ #define __put_user_nocheck(x,ptr,size) \
+@@ -396,7 +435,7 @@ unsigned long __copy_from_user_ll(void *
+ * On success, this will be zero.
+ */
+ static inline unsigned long
+-__copy_to_user(void __user *to, const void *from, unsigned long n)
++__direct_copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+ if (__builtin_constant_p(n)) {
+ unsigned long ret;
+@@ -434,7 +473,7 @@ __copy_to_user(void __user *to, const vo
+ * data to the requested size using zero bytes.
+ */
+ static inline unsigned long
+-__copy_from_user(void *to, const void __user *from, unsigned long n)
++__direct_copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+ if (__builtin_constant_p(n)) {
+ unsigned long ret;
+@@ -468,11 +507,11 @@ __copy_from_user(void *to, const void __
+ * On success, this will be zero.
+ */
+ static inline unsigned long
+-copy_to_user(void __user *to, const void *from, unsigned long n)
++direct_copy_to_user(void __user *to, const void *from, unsigned long n)
+ {
+ might_sleep();
+ if (access_ok(VERIFY_WRITE, to, n))
+- n = __copy_to_user(to, from, n);
++ n = __direct_copy_to_user(to, from, n);
+ return n;
+ }
+
+@@ -493,11 +532,11 @@ copy_to_user(void __user *to, const void
+ * data to the requested size using zero bytes.
+ */
+ static inline unsigned long
+-copy_from_user(void *to, const void __user *from, unsigned long n)
++direct_copy_from_user(void *to, const void __user *from, unsigned long n)
+ {
+ might_sleep();
+ if (access_ok(VERIFY_READ, from, n))
+- n = __copy_from_user(to, from, n);
++ n = __direct_copy_from_user(to, from, n);
+ else
+ memset(to, 0, n);
+ return n;
+@@ -520,10 +559,68 @@ long __strncpy_from_user(char *dst, cons
+ * If there is a limit on the length of a valid string, you may wish to
+ * consider using strnlen_user() instead.
+ */
+-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+
+-long strnlen_user(const char __user *str, long n);
+-unsigned long clear_user(void __user *mem, unsigned long len);
+-unsigned long __clear_user(void __user *mem, unsigned long len);
++long direct_strncpy_from_user(char *dst, const char *src, long count);
++long __direct_strncpy_from_user(char *dst, const char *src, long count);
++#define direct_strlen_user(str) direct_strnlen_user(str, ~0UL >> 1)
++long direct_strnlen_user(const char *str, long n);
++unsigned long direct_clear_user(void *mem, unsigned long len);
++unsigned long __direct_clear_user(void *mem, unsigned long len);
++
++extern int indirect_uaccess;
++
++#ifdef CONFIG_X86_UACCESS_INDIRECT
++
++/*
++ * Return code and zeroing semantics:
++
++ __clear_user 0 <-> bytes not done
++ clear_user 0 <-> bytes not done
++ __copy_to_user 0 <-> bytes not done
++ copy_to_user 0 <-> bytes not done
++ __copy_from_user 0 <-> bytes not done, zero rest
++ copy_from_user 0 <-> bytes not done, zero rest
++ __get_user 0 <-> -EFAULT
++ get_user 0 <-> -EFAULT
++ __put_user 0 <-> -EFAULT
++ put_user 0 <-> -EFAULT
++ strlen_user strlen + 1 <-> 0
++ strnlen_user strlen + 1 (or n+1) <-> 0
++ strncpy_from_user strlen (or n) <-> -EFAULT
++
++ */
++
++#define __clear_user(mem,len) __indirect_clear_user(mem,len)
++#define clear_user(mem,len) indirect_clear_user(mem,len)
++#define __copy_to_user(to,from,n) __indirect_copy_to_user(to,from,n)
++#define copy_to_user(to,from,n) indirect_copy_to_user(to,from,n)
++#define __copy_from_user(to,from,n) __indirect_copy_from_user(to,from,n)
++#define copy_from_user(to,from,n) indirect_copy_from_user(to,from,n)
++#define __get_user(val,ptr) __indirect_get_user(val,ptr)
++#define get_user(val,ptr) indirect_get_user(val,ptr)
++#define __put_user(val,ptr) __indirect_put_user(val,ptr)
++#define put_user(val,ptr) indirect_put_user(val,ptr)
++#define strlen_user(str) indirect_strlen_user(str)
++#define strnlen_user(src,count) indirect_strnlen_user(src,count)
++#define strncpy_from_user(dst,src,count) \
++ indirect_strncpy_from_user(dst,src,count)
++
++#else
++
++#define __clear_user __direct_clear_user
++#define clear_user direct_clear_user
++#define __copy_to_user __direct_copy_to_user
++#define copy_to_user direct_copy_to_user
++#define __copy_from_user __direct_copy_from_user
++#define copy_from_user direct_copy_from_user
++#define __get_user __direct_get_user
++#define get_user direct_get_user
++#define __put_user __direct_put_user
++#define put_user direct_put_user
++#define strlen_user direct_strlen_user
++#define strnlen_user direct_strnlen_user
++#define strncpy_from_user direct_strncpy_from_user
++
++#endif /* CONFIG_X86_UACCESS_INDIRECT */
+
+ #endif /* __i386_UACCESS_H */
+--- linux-2.6.0-test6/include/asm-i386/unistd.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-i386/unistd.h 2003-10-05 00:33:24.000000000 -0700
+@@ -278,8 +278,9 @@
+ #define __NR_tgkill 270
+ #define __NR_utimes 271
+ #define __NR_fadvise64_64 272
++#define __NR_vserver 273
+
+-#define NR_syscalls 273
++#define NR_syscalls 274
+
+ /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
+
+--- linux-2.6.0-test6/include/asm-ia64/acpi.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ia64/acpi.h 2003-10-05 00:34:41.000000000 -0700
+@@ -99,7 +99,7 @@ int acpi_get_addr_space (void *obj, u8 t
+ /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
+ #define MAX_PXM_DOMAINS (256)
+ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+-extern int __initdata nid_to_pxm_map[NR_NODES];
++extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
+ #endif
+
+ #endif /*__KERNEL__*/
+--- linux-2.6.0-test6/include/asm-ia64/cacheflush.h 2003-06-14 12:18:00.000000000 -0700
++++ 25/include/asm-ia64/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -21,6 +21,8 @@
+ #define flush_cache_range(vma, start, end) do { } while (0)
+ #define flush_cache_page(vma, vmaddr) do { } while (0)
+ #define flush_icache_page(vma,page) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
+
+ #define flush_dcache_page(page) \
+ do { \
+@@ -35,4 +37,11 @@ do { \
+ flush_icache_range(_addr, _addr + (len)); \
+ } while (0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ #endif /* _ASM_IA64_CACHEFLUSH_H */
+--- linux-2.6.0-test6/include/asm-ia64/elf.h 2003-07-27 12:14:40.000000000 -0700
++++ 25/include/asm-ia64/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -206,42 +206,46 @@ do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR); \
+ } while (0)
+
++
+ /*
+- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out extra segments
+- * containing the gate DSO contents. Dumping its contents makes post-mortem fully
+- * interpretable later without matching up the same kernel and hardware config to see what
+- * IP values meant. Dumping its extra ELF program headers includes all the other
+- * information a debugger needs to easily find how the gate DSO was being used.
++ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
++ * extra segments containing the gate DSO contents. Dumping its
++ * contents makes post-mortem fully interpretable later without matching up
++ * the same kernel and hardware config to see what PC values meant.
++ * Dumping its extra ELF program headers includes all the other information
++ * a debugger needs to easily find how the gate DSO was being used.
+ */
+ #define ELF_CORE_EXTRA_PHDRS (GATE_EHDR->e_phnum)
+ #define ELF_CORE_WRITE_EXTRA_PHDRS \
+ do { \
+- const struct elf_phdr *const gate_phdrs = \
+- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
++ const struct elf_phdr *const vsyscall_phdrs = \
++ (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
+ int i; \
+- Elf64_Off ofs = 0; \
++ Elf32_Off ofs = 0; \
+ for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
+- struct elf_phdr phdr = gate_phdrs[i]; \
++ struct elf_phdr phdr = vsyscall_phdrs[i]; \
+ if (phdr.p_type == PT_LOAD) { \
++ BUG_ON(ofs != 0); \
+ ofs = phdr.p_offset = offset; \
++ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
++ phdr.p_filesz = phdr.p_memsz; \
+ offset += phdr.p_filesz; \
+- } else \
++ } \
++ else \
+ phdr.p_offset += ofs; \
+ phdr.p_paddr = 0; /* match other core phdrs */ \
+ DUMP_WRITE(&phdr, sizeof(phdr)); \
+ } \
+ } while (0)
+-
+ #define ELF_CORE_WRITE_EXTRA_DATA \
+ do { \
+- const struct elf_phdr *const gate_phdrs = \
+- (const struct elf_phdr *) (GATE_ADDR \
+- + GATE_EHDR->e_phoff); \
++ const struct elf_phdr *const vsyscall_phdrs = \
++ (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
+ int i; \
+ for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
+- if (gate_phdrs[i].p_type == PT_LOAD) \
+- DUMP_WRITE((void *) gate_phdrs[i].p_vaddr, \
+- gate_phdrs[i].p_filesz); \
++ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
++ DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
++ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \
+ } \
+ } while (0)
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-ia64/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,72 @@
++/*
++ * Copyright (C) 1999,2000 Silicon Graphics, Inc.
++ *
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.h by Jack Steiner (steiner@sgi.com)
++ */
++
++#ifndef _IA64_LOCKMETER_H
++#define _IA64_LOCKMETER_H
++
++#ifdef local_cpu_data
++#define CPU_CYCLE_FREQUENCY local_cpu_data->itc_freq
++#else
++#define CPU_CYCLE_FREQUENCY my_cpu_data.itc_freq
++#endif
++#define get_cycles64() get_cycles()
++
++#define THIS_CPU_NUMBER smp_processor_id()
++
++/*
++ * macros to cache and retrieve an index value inside of a lock
++ * these macros assume that there are less than 65536 simultaneous
++ * (read mode) holders of a rwlock.
++ * we also assume that the hash table has less than 32767 entries.
++ */
++/*
++ * instrumented spinlock structure -- never used to allocate storage
++ * only used in macros below to overlay a spinlock_t
++ */
++typedef struct inst_spinlock_s {
++ /* remember, Intel is little endian */
++ volatile unsigned short lock;
++ volatile unsigned short index;
++} inst_spinlock_t;
++#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv
++#define GET_INDEX(lock_ptr) ((inst_spinlock_t *)(lock_ptr))->index
++
++/*
++ * macros to cache and retrieve an index value in a read/write lock
++ * as well as the cpu where a reader busy period started
++ * we use the 2nd word (the debug word) for this, so require the
++ * debug word to be present
++ */
++/*
++ * instrumented rwlock structure -- never used to allocate storage
++ * only used in macros below to overlay a rwlock_t
++ */
++typedef struct inst_rwlock_s {
++ volatile int read_counter:31;
++ volatile int write_lock:1;
++ volatile unsigned short index;
++ volatile unsigned short cpu;
++} inst_rwlock_t;
++#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
++#define GET_RWINDEX(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->index
++#define PUT_RW_CPU(rwlock_ptr,cpuv) ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
++#define GET_RW_CPU(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->cpu
++
++/*
++ * return the number of readers for a rwlock_t
++ */
++#define RWLOCK_READERS(rwlock_ptr) ((rwlock_ptr)->read_counter)
++
++/*
++ * return true if rwlock is write locked
++ * (note that other lock attempts can cause the lock value to be negative)
++ */
++#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->write_lock)
++#define RWLOCK_IS_READ_LOCKED(rwlock_ptr) ((rwlock_ptr)->read_counter)
++
++#endif /* _IA64_LOCKMETER_H */
++
+--- linux-2.6.0-test6/include/asm-ia64/mmzone.h 2003-06-14 12:18:52.000000000 -0700
++++ 25/include/asm-ia64/mmzone.h 2003-10-05 00:34:41.000000000 -0700
+@@ -92,14 +92,12 @@
+ extern unsigned long max_low_pfn;
+
+
+-#ifdef CONFIG_IA64_DIG
++#if defined(CONFIG_IA64_DIG)
+
+ /*
+ * Platform definitions for DIG platform with contiguous memory.
+ */
+-#define MAX_PHYSNODE_ID 8 /* Maximum node number +1 */
+-#define NR_NODES 8 /* Maximum number of nodes in SSI */
+-
++#define MAX_PHYSNODE_ID 8 /* Maximum node number +1 */
+ #define MAX_PHYS_MEMORY (1UL << 40) /* 1 TB */
+
+ /*
+@@ -119,37 +117,34 @@ extern unsigned long max_low_pfn;
+ # error Unsupported bank and nodesize!
+ #endif
+ #define BANKSIZE (1UL << BANKSHIFT)
+-#define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1))
+-#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES)
+-
+-/*
+- * VALID_MEM_KADDR returns a boolean to indicate if a kaddr is
+- * potentially a valid cacheable identity mapped RAM memory address.
+- * Note that the RAM may or may not actually be present!!
+- */
+-#define VALID_MEM_KADDR(kaddr) 1
+-
+-/*
+- * Given a nodeid & a bank number, find the address of the mem_map
+- * entry for the first page of the bank.
+- */
+-#define BANK_MEM_MAP_INDEX(kaddr) \
+- (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
+
+ #elif defined(CONFIG_IA64_SGI_SN2)
++
+ /*
+ * SGI SN2 discontig definitions
+ */
+ #define MAX_PHYSNODE_ID 2048 /* 2048 node ids (also called nasid) */
+-#define NR_NODES 128 /* Maximum number of nodes in SSI */
+ #define MAX_PHYS_MEMORY (1UL << 49)
+
+-#define BANKSHIFT 38
+ #define NR_BANKS_PER_NODE 4
++#define BANKSHIFT 38
+ #define SN2_NODE_SIZE (64UL*1024*1024*1024) /* 64GB per node */
+ #define BANKSIZE (SN2_NODE_SIZE/NR_BANKS_PER_NODE)
++
++#endif /* CONFIG_IA64_DIG */
++
++#if defined(CONFIG_IA64_DIG) || defined (CONFIG_IA64_SGI_SN2)
++/* Common defines for both platforms */
++#include <asm/numnodes.h>
+ #define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1))
+-#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES)
++#define NR_BANKS (NR_BANKS_PER_NODE * (1 << NODES_SHIFT))
++#define NR_MEMBLKS (NR_BANKS)
++
++/*
++ * VALID_MEM_KADDR returns a boolean to indicate if a kaddr is
++ * potentially a valid cacheable identity mapped RAM memory address.
++ * Note that the RAM may or may not actually be present!!
++ */
+ #define VALID_MEM_KADDR(kaddr) 1
+
+ /*
+@@ -159,5 +154,6 @@ extern unsigned long max_low_pfn;
+ #define BANK_MEM_MAP_INDEX(kaddr) \
+ (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT)
+
+-#endif /* CONFIG_IA64_DIG */
++#endif /* CONFIG_IA64_DIG || CONFIG_IA64_SGI_SN2 */
++
+ #endif /* _ASM_IA64_MMZONE_H */
+--- linux-2.6.0-test6/include/asm-ia64/nodedata.h 2003-06-22 12:04:45.000000000 -0700
++++ 25/include/asm-ia64/nodedata.h 2003-10-05 00:34:41.000000000 -0700
+@@ -8,12 +8,10 @@
+ * Copyright (c) 2002 Erich Focht <efocht@ess.nec.de>
+ * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
+ */
+-
+-
+ #ifndef _ASM_IA64_NODEDATA_H
+ #define _ASM_IA64_NODEDATA_H
+
+-
++#include <linux/numa.h>
+ #include <asm/mmzone.h>
+
+ /*
+@@ -24,9 +22,9 @@ struct pglist_data;
+ struct ia64_node_data {
+ short active_cpu_count;
+ short node;
+- struct pglist_data *pg_data_ptrs[NR_NODES];
++ struct pglist_data *pg_data_ptrs[MAX_NUMNODES];
+ struct page *bank_mem_map_base[NR_BANKS];
+- struct ia64_node_data *node_data_ptrs[NR_NODES];
++ struct ia64_node_data *node_data_ptrs[MAX_NUMNODES];
+ short node_id_map[NR_BANKS];
+ };
+
+--- linux-2.6.0-test6/include/asm-ia64/numa.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ia64/numa.h 2003-10-05 00:34:41.000000000 -0700
+@@ -16,17 +16,11 @@
+
+ #ifdef CONFIG_NUMA
+
+-#ifdef CONFIG_DISCONTIGMEM
+-# include <asm/mmzone.h>
+-# define NR_MEMBLKS (NR_BANKS)
+-#else
+-# define NR_NODES (8)
+-# define NR_MEMBLKS (NR_NODES * 8)
+-#endif
+-
++#include <linux/numa.h>
+ #include <linux/cache.h>
++
+ extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+-extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned;
++extern volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+
+ /* Stuff below this line could be architecture independent */
+
+@@ -60,7 +54,7 @@ extern struct node_cpuid_s node_cpuid[NR
+ * proportional to the memory access latency ratios.
+ */
+
+-extern u8 numa_slit[NR_NODES * NR_NODES];
++extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
+ #define node_distance(from,to) (numa_slit[from * numnodes + to])
+
+ extern int paddr_to_nid(unsigned long paddr);
+--- linux-2.6.0-test6/include/asm-ia64/numnodes.h 2003-06-14 12:18:52.000000000 -0700
++++ 25/include/asm-ia64/numnodes.h 2003-10-05 00:34:41.000000000 -0700
+@@ -1,7 +1,12 @@
+ #ifndef _ASM_MAX_NUMNODES_H
+ #define _ASM_MAX_NUMNODES_H
+
+-#include <asm/mmzone.h>
+-#define MAX_NUMNODES NR_NODES
++#ifdef CONFIG_IA64_DIG
++/* Max 8 Nodes */
++#define NODES_SHIFT 3
++#elif defined(CONFIG_IA64_SGI_SN2)
++/* Max 128 Nodes */
++#define NODES_SHIFT 7
++#endif
+
+ #endif /* _ASM_MAX_NUMNODES_H */
+--- linux-2.6.0-test6/include/asm-ia64/pgtable.h 2003-06-22 12:04:45.000000000 -0700
++++ 25/include/asm-ia64/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -207,7 +207,6 @@ ia64_phys_addr_valid (unsigned long addr
+ #define RGN_KERNEL 7
+
+ #define VMALLOC_START 0xa000000200000000
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #ifdef CONFIG_VIRTUAL_MEM_MAP
+ # define VMALLOC_END_INIT (0xa000000000000000 + (1UL << (4*PAGE_SHIFT - 9)))
+ # define VMALLOC_END vmalloc_end
+--- linux-2.6.0-test6/include/asm-ia64/sn/pda.h 2003-06-22 12:04:45.000000000 -0700
++++ 25/include/asm-ia64/sn/pda.h 2003-10-05 00:34:41.000000000 -0700
+@@ -10,6 +10,7 @@
+
+ #include <linux/config.h>
+ #include <linux/cache.h>
++#include <linux/numa.h>
+ #include <asm/percpu.h>
+ #include <asm/system.h>
+ #include <asm/processor.h>
+@@ -56,7 +57,7 @@ typedef struct pda_s {
+
+ unsigned long sn_soft_irr[4];
+ unsigned long sn_in_service_ivecs[4];
+- short cnodeid_to_nasid_table[NR_NODES];
++ short cnodeid_to_nasid_table[MAX_NUMNODES];
+ int sn_lb_int_war_ticks;
+ int sn_last_irq;
+ int sn_first_irq;
+--- linux-2.6.0-test6/include/asm-ia64/spinlock.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ia64/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -110,8 +110,18 @@ do { \
+ typedef struct {
+ volatile int read_counter : 31;
+ volatile int write_lock : 1;
++#ifdef CONFIG_LOCKMETER
++ /* required for LOCKMETER since all bits in lock are used */
++ /* and we need this storage for CPU and lock INDEX */
++ unsigned lockmeter_magic;
++#endif
+ } rwlock_t;
++
++#ifdef CONFIG_LOCKMETER
++#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0 }
++#else
+ #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
++#endif
+
+ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+ #define rwlock_is_locked(x) (*(volatile int *) (x) != 0)
+@@ -127,6 +137,48 @@ do { \
+ } \
+ } while (0)
+
++#ifdef CONFIG_LOCKMETER
++/*
++ * HACK: This works, but still have a timing window that affects performance:
++ * we see that no one owns the Write lock, then someone * else grabs for Write
++ * lock before we do a read_lock().
++ * This means that on rare occasions our read_lock() will stall and spin-wait
++ * until we acquire for Read, instead of simply returning a trylock failure.
++ */
++static inline int _raw_read_trylock(rwlock_t *rw)
++{
++ if (rw->write_lock) {
++ return 0;
++ } else {
++ _raw_read_lock(rw);
++ return 1;
++ }
++}
++
++static inline int _raw_write_trylock(rwlock_t *rw)
++{
++ if (!(rw->write_lock)) {
++ /* isn't currently write-locked... that looks promising... */
++ if (test_and_set_bit(31, rw) == 0) {
++ /* now it is write-locked by me... */
++ if (rw->read_counter) {
++ /* really read-locked, so release write-lock and fail */
++ clear_bit(31, rw);
++ } else {
++ /* we've the the write-lock, no read-lockers... success! */
++ barrier();
++ return 1;
++ }
++
++ }
++ }
++
++ /* falls through ... fails to write-lock */
++ barrier();
++ return 0;
++}
++#endif
++
+ #define _raw_read_unlock(rw) \
+ do { \
+ rwlock_t *__read_lock_ptr = (rw); \
+@@ -190,4 +242,25 @@ do { \
+ clear_bit(31, (x)); \
+ })
+
++#ifdef CONFIG_LOCKMETER
++extern void _metered_spin_lock (spinlock_t *lock);
++extern void _metered_spin_unlock(spinlock_t *lock);
++
++/*
++ * Use a less efficient, and inline, atomic_dec_and_lock() if lockmetering
++ * so we can see the callerPC of who is actually doing the spin_lock().
++ * Otherwise, all we see is the generic rollup of all locks done by
++ * atomic_dec_and_lock().
++ */
++static inline int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
++{
++ _metered_spin_lock(lock);
++ if (atomic_dec_and_test(atomic))
++ return 1;
++ _metered_spin_unlock(lock);
++ return 0;
++}
++#define ATOMIC_DEC_AND_LOCK
++#endif
++
+ #endif /* _ASM_IA64_SPINLOCK_H */
+--- linux-2.6.0-test6/include/asm-m68k/bitops.h 2003-06-14 12:18:52.000000000 -0700
++++ 25/include/asm-m68k/bitops.h 2003-10-05 00:33:24.000000000 -0700
+@@ -164,9 +164,10 @@ extern __inline__ int test_bit(int nr, c
+ return ((1UL << (nr & 31)) & (((const volatile unsigned long *) vaddr)[nr >> 5])) != 0;
+ }
+
+-extern __inline__ int find_first_zero_bit(unsigned long * vaddr, unsigned size)
++extern __inline__ int find_first_zero_bit(const unsigned long *vaddr,
++ unsigned size)
+ {
+- unsigned long *p = vaddr, *addr = vaddr;
++ const unsigned long *p = vaddr, *addr = vaddr;
+ unsigned long allones = ~0UL;
+ int res;
+ unsigned long num;
+@@ -187,11 +188,11 @@ extern __inline__ int find_first_zero_bi
+ return ((p - addr) << 5) + (res ^ 31);
+ }
+
+-extern __inline__ int find_next_zero_bit (unsigned long *vaddr, int size,
++extern __inline__ int find_next_zero_bit (const unsigned long *vaddr, int size,
+ int offset)
+ {
+- unsigned long *addr = vaddr;
+- unsigned long *p = addr + (offset >> 5);
++ const unsigned long *addr = vaddr;
++ const unsigned long *p = addr + (offset >> 5);
+ int set = 0, bit = offset & 31UL, res;
+
+ if (offset >= size)
+@@ -263,7 +264,7 @@ static inline int fls(int x)
+ * unlikely to be set. It's guaranteed that at least one of the 140
+ * bits is cleared.
+ */
+-static inline int sched_find_first_bit(unsigned long *b)
++static inline int sched_find_first_bit(const unsigned long *b)
+ {
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+--- linux-2.6.0-test6/include/asm-m68k/cacheflush.h 2003-07-27 12:14:40.000000000 -0700
++++ 25/include/asm-m68k/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -80,6 +80,9 @@ extern void cache_push_v(unsigned long v
+
+ #define flush_cache_all() __flush_cache_all()
+
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
++
+ extern inline void flush_cache_mm(struct mm_struct *mm)
+ {
+ if (mm == current->mm)
+@@ -127,6 +130,10 @@ extern inline void __flush_page_to_ram(v
+ #define flush_dcache_page(page) __flush_page_to_ram(page_address(page))
+ #define flush_icache_page(vma, page) __flush_page_to_ram(page_address(page))
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ extern void flush_icache_range(unsigned long address, unsigned long endaddr);
+
+--- linux-2.6.0-test6/include/asm-m68knommu/cacheflush.h 2003-06-14 12:18:34.000000000 -0700
++++ 25/include/asm-m68knommu/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -15,7 +15,13 @@
+ #define flush_icache_range(start,len) __flush_cache_all()
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ extern inline void __flush_cache_all(void)
+ {
+--- linux-2.6.0-test6/include/asm-m68k/pci.h 2003-06-14 12:18:09.000000000 -0700
++++ 25/include/asm-m68k/pci.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,6 +7,8 @@
+ * Written by Wout Klaren.
+ */
+
++#include <asm/scatterlist.h>
++
+ struct pci_ops;
+
+ /*
+--- linux-2.6.0-test6/include/asm-m68k/pgtable.h 2003-06-14 12:18:32.000000000 -0700
++++ 25/include/asm-m68k/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -79,12 +79,10 @@
+ */
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END KMAP_START
+ #else
+ extern unsigned long vmalloc_end;
+ #define VMALLOC_START 0x0f800000
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END vmalloc_end
+ #endif /* CONFIG_SUN3 */
+
+--- linux-2.6.0-test6/include/asm-m68k/zorro.h 2003-06-14 12:18:03.000000000 -0700
++++ 25/include/asm-m68k/zorro.h 2003-10-05 00:33:24.000000000 -0700
+@@ -42,4 +42,4 @@ extern inline void *z_remap_fullcache(un
+ #define z_iounmap iounmap
+ #define z_ioremap z_remap_nocache_ser
+
+-#endif /* _ASM_ZORRO_H */
++#endif /* _ASM_M68K_ZORRO_H */
+--- linux-2.6.0-test6/include/asm-mips/cacheflush.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/include/asm-mips/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -43,7 +43,15 @@ extern void (*flush_icache_page)(struct
+ extern void (*flush_icache_range)(unsigned long start, unsigned long end);
+ #define flush_icache_user_range(vma, page, addr, len) \
+ flush_icache_page(vma, page)
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ extern void (*flush_cache_sigtramp)(unsigned long addr);
+ extern void (*flush_icache_all)(void);
+--- linux-2.6.0-test6/include/asm-mips/highmem.h 2003-07-02 14:53:17.000000000 -0700
++++ 25/include/asm-mips/highmem.h 2003-10-05 00:33:24.000000000 -0700
+@@ -54,6 +54,8 @@ extern void *kmap_atomic(struct page *pa
+ extern void kunmap_atomic(void *kvaddr, enum km_type type);
+ extern struct page *kmap_atomic_to_page(void *ptr);
+
++#define flush_cache_kmaps() flush_cache_all()
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_HIGHMEM_H */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-mips/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,126 @@
++/*
++ * Copyright (C) 1999,2000 Silicon Graphics, Inc.
++ *
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.h by Jack Steiner (steiner@sgi.com)
++ * Ported to mips32 for Asita Technologies
++ * by D.J. Barrow ( dj.barrow@asitatechnologies.com )
++ */
++#ifndef _ASM_LOCKMETER_H
++#define _ASM_LOCKMETER_H
++
++/* do_gettimeoffset is a function pointer on mips */
++/* & it is not included by <linux/time.h> */
++#include <asm/time.h>
++#include <linux/time.h>
++#include <asm/div64.h>
++
++#define SPINLOCK_MAGIC_INIT /* */
++
++#define CPU_CYCLE_FREQUENCY get_cpu_cycle_frequency()
++
++#define THIS_CPU_NUMBER smp_processor_id()
++
++static uint32_t cpu_cycle_frequency = 0;
++
++static uint32_t get_cpu_cycle_frequency(void)
++{
++ /* a total hack, slow and invasive, but ... it works */
++ int sec;
++ uint32_t start_cycles;
++ struct timeval tv;
++
++ if (cpu_cycle_frequency == 0) { /* uninitialized */
++ do_gettimeofday(&tv);
++ sec = tv.tv_sec; /* set up to catch the tv_sec rollover */
++ while (sec == tv.tv_sec) { do_gettimeofday(&tv); }
++ sec = tv.tv_sec; /* rolled over to a new sec value */
++ start_cycles = get_cycles();
++ while (sec == tv.tv_sec) { do_gettimeofday(&tv); }
++ cpu_cycle_frequency = get_cycles() - start_cycles;
++ }
++
++ return cpu_cycle_frequency;
++}
++
++extern struct timeval xtime;
++
++static uint64_t get_cycles64(void)
++{
++ static uint64_t last_get_cycles64 = 0;
++ uint64_t ret;
++ unsigned long sec;
++ unsigned long usec, usec_offset;
++
++again:
++ sec = xtime.tv_sec;
++ usec = xtime.tv_usec;
++ usec_offset = do_gettimeoffset();
++ if ((xtime.tv_sec != sec) ||
++ (xtime.tv_usec != usec)||
++ (usec_offset >= 20000))
++ goto again;
++
++ ret = ((uint64_t)(usec + usec_offset) * cpu_cycle_frequency);
++ /* We can't do a normal 64 bit division on mips without libgcc.a */
++ do_div(ret,1000000);
++ ret += ((uint64_t)sec * cpu_cycle_frequency);
++
++ /* XXX why does time go backwards? do_gettimeoffset? general time adj? */
++ if (ret <= last_get_cycles64)
++ ret = last_get_cycles64+1;
++ last_get_cycles64 = ret;
++
++ return ret;
++}
++
++/*
++ * macros to cache and retrieve an index value inside of a lock
++ * these macros assume that there are less than 65536 simultaneous
++ * (read mode) holders of a rwlock.
++ * we also assume that the hash table has less than 32767 entries.
++ * the high order bit is used for write locking a rw_lock
++ */
++#define INDEX_MASK 0x7FFF0000
++#define READERS_MASK 0x0000FFFF
++#define INDEX_SHIFT 16
++#define PUT_INDEX(lockp,index) \
++ lockp->lock = (((lockp->lock) & ~INDEX_MASK) | (index) << INDEX_SHIFT)
++#define GET_INDEX(lockp) \
++ (((lockp->lock) & INDEX_MASK) >> INDEX_SHIFT)
++
++/*
++ * macros to cache and retrieve an index value in a read/write lock
++ * as well as the cpu where a reader busy period started
++ * we use the 2nd word (the debug word) for this, so require the
++ * debug word to be present
++ */
++/*
++ * instrumented rwlock structure -- never used to allocate storage
++ * only used in macros below to overlay a rwlock_t
++ */
++typedef struct inst_rwlock_s {
++ volatile int lock;
++ unsigned short index;
++ unsigned short cpu;
++} inst_rwlock_t;
++#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv
++#define GET_RWINDEX(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->index
++#define PUT_RW_CPU(rwlock_ptr,cpuv) ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv
++#define GET_RW_CPU(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->cpu
++
++/*
++ * return the number of readers for a rwlock_t
++ */
++#define RWLOCK_READERS(rwlock_ptr) rwlock_readers(rwlock_ptr)
++
++extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
++{
++ int tmp = (int) rwlock_ptr->lock;
++ return (tmp >= 0) ? tmp : 0;
++}
++
++#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((rwlock_ptr)->lock < 0)
++#define RWLOCK_IS_READ_LOCKED(rwlock_ptr) ((rwlock_ptr)->lock > 0)
++
++#endif /* _ASM_LOCKMETER_H */
+--- linux-2.6.0-test6/include/asm-mips/pgtable-32.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/include/asm-mips/pgtable-32.h 2003-10-05 00:33:24.000000000 -0700
+@@ -79,7 +79,6 @@ extern int add_temporary_entry(unsigned
+ #define FIRST_USER_PGD_NR 0
+
+ #define VMALLOC_START KSEG2
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+ #if CONFIG_HIGHMEM
+ # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
+--- linux-2.6.0-test6/include/asm-mips/pgtable-64.h 2003-08-08 22:55:13.000000000 -0700
++++ 25/include/asm-mips/pgtable-64.h 2003-10-05 00:33:24.000000000 -0700
+@@ -64,7 +64,6 @@
+ #define FIRST_USER_PGD_NR 0
+
+ #define VMALLOC_START XKSEG
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END \
+ (VMALLOC_START + ((1 << PGD_ORDER) * PTRS_PER_PTE * PAGE_SIZE))
+
+--- linux-2.6.0-test6/include/asm-mips/spinlock.h 2003-07-02 14:53:17.000000000 -0700
++++ 25/include/asm-mips/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -91,9 +91,18 @@ static inline unsigned int _raw_spin_try
+
+ typedef struct {
+ volatile unsigned int lock;
++#ifdef CONFIG_LOCKMETER
++ /* required for LOCKMETER since all bits in lock are used */
++ /* and we need this storage for CPU and lock INDEX */
++ unsigned lockmeter_magic;
++#endif
+ } rwlock_t;
+
++#ifdef CONFIG_LOCKMETER
++#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
++#else
+ #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
++#endif
+
+ #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+--- linux-2.6.0-test6/include/asm-parisc/atomic.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-parisc/atomic.h 2003-10-05 00:33:24.000000000 -0700
+@@ -129,8 +129,9 @@ __cmpxchg(volatile void *ptr, unsigned l
+
+
+ /* It's possible to reduce all atomic operations to either
+- * __atomic_add_return, __atomic_set and __atomic_ret (the latter
+- * is there only for consistency). */
++ * __atomic_add_return, atomic_set and atomic_read (the latter
++ * is there only for consistency).
++ */
+
+ static __inline__ int __atomic_add_return(int i, atomic_t *v)
+ {
+@@ -144,7 +145,7 @@ static __inline__ int __atomic_add_retur
+ return ret;
+ }
+
+-static __inline__ void __atomic_set(atomic_t *v, int i)
++static __inline__ void atomic_set(atomic_t *v, int i)
+ {
+ unsigned long flags;
+ SPIN_LOCK_IRQSAVE(ATOMIC_HASH(v), flags);
+@@ -154,28 +155,25 @@ static __inline__ void __atomic_set(atom
+ SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(v), flags);
+ }
+
+-static __inline__ int __atomic_read(atomic_t *v)
++static __inline__ int atomic_read(const atomic_t *v)
+ {
+ return v->counter;
+ }
+
+ /* exported interface */
+
+-#define atomic_add(i,v) ((void)(__atomic_add_return( (i),(v))))
+-#define atomic_sub(i,v) ((void)(__atomic_add_return(-(i),(v))))
+-#define atomic_inc(v) ((void)(__atomic_add_return( 1,(v))))
+-#define atomic_dec(v) ((void)(__atomic_add_return( -1,(v))))
++#define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v))))
++#define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v))))
++#define atomic_inc(v) ((void)(__atomic_add_return( 1,(v))))
++#define atomic_dec(v) ((void)(__atomic_add_return( -1,(v))))
+
+-#define atomic_add_return(i,v) (__atomic_add_return( (i),(v)))
+-#define atomic_sub_return(i,v) (__atomic_add_return(-(i),(v)))
++#define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v)))
++#define atomic_sub_return(i,v) (__atomic_add_return(-((int)i),(v)))
+ #define atomic_inc_return(v) (__atomic_add_return( 1,(v)))
+ #define atomic_dec_return(v) (__atomic_add_return( -1,(v)))
+
+ #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+
+-#define atomic_set(v,i) (__atomic_set((v),i))
+-#define atomic_read(v) (__atomic_read(v))
+-
+ #define ATOMIC_INIT(i) { (i) }
+
+ #define smp_mb__before_atomic_dec() smp_mb()
+--- linux-2.6.0-test6/include/asm-parisc/bitops.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-parisc/bitops.h 2003-10-05 00:33:24.000000000 -0700
+@@ -232,24 +232,24 @@ static __inline__ unsigned long __ffs(un
+ #if BITS_PER_LONG > 32
+ " ldi 63,%1\n"
+ " extrd,u,*<> %0,63,32,%%r0\n"
+- " extrd,u,*TR %0,31,32,%0\n"
++ " extrd,u,*TR %0,31,32,%0\n" /* move top 32-bits down */
+ " addi -32,%1,%1\n"
+ #else
+ " ldi 31,%1\n"
+ #endif
+ " extru,<> %0,31,16,%%r0\n"
+- " extru,TR %0,15,16,%0\n"
++ " extru,TR %0,15,16,%0\n" /* xxxx0000 -> 0000xxxx */
+ " addi -16,%1,%1\n"
+ " extru,<> %0,31,8,%%r0\n"
+- " extru,TR %0,23,8,%0\n"
++ " extru,TR %0,23,8,%0\n" /* 0000xx00 -> 000000xx */
+ " addi -8,%1,%1\n"
+ " extru,<> %0,31,4,%%r0\n"
+- " extru,TR %0,27,4,%0\n"
++ " extru,TR %0,27,4,%0\n" /* 000000x0 -> 0000000x */
+ " addi -4,%1,%1\n"
+ " extru,<> %0,31,2,%%r0\n"
+- " extru,TR %0,29,2,%0\n"
++ " extru,TR %0,29,2,%0\n" /* 0000000y, 1100b -> 0011b */
+ " addi -2,%1,%1\n"
+- " extru,= %0,31,1,%%r0\n"
++ " extru,= %0,31,1,%%r0\n" /* check last bit */
+ " addi -1,%1,%1\n"
+ : "+r" (x), "=r" (ret) );
+ return ret;
+@@ -291,7 +291,7 @@ static __inline__ int fls(int x)
+ " zdep,TR %0,27,28,%0\n" /* x0000000 */
+ " addi 4,%1,%1\n"
+ " extru,<> %0,1,2,%%r0\n"
+- " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0 */
++ " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0) */
+ " addi 2,%1,%1\n"
+ " extru,= %0,0,1,%%r0\n"
+ " addi 1,%1,%1\n" /* if y & 8, add 1 */
+--- linux-2.6.0-test6/include/asm-parisc/cacheflush.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-parisc/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -30,6 +30,9 @@ static inline void flush_cache_all(void)
+ on_each_cpu(cacheflush_h_tmp_function, NULL, 1, 1);
+ }
+
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
++
+ /* The following value needs to be tuned and probably scaled with the
+ * cache size.
+ */
+@@ -82,6 +85,13 @@ static inline void flush_dcache_page(str
+ flush_user_dcache_range(addr, addr + len); \
+ flush_user_icache_range(addr, addr + len); } while (0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ static inline void flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+ {
+--- linux-2.6.0-test6/include/asm-parisc/dma-mapping.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/asm-parisc/dma-mapping.h 2003-10-05 00:33:24.000000000 -0700
+@@ -2,6 +2,7 @@
+ #define _PARISC_DMA_MAPPING_H
+
+ #include <linux/mm.h>
++#include <linux/config.h>
+ #include <asm/cacheflush.h>
+
+ /*
+--- linux-2.6.0-test6/include/asm-parisc/elf.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-parisc/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -144,6 +144,30 @@
+ #define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
+ #define R_PARISC_HIRESERVE 255
+
++#define PA_PLABEL_FDESC 0x02 /* bit set if PLABEL points to
++ * a function descriptor, not
++ * an address */
++
++/* The following are PA function descriptors
++ *
++ * addr: the absolute address of the function
++ * gp: either the data pointer (r27) for non-PIC code or the
++ * the PLT pointer (r19) for PIC code */
++
++/* Format for the Elf32 Function descriptor */
++typedef struct elf32_fdesc {
++ __u32 addr;
++ __u32 gp;
++} Elf32_Fdesc;
++
++/* Format for the Elf64 Function descriptor */
++typedef struct elf64_fdesc {
++ __u64 dummy[2]; /* FIXME: nothing uses these, why waste
++ * the space */
++ __u64 addr;
++ __u64 gp;
++} Elf64_Fdesc;
++
+ /* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
+
+ #define PT_HP_TLS (PT_LOOS + 0x0)
+@@ -215,7 +239,10 @@ typedef unsigned long elf_greg_t;
+
+ #ifdef __KERNEL__
+ #define SET_PERSONALITY(ex, ibcs2) \
+- current->personality = PER_LINUX
++ current->personality = PER_LINUX; \
++ current->thread.map_base = DEFAULT_MAP_BASE; \
++ current->thread.task_size = DEFAULT_TASK_SIZE \
++
+ #endif
+
+ /*
+--- linux-2.6.0-test6/include/asm-parisc/ioctl.h 2003-06-14 12:17:55.000000000 -0700
++++ 25/include/asm-parisc/ioctl.h 2003-10-05 00:33:24.000000000 -0700
+@@ -44,11 +44,21 @@
+ ((nr) << _IOC_NRSHIFT) | \
+ ((size) << _IOC_SIZESHIFT))
+
++/* provoke compile error for invalid uses of size argument */
++extern int __invalid_size_argument_for_IOC;
++#define _IOC_TYPECHECK(t) \
++ ((sizeof(t) == sizeof(t[1]) && \
++ sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
++ sizeof(t) : __invalid_size_argument_for_IOC)
++
+ /* used to create numbers */
+ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
+-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
+-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
++#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
++#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
++#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
++#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
++#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
++#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+ /* used to decode ioctl numbers.. */
+ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+--- linux-2.6.0-test6/include/asm-parisc/irq.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/asm-parisc/irq.h 2003-10-05 00:33:24.000000000 -0700
+@@ -17,6 +17,7 @@
+
+ #include <linux/string.h>
+ #include <linux/interrupt.h>
++#include <linux/config.h>
+
+
+ #define CPU_IRQ_REGION 1
+--- linux-2.6.0-test6/include/asm-parisc/keyboard.h 2003-06-14 12:18:04.000000000 -0700
++++ 25/include/asm-parisc/keyboard.h 2003-10-05 00:33:24.000000000 -0700
+@@ -25,8 +25,6 @@
+ #ifndef _PARISC_KEYBOARD_H
+ #define _PARISC_KEYBOARD_H
+
+-#include <linux/config.h>
+-
+ #ifdef __KERNEL__
+
+ #include <linux/kernel.h>
+--- linux-2.6.0-test6/include/asm-parisc/page.h 2003-06-14 12:18:00.000000000 -0700
++++ 25/include/asm-parisc/page.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,6 +7,7 @@
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+
+ #ifdef __KERNEL__
++#include <linux/config.h>
+ #ifndef __ASSEMBLY__
+
+ #include <asm/cache.h>
+--- linux-2.6.0-test6/include/asm-parisc/param.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/include/asm-parisc/param.h 2003-10-05 00:33:24.000000000 -0700
+@@ -2,6 +2,7 @@
+ #define _ASMPARISC_PARAM_H
+
+ #ifdef __KERNEL__
++#include <linux/config.h>
+ # ifdef CONFIG_PA20
+ # define HZ 1000 /* Faster machines */
+ # else
+--- linux-2.6.0-test6/include/asm-parisc/pci.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-parisc/pci.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,6 +1,7 @@
+ #ifndef __ASM_PARISC_PCI_H
+ #define __ASM_PARISC_PCI_H
+
++#include <linux/config.h>
+ #include <asm/scatterlist.h>
+
+ /*
+--- linux-2.6.0-test6/include/asm-parisc/pdc.h 2003-06-14 12:17:55.000000000 -0700
++++ 25/include/asm-parisc/pdc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,6 +1,8 @@
+ #ifndef _PARISC_PDC_H
+ #define _PARISC_PDC_H
+
++#include <linux/config.h>
++
+ /*
+ * PDC return values ...
+ * All PDC calls return a subset of these errors.
+@@ -191,8 +193,8 @@ typedef struct {
+
+ #define PDC_IO 135 /* log error info, reset IO system */
+ #define PDC_IO_READ_AND_CLEAR_ERRORS 0
+-#define PDC_IO_READ_AND_LOG_ERRORS 1
+-#define PDC_IO_SUSPEND_USB 2
++#define PDC_IO_RESET 1
++#define PDC_IO_RESET_DEVICES 2
+ /* sets bits 6&7 (little endian) of the HcControl Register */
+ #define PDC_IO_USB_SUSPEND 0xC000000000000000
+ #define PDC_IO_EEPROM_IO_ERR_TABLE_FULL -5 /* return value */
+@@ -951,7 +953,8 @@ int pdc_do_firm_test_reset(unsigned long
+ int pdc_do_reset(void);
+ int pdc_soft_power_info(unsigned long *power_reg);
+ int pdc_soft_power_button(int sw_control);
+-void pdc_suspend_usb(void);
++void pdc_io_reset(void);
++void pdc_io_reset_devices(void);
+ int pdc_iodc_getc(void);
+ void pdc_iodc_putc(unsigned char c);
+ void pdc_iodc_outc(unsigned char c);
+--- linux-2.6.0-test6/include/asm-parisc/pgalloc.h 2003-06-14 12:18:35.000000000 -0700
++++ 25/include/asm-parisc/pgalloc.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,7 +1,6 @@
+ #ifndef _ASM_PGALLOC_H
+ #define _ASM_PGALLOC_H
+
+-#include <linux/config.h>
+ #include <linux/gfp.h>
+ #include <linux/mm.h>
+ #include <linux/threads.h>
+--- linux-2.6.0-test6/include/asm-parisc/pgtable.h 2003-07-13 21:44:35.000000000 -0700
++++ 25/include/asm-parisc/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -1,6 +1,7 @@
+ #ifndef _PARISC_PGTABLE_H
+ #define _PARISC_PGTABLE_H
+
++#include <linux/config.h>
+ #include <asm/fixmap.h>
+
+ #ifndef __ASSEMBLY__
+@@ -108,7 +109,6 @@
+ extern void *vmalloc_start;
+ #define PCXL_DMA_MAP_SIZE (8*1024*1024)
+ #define VMALLOC_START ((unsigned long)vmalloc_start)
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ /* this is a fixmap remnant, see fixmap.h */
+ #define VMALLOC_END (TMPALIAS_MAP_START)
+ #endif
+--- linux-2.6.0-test6/include/asm-parisc/processor.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-parisc/processor.h 2003-10-05 00:33:24.000000000 -0700
+@@ -36,10 +36,18 @@
+ #define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; })
+
+ #define TASK_SIZE (current->thread.task_size)
+-#define DEFAULT_TASK_SIZE (0xFFF00000UL)
+-
+ #define TASK_UNMAPPED_BASE (current->thread.map_base)
+-#define DEFAULT_MAP_BASE (0x40000000UL)
++
++#define DEFAULT_TASK_SIZE32 (0xFFF00000UL)
++#define DEFAULT_MAP_BASE32 (0x40000000UL)
++
++#ifdef __LP64__
++#define DEFAULT_TASK_SIZE (MAX_ADDRESS-0xf000000)
++#define DEFAULT_MAP_BASE (0x200000000UL)
++#else
++#define DEFAULT_TASK_SIZE DEFAULT_TASK_SIZE32
++#define DEFAULT_MAP_BASE DEFAULT_MAP_BASE32
++#endif
+
+ #ifndef __ASSEMBLY__
+
+@@ -247,8 +255,18 @@ on downward growing arches, it looks lik
+ *
+ * Note that the S/390 people took the easy way out and hacked their
+ * GCC to make the stack grow downwards.
++ *
++ * Final Note: For entry from syscall, the W (wide) bit of the PSW
++ * is stuffed into the lowest bit of the user sp (%r30), so we fill
++ * it in here from the current->personality
+ */
+
++#ifdef __LP64__
++#define USER_WIDE_MODE (personality(current->personality) == PER_LINUX)
++#else
++#define USER_WIDE_MODE 0
++#endif
++
+ #define start_thread(regs, new_pc, new_sp) do { \
+ elf_addr_t *sp = (elf_addr_t *)new_sp; \
+ __u32 spaceid = (__u32)current->mm->context; \
+@@ -266,12 +284,12 @@ on downward growing arches, it looks lik
+ regs->sr[5] = spaceid; \
+ regs->sr[6] = spaceid; \
+ regs->sr[7] = spaceid; \
+- regs->gr[ 0] = USER_PSW; \
++ regs->gr[ 0] = USER_PSW | (USER_WIDE_MODE ? PSW_W : 0); \
+ regs->fr[ 0] = 0LL; \
+ regs->fr[ 1] = 0LL; \
+ regs->fr[ 2] = 0LL; \
+ regs->fr[ 3] = 0LL; \
+- regs->gr[30] = ((unsigned long)sp + 63) &~ 63; \
++ regs->gr[30] = (((unsigned long)sp + 63) &~ 63) | (USER_WIDE_MODE ? 1 : 0); \
+ regs->gr[31] = pc; \
+ \
+ get_user(regs->gr[25], (argv - 1)); \
+@@ -299,8 +317,6 @@ static inline unsigned long get_wchan(st
+ #define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0])
+ #define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30])
+
+-#endif /* __ASSEMBLY__ */
+-
+ #ifdef CONFIG_PA20
+ #define ARCH_HAS_PREFETCH
+ extern inline void prefetch(const void *addr)
+@@ -317,4 +333,6 @@ extern inline void prefetchw(const void
+
+ #define cpu_relax() barrier()
+
++#endif /* __ASSEMBLY__ */
++
+ #endif /* __ASM_PARISC_PROCESSOR_H */
+--- linux-2.6.0-test6/include/asm-parisc/rt_sigframe.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/include/asm-parisc/rt_sigframe.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,7 +13,20 @@ struct rt_sigframe {
+ * which Linux/parisc uses is sp-20 for the saved return pointer...)
+ * Then, the stack pointer must be rounded to a cache line (64 bytes).
+ */
++#define SIGFRAME32 64
++#define FUNCTIONCALLFRAME32 48
++#define PARISC_RT_SIGFRAME_SIZE32 \
++ (((sizeof(struct rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32)
++
++#ifdef __LP64__
++#define SIGFRAME 128
++#define FUNCTIONCALLFRAME 96
+ #define PARISC_RT_SIGFRAME_SIZE \
+- (((sizeof(struct rt_sigframe) + 48) + 63) & -64)
++ (((sizeof(struct rt_sigframe) + FUNCTIONCALLFRAME) + SIGFRAME) & -SIGFRAME)
++#else
++#define SIGFRAME SIGFRAME32
++#define FUNCTIONCALLFRAME FUNCTIONCALLFRAME32
++#define PARISC_RT_SIGFRAME_SIZE PARISC_RT_SIGFRAME_SIZE32
++#endif
+
+ #endif
+--- linux-2.6.0-test6/include/asm-parisc/tlbflush.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-parisc/tlbflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -3,6 +3,7 @@
+
+ /* TLB flushing routines.... */
+
++#include <linux/config.h>
+ #include <linux/mm.h>
+ #include <asm/mmu_context.h>
+
+--- linux-2.6.0-test6/include/asm-ppc64/cacheflush.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-ppc64/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -14,12 +14,22 @@
+ #define flush_cache_range(vma, start, end) do { } while (0)
+ #define flush_cache_page(vma, vmaddr) do { } while (0)
+ #define flush_icache_page(vma, page) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
+
+ extern void flush_dcache_page(struct page *page);
+ extern void flush_icache_range(unsigned long, unsigned long);
+ extern void flush_icache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long addr,
+ int len);
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ extern void __flush_dcache_icache(void *page_va);
+
+ #endif /* _PPC64_CACHEFLUSH_H */
+--- linux-2.6.0-test6/include/asm-ppc64/elf.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-ppc64/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -128,11 +128,6 @@ static inline int dump_task_regs(struct
+ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
+ #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+
+-#ifdef CONFIG_SMP
+-extern void dump_smp_unlazy_fpu(void);
+-#define ELF_CORE_SYNC dump_smp_unlazy_fpu
+-#endif
+-
+ #endif
+
+ /* This yields a mask that user programs can use to figure out what
+--- linux-2.6.0-test6/include/asm-ppc64/numnodes.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/include/asm-ppc64/numnodes.h 2003-10-05 00:34:38.000000000 -0700
+@@ -1,6 +1,7 @@
+ #ifndef _ASM_MAX_NUMNODES_H
+ #define _ASM_MAX_NUMNODES_H
+
+-#define MAX_NUMNODES 16
++/* Max 16 Nodes */
++#define NODES_SHIFT 4
+
+ #endif /* _ASM_MAX_NUMNODES_H */
+--- linux-2.6.0-test6/include/asm-ppc64/pgtable.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ppc64/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -45,7 +45,6 @@
+ * Define the address range of the vmalloc VM area.
+ */
+ #define VMALLOC_START (0xD000000000000000)
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END (VMALLOC_START + VALID_EA_BITS)
+
+ /*
+--- linux-2.6.0-test6/include/asm-ppc64/semaphore.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ppc64/semaphore.h 2003-10-05 00:34:19.000000000 -0700
+@@ -22,6 +22,7 @@ struct semaphore {
+ * sleeping on `wait'.
+ */
+ atomic_t count;
++ int sleepers;
+ wait_queue_head_t wait;
+ #ifdef WAITQUEUE_DEBUG
+ long __magic;
+@@ -37,6 +38,7 @@ struct semaphore {
+
+ #define __SEMAPHORE_INITIALIZER(name, count) \
+ { ATOMIC_INIT(count), \
++ 0, \
+ __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+ __SEM_DEBUG_INIT(name) }
+
+@@ -52,6 +54,7 @@ struct semaphore {
+ static inline void sema_init (struct semaphore *sem, int val)
+ {
+ atomic_set(&sem->count, val);
++ sem->sleepers = 0;
+ init_waitqueue_head(&sem->wait);
+ #ifdef WAITQUEUE_DEBUG
+ sem->__magic = (long)&sem->__magic;
+--- linux-2.6.0-test6/include/asm-ppc/cacheflush.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-ppc/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -24,12 +24,21 @@
+ #define flush_cache_range(vma, a, b) do { } while (0)
+ #define flush_cache_page(vma, p) do { } while (0)
+ #define flush_icache_page(vma, page) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
+
+ extern void flush_dcache_page(struct page *page);
+ extern void flush_icache_range(unsigned long, unsigned long);
+ extern void flush_icache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long addr, int len);
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ extern void __flush_dcache_icache(void *page_va);
+ extern void __flush_dcache_icache_phys(unsigned long physaddr);
+
+--- linux-2.6.0-test6/include/asm-ppc/highmem.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ppc/highmem.h 2003-10-05 00:33:24.000000000 -0700
+@@ -132,6 +132,8 @@ static inline struct page *kmap_atomic_t
+ return pte_page(kmap_pte[idx]);
+ }
+
++#define flush_cache_kmaps() flush_cache_all()
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_HIGHMEM_H */
+--- linux-2.6.0-test6/include/asm-ppc/pgtable.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/asm-ppc/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -129,7 +129,6 @@ extern unsigned long ioremap_bot, iorema
+ #else
+ #define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
+ #endif
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END ioremap_bot
+
+ /*
+--- linux-2.6.0-test6/include/asm-ppc/zorro.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/include/asm-ppc/zorro.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,4 +27,4 @@ extern void *__ioremap(unsigned long add
+ #define z_ioremap ioremap
+ #define z_iounmap iounmap
+
+-#endif /* _ASM_ZORRO_H */
++#endif /* _ASM_PPC_ZORRO_H */
+--- linux-2.6.0-test6/include/asm-s390/cacheflush.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-s390/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,5 +13,12 @@
+ #define flush_icache_range(start, end) do { } while (0)
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ #endif /* _S390_CACHEFLUSH_H */
+--- linux-2.6.0-test6/include/asm-s390/pgtable.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/include/asm-s390/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -117,7 +117,6 @@ extern char empty_zero_page[PAGE_SIZE];
+ #define VMALLOC_OFFSET (8*1024*1024)
+ #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
+ & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #ifndef __s390x__
+ # define VMALLOC_END (0x7fffffffL)
+ #else /* __s390x__ */
+--- linux-2.6.0-test6/include/asm-sh/cacheflush.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/asm-sh/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -10,4 +10,14 @@ extern void __flush_purge_region(void *s
+ /* Flush (invalidate only) a region (smaller than a page) */
+ extern void __flush_invalidate_region(void *start, int size);
+
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ #endif /* __ASM_SH_CACHEFLUSH_H */
+--- linux-2.6.0-test6/include/asm-sh/mmzone.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/asm-sh/mmzone.h 2003-10-05 00:34:40.000000000 -0700
+@@ -10,14 +10,14 @@
+
+ #include <linux/config.h>
+
++#ifdef CONFIG_DISCONTIGMEM
++
+ /* Currently, just for HP690 */
+ #define PHYSADDR_TO_NID(phys) ((((phys) - __MEMORY_START) >= 0x01000000)?1:0)
+-#define NR_NODES 2
+
+-extern pg_data_t discontig_page_data[NR_NODES];
+-extern bootmem_data_t discontig_node_bdata[NR_NODES];
++extern pg_data_t discontig_page_data[MAX_NUMNODES];
++extern bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
+
+-#ifdef CONFIG_DISCONTIGMEM
+ /*
+ * Following are macros that each numa implmentation must define.
+ */
+@@ -46,7 +46,7 @@ static inline int is_valid_page(struct p
+ {
+ unsigned int i;
+
+- for (i = 0; i < NR_NODES; i++) {
++ for (i = 0; i < MAX_NUMNODES; i++) {
+ if (page >= NODE_MEM_MAP(i) &&
+ page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size)
+ return 1;
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-sh/numnodes.h 2003-10-05 00:34:40.000000000 -0700
+@@ -0,0 +1,7 @@
++#ifndef _ASM_MAX_NUMNODES_H
++#define _ASM_MAX_NUMNODES_H
++
++/* Max 2 Nodes */
++#define NODES_SHIFT 1
++
++#endif /* _ASM_MAX_NUMNODES_H */
+--- linux-2.6.0-test6/include/asm-sh/pgtable.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/asm-sh/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -51,7 +51,6 @@ extern unsigned long empty_zero_page[102
+ * Currently only 4-enty (16kB) is used (see arch/sh/mm/cache.c)
+ */
+ #define VMALLOC_START (P3SEG+0x00100000)
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END P4SEG
+
+ /* 0x001 WT-bit on SH-4, 0 on SH-3 */
+--- linux-2.6.0-test6/include/asm-sparc64/cacheflush.h 2003-06-14 12:18:35.000000000 -0700
++++ 25/include/asm-sparc64/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -33,21 +33,17 @@ extern void flush_dcache_page_all(struct
+
+ extern void __flush_dcache_range(unsigned long start, unsigned long end);
+
+-extern void __flush_cache_all(void);
+-
+-#ifndef CONFIG_SMP
+-
+-#define flush_cache_all() __flush_cache_all()
+-
+-#else /* CONFIG_SMP */
+-
+-extern void smp_flush_cache_all(void);
+-
+-#endif /* ! CONFIG_SMP */
+-
+ #define flush_icache_page(vma, pg) do { } while(0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ extern void flush_dcache_page(struct page *page);
+
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
++
+ #endif /* _SPARC64_CACHEFLUSH_H */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-sparc64/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
++ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
++ */
++
++#ifndef _SPARC64_LOCKMETER_H
++#define _SPARC64_LOCKMETER_H
++
++#include <linux/smp.h>
++#include <asm/spinlock.h>
++#include <asm/timer.h>
++#include <asm/timex.h>
++
++/* Actually, this is not the CPU frequency by the system tick
++ * frequency which is good enough for lock metering.
++ */
++#define CPU_CYCLE_FREQUENCY (timer_tick_offset * HZ)
++#define THIS_CPU_NUMBER smp_processor_id()
++
++#define PUT_INDEX(lock_ptr,indexv) (lock_ptr)->index = (indexv)
++#define GET_INDEX(lock_ptr) (lock_ptr)->index
++
++#define PUT_RWINDEX(rwlock_ptr,indexv) (rwlock_ptr)->index = (indexv)
++#define GET_RWINDEX(rwlock_ptr) (rwlock_ptr)->index
++#define PUT_RW_CPU(rwlock_ptr,cpuv) (rwlock_ptr)->cpu = (cpuv)
++#define GET_RW_CPU(rwlock_ptr) (rwlock_ptr)->cpu
++
++#define RWLOCK_READERS(rwlock_ptr) rwlock_readers(rwlock_ptr)
++
++extern inline int rwlock_readers(rwlock_t *rwlock_ptr)
++{
++ signed int tmp = rwlock_ptr->lock;
++
++ if (tmp > 0)
++ return tmp;
++ else
++ return 0;
++}
++
++#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((signed int)((rwlock_ptr)->lock) < 0)
++#define RWLOCK_IS_READ_LOCKED(rwlock_ptr) ((signed int)((rwlock_ptr)->lock) > 0)
++
++#define get_cycles64() get_cycles()
++
++#endif /* _SPARC64_LOCKMETER_H */
+--- linux-2.6.0-test6/include/asm-sparc64/pgtable.h 2003-06-14 12:17:56.000000000 -0700
++++ 25/include/asm-sparc64/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -30,7 +30,6 @@
+ #define MODULES_LEN 0x000000007e000000
+ #define MODULES_END 0x0000000080000000
+ #define VMALLOC_START 0x0000000140000000
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define VMALLOC_END 0x0000000200000000
+ #define LOW_OBP_ADDRESS 0x00000000f0000000
+ #define HI_OBP_ADDRESS 0x0000000100000000
+--- linux-2.6.0-test6/include/asm-sparc64/spinlock.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/asm-sparc64/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -30,15 +30,23 @@
+
+ #ifndef CONFIG_DEBUG_SPINLOCK
+
+-typedef unsigned char spinlock_t;
+-#define SPIN_LOCK_UNLOCKED 0
++typedef struct {
++ unsigned char lock;
++ unsigned int index;
++} spinlock_t;
+
+-#define spin_lock_init(lock) (*((unsigned char *)(lock)) = 0)
+-#define spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
++#ifdef CONFIG_LOCKMETER
++#define SPIN_LOCK_UNLOCKED (spinlock_t) {0, 0}
++#else
++#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
++#endif
+
+-#define spin_unlock_wait(lock) \
++#define spin_lock_init(__lock) do { *(__lock) = SPIN_LOCK_UNLOCKED; } while(0)
++#define spin_is_locked(__lock) (*((volatile unsigned char *)(&((__lock)->lock))) != 0)
++
++#define spin_unlock_wait(__lock) \
+ do { membar("#LoadLoad"); \
+-} while(*((volatile unsigned char *)lock))
++} while(*((volatile unsigned char *)(&(((spinlock_t *)__lock)->lock))))
+
+ static __inline__ void _raw_spin_lock(spinlock_t *lock)
+ {
+@@ -109,18 +117,34 @@ extern int _spin_trylock (spinlock_t *lo
+
+ #ifndef CONFIG_DEBUG_SPINLOCK
+
+-typedef unsigned int rwlock_t;
+-#define RW_LOCK_UNLOCKED 0
+-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
+-#define rwlock_is_locked(x) (*(x) != RW_LOCK_UNLOCKED)
++#ifdef CONFIG_LOCKMETER
++typedef struct {
++ unsigned int lock;
++ unsigned int index;
++ unsigned int cpu;
++} rwlock_t;
++#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff }
++#else
++typedef struct {
++ unsigned int lock;
++} rwlock_t;
++#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
++#endif
++
++#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
++#define rwlock_is_locked(x) ((x)->lock != 0)
+
++extern int __read_trylock(rwlock_t *);
+ extern void __read_lock(rwlock_t *);
+ extern void __read_unlock(rwlock_t *);
++extern int __write_trylock(rwlock_t *);
+ extern void __write_lock(rwlock_t *);
+ extern void __write_unlock(rwlock_t *);
+
++#define _raw_read_trylock(p) __read_trylock(p)
+ #define _raw_read_lock(p) __read_lock(p)
+ #define _raw_read_unlock(p) __read_unlock(p)
++#define _raw_write_trylock(p) __write_trylock(p)
+ #define _raw_write_lock(p) __write_lock(p)
+ #define _raw_write_unlock(p) __write_unlock(p)
+
+--- linux-2.6.0-test6/include/asm-sparc64/tlbflush.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/asm-sparc64/tlbflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -70,7 +70,6 @@ extern void smp_flush_tlb_range(struct m
+ extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+ extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
+
+-#define flush_cache_all() smp_flush_cache_all()
+ #define flush_tlb_all() smp_flush_tlb_all()
+ #define flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
+ #define flush_tlb_range(vma, start, end) \
+--- linux-2.6.0-test6/include/asm-sparc64/unistd.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/asm-sparc64/unistd.h 2003-10-05 00:33:24.000000000 -0700
+@@ -285,7 +285,8 @@
+ #define __NR_timer_getoverrun 264
+ #define __NR_timer_delete 265
+ #define __NR_timer_create 266
+-/* WARNING: You MAY NOT add syscall numbers larger than 266, since
++/* #define __NR_vserver 267 Reserved for VSERVER */
++/* WARNING: You MAY NOT add syscall numbers larger than 267, since
+ * all of the syscall tables in the Sparc kernel are
+ * sized to have 267 entries (starting at zero). Therefore
+ * find a free slot in the 0-266 range.
+--- linux-2.6.0-test6/include/asm-sparc64/visasm.h 2003-06-14 12:17:58.000000000 -0700
++++ 25/include/asm-sparc64/visasm.h 2003-10-05 00:33:24.000000000 -0700
+@@ -17,7 +17,8 @@
+ andcc %o5, (FPRS_FEF|FPRS_DU), %g0; \
+ be,pt %icc, 297f; \
+ sethi %hi(297f), %g7; \
+- ba,pt %xcc, VISenter; \
++ sethi %hi(VISenter), %g1; \
++ jmpl %g1 + %lo(VISenter), %g0; \
+ or %g7, %lo(297f), %g7; \
+ 297: wr %g0, FPRS_FEF, %fprs; \
+
+@@ -32,7 +33,8 @@
+ andcc %o5, FPRS_FEF, %g0; \
+ be,pt %icc, 297f; \
+ sethi %hi(298f), %g7; \
+- ba,pt %xcc, VISenterhalf; \
++ sethi %hi(VISenterhalf), %g1; \
++ jmpl %g1 + %lo(VISenterhalf), %g0; \
+ or %g7, %lo(298f), %g7; \
+ clr %o5; \
+ 297: wr %o5, FPRS_FEF, %fprs; \
+@@ -48,7 +50,8 @@ static __inline__ void save_and_clear_fp
+ " andcc %%o5, %0, %%g0\n"
+ " be,pt %%icc, 299f\n"
+ " sethi %%hi(298f), %%g7\n"
+-" ba VISenter ! Note. This cannot be bp, as it may be too far from VISenter.\n"
++" sethi %%hi(VISenter), %%g1\n"
++" jmpl %%g1 + %%lo(VISenter), %%g0\n"
+ " or %%g7, %%lo(298f), %%g7\n"
+ " 298: wr %%g0, 0, %%fprs\n"
+ " 299:\n"
+--- linux-2.6.0-test6/include/asm-sparc/cacheflush.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/include/asm-sparc/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -56,6 +56,11 @@ BTFIXUPDEF_CALL(void, flush_cache_page,
+
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++
+ BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
+ BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
+
+@@ -66,4 +71,7 @@ extern void sparc_flush_page_to_ram(stru
+
+ #define flush_dcache_page(page) sparc_flush_page_to_ram(page)
+
++#define flush_cache_vmap(start, end) flush_cache_all()
++#define flush_cache_vunmap(start, end) flush_cache_all()
++
+ #endif /* _SPARC_CACHEFLUSH_H */
+--- linux-2.6.0-test6/include/asm-sparc/highmem.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-sparc/highmem.h 2003-10-05 00:33:24.000000000 -0700
+@@ -89,6 +89,8 @@ static inline struct page *kmap_atomic_t
+ return pte_page(*pte);
+ }
+
++#define flush_cache_kmaps() flush_cache_all()
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _ASM_HIGHMEM_H */
+--- linux-2.6.0-test6/include/asm-sparc/pgtable.h 2003-06-14 12:18:22.000000000 -0700
++++ 25/include/asm-sparc/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -101,8 +101,6 @@ BTFIXUPDEF_SIMM13(ptrs_per_pmd)
+ BTFIXUPDEF_SIMM13(ptrs_per_pgd)
+ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
+
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+-
+ #define pte_ERROR(e) __builtin_trap()
+ #define pmd_ERROR(e) __builtin_trap()
+ #define pgd_ERROR(e) __builtin_trap()
+--- linux-2.6.0-test6/include/asm-sparc/unistd.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/asm-sparc/unistd.h 2003-10-05 00:33:24.000000000 -0700
+@@ -283,7 +283,8 @@
+ #define __NR_timer_getoverrun 264
+ #define __NR_timer_delete 265
+ #define __NR_timer_create 266
+-/* WARNING: You MAY NOT add syscall numbers larger than 266, since
++/* #define __NR_vserver 267 Reserved for VSERVER */
++/* WARNING: You MAY NOT add syscall numbers larger than 267, since
+ * all of the syscall tables in the Sparc kernel are
+ * sized to have 267 entries (starting at zero). Therefore
+ * find a free slot in the 0-266 range.
+--- linux-2.6.0-test6/include/asm-um/archparam-i386.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/include/asm-um/archparam-i386.h 2003-10-05 00:34:32.000000000 -0700
+@@ -56,6 +56,65 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
+ pr_reg[16] = PT_REGS_SS(regs); \
+ } while(0);
+
++#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
++#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
++#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
++extern void *__kernel_vsyscall;
++
++/*
++ * Architecture-neutral AT_ values in 0-17, leave some room
++ * for more of them, start the x86-specific ones at 32.
++ */
++#define AT_SYSINFO 32
++#define AT_SYSINFO_EHDR 33
++
++#define ARCH_DLINFO \
++do { \
++ NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \
++ NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \
++} while (0)
++
++/*
++ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
++ * extra segments containing the vsyscall DSO contents. Dumping its
++ * contents makes post-mortem fully interpretable later without matching up
++ * the same kernel and hardware config to see what PC values meant.
++ * Dumping its extra ELF program headers includes all the other information
++ * a debugger needs to easily find how the vsyscall DSO was being used.
++ */
++#define ELF_CORE_EXTRA_PHDRS (VSYSCALL_EHDR->e_phnum)
++#define ELF_CORE_WRITE_EXTRA_PHDRS \
++do { \
++ const struct elf_phdr *const vsyscall_phdrs = \
++ (const struct elf_phdr *) (VSYSCALL_BASE \
++ + VSYSCALL_EHDR->e_phoff); \
++ int i; \
++ Elf32_Off ofs = 0; \
++ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
++ struct elf_phdr phdr = vsyscall_phdrs[i]; \
++ if (phdr.p_type == PT_LOAD) { \
++ ofs = phdr.p_offset = offset; \
++ offset += phdr.p_filesz; \
++ } \
++ else \
++ phdr.p_offset += ofs; \
++ phdr.p_paddr = 0; /* match other core phdrs */ \
++ DUMP_WRITE(&phdr, sizeof(phdr)); \
++ } \
++} while (0)
++#define ELF_CORE_WRITE_EXTRA_DATA \
++do { \
++ const struct elf_phdr *const vsyscall_phdrs = \
++ (const struct elf_phdr *) (VSYSCALL_BASE \
++ + VSYSCALL_EHDR->e_phoff); \
++ int i; \
++ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
++ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
++ DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
++ vsyscall_phdrs[i].p_filesz); \
++ } \
++} while (0)
++
+ /********* Bits for asm-um/delay.h **********/
+
+ typedef unsigned long um_udelay_t;
+--- linux-2.6.0-test6/include/asm-um/common.lds.S 2003-06-14 12:18:00.000000000 -0700
++++ 25/include/asm-um/common.lds.S 2003-10-05 00:34:32.000000000 -0700
+@@ -1,3 +1,5 @@
++#include <asm-generic/vmlinux.lds.h>
++
+ .fini : { *(.fini) } =0x9090
+ _etext = .;
+ PROVIDE (etext = .);
+@@ -67,6 +69,10 @@
+ }
+ __initcall_end = .;
+
++ __con_initcall_start = .;
++ .con_initcall.init : { *(.con_initcall.init) }
++ __con_initcall_end = .;
++
+ __uml_initcall_start = .;
+ .uml.initcall.init : { *(.uml.initcall.init) }
+ __uml_initcall_end = .;
+@@ -80,7 +86,33 @@
+ .uml.exitcall : { *(.uml.exitcall.exit) }
+ __uml_exitcall_end = .;
+
+- . = ALIGN(4096);
++ . = ALIGN(4);
++ __alt_instructions = .;
++ .altinstructions : { *(.altinstructions) }
++ __alt_instructions_end = .;
++ .altinstr_replacement : { *(.altinstr_replacement) }
++ /* .exit.text is discard at runtime, not link time, to deal with references
++ from .altinstructions and .eh_frame */
++ .exit.text : { *(.exit.text) }
++ .exit.data : { *(.exit.data) }
++
++ __preinit_array_start = .;
++ .preinit_array : { *(.preinit_array) }
++ __preinit_array_end = .;
++ __init_array_start = .;
++ .init_array : { *(.init_array) }
++ __init_array_end = .;
++ __fini_array_start = .;
++ .fini_array : { *(.fini_array) }
++ __fini_array_end = .;
++
++ . = ALIGN(4096);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
++
++ /* Sections to be discarded */
++ /DISCARD/ : {
++ *(.exitcall.exit)
++ }
++
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-um/cpufeature.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,6 @@
++#ifndef __UM_CPUFEATURE_H
++#define __UM_CPUFEATURE_H
++
++#include "asm/arch/cpufeature.h"
++
++#endif
+--- linux-2.6.0-test6/include/asm-um/current.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-um/current.h 2003-10-05 00:34:32.000000000 -0700
+@@ -16,8 +16,10 @@ struct thread_info;
+ #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
+ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
+
+-#define current ({ int dummy; \
+- ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
++#define current_thread \
++ ({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
++
++#define current (current_thread->task)
+
+ #endif /* __ASSEMBLY__ */
+
+--- linux-2.6.0-test6/include/asm-um/fixmap.h 2003-06-14 12:18:33.000000000 -0700
++++ 25/include/asm-um/fixmap.h 2003-10-05 00:34:32.000000000 -0700
+@@ -34,6 +34,7 @@ enum fixed_addresses {
+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ #endif
++ FIX_VSYSCALL,
+ __end_of_fixed_addresses
+ };
+
+@@ -63,6 +64,13 @@ extern unsigned long get_kmem_end(void);
+ #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+ #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+
++/*
++ * This is the range that is readable by user mode, and things
++ * acting like user mode such as get_user_pages.
++ */
++#define FIXADDR_USER_START (__fix_to_virt(FIX_VSYSCALL))
++#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
++
+ extern void __this_fixmap_does_not_exist(void);
+
+ /*
+--- linux-2.6.0-test6/include/asm-um/irq.h 2003-06-14 12:18:49.000000000 -0700
++++ 25/include/asm-um/irq.h 2003-10-05 00:34:32.000000000 -0700
+@@ -1,15 +1,6 @@
+ #ifndef __UM_IRQ_H
+ #define __UM_IRQ_H
+
+-/* The i386 irq.h has a struct task_struct in a prototype without including
+- * sched.h. This forward declaration kills the resulting warning.
+- */
+-struct task_struct;
+-
+-#include "asm/ptrace.h"
+-
+-#undef NR_IRQS
+-
+ #define TIMER_IRQ 0
+ #define UMN_IRQ 1
+ #define CONSOLE_IRQ 2
+@@ -28,8 +19,4 @@ struct task_struct;
+ #define LAST_IRQ XTERM_IRQ
+ #define NR_IRQS (LAST_IRQ + 1)
+
+-extern int um_request_irq(unsigned int irq, int fd, int type,
+- void (*handler)(int, void *, struct pt_regs *),
+- unsigned long irqflags, const char * devname,
+- void *dev_id);
+ #endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-um/local.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,6 @@
++#ifndef __UM_LOCAL_H
++#define __UM_LOCAL_H
++
++#include "asm/arch/local.h"
++
++#endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-um/module-generic.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,6 @@
++#ifndef __UM_MODULE_GENERIC_H
++#define __UM_MODULE_GENERIC_H
++
++#include "asm/arch/module.h"
++
++#endif
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-um/module-i386.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,13 @@
++#ifndef __UM_MODULE_I386_H
++#define __UM_MODULE_I386_H
++
++/* UML is simple */
++struct mod_arch_specific
++{
++};
++
++#define Elf_Shdr Elf32_Shdr
++#define Elf_Sym Elf32_Sym
++#define Elf_Ehdr Elf32_Ehdr
++
++#endif
+--- linux-2.6.0-test6/include/asm-um/page.h 2003-06-14 12:18:23.000000000 -0700
++++ 25/include/asm-um/page.h 2003-10-05 00:34:32.000000000 -0700
+@@ -4,7 +4,6 @@
+ struct page;
+
+ #include "asm/arch/page.h"
+-#include "asm/bug.h"
+
+ #undef __pa
+ #undef __va
+--- linux-2.6.0-test6/include/asm-um/pgtable.h 2003-06-14 12:18:52.000000000 -0700
++++ 25/include/asm-um/pgtable.h 2003-10-05 00:34:32.000000000 -0700
+@@ -69,7 +69,6 @@ extern unsigned long high_physmem;
+
+ #define VMALLOC_OFFSET (__va_space)
+ #define VMALLOC_START (((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
+ #ifdef CONFIG_HIGHMEM
+ # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
+@@ -79,12 +78,13 @@ extern unsigned long high_physmem;
+
+ #define _PAGE_PRESENT 0x001
+ #define _PAGE_NEWPAGE 0x002
+-#define _PAGE_PROTNONE 0x004 /* If not present */
+-#define _PAGE_RW 0x008
+-#define _PAGE_USER 0x010
+-#define _PAGE_ACCESSED 0x020
+-#define _PAGE_DIRTY 0x040
+-#define _PAGE_NEWPROT 0x080
++#define _PAGE_NEWPROT 0x004
++#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */
++#define _PAGE_PROTNONE 0x010 /* If not present */
++#define _PAGE_RW 0x020
++#define _PAGE_USER 0x040
++#define _PAGE_ACCESSED 0x080
++#define _PAGE_DIRTY 0x100
+
+ #define REGION_MASK 0xf0000000
+ #define REGION_SHIFT 28
+@@ -203,6 +203,16 @@ extern unsigned long pfn_to_phys(unsigne
+ #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
+ #define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
++/*
++ * Bits 0 through 3 are taken
++ */
++#define PTE_FILE_MAX_BITS 28
++
++#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
++
++#define pgoff_to_pte(off) \
++ ((pte_t) { ((off) << 4) + _PAGE_FILE })
++
+ static inline pte_t pte_mknewprot(pte_t pte)
+ {
+ pte_val(pte) |= _PAGE_NEWPROT;
+@@ -236,6 +246,12 @@ static inline void set_pte(pte_t *pteptr
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
++static inline int pte_user(pte_t pte)
++{
++ return((pte_val(pte) & _PAGE_USER) &&
++ !(pte_val(pte) & _PAGE_PROTNONE));
++}
++
+ static inline int pte_read(pte_t pte)
+ {
+ return((pte_val(pte) & _PAGE_USER) &&
+@@ -253,6 +269,14 @@ static inline int pte_write(pte_t pte)
+ !(pte_val(pte) & _PAGE_PROTNONE));
+ }
+
++/*
++ * The following only works if pte_present() is not true.
++ */
++static inline int pte_file(pte_t pte)
++{
++ return (pte).pte_low & _PAGE_FILE;
++}
++
+ static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+ static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
+@@ -355,14 +379,26 @@ static inline pte_t pte_modify(pte_t pte
+ #define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
+ ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
+
+-/* to find an entry in a page-table-directory. */
++/*
++ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
++ *
++ * this macro returns the index of the entry in the pgd page which would
++ * control the given virtual address
++ */
+ #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+-/* to find an entry in a page-table-directory */
++/*
++ * pgd_offset() returns a (pgd_t *)
++ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
++ */
+ #define pgd_offset(mm, address) \
+ ((mm)->pgd + ((address) >> PGDIR_SHIFT))
+
+-/* to find an entry in a kernel page-table-directory */
++
++/*
++ * a shortcut which implies the use of the kernel's pgd, instead
++ * of a process's
++ */
+ #define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+ #define pmd_index(address) \
+@@ -374,7 +410,12 @@ static inline pmd_t * pmd_offset(pgd_t *
+ return (pmd_t *) dir;
+ }
+
+-/* Find an entry in the third-level page table.. */
++/*
++ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
++ *
++ * this macro returns the index of the entry in the pte page which would
++ * control the given virtual address
++ */
+ #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset_kernel(dir, address) \
+ ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address))
+@@ -400,11 +441,11 @@ typedef pte_t *pte_addr_t;
+ #define update_mmu_cache(vma,address,pte) do ; while (0)
+
+ /* Encode and de-code a swap entry */
+-#define __swp_type(x) (((x).val >> 3) & 0x7f)
+-#define __swp_offset(x) ((x).val >> 10)
++#define __swp_type(x) (((x).val >> 4) & 0x3f)
++#define __swp_offset(x) ((x).val >> 11)
+
+ #define __swp_entry(type, offset) \
+- ((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
++ ((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
+ #define __pte_to_swp_entry(pte) \
+ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
+ #define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+--- linux-2.6.0-test6/include/asm-um/processor-generic.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/include/asm-um/processor-generic.h 2003-10-05 00:34:32.000000000 -0700
+@@ -11,9 +11,7 @@ struct pt_regs;
+ struct task_struct;
+
+ #include "linux/config.h"
+-#include "linux/signal.h"
+ #include "asm/ptrace.h"
+-#include "asm/siginfo.h"
+ #include "choose-mode.h"
+
+ struct mm_struct;
+@@ -101,14 +99,19 @@ typedef struct {
+ } mm_segment_t;
+
+ extern struct task_struct *alloc_task_struct(void);
+-extern void free_task_struct(struct task_struct *task);
+
+ extern void release_thread(struct task_struct *);
+ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+ extern void dump_thread(struct pt_regs *regs, struct user *u);
++extern void prepare_to_copy(struct task_struct *tsk);
+
+ extern unsigned long thread_saved_pc(struct task_struct *t);
+
++static inline void mm_copy_segments(struct mm_struct *from_mm,
++ struct mm_struct *new_mm)
++{
++}
++
+ #define init_stack (init_thread_union.stack)
+
+ /*
+--- linux-2.6.0-test6/include/asm-um/processor-i386.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/asm-um/processor-i386.h 2003-10-05 00:34:32.000000000 -0700
+@@ -6,8 +6,8 @@
+ #ifndef __UM_PROCESSOR_I386_H
+ #define __UM_PROCESSOR_I386_H
+
+-extern int cpu_has_xmm;
+-extern int cpu_has_cmov;
++extern int host_has_xmm;
++extern int host_has_cmov;
+
+ struct arch_thread {
+ unsigned long debugregs[8];
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/asm-um/sections.h 2003-10-05 00:34:32.000000000 -0700
+@@ -0,0 +1,7 @@
++#ifndef _UM_SECTIONS_H
++#define _UM_SECTIONS_H
++
++/* nothing to see, move along */
++#include <asm-generic/sections.h>
++
++#endif
+--- linux-2.6.0-test6/include/asm-um/smp.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/asm-um/smp.h 2003-10-05 00:34:32.000000000 -0700
+@@ -10,7 +10,7 @@
+
+ extern cpumask_t cpu_online_map;
+
+-#define smp_processor_id() (current->thread_info->cpu)
++#define smp_processor_id() (current_thread->cpu)
+ #define cpu_logical_map(n) (n)
+ #define cpu_number_map(n) (n)
+ #define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */
+--- linux-2.6.0-test6/include/asm-um/system-generic.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/asm-um/system-generic.h 2003-10-05 00:34:32.000000000 -0700
+@@ -23,8 +23,10 @@ extern int get_signals(void);
+ extern void block_signals(void);
+ extern void unblock_signals(void);
+
+-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
+-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
++#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
++ (flags) = get_signals(); } while(0)
++#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
++ set_signals(flags); } while(0)
+
+ #define local_irq_save(flags) do { local_save_flags(flags); \
+ local_irq_disable(); } while(0)
+@@ -39,4 +41,7 @@ extern void unblock_signals(void);
+ (flags == 0); \
+ })
+
++extern void *_switch_to(void *prev, void *next, void *last);
++#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
++
+ #endif
+--- linux-2.6.0-test6/include/asm-um/thread_info.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/include/asm-um/thread_info.h 2003-10-05 00:34:32.000000000 -0700
+@@ -9,6 +9,7 @@
+ #ifndef __ASSEMBLY__
+
+ #include <asm/processor.h>
++#include <asm/types.h>
+
+ struct thread_info {
+ struct task_struct *task; /* main task structure */
+@@ -43,15 +44,18 @@ struct thread_info {
+ static inline struct thread_info *current_thread_info(void)
+ {
+ struct thread_info *ti;
+- __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
++ unsigned long mask = PAGE_SIZE *
++ (1 << CONFIG_KERNEL_STACK_ORDER) - 1;
++ __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
+ return ti;
+ }
+
+ /* thread information allocation */
+-#define THREAD_SIZE (4*PAGE_SIZE)
+-#define alloc_thread_info(tsk) ((struct thread_info *) \
+- __get_free_pages(GFP_KERNEL,2))
+-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
++#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
++#define alloc_thread_info(tsk) \
++ ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
++#define free_thread_info(ti) kfree(ti)
++
+ #define get_thread_info(ti) get_task_struct((ti)->task)
+ #define put_thread_info(ti) put_task_struct((ti)->task)
+
+@@ -65,11 +69,13 @@ static inline struct thread_info *curren
+ #define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
+ * TIF_NEED_RESCHED
+ */
++#define TIF_RESTART_BLOCK 4
+
+ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
+ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+ #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
++#define _TIF_RESTART_BLOCK (1 << TIF_RESTART_BLOCK)
+
+ #endif
+
+--- linux-2.6.0-test6/include/asm-um/timex.h 2003-06-14 12:18:24.000000000 -0700
++++ 25/include/asm-um/timex.h 2003-10-05 00:34:32.000000000 -0700
+@@ -1,8 +1,6 @@
+ #ifndef __UM_TIMEX_H
+ #define __UM_TIMEX_H
+
+-#include "linux/time.h"
+-
+ typedef unsigned long cycles_t;
+
+ #define cacheflush_time (0)
+--- linux-2.6.0-test6/include/asm-v850/cacheflush.h 2003-07-27 12:14:40.000000000 -0700
++++ 25/include/asm-v850/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -27,6 +27,8 @@
+ #define flush_cache_range(vma, start, end) ((void)0)
+ #define flush_cache_page(vma, vmaddr) ((void)0)
+ #define flush_dcache_page(page) ((void)0)
++#define flush_cache_vmap(start, end) ((void)0)
++#define flush_cache_vunmap(start, end) ((void)0)
+
+ #ifdef CONFIG_NO_CACHE
+
+@@ -55,5 +57,11 @@ extern void flush_cache_sigtramp (unsign
+
+ #endif /* CONFIG_NO_CACHE */
+
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++do { memcpy(dst, src, len); \
++ flush_icache_user_range(vma, page, vaddr, len); \
++} while (0)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ #endif /* __V850_CACHEFLUSH_H__ */
+--- linux-2.6.0-test6/include/asm-x86_64/cacheflush.h 2003-06-14 12:17:59.000000000 -0700
++++ 25/include/asm-x86_64/cacheflush.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,6 +13,13 @@
+ #define flush_icache_range(start, end) do { } while (0)
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
++#define flush_cache_vmap(start, end) do { } while (0)
++#define flush_cache_vunmap(start, end) do { } while (0)
++
++#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
++#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
++ memcpy(dst, src, len)
+
+ void global_flush_tlb(void);
+ int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+--- linux-2.6.0-test6/include/asm-x86_64/elf.h 2003-06-14 12:18:30.000000000 -0700
++++ 25/include/asm-x86_64/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -150,11 +150,6 @@ extern int dump_task_fpu (struct task_st
+ #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+ #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
+
+-#ifdef CONFIG_SMP
+-extern void dump_smp_unlazy_fpu(void);
+-#define ELF_CORE_SYNC dump_smp_unlazy_fpu
+-#endif
+-
+ #endif
+
+ #endif
+--- linux-2.6.0-test6/include/asm-x86_64/mmzone.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/asm-x86_64/mmzone.h 2003-10-05 00:34:38.000000000 -0700
+@@ -10,7 +10,6 @@
+
+ #define VIRTUAL_BUG_ON(x)
+
+-#include <asm/numnodes.h>
+ #include <asm/smp.h>
+
+ #define MAXNODE 8
+--- linux-2.6.0-test6/include/asm-x86_64/numnodes.h 2003-06-14 12:18:08.000000000 -0700
++++ 25/include/asm-x86_64/numnodes.h 2003-10-05 00:34:38.000000000 -0700
+@@ -3,10 +3,7 @@
+
+ #include <linux/config.h>
+
+-#ifdef CONFIG_DISCONTIGMEM
+-#define MAX_NUMNODES 8 /* APIC limit currently */
+-#else
+-#define MAX_NUMNODES 1
+-#endif
++/* Max 8 Nodes - APIC limit currently */
++#define NODES_SHIFT 3
+
+ #endif
+--- linux-2.6.0-test6/include/asm-x86_64/pgtable.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/asm-x86_64/pgtable.h 2003-10-05 00:33:24.000000000 -0700
+@@ -126,7 +126,6 @@ static inline void set_pml4(pml4_t *dst,
+ #ifndef __ASSEMBLY__
+ #define VMALLOC_START 0xffffff0000000000
+ #define VMALLOC_END 0xffffff7fffffffff
+-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #define MODULES_VADDR 0xffffffffa0000000
+ #define MODULES_END 0xffffffffafffffff
+ #define MODULES_LEN (MODULES_END - MODULES_VADDR)
+--- linux-2.6.0-test6/include/linux/acpi.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/acpi.h 2003-10-05 00:33:24.000000000 -0700
+@@ -424,17 +424,17 @@ int ec_write(u8 addr, u8 val);
+
+ #endif /*CONFIG_ACPI_EC*/
+
+-#ifdef CONFIG_ACPI
++#ifdef CONFIG_ACPI_INTERPRETER
+
+ int acpi_blacklisted(void);
+
+-#else
++#else /*!CONFIG_ACPI_INTERPRETER*/
+
+ static inline int acpi_blacklisted(void)
+ {
+ return 0;
+ }
+
+-#endif /*CONFIG_ACPI*/
++#endif /*!CONFIG_ACPI_INTERPRETER*/
+
+ #endif /*_LINUX_ACPI_H*/
+--- linux-2.6.0-test6/include/linux/aio.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/linux/aio.h 2003-10-05 00:37:05.000000000 -0700
+@@ -29,21 +29,26 @@ struct kioctx;
+ #define KIF_LOCKED 0
+ #define KIF_KICKED 1
+ #define KIF_CANCELLED 2
++#define KIF_SYNCED 3
+
+ #define kiocbTryLock(iocb) test_and_set_bit(KIF_LOCKED, &(iocb)->ki_flags)
+ #define kiocbTryKick(iocb) test_and_set_bit(KIF_KICKED, &(iocb)->ki_flags)
++#define kiocbTrySync(iocb) test_and_set_bit(KIF_SYNCED, &(iocb)->ki_flags)
+
+ #define kiocbSetLocked(iocb) set_bit(KIF_LOCKED, &(iocb)->ki_flags)
+ #define kiocbSetKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags)
+ #define kiocbSetCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
++#define kiocbSetSynced(iocb) set_bit(KIF_SYNCED, &(iocb)->ki_flags)
+
+ #define kiocbClearLocked(iocb) clear_bit(KIF_LOCKED, &(iocb)->ki_flags)
+ #define kiocbClearKicked(iocb) clear_bit(KIF_KICKED, &(iocb)->ki_flags)
+ #define kiocbClearCancelled(iocb) clear_bit(KIF_CANCELLED, &(iocb)->ki_flags)
++#define kiocbClearSynced(iocb) clear_bit(KIF_SYNCED, &(iocb)->ki_flags)
+
+ #define kiocbIsLocked(iocb) test_bit(KIF_LOCKED, &(iocb)->ki_flags)
+ #define kiocbIsKicked(iocb) test_bit(KIF_KICKED, &(iocb)->ki_flags)
+ #define kiocbIsCancelled(iocb) test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
++#define kiocbIsSynced(iocb) test_bit(KIF_SYNCED, &(iocb)->ki_flags)
+
+ struct kiocb {
+ struct list_head ki_run_list;
+@@ -54,7 +59,7 @@ struct kiocb {
+ struct file *ki_filp;
+ struct kioctx *ki_ctx; /* may be NULL for sync ops */
+ int (*ki_cancel)(struct kiocb *, struct io_event *);
+- long (*ki_retry)(struct kiocb *);
++ ssize_t (*ki_retry)(struct kiocb *);
+
+ struct list_head ki_list; /* the aio core uses this
+ * for cancellation */
+@@ -63,6 +68,16 @@ struct kiocb {
+ __u64 ki_user_data; /* user's data for completion */
+ loff_t ki_pos;
+
++ /* State that we remember to be able to restart/retry */
++ unsigned short ki_opcode;
++ size_t ki_nbytes; /* copy of iocb->aio_nbytes */
++ char *ki_buf; /* remaining iocb->aio_buf */
++ size_t ki_left; /* remaining bytes */
++ wait_queue_t ki_wait;
++ long ki_retried; /* just for testing */
++ long ki_kicked; /* just for testing */
++ long ki_queued; /* just for testing */
++
+ char private[KIOCB_PRIVATE_SIZE];
+ };
+
+@@ -77,6 +92,8 @@ struct kiocb {
+ (x)->ki_ctx = &tsk->active_mm->default_kioctx; \
+ (x)->ki_cancel = NULL; \
+ (x)->ki_user_obj = tsk; \
++ (x)->ki_user_data = 0; \
++ init_wait((&(x)->ki_wait)); \
+ } while (0)
+
+ #define AIO_RING_MAGIC 0xa10a10a1
+@@ -159,6 +176,17 @@ int FASTCALL(io_submit_one(struct kioctx
+ #define get_ioctx(kioctx) do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0)
+ #define put_ioctx(kioctx) do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0)
+
++#define in_aio() !is_sync_wait(current->io_wait)
++/* may be used for debugging */
++#define warn_if_async() if (in_aio()) {\
++ printk(KERN_ERR "%s(%s:%d) called in async context!\n", \
++ __FUNCTION__, __FILE__, __LINE__); \
++ dump_stack(); \
++ }
++
++#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
++#define is_retried_kiocb(iocb) ((iocb)->ki_retried > 1)
++
+ #include <linux/aio_abi.h>
+
+ static inline struct kiocb *list_kiocb(struct list_head *h)
+--- linux-2.6.0-test6/include/linux/blkdev.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/blkdev.h 2003-10-05 00:36:58.000000000 -0700
+@@ -585,6 +585,7 @@ extern void blk_queue_free_tags(request_
+ extern int blk_queue_resize_tags(request_queue_t *, int);
+ extern void blk_queue_invalidate_tags(request_queue_t *);
+ extern void blk_congestion_wait(int rw, long timeout);
++extern int blk_congestion_wait_wq(int rw, long timeout, wait_queue_t *wait);
+
+ extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
+ extern void blk_rq_prep_restart(struct request *);
+--- linux-2.6.0-test6/include/linux/buffer_head.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/buffer_head.h 2003-10-05 00:37:00.000000000 -0700
+@@ -162,6 +162,7 @@ void mark_buffer_async_write(struct buff
+ void invalidate_bdev(struct block_device *, int);
+ int sync_blockdev(struct block_device *bdev);
+ void __wait_on_buffer(struct buffer_head *);
++int __wait_on_buffer_wq(struct buffer_head *, wait_queue_t *wait);
+ wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
+ void wake_up_buffer(struct buffer_head *bh);
+ int fsync_bdev(struct block_device *);
+@@ -173,6 +174,8 @@ void __brelse(struct buffer_head *);
+ void __bforget(struct buffer_head *);
+ void __breadahead(struct block_device *, sector_t block, int size);
+ struct buffer_head *__bread(struct block_device *, sector_t block, int size);
++struct buffer_head *__bread_wq(struct block_device *, sector_t block,
++ int size, wait_queue_t *wait);
+ struct buffer_head *alloc_buffer_head(int gfp_flags);
+ void free_buffer_head(struct buffer_head * bh);
+ void FASTCALL(unlock_buffer(struct buffer_head *bh));
+@@ -207,12 +210,6 @@ int nobh_prepare_write(struct page*, uns
+ int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
+ int nobh_truncate_page(struct address_space *, loff_t);
+
+-#define OSYNC_METADATA (1<<0)
+-#define OSYNC_DATA (1<<1)
+-#define OSYNC_INODE (1<<2)
+-int generic_osync_inode(struct inode *, int);
+-
+-
+ /*
+ * inline definitions
+ */
+@@ -230,13 +227,13 @@ static inline void put_bh(struct buffer_
+
+ static inline void brelse(struct buffer_head *bh)
+ {
+- if (bh)
++ if (bh && !IS_ERR(bh))
+ __brelse(bh);
+ }
+
+ static inline void bforget(struct buffer_head *bh)
+ {
+- if (bh)
++ if (bh && !IS_ERR(bh))
+ __bforget(bh);
+ }
+
+@@ -253,7 +250,12 @@ sb_breadahead(struct super_block *sb, se
+ }
+
+ static inline struct buffer_head *
+-sb_getblk(struct super_block *sb, sector_t block)
++sb_bread_wq(struct super_block *sb, sector_t block, wait_queue_t *wait)
++{
++ return __bread_wq(sb->s_bdev, block, sb->s_blocksize, wait);
++}
++
++static inline struct buffer_head *sb_getblk(struct super_block *sb, sector_t block)
+ {
+ return __getblk(sb->s_bdev, block, sb->s_blocksize);
+ }
+@@ -277,16 +279,34 @@ map_bh(struct buffer_head *bh, struct su
+ * __wait_on_buffer() just to trip a debug check. Because debug code in inline
+ * functions is bloaty.
+ */
+-static inline void wait_on_buffer(struct buffer_head *bh)
++
++static inline int wait_on_buffer_wq(struct buffer_head *bh, wait_queue_t *wait)
+ {
+ if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0)
+- __wait_on_buffer(bh);
++ return __wait_on_buffer_wq(bh, wait);
++
++ return 0;
++}
++
++static inline void wait_on_buffer(struct buffer_head *bh)
++{
++ wait_on_buffer_wq(bh, NULL);
++}
++
++static inline int lock_buffer_wq(struct buffer_head *bh, wait_queue_t *wait)
++{
++ while (test_set_buffer_locked(bh)) {
++ int ret = __wait_on_buffer_wq(bh, wait);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
+ }
+
+ static inline void lock_buffer(struct buffer_head *bh)
+ {
+- while (test_set_buffer_locked(bh))
+- __wait_on_buffer(bh);
++ lock_buffer_wq(bh, NULL);
+ }
+
+ #endif /* _LINUX_BUFFER_HEAD_H */
+--- linux-2.6.0-test6/include/linux/cdrom.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/linux/cdrom.h 2003-10-05 00:33:59.000000000 -0700
+@@ -743,6 +743,7 @@ struct cdrom_device_info {
+ /* per-device flags */
+ __u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
+ __u8 reserved : 6; /* not used yet */
++ int for_data;
+ struct cdrom_write_settings write;
+ };
+
+@@ -776,9 +777,9 @@ struct cdrom_device_ops {
+ };
+
+ /* the general block_device operations structure: */
+-extern int cdrom_open(struct cdrom_device_info *, struct inode *, struct file *);
+-extern int cdrom_release(struct cdrom_device_info *, struct file *);
+-extern int cdrom_ioctl(struct cdrom_device_info *, struct inode *, unsigned, unsigned long);
++extern int cdrom_open(struct cdrom_device_info *, struct block_device *, struct file *);
++extern int cdrom_release(struct cdrom_device_info *);
++extern int cdrom_ioctl(struct cdrom_device_info *, struct block_device *, unsigned, unsigned long);
+ extern int cdrom_media_changed(struct cdrom_device_info *);
+
+ extern int register_cdrom(struct cdrom_device_info *cdi);
+--- linux-2.6.0-test6/include/linux/compat.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/compat.h 2003-10-05 00:34:44.000000000 -0700
+@@ -90,5 +90,12 @@ struct compat_statfs64 {
+ __u32 f_spare[5];
+ };
+
++struct compat_dirent {
++ u32 d_ino;
++ compat_off_t d_off;
++ u16 d_reclen;
++ char d_name[256];
++};
++
+ #endif /* CONFIG_COMPAT */
+ #endif /* _LINUX_COMPAT_H */
+--- linux-2.6.0-test6/include/linux/compat_ioctl.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/compat_ioctl.h 2003-10-05 00:33:24.000000000 -0700
+@@ -68,7 +68,7 @@ COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
+ COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+ COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
+ COMPATIBLE_IOCTL(HDIO_SET_NICE)
+-#ifndef CONFIG_ARCH_S390
++#ifdef CONFIG_BLK_DEV_FD
+ /* 0x02 -- Floppy ioctls */
+ COMPATIBLE_IOCTL(FDMSGON)
+ COMPATIBLE_IOCTL(FDMSGOFF)
+--- linux-2.6.0-test6/include/linux/compiler-gcc.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/compiler-gcc.h 2003-10-05 00:34:18.000000000 -0700
+@@ -13,5 +13,5 @@
+ shouldn't recognize the original var, and make assumptions about it */
+ #define RELOC_HIDE(ptr, off) \
+ ({ unsigned long __ptr; \
+- __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \
++ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
+ (typeof(ptr)) (__ptr + (off)); })
+--- linux-2.6.0-test6/include/linux/config.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/linux/config.h 2003-10-05 00:33:43.000000000 -0700
+@@ -2,5 +2,8 @@
+ #define _LINUX_CONFIG_H
+
+ #include <linux/autoconf.h>
++#if defined(__i386__) && !defined(IN_BOOTLOADER)
++#include <asm/kgdb.h>
++#endif
+
+ #endif
+--- linux-2.6.0-test6/include/linux/dqblk_xfs.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/linux/dqblk_xfs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -105,15 +105,6 @@ typedef struct fs_disk_quota {
+ #define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
+
+ /*
+- * The following constants define the default amount of time given a user
+- * before the soft limits are treated as hard limits (usually resulting
+- * in an allocation failure). These may be modified by the quotactl(2)
+- * system call with the Q_XSETQLIM command.
+- */
+-#define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */
+-#define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */
+-
+-/*
+ * Various flags related to quotactl(2). Only relevant to XFS filesystems.
+ */
+ #define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/dwarf2.h 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,738 @@
++/* Declarations and definitions of codes relating to the DWARF2 symbolic
++ debugging information format.
++ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002
++ Free Software Foundation, Inc.
++
++ Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
++ Office (AJPO), Florida State Unviversity and Silicon Graphics Inc.
++ provided support for this effort -- June 21, 1995.
++
++ Derived from the DWARF 1 implementation written by Ron Guilmette
++ (rfg@netcom.com), November 1990.
++
++ This file is part of GCC.
++
++ GCC is free software; you can redistribute it and/or modify it under
++ the terms of the GNU General Public License as published by the Free
++ Software Foundation; either version 2, or (at your option) any later
++ version.
++
++ GCC is distributed in the hope that it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
++ License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with GCC; see the file COPYING. If not, write to the Free
++ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
++ 02111-1307, USA. */
++
++/* This file is derived from the DWARF specification (a public document)
++ Revision 2.0.0 (July 27, 1993) developed by the UNIX International
++ Programming Languages Special Interest Group (UI/PLSIG) and distributed
++ by UNIX International. Copies of this specification are available from
++ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
++
++ This file also now contains definitions from the DWARF 3 specification. */
++
++/* This file is shared between GCC and GDB, and should not contain
++ prototypes. */
++
++#ifndef _ELF_DWARF2_H
++#define _ELF_DWARF2_H
++
++/* Structure found in the .debug_line section. */
++#ifndef __ASSEMBLY__
++typedef struct
++{
++ unsigned char li_length [4];
++ unsigned char li_version [2];
++ unsigned char li_prologue_length [4];
++ unsigned char li_min_insn_length [1];
++ unsigned char li_default_is_stmt [1];
++ unsigned char li_line_base [1];
++ unsigned char li_line_range [1];
++ unsigned char li_opcode_base [1];
++}
++DWARF2_External_LineInfo;
++
++typedef struct
++{
++ unsigned long li_length;
++ unsigned short li_version;
++ unsigned int li_prologue_length;
++ unsigned char li_min_insn_length;
++ unsigned char li_default_is_stmt;
++ int li_line_base;
++ unsigned char li_line_range;
++ unsigned char li_opcode_base;
++}
++DWARF2_Internal_LineInfo;
++
++/* Structure found in .debug_pubnames section. */
++typedef struct
++{
++ unsigned char pn_length [4];
++ unsigned char pn_version [2];
++ unsigned char pn_offset [4];
++ unsigned char pn_size [4];
++}
++DWARF2_External_PubNames;
++
++typedef struct
++{
++ unsigned long pn_length;
++ unsigned short pn_version;
++ unsigned long pn_offset;
++ unsigned long pn_size;
++}
++DWARF2_Internal_PubNames;
++
++/* Structure found in .debug_info section. */
++typedef struct
++{
++ unsigned char cu_length [4];
++ unsigned char cu_version [2];
++ unsigned char cu_abbrev_offset [4];
++ unsigned char cu_pointer_size [1];
++}
++DWARF2_External_CompUnit;
++
++typedef struct
++{
++ unsigned long cu_length;
++ unsigned short cu_version;
++ unsigned long cu_abbrev_offset;
++ unsigned char cu_pointer_size;
++}
++DWARF2_Internal_CompUnit;
++
++typedef struct
++{
++ unsigned char ar_length [4];
++ unsigned char ar_version [2];
++ unsigned char ar_info_offset [4];
++ unsigned char ar_pointer_size [1];
++ unsigned char ar_segment_size [1];
++}
++DWARF2_External_ARange;
++
++typedef struct
++{
++ unsigned long ar_length;
++ unsigned short ar_version;
++ unsigned long ar_info_offset;
++ unsigned char ar_pointer_size;
++ unsigned char ar_segment_size;
++}
++DWARF2_Internal_ARange;
++
++#define ENUM(name) enum name {
++#define IF_NOT_ASM(a) a
++#define COMMA ,
++#else
++#define ENUM(name)
++#define IF_NOT_ASM(a)
++#define COMMA
++
++#endif
++
++/* Tag names and codes. */
++ENUM(dwarf_tag)
++
++ DW_TAG_padding = 0x00 COMMA
++ DW_TAG_array_type = 0x01 COMMA
++ DW_TAG_class_type = 0x02 COMMA
++ DW_TAG_entry_point = 0x03 COMMA
++ DW_TAG_enumeration_type = 0x04 COMMA
++ DW_TAG_formal_parameter = 0x05 COMMA
++ DW_TAG_imported_declaration = 0x08 COMMA
++ DW_TAG_label = 0x0a COMMA
++ DW_TAG_lexical_block = 0x0b COMMA
++ DW_TAG_member = 0x0d COMMA
++ DW_TAG_pointer_type = 0x0f COMMA
++ DW_TAG_reference_type = 0x10 COMMA
++ DW_TAG_compile_unit = 0x11 COMMA
++ DW_TAG_string_type = 0x12 COMMA
++ DW_TAG_structure_type = 0x13 COMMA
++ DW_TAG_subroutine_type = 0x15 COMMA
++ DW_TAG_typedef = 0x16 COMMA
++ DW_TAG_union_type = 0x17 COMMA
++ DW_TAG_unspecified_parameters = 0x18 COMMA
++ DW_TAG_variant = 0x19 COMMA
++ DW_TAG_common_block = 0x1a COMMA
++ DW_TAG_common_inclusion = 0x1b COMMA
++ DW_TAG_inheritance = 0x1c COMMA
++ DW_TAG_inlined_subroutine = 0x1d COMMA
++ DW_TAG_module = 0x1e COMMA
++ DW_TAG_ptr_to_member_type = 0x1f COMMA
++ DW_TAG_set_type = 0x20 COMMA
++ DW_TAG_subrange_type = 0x21 COMMA
++ DW_TAG_with_stmt = 0x22 COMMA
++ DW_TAG_access_declaration = 0x23 COMMA
++ DW_TAG_base_type = 0x24 COMMA
++ DW_TAG_catch_block = 0x25 COMMA
++ DW_TAG_const_type = 0x26 COMMA
++ DW_TAG_constant = 0x27 COMMA
++ DW_TAG_enumerator = 0x28 COMMA
++ DW_TAG_file_type = 0x29 COMMA
++ DW_TAG_friend = 0x2a COMMA
++ DW_TAG_namelist = 0x2b COMMA
++ DW_TAG_namelist_item = 0x2c COMMA
++ DW_TAG_packed_type = 0x2d COMMA
++ DW_TAG_subprogram = 0x2e COMMA
++ DW_TAG_template_type_param = 0x2f COMMA
++ DW_TAG_template_value_param = 0x30 COMMA
++ DW_TAG_thrown_type = 0x31 COMMA
++ DW_TAG_try_block = 0x32 COMMA
++ DW_TAG_variant_part = 0x33 COMMA
++ DW_TAG_variable = 0x34 COMMA
++ DW_TAG_volatile_type = 0x35 COMMA
++ /* DWARF 3. */
++ DW_TAG_dwarf_procedure = 0x36 COMMA
++ DW_TAG_restrict_type = 0x37 COMMA
++ DW_TAG_interface_type = 0x38 COMMA
++ DW_TAG_namespace = 0x39 COMMA
++ DW_TAG_imported_module = 0x3a COMMA
++ DW_TAG_unspecified_type = 0x3b COMMA
++ DW_TAG_partial_unit = 0x3c COMMA
++ DW_TAG_imported_unit = 0x3d COMMA
++ /* SGI/MIPS Extensions. */
++ DW_TAG_MIPS_loop = 0x4081 COMMA
++ /* GNU extensions. */
++ DW_TAG_format_label = 0x4101 COMMA /* For FORTRAN 77 and Fortran 90. */
++ DW_TAG_function_template = 0x4102 COMMA /* For C++. */
++ DW_TAG_class_template = 0x4103 COMMA /* For C++. */
++ DW_TAG_GNU_BINCL = 0x4104 COMMA
++ DW_TAG_GNU_EINCL = 0x4105 COMMA
++ /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
++ DW_TAG_upc_shared_type = 0x8765 COMMA
++ DW_TAG_upc_strict_type = 0x8766 COMMA
++ DW_TAG_upc_relaxed_type = 0x8767
++IF_NOT_ASM(};)
++
++#define DW_TAG_lo_user 0x4080
++#define DW_TAG_hi_user 0xffff
++
++/* Flag that tells whether entry has a child or not. */
++#define DW_children_no 0
++#define DW_children_yes 1
++
++/* Form names and codes. */
++ENUM(dwarf_form)
++
++ DW_FORM_addr = 0x01 COMMA
++ DW_FORM_block2 = 0x03 COMMA
++ DW_FORM_block4 = 0x04 COMMA
++ DW_FORM_data2 = 0x05 COMMA
++ DW_FORM_data4 = 0x06 COMMA
++ DW_FORM_data8 = 0x07 COMMA
++ DW_FORM_string = 0x08 COMMA
++ DW_FORM_block = 0x09 COMMA
++ DW_FORM_block1 = 0x0a COMMA
++ DW_FORM_data1 = 0x0b COMMA
++ DW_FORM_flag = 0x0c COMMA
++ DW_FORM_sdata = 0x0d COMMA
++ DW_FORM_strp = 0x0e COMMA
++ DW_FORM_udata = 0x0f COMMA
++ DW_FORM_ref_addr = 0x10 COMMA
++ DW_FORM_ref1 = 0x11 COMMA
++ DW_FORM_ref2 = 0x12 COMMA
++ DW_FORM_ref4 = 0x13 COMMA
++ DW_FORM_ref8 = 0x14 COMMA
++ DW_FORM_ref_udata = 0x15 COMMA
++ DW_FORM_indirect = 0x16
++IF_NOT_ASM(};)
++
++/* Attribute names and codes. */
++
++ENUM(dwarf_attribute)
++
++ DW_AT_sibling = 0x01 COMMA
++ DW_AT_location = 0x02 COMMA
++ DW_AT_name = 0x03 COMMA
++ DW_AT_ordering = 0x09 COMMA
++ DW_AT_subscr_data = 0x0a COMMA
++ DW_AT_byte_size = 0x0b COMMA
++ DW_AT_bit_offset = 0x0c COMMA
++ DW_AT_bit_size = 0x0d COMMA
++ DW_AT_element_list = 0x0f COMMA
++ DW_AT_stmt_list = 0x10 COMMA
++ DW_AT_low_pc = 0x11 COMMA
++ DW_AT_high_pc = 0x12 COMMA
++ DW_AT_language = 0x13 COMMA
++ DW_AT_member = 0x14 COMMA
++ DW_AT_discr = 0x15 COMMA
++ DW_AT_discr_value = 0x16 COMMA
++ DW_AT_visibility = 0x17 COMMA
++ DW_AT_import = 0x18 COMMA
++ DW_AT_string_length = 0x19 COMMA
++ DW_AT_common_reference = 0x1a COMMA
++ DW_AT_comp_dir = 0x1b COMMA
++ DW_AT_const_value = 0x1c COMMA
++ DW_AT_containing_type = 0x1d COMMA
++ DW_AT_default_value = 0x1e COMMA
++ DW_AT_inline = 0x20 COMMA
++ DW_AT_is_optional = 0x21 COMMA
++ DW_AT_lower_bound = 0x22 COMMA
++ DW_AT_producer = 0x25 COMMA
++ DW_AT_prototyped = 0x27 COMMA
++ DW_AT_return_addr = 0x2a COMMA
++ DW_AT_start_scope = 0x2c COMMA
++ DW_AT_stride_size = 0x2e COMMA
++ DW_AT_upper_bound = 0x2f COMMA
++ DW_AT_abstract_origin = 0x31 COMMA
++ DW_AT_accessibility = 0x32 COMMA
++ DW_AT_address_class = 0x33 COMMA
++ DW_AT_artificial = 0x34 COMMA
++ DW_AT_base_types = 0x35 COMMA
++ DW_AT_calling_convention = 0x36 COMMA
++ DW_AT_count = 0x37 COMMA
++ DW_AT_data_member_location = 0x38 COMMA
++ DW_AT_decl_column = 0x39 COMMA
++ DW_AT_decl_file = 0x3a COMMA
++ DW_AT_decl_line = 0x3b COMMA
++ DW_AT_declaration = 0x3c COMMA
++ DW_AT_discr_list = 0x3d COMMA
++ DW_AT_encoding = 0x3e COMMA
++ DW_AT_external = 0x3f COMMA
++ DW_AT_frame_base = 0x40 COMMA
++ DW_AT_friend = 0x41 COMMA
++ DW_AT_identifier_case = 0x42 COMMA
++ DW_AT_macro_info = 0x43 COMMA
++ DW_AT_namelist_items = 0x44 COMMA
++ DW_AT_priority = 0x45 COMMA
++ DW_AT_segment = 0x46 COMMA
++ DW_AT_specification = 0x47 COMMA
++ DW_AT_static_link = 0x48 COMMA
++ DW_AT_type = 0x49 COMMA
++ DW_AT_use_location = 0x4a COMMA
++ DW_AT_variable_parameter = 0x4b COMMA
++ DW_AT_virtuality = 0x4c COMMA
++ DW_AT_vtable_elem_location = 0x4d COMMA
++ /* DWARF 3 values. */
++ DW_AT_allocated = 0x4e COMMA
++ DW_AT_associated = 0x4f COMMA
++ DW_AT_data_location = 0x50 COMMA
++ DW_AT_stride = 0x51 COMMA
++ DW_AT_entry_pc = 0x52 COMMA
++ DW_AT_use_UTF8 = 0x53 COMMA
++ DW_AT_extension = 0x54 COMMA
++ DW_AT_ranges = 0x55 COMMA
++ DW_AT_trampoline = 0x56 COMMA
++ DW_AT_call_column = 0x57 COMMA
++ DW_AT_call_file = 0x58 COMMA
++ DW_AT_call_line = 0x59 COMMA
++ /* SGI/MIPS extensions. */
++ DW_AT_MIPS_fde = 0x2001 COMMA
++ DW_AT_MIPS_loop_begin = 0x2002 COMMA
++ DW_AT_MIPS_tail_loop_begin = 0x2003 COMMA
++ DW_AT_MIPS_epilog_begin = 0x2004 COMMA
++ DW_AT_MIPS_loop_unroll_factor = 0x2005 COMMA
++ DW_AT_MIPS_software_pipeline_depth = 0x2006 COMMA
++ DW_AT_MIPS_linkage_name = 0x2007 COMMA
++ DW_AT_MIPS_stride = 0x2008 COMMA
++ DW_AT_MIPS_abstract_name = 0x2009 COMMA
++ DW_AT_MIPS_clone_origin = 0x200a COMMA
++ DW_AT_MIPS_has_inlines = 0x200b COMMA
++ /* GNU extensions. */
++ DW_AT_sf_names = 0x2101 COMMA
++ DW_AT_src_info = 0x2102 COMMA
++ DW_AT_mac_info = 0x2103 COMMA
++ DW_AT_src_coords = 0x2104 COMMA
++ DW_AT_body_begin = 0x2105 COMMA
++ DW_AT_body_end = 0x2106 COMMA
++ DW_AT_GNU_vector = 0x2107 COMMA
++ /* VMS extensions. */
++ DW_AT_VMS_rtnbeg_pd_address = 0x2201 COMMA
++ /* UPC extension. */
++ DW_AT_upc_threads_scaled = 0x3210
++IF_NOT_ASM(};)
++
++#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
++#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
++
++/* Location atom names and codes. */
++ENUM(dwarf_location_atom)
++
++ DW_OP_addr = 0x03 COMMA
++ DW_OP_deref = 0x06 COMMA
++ DW_OP_const1u = 0x08 COMMA
++ DW_OP_const1s = 0x09 COMMA
++ DW_OP_const2u = 0x0a COMMA
++ DW_OP_const2s = 0x0b COMMA
++ DW_OP_const4u = 0x0c COMMA
++ DW_OP_const4s = 0x0d COMMA
++ DW_OP_const8u = 0x0e COMMA
++ DW_OP_const8s = 0x0f COMMA
++ DW_OP_constu = 0x10 COMMA
++ DW_OP_consts = 0x11 COMMA
++ DW_OP_dup = 0x12 COMMA
++ DW_OP_drop = 0x13 COMMA
++ DW_OP_over = 0x14 COMMA
++ DW_OP_pick = 0x15 COMMA
++ DW_OP_swap = 0x16 COMMA
++ DW_OP_rot = 0x17 COMMA
++ DW_OP_xderef = 0x18 COMMA
++ DW_OP_abs = 0x19 COMMA
++ DW_OP_and = 0x1a COMMA
++ DW_OP_div = 0x1b COMMA
++ DW_OP_minus = 0x1c COMMA
++ DW_OP_mod = 0x1d COMMA
++ DW_OP_mul = 0x1e COMMA
++ DW_OP_neg = 0x1f COMMA
++ DW_OP_not = 0x20 COMMA
++ DW_OP_or = 0x21 COMMA
++ DW_OP_plus = 0x22 COMMA
++ DW_OP_plus_uconst = 0x23 COMMA
++ DW_OP_shl = 0x24 COMMA
++ DW_OP_shr = 0x25 COMMA
++ DW_OP_shra = 0x26 COMMA
++ DW_OP_xor = 0x27 COMMA
++ DW_OP_bra = 0x28 COMMA
++ DW_OP_eq = 0x29 COMMA
++ DW_OP_ge = 0x2a COMMA
++ DW_OP_gt = 0x2b COMMA
++ DW_OP_le = 0x2c COMMA
++ DW_OP_lt = 0x2d COMMA
++ DW_OP_ne = 0x2e COMMA
++ DW_OP_skip = 0x2f COMMA
++ DW_OP_lit0 = 0x30 COMMA
++ DW_OP_lit1 = 0x31 COMMA
++ DW_OP_lit2 = 0x32 COMMA
++ DW_OP_lit3 = 0x33 COMMA
++ DW_OP_lit4 = 0x34 COMMA
++ DW_OP_lit5 = 0x35 COMMA
++ DW_OP_lit6 = 0x36 COMMA
++ DW_OP_lit7 = 0x37 COMMA
++ DW_OP_lit8 = 0x38 COMMA
++ DW_OP_lit9 = 0x39 COMMA
++ DW_OP_lit10 = 0x3a COMMA
++ DW_OP_lit11 = 0x3b COMMA
++ DW_OP_lit12 = 0x3c COMMA
++ DW_OP_lit13 = 0x3d COMMA
++ DW_OP_lit14 = 0x3e COMMA
++ DW_OP_lit15 = 0x3f COMMA
++ DW_OP_lit16 = 0x40 COMMA
++ DW_OP_lit17 = 0x41 COMMA
++ DW_OP_lit18 = 0x42 COMMA
++ DW_OP_lit19 = 0x43 COMMA
++ DW_OP_lit20 = 0x44 COMMA
++ DW_OP_lit21 = 0x45 COMMA
++ DW_OP_lit22 = 0x46 COMMA
++ DW_OP_lit23 = 0x47 COMMA
++ DW_OP_lit24 = 0x48 COMMA
++ DW_OP_lit25 = 0x49 COMMA
++ DW_OP_lit26 = 0x4a COMMA
++ DW_OP_lit27 = 0x4b COMMA
++ DW_OP_lit28 = 0x4c COMMA
++ DW_OP_lit29 = 0x4d COMMA
++ DW_OP_lit30 = 0x4e COMMA
++ DW_OP_lit31 = 0x4f COMMA
++ DW_OP_reg0 = 0x50 COMMA
++ DW_OP_reg1 = 0x51 COMMA
++ DW_OP_reg2 = 0x52 COMMA
++ DW_OP_reg3 = 0x53 COMMA
++ DW_OP_reg4 = 0x54 COMMA
++ DW_OP_reg5 = 0x55 COMMA
++ DW_OP_reg6 = 0x56 COMMA
++ DW_OP_reg7 = 0x57 COMMA
++ DW_OP_reg8 = 0x58 COMMA
++ DW_OP_reg9 = 0x59 COMMA
++ DW_OP_reg10 = 0x5a COMMA
++ DW_OP_reg11 = 0x5b COMMA
++ DW_OP_reg12 = 0x5c COMMA
++ DW_OP_reg13 = 0x5d COMMA
++ DW_OP_reg14 = 0x5e COMMA
++ DW_OP_reg15 = 0x5f COMMA
++ DW_OP_reg16 = 0x60 COMMA
++ DW_OP_reg17 = 0x61 COMMA
++ DW_OP_reg18 = 0x62 COMMA
++ DW_OP_reg19 = 0x63 COMMA
++ DW_OP_reg20 = 0x64 COMMA
++ DW_OP_reg21 = 0x65 COMMA
++ DW_OP_reg22 = 0x66 COMMA
++ DW_OP_reg23 = 0x67 COMMA
++ DW_OP_reg24 = 0x68 COMMA
++ DW_OP_reg25 = 0x69 COMMA
++ DW_OP_reg26 = 0x6a COMMA
++ DW_OP_reg27 = 0x6b COMMA
++ DW_OP_reg28 = 0x6c COMMA
++ DW_OP_reg29 = 0x6d COMMA
++ DW_OP_reg30 = 0x6e COMMA
++ DW_OP_reg31 = 0x6f COMMA
++ DW_OP_breg0 = 0x70 COMMA
++ DW_OP_breg1 = 0x71 COMMA
++ DW_OP_breg2 = 0x72 COMMA
++ DW_OP_breg3 = 0x73 COMMA
++ DW_OP_breg4 = 0x74 COMMA
++ DW_OP_breg5 = 0x75 COMMA
++ DW_OP_breg6 = 0x76 COMMA
++ DW_OP_breg7 = 0x77 COMMA
++ DW_OP_breg8 = 0x78 COMMA
++ DW_OP_breg9 = 0x79 COMMA
++ DW_OP_breg10 = 0x7a COMMA
++ DW_OP_breg11 = 0x7b COMMA
++ DW_OP_breg12 = 0x7c COMMA
++ DW_OP_breg13 = 0x7d COMMA
++ DW_OP_breg14 = 0x7e COMMA
++ DW_OP_breg15 = 0x7f COMMA
++ DW_OP_breg16 = 0x80 COMMA
++ DW_OP_breg17 = 0x81 COMMA
++ DW_OP_breg18 = 0x82 COMMA
++ DW_OP_breg19 = 0x83 COMMA
++ DW_OP_breg20 = 0x84 COMMA
++ DW_OP_breg21 = 0x85 COMMA
++ DW_OP_breg22 = 0x86 COMMA
++ DW_OP_breg23 = 0x87 COMMA
++ DW_OP_breg24 = 0x88 COMMA
++ DW_OP_breg25 = 0x89 COMMA
++ DW_OP_breg26 = 0x8a COMMA
++ DW_OP_breg27 = 0x8b COMMA
++ DW_OP_breg28 = 0x8c COMMA
++ DW_OP_breg29 = 0x8d COMMA
++ DW_OP_breg30 = 0x8e COMMA
++ DW_OP_breg31 = 0x8f COMMA
++ DW_OP_regx = 0x90 COMMA
++ DW_OP_fbreg = 0x91 COMMA
++ DW_OP_bregx = 0x92 COMMA
++ DW_OP_piece = 0x93 COMMA
++ DW_OP_deref_size = 0x94 COMMA
++ DW_OP_xderef_size = 0x95 COMMA
++ DW_OP_nop = 0x96 COMMA
++ /* DWARF 3 extensions. */
++ DW_OP_push_object_address = 0x97 COMMA
++ DW_OP_call2 = 0x98 COMMA
++ DW_OP_call4 = 0x99 COMMA
++ DW_OP_call_ref = 0x9a COMMA
++ /* GNU extensions. */
++ DW_OP_GNU_push_tls_address = 0xe0
++IF_NOT_ASM(};)
++
++#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
++#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
++
++/* Type encodings. */
++ENUM(dwarf_type)
++
++ DW_ATE_void = 0x0 COMMA
++ DW_ATE_address = 0x1 COMMA
++ DW_ATE_boolean = 0x2 COMMA
++ DW_ATE_complex_float = 0x3 COMMA
++ DW_ATE_float = 0x4 COMMA
++ DW_ATE_signed = 0x5 COMMA
++ DW_ATE_signed_char = 0x6 COMMA
++ DW_ATE_unsigned = 0x7 COMMA
++ DW_ATE_unsigned_char = 0x8 COMMA
++ /* DWARF 3. */
++ DW_ATE_imaginary_float = 0x9
++IF_NOT_ASM(};)
++
++#define DW_ATE_lo_user 0x80
++#define DW_ATE_hi_user 0xff
++
++/* Array ordering names and codes. */
++ENUM(dwarf_array_dim_ordering)
++
++ DW_ORD_row_major = 0 COMMA
++ DW_ORD_col_major = 1
++IF_NOT_ASM(};)
++
++/* Access attribute. */
++ENUM(dwarf_access_attribute)
++
++ DW_ACCESS_public = 1 COMMA
++ DW_ACCESS_protected = 2 COMMA
++ DW_ACCESS_private = 3
++IF_NOT_ASM(};)
++
++/* Visibility. */
++ENUM(dwarf_visibility_attribute)
++
++ DW_VIS_local = 1 COMMA
++ DW_VIS_exported = 2 COMMA
++ DW_VIS_qualified = 3
++IF_NOT_ASM(};)
++
++/* Virtuality. */
++ENUM(dwarf_virtuality_attribute)
++
++ DW_VIRTUALITY_none = 0 COMMA
++ DW_VIRTUALITY_virtual = 1 COMMA
++ DW_VIRTUALITY_pure_virtual = 2
++IF_NOT_ASM(};)
++
++/* Case sensitivity. */
++ENUM(dwarf_id_case)
++
++ DW_ID_case_sensitive = 0 COMMA
++ DW_ID_up_case = 1 COMMA
++ DW_ID_down_case = 2 COMMA
++ DW_ID_case_insensitive = 3
++IF_NOT_ASM(};)
++
++/* Calling convention. */
++ENUM(dwarf_calling_convention)
++
++ DW_CC_normal = 0x1 COMMA
++ DW_CC_program = 0x2 COMMA
++ DW_CC_nocall = 0x3
++IF_NOT_ASM(};)
++
++#define DW_CC_lo_user 0x40
++#define DW_CC_hi_user 0xff
++
++/* Inline attribute. */
++ENUM(dwarf_inline_attribute)
++
++ DW_INL_not_inlined = 0 COMMA
++ DW_INL_inlined = 1 COMMA
++ DW_INL_declared_not_inlined = 2 COMMA
++ DW_INL_declared_inlined = 3
++IF_NOT_ASM(};)
++
++/* Discriminant lists. */
++ENUM(dwarf_discrim_list)
++
++ DW_DSC_label = 0 COMMA
++ DW_DSC_range = 1
++IF_NOT_ASM(};)
++
++/* Line number opcodes. */
++ENUM(dwarf_line_number_ops)
++
++ DW_LNS_extended_op = 0 COMMA
++ DW_LNS_copy = 1 COMMA
++ DW_LNS_advance_pc = 2 COMMA
++ DW_LNS_advance_line = 3 COMMA
++ DW_LNS_set_file = 4 COMMA
++ DW_LNS_set_column = 5 COMMA
++ DW_LNS_negate_stmt = 6 COMMA
++ DW_LNS_set_basic_block = 7 COMMA
++ DW_LNS_const_add_pc = 8 COMMA
++ DW_LNS_fixed_advance_pc = 9 COMMA
++ /* DWARF 3. */
++ DW_LNS_set_prologue_end = 10 COMMA
++ DW_LNS_set_epilogue_begin = 11 COMMA
++ DW_LNS_set_isa = 12
++IF_NOT_ASM(};)
++
++/* Line number extended opcodes. */
++ENUM(dwarf_line_number_x_ops)
++
++ DW_LNE_end_sequence = 1 COMMA
++ DW_LNE_set_address = 2 COMMA
++ DW_LNE_define_file = 3
++IF_NOT_ASM(};)
++
++/* Call frame information. */
++ENUM(dwarf_call_frame_info)
++
++ DW_CFA_advance_loc = 0x40 COMMA
++ DW_CFA_offset = 0x80 COMMA
++ DW_CFA_restore = 0xc0 COMMA
++ DW_CFA_nop = 0x00 COMMA
++ DW_CFA_set_loc = 0x01 COMMA
++ DW_CFA_advance_loc1 = 0x02 COMMA
++ DW_CFA_advance_loc2 = 0x03 COMMA
++ DW_CFA_advance_loc4 = 0x04 COMMA
++ DW_CFA_offset_extended = 0x05 COMMA
++ DW_CFA_restore_extended = 0x06 COMMA
++ DW_CFA_undefined = 0x07 COMMA
++ DW_CFA_same_value = 0x08 COMMA
++ DW_CFA_register = 0x09 COMMA
++ DW_CFA_remember_state = 0x0a COMMA
++ DW_CFA_restore_state = 0x0b COMMA
++ DW_CFA_def_cfa = 0x0c COMMA
++ DW_CFA_def_cfa_register = 0x0d COMMA
++ DW_CFA_def_cfa_offset = 0x0e COMMA
++
++ /* DWARF 3. */
++ DW_CFA_def_cfa_expression = 0x0f COMMA
++ DW_CFA_expression = 0x10 COMMA
++ DW_CFA_offset_extended_sf = 0x11 COMMA
++ DW_CFA_def_cfa_sf = 0x12 COMMA
++ DW_CFA_def_cfa_offset_sf = 0x13 COMMA
++
++ /* SGI/MIPS specific. */
++ DW_CFA_MIPS_advance_loc8 = 0x1d COMMA
++
++ /* GNU extensions. */
++ DW_CFA_GNU_window_save = 0x2d COMMA
++ DW_CFA_GNU_args_size = 0x2e COMMA
++ DW_CFA_GNU_negative_offset_extended = 0x2f
++IF_NOT_ASM(};)
++
++#define DW_CIE_ID 0xffffffff
++#define DW_CIE_VERSION 1
++
++#define DW_CFA_extended 0
++#define DW_CFA_lo_user 0x1c
++#define DW_CFA_hi_user 0x3f
++
++#define DW_CHILDREN_no 0x00
++#define DW_CHILDREN_yes 0x01
++
++#define DW_ADDR_none 0
++
++/* Source language names and codes. */
++ENUM(dwarf_source_language)
++
++ DW_LANG_C89 = 0x0001 COMMA
++ DW_LANG_C = 0x0002 COMMA
++ DW_LANG_Ada83 = 0x0003 COMMA
++ DW_LANG_C_plus_plus = 0x0004 COMMA
++ DW_LANG_Cobol74 = 0x0005 COMMA
++ DW_LANG_Cobol85 = 0x0006 COMMA
++ DW_LANG_Fortran77 = 0x0007 COMMA
++ DW_LANG_Fortran90 = 0x0008 COMMA
++ DW_LANG_Pascal83 = 0x0009 COMMA
++ DW_LANG_Modula2 = 0x000a COMMA
++ DW_LANG_Java = 0x000b COMMA
++ /* DWARF 3. */
++ DW_LANG_C99 = 0x000c COMMA
++ DW_LANG_Ada95 = 0x000d COMMA
++ DW_LANG_Fortran95 = 0x000e COMMA
++ /* MIPS. */
++ DW_LANG_Mips_Assembler = 0x8001 COMMA
++ /* UPC. */
++ DW_LANG_Upc = 0x8765
++IF_NOT_ASM(};)
++
++#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
++#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
++
++/* Names and codes for macro information. */
++ENUM(dwarf_macinfo_record_type)
++
++ DW_MACINFO_define = 1 COMMA
++ DW_MACINFO_undef = 2 COMMA
++ DW_MACINFO_start_file = 3 COMMA
++ DW_MACINFO_end_file = 4 COMMA
++ DW_MACINFO_vendor_ext = 255
++IF_NOT_ASM(};)
++\f
++/* @@@ For use with GNU frame unwind information. */
++
++#define DW_EH_PE_absptr 0x00
++#define DW_EH_PE_omit 0xff
++
++#define DW_EH_PE_uleb128 0x01
++#define DW_EH_PE_udata2 0x02
++#define DW_EH_PE_udata4 0x03
++#define DW_EH_PE_udata8 0x04
++#define DW_EH_PE_sleb128 0x09
++#define DW_EH_PE_sdata2 0x0A
++#define DW_EH_PE_sdata4 0x0B
++#define DW_EH_PE_sdata8 0x0C
++#define DW_EH_PE_signed 0x08
++
++#define DW_EH_PE_pcrel 0x10
++#define DW_EH_PE_textrel 0x20
++#define DW_EH_PE_datarel 0x30
++#define DW_EH_PE_funcrel 0x40
++#define DW_EH_PE_aligned 0x50
++
++#define DW_EH_PE_indirect 0x80
++
++#endif /* _ELF_DWARF2_H */
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/dwarf2-lang.h 2003-10-05 00:33:38.000000000 -0700
+@@ -0,0 +1,132 @@
++#ifndef DWARF2_LANG
++#define DWARF2_LANG
++#include <linux/dwarf2.h>
++
++/*
++ * This is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2, or (at your option) any later
++ * version.
++ */
++/*
++ * This file defines macros that allow generation of DWARF debug records
++ * for asm files. This file is platform independent. Register numbers
++ * (which are about the only thing that is platform dependent) are to be
++ * supplied by a platform defined file.
++ */
++#define DWARF_preamble() .section .debug_frame,"",@progbits
++/*
++ * This macro starts a debug frame section. The debug_frame describes
++ * where to find the registers that the enclosing function saved on
++ * entry.
++ *
++ * ORD is use by the label generator and should be the same as what is
++ * passed to CFI_postamble.
++ *
++ * pc, pc register gdb ordinal.
++ *
++ * code_align this is the factor used to define locations or regions
++ * where the given definitions apply. If you use labels to define these
++ * this should be 1.
++ *
++ * data_align this is the factor used to define register offsets. If
++ * you use struct offset, this should be the size of the register in
++ * bytes or the negative of that. This is how it is used: you will
++ * define a register as the reference register, say the stack pointer,
++ * then you will say where a register is located relative to this
++ * reference registers value, say 40 for register 3 (the gdb register
++ * number). The <40> will be multiplied by <data_align> to define the
++ * byte offset of the given register (3, in this example). So if your
++ * <40> is the byte offset and the reference register points at the
++ * begining, you would want 1 for the data_offset. If <40> was the 40th
++ * 4-byte element in that structure you would want 4. And if your
++ * reference register points at the end of the structure you would want
++ * a negative data_align value(and you would have to do other math as
++ * well).
++ */
++
++#define CFI_preamble(ORD, pc, code_align, data_align) \
++.section .debug_frame,"",@progbits ; \
++frame/**/_/**/ORD: \
++ .long end/**/_/**/ORD-start/**/_/**/ORD; \
++start/**/_/**/ORD: \
++ .long DW_CIE_ID; \
++ .byte DW_CIE_VERSION; \
++ .byte 0 ; \
++ .uleb128 code_align; \
++ .sleb128 data_align; \
++ .byte pc;
++
++/*
++ * After the above macro and prior to the CFI_postamble, you need to
++ * define the initial state. This starts with defining the reference
++ * register and, usually the pc. Here are some helper macros:
++ */
++
++#define CFA_define_reference(reg, offset) \
++ .byte DW_CFA_def_cfa; \
++ .uleb128 reg; \
++ .uleb128 (offset);
++
++#define CFA_define_offset(reg, offset) \
++ .byte (DW_CFA_offset + reg); \
++ .uleb128 (offset);
++
++#define CFI_postamble(ORD) \
++ .align 4; \
++end/**/_/**/ORD:
++/*
++ * So now your code pushs stuff on the stack, you need a new location
++ * and the rules for what to do. This starts a running description of
++ * the call frame. You need to describe what changes with respect to
++ * the call registers as the location of the pc moves through the code.
++ * The following builds an FDE (fram descriptor entry?). Like the
++ * above, it has a preamble and a postamble. It also is tied to the CFI
++ * above.
++ * The first entry after the preamble must be the location in the code
++ * that the call frame is being described for.
++ */
++#define FDE_preamble(ORD, fde_no, initial_address, length) \
++ .long FDE_end/**/_/**/fde_no-FDE_start/**/_/**/fde_no; \
++FDE_start/**/_/**/fde_no: \
++ .long frame/**/_/**/ORD; \
++ .long initial_address; \
++ .long length;
++
++#define FDE_postamble(fde_no) \
++ .align 4; \
++FDE_end/**/_/**/fde_no:
++/*
++ * That done, you can now add registers, subtract registers, move the
++ * reference and even change the reference. You can also define a new
++ * area of code the info applies to. For discontinuous bits you should
++ * start a new FDE. You may have as many as you like.
++ */
++
++/*
++ * To advance the address by <bytes>
++ */
++
++#define FDE_advance(bytes) \
++ .byte DW_CFA_advance_loc4 \
++ .long bytes
++
++
++
++/*
++ * With the above you can define all the register locations. But
++ * suppose the reference register moves... Takes the new offset NOT an
++ * increment. This is how esp is tracked if it is not saved.
++ */
++
++#define CFA_define_cfa_offset(offset) \
++ .byte $DW_CFA_def_cfa_offset; \
++ .uleb128 (offset);
++/*
++ * Or suppose you want to use a different reference register...
++ */
++#define CFA_define_cfa_register(reg) \
++ .byte DW_CFA_def_cfa_register; \
++ .uleb128 reg;
++
++#endif
+--- linux-2.6.0-test6/include/linux/efi.h 2003-08-08 22:55:14.000000000 -0700
++++ 25/include/linux/efi.h 2003-10-05 00:36:22.000000000 -0700
+@@ -16,6 +16,8 @@
+ #include <linux/time.h>
+ #include <linux/types.h>
+ #include <linux/proc_fs.h>
++#include <linux/rtc.h>
++#include <linux/ioport.h>
+
+ #include <asm/page.h>
+ #include <asm/system.h>
+@@ -89,6 +91,11 @@ typedef struct {
+
+ #define EFI_PAGE_SHIFT 12
+
++/*
++ * For current x86 implementations of EFI, there is
++ * additional padding in the mem descriptors. This is not
++ * the case in ia64. Need to have this fixed in the f/w.
++ */
+ typedef struct {
+ u32 type;
+ u32 pad;
+@@ -96,6 +103,9 @@ typedef struct {
+ u64 virt_addr;
+ u64 num_pages;
+ u64 attribute;
++#if defined (__i386__)
++ u64 pad1;
++#endif
+ } efi_memory_desc_t;
+
+ typedef int efi_freemem_callback_t (unsigned long start, unsigned long end, void *arg);
+@@ -132,6 +142,7 @@ typedef struct {
+ */
+ #define EFI_RESET_COLD 0
+ #define EFI_RESET_WARM 1
++#define EFI_RESET_SHUTDOWN 2
+
+ /*
+ * EFI Runtime Services table
+@@ -169,6 +180,10 @@ typedef efi_status_t efi_set_variable_t
+ typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
+ typedef void efi_reset_system_t (int reset_type, efi_status_t status,
+ unsigned long data_size, efi_char16_t *data);
++typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
++ unsigned long descriptor_size,
++ u32 descriptor_version,
++ efi_memory_desc_t *virtual_map);
+
+ /*
+ * EFI Configuration Table and GUID definitions
+@@ -194,6 +209,9 @@ typedef void efi_reset_system_t (int res
+ #define HCDP_TABLE_GUID \
+ EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
+
++#define UGA_IO_PROTOCOL_GUID \
++ EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
++
+ typedef struct {
+ efi_guid_t guid;
+ unsigned long table;
+@@ -218,6 +236,13 @@ typedef struct {
+ unsigned long tables;
+ } efi_system_table_t;
+
++struct efi_memory_map {
++ efi_memory_desc_t *phys_map;
++ efi_memory_desc_t *map;
++ int nr_map;
++ unsigned long desc_version;
++};
++
+ /*
+ * All runtime access to EFI goes through this structure:
+ */
+@@ -230,6 +255,7 @@ extern struct efi {
+ void *sal_systab; /* SAL system table */
+ void *boot_info; /* boot info table */
+ void *hcdp; /* HCDP table */
++ void *uga; /* UGA table */
+ efi_get_time_t *get_time;
+ efi_set_time_t *set_time;
+ efi_get_wakeup_time_t *get_wakeup_time;
+@@ -239,6 +265,7 @@ extern struct efi {
+ efi_set_variable_t *set_variable;
+ efi_get_next_high_mono_count_t *get_next_high_mono_count;
+ efi_reset_system_t *reset_system;
++ efi_set_virtual_address_map_t *set_virtual_address_map;
+ } efi;
+
+ static inline int
+@@ -260,12 +287,18 @@ efi_guid_unparse(efi_guid_t *guid, char
+
+ extern void efi_init (void);
+ extern void efi_map_pal_code (void);
++extern void efi_map_memmap(void);
+ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
+ extern void efi_gettimeofday (struct timespec *ts);
+ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
+ extern u64 efi_get_iobase (void);
+ extern u32 efi_mem_type (unsigned long phys_addr);
+ extern u64 efi_mem_attributes (unsigned long phys_addr);
++extern void efi_initialize_iomem_resources(struct resource *code_resource,
++ struct resource *data_resource);
++extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc);
++extern struct efi_memory_map memmap;
++extern int efi_enabled;
+
+ /*
+ * Variable Attributes
+--- linux-2.6.0-test6/include/linux/eisa.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/eisa.h 2003-10-05 00:36:11.000000000 -0700
+@@ -4,16 +4,6 @@
+ #include <linux/ioport.h>
+ #include <linux/device.h>
+
+-#ifdef CONFIG_EISA
+-# ifdef CONFIG_EISA_ALWAYS
+-# define EISA_bus 1
+-# else
+- extern int EISA_bus;
+-# endif
+-#else
+-# define EISA_bus 0
+-#endif
+-
+ #define EISA_SIG_LEN 8
+ #define EISA_MAX_SLOTS 8
+
+@@ -108,4 +98,10 @@ struct eisa_root_device {
+
+ int eisa_root_register (struct eisa_root_device *root);
+
++#ifdef CONFIG_EISA
++extern int EISA_bus;
++#else
++# define EISA_bus 0
++#endif
++
+ #endif
+--- linux-2.6.0-test6/include/linux/elevator.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/elevator.h 2003-10-05 00:34:17.000000000 -0700
+@@ -94,6 +94,11 @@ extern elevator_t iosched_deadline;
+ */
+ extern elevator_t iosched_as;
+
++/*
++ * completely fair queueing I/O scheduler
++ */
++extern elevator_t iosched_cfq;
++
+ extern int elevator_init(request_queue_t *, elevator_t *);
+ extern void elevator_exit(request_queue_t *);
+ extern inline int elv_rq_merge_ok(struct request *, struct bio *);
+--- linux-2.6.0-test6/include/linux/elf.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/elf.h 2003-10-05 00:33:24.000000000 -0700
+@@ -395,6 +395,7 @@ typedef struct elf64_shdr {
+ #define NT_PRFPREG 2
+ #define NT_PRPSINFO 3
+ #define NT_TASKSTRUCT 4
++#define NT_AUXV 6
+ #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */
+
+
+--- linux-2.6.0-test6/include/linux/errno.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/linux/errno.h 2003-10-05 00:36:54.000000000 -0700
+@@ -22,6 +22,7 @@
+ #define EBADTYPE 527 /* Type not supported by server */
+ #define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
+ #define EIOCBQUEUED 529 /* iocb queued, will get completion event */
++#define EIOCBRETRY 530 /* iocb queued, will trigger a retry */
+
+ #endif
+
+--- linux-2.6.0-test6/include/linux/ext3_fs_i.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/linux/ext3_fs_i.h 2003-10-05 00:36:12.000000000 -0700
+@@ -106,7 +106,7 @@ struct ext3_inode_info {
+ * during recovery. Hence we must fix the get_block-vs-truncate race
+ * by other means, so we have truncate_sem.
+ */
+- struct rw_semaphore truncate_sem;
++ struct semaphore truncate_sem;
+ struct inode vfs_inode;
+ };
+
+--- linux-2.6.0-test6/include/linux/fb.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/include/linux/fb.h 2003-10-05 00:34:22.000000000 -0700
+@@ -2,7 +2,6 @@
+ #define _LINUX_FB_H
+
+ #include <linux/tty.h>
+-#include <linux/workqueue.h>
+ #include <asm/types.h>
+ #include <asm/io.h>
+
+@@ -326,28 +325,38 @@ struct fb_cursor {
+ struct fb_image image; /* Cursor image */
+ };
+
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/workqueue.h>
++#include <linux/devfs_fs_kernel.h>
++
++/*
++ * The purpose of this structure is to translate data
++ * from the hardwre independent format of fbdev to what
++ * format the hardware needs.
++ */
++
+ #define FB_PIXMAP_DEFAULT 1 /* used internally by fbcon */
+ #define FB_PIXMAP_SYSTEM 2 /* memory is in system RAM */
+ #define FB_PIXMAP_IO 4 /* memory is iomapped */
+ #define FB_PIXMAP_SYNC 256 /* set if GPU can DMA */
+
+ struct fb_pixmap {
+- __u8 *addr; /* pointer to memory */
+- __u32 size; /* size of buffer in bytes */
+- __u32 offset; /* current offset to buffer */
+- __u32 buf_align; /* byte alignment of each bitmap */
+- __u32 scan_align; /* alignment per scanline */
+- __u32 flags; /* see FB_PIXMAP_* */
+- /* access methods */
+- void (*outbuf)(u8 *dst, u8 *addr, unsigned int size);
+- u8 (*inbuf) (u8 *addr);
+- spinlock_t lock; /* spinlock */
++ u8 *addr; /* pointer to memory */
++ u32 size; /* size of buffer in bytes */
++ u32 offset; /* current offset to buffer */
++ u32 buf_align; /* byte alignment of each bitmap */
++ u32 scan_align; /* alignment per scanline */
++ u32 access_align; /* alignment per read/write */
++ u32 flags; /* see FB_PIXMAP_* */
++ spinlock_t lock; /* spinlock */
+ atomic_t count;
++ /* access methods */
++ void (*outbuf)(u8 *addr, u8 *dst, unsigned int size);
++ u8 (*inbuf) (u8 *addr);
+ };
+-#ifdef __KERNEL__
+-
+-#include <linux/fs.h>
+-#include <linux/init.h>
+
+ struct fb_info;
+ struct vm_area_struct;
+@@ -396,24 +405,24 @@ struct fb_ops {
+ };
+
+ struct fb_info {
+- int node;
+- int flags;
+- int open; /* Has this been open already ? */
++ int node;
++ int flags;
+ #define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
+- struct fb_var_screeninfo var; /* Current var */
+- struct fb_fix_screeninfo fix; /* Current fix */
+- struct fb_monspecs monspecs; /* Current Monitor specs */
+- struct fb_cursor cursor; /* Current cursor */
+- struct work_struct queue; /* Framebuffer event queue */
+- struct fb_pixmap pixmap; /* Current pixmap */
+- struct fb_cmap cmap; /* Current cmap */
+- struct fb_ops *fbops;
+- char *screen_base; /* Virtual address */
+- struct vc_data *display_fg; /* Console visible on this display */
+- int currcon; /* Current VC. */
+- void *pseudo_palette; /* Fake palette of 16 colors */
+- /* From here on everything is device dependent */
+- void *par;
++ struct fb_var_screeninfo var; /* Current var */
++ struct fb_fix_screeninfo fix; /* Current fix */
++ struct fb_monspecs monspecs; /* Current Monitor specs */
++ struct fb_cursor cursor; /* Current cursor */
++ struct work_struct queue; /* Framebuffer event queue */
++ struct fb_pixmap pixmap; /* Image HW mapper */
++ struct fb_pixmap sprite; /* Cursor HW mapper */
++ struct fb_cmap cmap; /* Current cmap */
++ struct fb_ops *fbops;
++ char *screen_base; /* Virtual address */
++ struct vc_data *display_fg; /* Console visible on this display */
++ void *pseudo_palette; /* Fake palette of 16 colors */
++ int currcon; /* Current VC. */
++ /* From here on everything is device dependent */
++ void *par;
+ };
+
+ #ifdef MODULE
+@@ -481,12 +490,12 @@ extern int register_framebuffer(struct f
+ extern int unregister_framebuffer(struct fb_info *fb_info);
+ extern int fb_prepare_logo(struct fb_info *fb_info);
+ extern int fb_show_logo(struct fb_info *fb_info);
+-extern u32 fb_get_buffer_offset(struct fb_info *info, u32 size);
+-extern void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
+- u32 height, u32 mask, u32 shift_high, u32 shift_low,
++extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
++extern void move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf, u8 *dst, u8 *src,
++ u32 d_pitch, u32 height, u32 mask, u32 shift_high, u32 shift_low,
+ u32 mod, u32 idx);
+-extern void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
+- u32 s_pitch, u32 height);
++extern void move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf, u8 *dst, u8 *src,
++ u32 d_pitch, u32 s_pitch, u32 height);
+ extern struct fb_info *registered_fb[FB_MAX];
+ extern int num_registered_fb;
+
+--- linux-2.6.0-test6/include/linux/fs.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/fs.h 2003-10-05 00:37:00.000000000 -0700
+@@ -388,6 +388,7 @@ struct inode {
+ unsigned short i_bytes;
+ spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
+ struct semaphore i_sem;
++ struct rw_semaphore i_alloc_sem;
+ struct inode_operations *i_op;
+ struct file_operations *i_fop; /* former ->i_op->default_file_ops */
+ struct super_block *i_sb;
+@@ -480,6 +481,8 @@ static inline unsigned imajor(struct ino
+ return MAJOR(inode->i_rdev);
+ }
+
++extern struct block_device *I_BDEV(struct inode *inode);
++
+ struct fown_struct {
+ rwlock_t lock; /* protects pid, uid, euid fields */
+ int pid; /* pid or -pgrp where SIGIO should be sent */
+@@ -526,6 +529,7 @@ struct file {
+ /* Used by fs/eventpoll.c to link all the hooks to this file */
+ struct list_head f_ep_links;
+ spinlock_t f_ep_lock;
++ struct address_space *f_mapping;
+ };
+ extern spinlock_t files_lock;
+ #define file_list_lock() spin_lock(&files_lock);
+@@ -749,6 +753,11 @@ extern int vfs_rename(struct inode *, st
+ #define DT_SOCK 12
+ #define DT_WHT 14
+
++#define OSYNC_METADATA (1<<0)
++#define OSYNC_DATA (1<<1)
++#define OSYNC_INODE (1<<2)
++int generic_osync_inode(struct inode *, struct address_space *, int);
++
+ /*
+ * This is the "filldir" function type, used by readdir() to let
+ * the kernel specify what kind of dirent layout it wants to have.
+@@ -758,9 +767,9 @@ extern int vfs_rename(struct inode *, st
+ typedef int (*filldir_t)(void *, const char *, int, loff_t, ino_t, unsigned);
+
+ struct block_device_operations {
+- int (*open) (struct inode *, struct file *);
+- int (*release) (struct inode *, struct file *);
+- int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
++ int (*open) (struct block_device *, struct file *);
++ int (*release) (struct gendisk *);
++ int (*ioctl) (struct block_device *, struct file *, unsigned, unsigned long);
+ int (*media_changed) (struct gendisk *);
+ int (*revalidate_disk) (struct gendisk *);
+ struct module *owner;
+@@ -1123,11 +1132,9 @@ enum {BDEV_FILE, BDEV_SWAP, BDEV_FS, BDE
+ extern int register_blkdev(unsigned int, const char *);
+ extern int unregister_blkdev(unsigned int, const char *);
+ extern struct block_device *bdget(dev_t);
+-extern int bd_acquire(struct inode *inode);
+ extern void bd_forget(struct inode *inode);
+ extern void bdput(struct block_device *);
+ extern int blkdev_open(struct inode *, struct file *);
+-extern int blkdev_close(struct inode *, struct file *);
+ extern struct block_device *open_by_devnum(dev_t, unsigned, int);
+ extern struct file_operations def_blk_fops;
+ extern struct address_space_operations def_blk_aops;
+@@ -1135,7 +1142,7 @@ extern struct file_operations def_chr_fo
+ extern struct file_operations bad_sock_fops;
+ extern struct file_operations def_fifo_fops;
+ extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
+-extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long);
++extern int blkdev_ioctl(struct block_device *, struct file *, unsigned, unsigned long);
+ extern int blkdev_get(struct block_device *, mode_t, unsigned, int);
+ extern int blkdev_put(struct block_device *, int);
+ extern int bd_claim(struct block_device *, void *);
+@@ -1202,6 +1209,7 @@ extern void write_inode_now(struct inode
+ extern int filemap_fdatawrite(struct address_space *);
+ extern int filemap_flush(struct address_space *);
+ extern int filemap_fdatawait(struct address_space *);
++extern int filemap_write_and_wait(struct address_space *mapping);
+ extern void sync_supers(void);
+ extern void sync_filesystems(int wait);
+ extern void emergency_sync(void);
+@@ -1295,8 +1303,7 @@ extern int generic_file_readonly_mmap(st
+ extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
+ extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
+ extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *);
+-int generic_write_checks(struct inode *inode, struct file *file,
+- loff_t *pos, size_t *count, int isblk);
++int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
+ extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *);
+ extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t);
+ extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
+@@ -1314,9 +1321,6 @@ extern void
+ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
+ extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
+ const struct iovec *iov, loff_t offset, unsigned long nr_segs);
+-extern int blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
+- struct block_device *bdev, const struct iovec *iov, loff_t offset,
+- unsigned long nr_segs, get_blocks_t *get_blocks, dio_iodone_t *end_io);
+ extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos);
+ ssize_t generic_file_writev(struct file *filp, const struct iovec *iov,
+@@ -1330,7 +1334,7 @@ static inline void do_generic_file_read(
+ read_descriptor_t * desc,
+ read_actor_t actor)
+ {
+- do_generic_mapping_read(filp->f_dentry->d_inode->i_mapping,
++ do_generic_mapping_read(filp->f_mapping,
+ &filp->f_ra,
+ filp,
+ ppos,
+@@ -1338,6 +1342,32 @@ static inline void do_generic_file_read(
+ actor);
+ }
+
++int __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
++ struct block_device *bdev, const struct iovec *iov, loff_t offset,
++ unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
++ int needs_special_locking);
++
++/*
++ * For filesystems which need locking between buffered and direct access
++ */
++static inline int blockdev_direct_IO(int rw, struct kiocb *iocb,
++ struct inode *inode, struct block_device *bdev, const struct iovec *iov,
++ loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
++ dio_iodone_t end_io)
++{
++ return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
++ nr_segs, get_blocks, end_io, 1);
++}
++
++static inline int blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
++ struct inode *inode, struct block_device *bdev, const struct iovec *iov,
++ loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
++ dio_iodone_t end_io)
++{
++ return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
++ nr_segs, get_blocks, end_io, 0);
++}
++
+ extern struct file_operations generic_ro_fops;
+
+ #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
+--- linux-2.6.0-test6/include/linux/ftape.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/ftape.h 2003-10-05 00:33:24.000000000 -0700
+@@ -35,7 +35,6 @@
+ #include <linux/mm.h>
+ #endif
+ #include <linux/types.h>
+-#include <linux/version.h>
+ #include <linux/config.h>
+ #include <linux/mtio.h>
+
+--- linux-2.6.0-test6/include/linux/hdlcdrv.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/hdlcdrv.h 2003-10-05 00:33:24.000000000 -0700
+@@ -359,11 +359,11 @@ static inline int hdlcdrv_ptt(struct hdl
+ void hdlcdrv_receiver(struct net_device *, struct hdlcdrv_state *);
+ void hdlcdrv_transmitter(struct net_device *, struct hdlcdrv_state *);
+ void hdlcdrv_arbitrate(struct net_device *, struct hdlcdrv_state *);
+-int hdlcdrv_register_hdlcdrv(struct net_device *dev, const struct hdlcdrv_ops *ops,
+- unsigned int privsize, char *ifname,
+- unsigned int baseaddr, unsigned int irq,
+- unsigned int dma);
+-int hdlcdrv_unregister_hdlcdrv(struct net_device *dev);
++struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
++ unsigned int privsize, const char *ifname,
++ unsigned int baseaddr, unsigned int irq,
++ unsigned int dma);
++void hdlcdrv_unregister(struct net_device *dev);
+
+ /* -------------------------------------------------------------------- */
+
+--- linux-2.6.0-test6/include/linux/hfs_fs.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/linux/hfs_fs.h 2003-10-05 00:33:24.000000000 -0700
+@@ -267,9 +267,9 @@ extern void hfs_nat_drop_dentry(struct d
+
+ /* file.c */
+ extern hfs_s32 hfs_do_read(struct inode *, struct hfs_fork *, hfs_u32,
+- char *, hfs_u32);
++ char __user *, hfs_u32);
+ extern hfs_s32 hfs_do_write(struct inode *, struct hfs_fork *, hfs_u32,
+- const char *, hfs_u32);
++ const char __user *, hfs_u32);
+ extern void hfs_file_fix_mode(struct hfs_cat_entry *entry);
+ extern struct inode_operations hfs_file_inode_operations;
+ extern struct file_operations hfs_file_operations;
+--- linux-2.6.0-test6/include/linux/highuid.h 2003-06-14 12:18:23.000000000 -0700
++++ 25/include/linux/highuid.h 2003-10-05 00:33:24.000000000 -0700
+@@ -56,6 +56,8 @@ extern int overflowgid;
+ #define SET_GID16(var, gid) var = high2lowgid(gid)
+ #define NEW_TO_OLD_UID(uid) high2lowuid(uid)
+ #define NEW_TO_OLD_GID(gid) high2lowgid(gid)
++#define OLD_TO_NEW_UID(uid) low2highuid(uid)
++#define OLD_TO_NEW_GID(gid) low2highgid(gid)
+
+ /* specific to fs/stat.c */
+ #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
+@@ -69,6 +71,8 @@ extern int overflowgid;
+ #define SET_GID16(var, gid) do { ; } while (0)
+ #define NEW_TO_OLD_UID(uid) (uid)
+ #define NEW_TO_OLD_GID(gid) (gid)
++#define OLD_TO_NEW_UID(uid) (uid)
++#define OLD_TO_NEW_GID(gid) (gid)
+
+ #define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = (uid)
+ #define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = (gid)
+--- linux-2.6.0-test6/include/linux/init_task.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/init_task.h 2003-10-05 00:36:54.000000000 -0700
+@@ -108,6 +108,7 @@
+ .proc_lock = SPIN_LOCK_UNLOCKED, \
+ .switch_lock = SPIN_LOCK_UNLOCKED, \
+ .journal_info = NULL, \
++ .io_wait = NULL, \
+ }
+
+
+--- linux-2.6.0-test6/include/linux/input.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/input.h 2003-10-05 00:34:14.000000000 -0700
+@@ -870,6 +870,7 @@ struct input_handler {
+ char *name;
+
+ struct input_device_id *id_table;
++ struct input_device_id *blacklist;
+
+ struct list_head h_list;
+ struct list_head node;
+--- linux-2.6.0-test6/include/linux/istallion.h 2003-06-14 12:18:01.000000000 -0700
++++ 25/include/linux/istallion.h 2003-10-05 00:33:24.000000000 -0700
+@@ -21,6 +21,8 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
++#include <linux/version.h>
++
+ /*****************************************************************************/
+ #ifndef _ISTALLION_H
+ #define _ISTALLION_H
+--- linux-2.6.0-test6/include/linux/linux_logo.h 2003-06-14 12:18:05.000000000 -0700
++++ 25/include/linux/linux_logo.h 2003-10-05 00:34:22.000000000 -0700
+@@ -16,13 +16,11 @@
+
+ #include <linux/init.h>
+
+-
+ #define LINUX_LOGO_MONO 1 /* monochrome black/white */
+ #define LINUX_LOGO_VGA16 2 /* 16 colors VGA text palette */
+ #define LINUX_LOGO_CLUT224 3 /* 224 colors */
+ #define LINUX_LOGO_GRAY256 4 /* 256 levels grayscale */
+
+-
+ struct linux_logo {
+ int type; /* one of LINUX_LOGO_* */
+ unsigned int width;
+@@ -32,6 +30,6 @@ struct linux_logo {
+ const unsigned char *data;
+ };
+
+-extern const struct linux_logo *fb_find_logo(int depth);
++extern const struct linux_logo *find_logo(int depth);
+
+ #endif /* _LINUX_LINUX_LOGO_H */
+--- linux-2.6.0-test6/include/linux/list.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/linux/list.h 2003-10-05 00:36:37.000000000 -0700
+@@ -142,8 +142,11 @@ static inline void __list_del(struct lis
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
++#include <linux/kernel.h> /* BUG_ON */
+ static inline void list_del(struct list_head *entry)
+ {
++ BUG_ON(entry->prev->next != entry);
++ BUG_ON(entry->next->prev != entry);
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+@@ -325,6 +328,19 @@ static inline void list_splice_init(stru
+ pos = list_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
++/**
++ * list_for_each_entry_continue - iterate over list of given type
++ * continuing after existing point
++ * @pos: the type * to use as a loop counter.
++ * @head: the head for your list.
++ * @member: the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_continue(pos, head, member) \
++ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
++ prefetch(pos->member.next); \
++ &pos->member != (head); \
++ pos = list_entry(pos->member.next, typeof(*pos), member), \
++ prefetch(pos->member.next))
+
+ /**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+@@ -436,7 +452,7 @@ static __inline__ void hlist_del(struct
+
+ /**
+ * hlist_del_rcu - deletes entry from hash list without re-initialization
+- * @entry: the element to delete from the hash list.
++ * @n: the element to delete from the hash list.
+ *
+ * Note: list_unhashed() on entry does not return true after this,
+ * the entry is in an undefined state. It is useful for RCU based
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/lockmeter.h 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,320 @@
++/*
++ * Copyright (C) 1999-2002 Silicon Graphics, Inc.
++ *
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.h by Jack Steiner (steiner@sgi.com)
++ *
++ * Modified by Ray Bryant (raybry@us.ibm.com) Feb-Apr 2000
++ * Changes Copyright (C) 2000 IBM, Inc.
++ * Added save of index in spinlock_t to improve efficiency
++ * of "hold" time reporting for spinlocks
++ * Added support for hold time statistics for read and write
++ * locks.
++ * Moved machine dependent code to include/asm/lockmeter.h.
++ *
++ */
++
++#ifndef _LINUX_LOCKMETER_H
++#define _LINUX_LOCKMETER_H
++
++
++/*---------------------------------------------------
++ * architecture-independent lockmeter.h
++ *-------------------------------------------------*/
++
++/*
++ * raybry -- version 2: added efficient hold time statistics
++ * requires lstat recompile, so flagged as new version
++ * raybry -- version 3: added global reader lock data
++ * hawkes -- version 4: removed some unnecessary fields to simplify mips64 port
++ */
++#define LSTAT_VERSION 5
++
++int lstat_update(void*, void*, int);
++int lstat_update_time(void*, void*, int, uint32_t);
++
++/*
++ * Currently, the mips64 and sparc64 kernels talk to a 32-bit lockstat, so we
++ * need to force compatibility in the inter-communication data structure.
++ */
++
++#if defined(CONFIG_MIPS32_COMPAT)
++#define TIME_T uint32_t
++#elif defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
++#define TIME_T uint64_t
++#else
++#define TIME_T time_t
++#endif
++
++#if defined(__KERNEL__) || (!defined(CONFIG_MIPS32_COMPAT) && !defined(CONFIG_SPARC) && !defined(CONFIG_SPARC64)) || (_MIPS_SZLONG==32)
++#define POINTER void *
++#else
++#define POINTER int64_t
++#endif
++
++/*
++ * Values for the "action" parameter passed to lstat_update.
++ * ZZZ - do we want a try-success status here???
++ */
++#define LSTAT_ACT_NO_WAIT 0
++#define LSTAT_ACT_SPIN 1
++#define LSTAT_ACT_REJECT 2
++#define LSTAT_ACT_WW_SPIN 3
++#define LSTAT_ACT_SLEPT 4 /* UNUSED */
++
++#define LSTAT_ACT_MAX_VALUES 4 /* NOTE: Increase to 5 if use ACT_SLEPT */
++
++/*
++ * Special values for the low 2 bits of an RA passed to
++ * lstat_update.
++ */
++/* we use these values to figure out what kind of lock data */
++/* is stored in the statistics table entry at index ....... */
++#define LSTAT_RA_SPIN 0 /* spin lock data */
++#define LSTAT_RA_READ 1 /* read lock statistics */
++#define LSTAT_RA_SEMA 2 /* RESERVED */
++#define LSTAT_RA_WRITE 3 /* write lock statistics*/
++
++#define LSTAT_RA(n) \
++ ((void*)( ((unsigned long)__builtin_return_address(0) & ~3) | n) )
++
++/*
++ * Constants used for lock addresses in the lstat_directory
++ * to indicate special values of the lock address.
++ */
++#define LSTAT_MULTI_LOCK_ADDRESS NULL
++
++/*
++ * Maximum size of the lockstats tables. Increase this value
++ * if its not big enough. (Nothing bad happens if its not
++ * big enough although some locks will not be monitored.)
++ * We record overflows of this quantity in lstat_control.dir_overflows
++ *
++ * Note: The max value here must fit into the field set
++ * and obtained by the macro's PUT_INDEX() and GET_INDEX().
++ * This value depends on how many bits are available in the
++ * lock word in the particular machine implementation we are on.
++ */
++#define LSTAT_MAX_STAT_INDEX 2000
++
++/*
++ * Size and mask for the hash table into the directory.
++ */
++#define LSTAT_HASH_TABLE_SIZE 4096 /* must be 2**N */
++#define LSTAT_HASH_TABLE_MASK (LSTAT_HASH_TABLE_SIZE-1)
++
++#define DIRHASH(ra) ((unsigned long)(ra)>>2 & LSTAT_HASH_TABLE_MASK)
++
++/*
++ * This defines an entry in the lockstat directory. It contains
++ * information about a lock being monitored.
++ * A directory entry only contains the lock identification -
++ * counts on usage of the lock are kept elsewhere in a per-cpu
++ * data structure to minimize cache line pinging.
++ */
++typedef struct {
++ POINTER caller_ra; /* RA of code that set lock */
++ POINTER lock_ptr; /* lock address */
++ ushort next_stat_index; /* Used to link multiple locks that have the same hash table value */
++} lstat_directory_entry_t;
++
++/*
++ * A multi-dimensioned array used to contain counts for lock accesses.
++ * The array is 3-dimensional:
++ * - CPU number. Keep from thrashing cache lines between CPUs
++ * - Directory entry index. Identifies the lock
++ * - Action. Indicates what kind of contention occurred on an
++ * access to the lock.
++ *
++ * The index of an entry in the directory is the same as the 2nd index
++ * of the entry in the counts array.
++ */
++/*
++ * This table contains data for spin_locks, write locks, and read locks
++ * Not all data is used for all cases. In particular, the hold time
++ * information is not stored here for read locks since that is a global
++ * (e. g. cannot be separated out by return address) quantity.
++ * See the lstat_read_lock_counts_t structure for the global read lock
++ * hold time.
++ */
++typedef struct {
++ uint64_t cum_wait_ticks; /* sum of wait times */
++ /* for write locks, sum of time a */
++ /* writer is waiting for a reader */
++ int64_t cum_hold_ticks; /* cumulative sum of holds */
++ /* not used for read mode locks */
++ /* must be signed. ............... */
++ uint32_t max_wait_ticks; /* max waiting time */
++ uint32_t max_hold_ticks; /* max holding time */
++ uint64_t cum_wait_ww_ticks; /* sum times writer waits on writer*/
++ uint32_t max_wait_ww_ticks; /* max wait time writer vs writer */
++ /* prev 2 only used for write locks*/
++ uint32_t acquire_time; /* time lock acquired this CPU */
++ uint32_t count[LSTAT_ACT_MAX_VALUES];
++} lstat_lock_counts_t;
++
++typedef lstat_lock_counts_t lstat_cpu_counts_t[LSTAT_MAX_STAT_INDEX];
++
++/*
++ * User request to:
++ * - turn statistic collection on/off, or to reset
++ */
++#define LSTAT_OFF 0
++#define LSTAT_ON 1
++#define LSTAT_RESET 2
++#define LSTAT_RELEASE 3
++
++#define LSTAT_MAX_READ_LOCK_INDEX 1000
++typedef struct {
++ POINTER lock_ptr; /* address of lock for output stats */
++ uint32_t read_lock_count;
++ int64_t cum_hold_ticks; /* sum of read lock hold times over */
++ /* all callers. ....................*/
++ uint32_t write_index; /* last write lock hash table index */
++ uint32_t busy_periods; /* count of busy periods ended this */
++ uint64_t start_busy; /* time this busy period started. ..*/
++ uint64_t busy_ticks; /* sum of busy periods this lock. ..*/
++ uint64_t max_busy; /* longest busy period for this lock*/
++ uint32_t max_readers; /* maximum number of readers ...... */
++#ifdef USER_MODE_TESTING
++ rwlock_t entry_lock; /* lock for this read lock entry... */
++ /* avoid having more than one rdr at*/
++ /* needed for user space testing... */
++ /* not needed for kernel 'cause it */
++ /* is non-preemptive. ............. */
++#endif
++} lstat_read_lock_counts_t;
++typedef lstat_read_lock_counts_t lstat_read_lock_cpu_counts_t[LSTAT_MAX_READ_LOCK_INDEX];
++
++#if defined(__KERNEL__) || defined(USER_MODE_TESTING)
++
++#ifndef USER_MODE_TESTING
++#include <asm/lockmeter.h>
++#else
++#include "asm_newlockmeter.h"
++#endif
++
++/*
++ * Size and mask for the hash table into the directory.
++ */
++#define LSTAT_HASH_TABLE_SIZE 4096 /* must be 2**N */
++#define LSTAT_HASH_TABLE_MASK (LSTAT_HASH_TABLE_SIZE-1)
++
++#define DIRHASH(ra) ((unsigned long)(ra)>>2 & LSTAT_HASH_TABLE_MASK)
++
++/*
++ * This version eliminates the per processor lock stack. What we do is to
++ * store the index of the lock hash structure in unused bits in the lock
++ * itself. Then on unlock we can find the statistics record without doing
++ * any additional hash or lock stack lookup. This works for spin_locks.
++ * Hold time reporting is now basically as cheap as wait time reporting
++ * so we ignore the difference between LSTAT_ON_HOLD and LSTAT_ON_WAIT
++ * as in version 1.1.* of lockmeter.
++ *
++ * For rw_locks, we store the index of a global reader stats structure in
++ * the lock and the writer index is stored in the latter structure.
++ * For read mode locks we hash at the time of the lock to find an entry
++ * in the directory for reader wait time and the like.
++ * At unlock time for read mode locks, we update just the global structure
++ * so we don't need to know the reader directory index value at unlock time.
++ *
++ */
++
++/*
++ * Protocol to change lstat_control.state
++ * This is complicated because we don't want the cum_hold_time for
++ * a rw_lock to be decremented in _read_lock_ without making sure it
++ * is incremented in _read_lock_ and vice versa. So here is the
++ * way we change the state of lstat_control.state:
++ * I. To Turn Statistics On
++ * After allocating storage, set lstat_control.state non-zero.
++ * This works because we don't start updating statistics for in use
++ * locks until the reader lock count goes to zero.
++ * II. To Turn Statistics Off:
++ * (0) Disable interrupts on this CPU
++ * (1) Seize the lstat_control.directory_lock
++ * (2) Obtain the current value of lstat_control.next_free_read_lock_index
++ * (3) Store a zero in lstat_control.state.
++ * (4) Release the lstat_control.directory_lock
++ * (5) For each lock in the read lock list up to the saved value
++ * (well, -1) of the next_free_read_lock_index, do the following:
++ * (a) Check validity of the stored lock address
++ * by making sure that the word at the saved addr
++ * has an index that matches this entry. If not
++ * valid, then skip this entry.
++ * (b) If there is a write lock already set on this lock,
++ * skip to (d) below.
++ * (c) Set a non-metered write lock on the lock
++ * (d) set the cached INDEX in the lock to zero
++ * (e) Release the non-metered write lock.
++ * (6) Re-enable interrupts
++ *
++ * These rules ensure that a read lock will not have its statistics
++ * partially updated even though the global lock recording state has
++ * changed. See put_lockmeter_info() for implementation.
++ *
++ * The reason for (b) is that there may be write locks set on the
++ * syscall path to put_lockmeter_info() from user space. If we do
++ * not do this check, then we can deadlock. A similar problem would
++ * occur if the lock was read locked by the current CPU. At the
++ * moment this does not appear to happen.
++ */
++
++/*
++ * Main control structure for lockstat. Used to turn statistics on/off
++ * and to maintain directory info.
++ */
++typedef struct {
++ int state;
++ spinlock_t control_lock; /* used to serialize turning statistics on/off */
++ spinlock_t directory_lock; /* for serialize adding entries to directory */
++ volatile int next_free_dir_index;/* next free entry in the directory */
++ /* FIXME not all of these fields are used / needed .............. */
++ /* the following fields represent data since */
++ /* first "lstat on" or most recent "lstat reset" */
++ TIME_T first_started_time; /* time when measurement first enabled */
++ TIME_T started_time; /* time when measurement last started */
++ TIME_T ending_time; /* time when measurement last disabled */
++ uint64_t started_cycles64; /* cycles when measurement last started */
++ uint64_t ending_cycles64; /* cycles when measurement last disabled */
++ uint64_t enabled_cycles64; /* total cycles with measurement enabled */
++ int intervals; /* number of measurement intervals recorded */
++ /* i. e. number of times did lstat on;lstat off */
++ lstat_directory_entry_t *dir; /* directory */
++ int dir_overflow; /* count of times ran out of space in directory */
++ int rwlock_overflow; /* count of times we couldn't allocate a rw block*/
++ ushort *hashtab; /* hash table for quick dir scans */
++ lstat_cpu_counts_t *counts[NR_CPUS]; /* Array of pointers to per-cpu stats */
++ int next_free_read_lock_index; /* next rwlock reader (global) stats block */
++ lstat_read_lock_cpu_counts_t *read_lock_counts[NR_CPUS]; /* per cpu read lock stats */
++} lstat_control_t;
++
++#endif /* defined(__KERNEL__) || defined(USER_MODE_TESTING) */
++
++typedef struct {
++ short lstat_version; /* version of the data */
++ short state; /* the current state is returned */
++ int maxcpus; /* Number of cpus present */
++ int next_free_dir_index; /* index of the next free directory entry */
++ TIME_T first_started_time; /* when measurement enabled for first time */
++ TIME_T started_time; /* time in secs since 1969 when stats last turned on */
++ TIME_T ending_time; /* time in secs since 1969 when stats last turned off */
++ uint32_t cycleval; /* cycles per second */
++#ifdef notyet
++ void *kernel_magic_addr; /* address of kernel_magic */
++ void *kernel_end_addr; /* contents of kernel magic (points to "end") */
++#endif
++ int next_free_read_lock_index; /* index of next (global) read lock stats struct */
++ uint64_t started_cycles64; /* cycles when measurement last started */
++ uint64_t ending_cycles64; /* cycles when stats last turned off */
++ uint64_t enabled_cycles64; /* total cycles with measurement enabled */
++ int intervals; /* number of measurement intervals recorded */
++ /* i.e. number of times we did lstat on;lstat off*/
++ int dir_overflow; /* number of times we wanted more space in directory */
++ int rwlock_overflow; /* # of times we wanted more space in read_locks_count */
++ struct new_utsname uts; /* info about machine where stats are measured */
++ /* -T option of lockstat allows data to be */
++ /* moved to another machine. ................. */
++} lstat_user_request_t;
++
++#endif /* _LINUX_LOCKMETER_H */
+--- linux-2.6.0-test6/include/linux/mca.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/mca.h 2003-10-05 00:33:24.000000000 -0700
+@@ -136,10 +136,6 @@ extern void mca_unregister_driver(struct
+ /* WARNING: only called by the boot time device setup */
+ extern int mca_register_device(int bus, struct mca_device *mca_dev);
+
+-#ifdef CONFIG_MCA_LEGACY
+-#include <linux/mca-legacy.h>
+-#endif
+-
+ #ifdef CONFIG_MCA_PROC_FS
+ extern void mca_do_proc_init(void);
+ extern void mca_set_adapter_procfn(int slot, MCA_ProcFn, void* dev);
+--- linux-2.6.0-test6/include/linux/mca-legacy.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/linux/mca-legacy.h 2003-10-05 00:33:24.000000000 -0700
+@@ -7,6 +7,8 @@
+ #ifndef _LINUX_MCA_LEGACY_H
+ #define _LINUX_MCA_LEGACY_H
+
++#include <linux/mca.h>
++
+ #warning "MCA legacy - please move your driver to the new sysfs api"
+
+ /* MCA_NOTFOUND is an error condition. The other two indicate
+--- linux-2.6.0-test6/include/linux/mman.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/mman.h 2003-10-05 00:34:49.000000000 -0700
+@@ -28,8 +28,13 @@ static inline void vm_unacct_memory(long
+ vm_acct_memory(-pages);
+ }
+
+-/* Optimisation macro. */
+-#define _calc_vm_trans(x,bit1,bit2) \
++/*
++ * Optimisation macro. It is equivalent to:
++ * (x & bit1) ? bit2 : 0
++ * but this version is faster.
++ * ("bit1" and "bit2" must be single bits)
++ */
++#define _calc_vm_trans(x, bit1, bit2) \
+ ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \
+ : ((x) & (bit1)) / ((bit1) / (bit2)))
+
+--- linux-2.6.0-test6/include/linux/mm.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/mm.h 2003-10-05 00:34:41.000000000 -0700
+@@ -196,7 +196,7 @@ struct page {
+ #if defined(WANT_PAGE_VIRTUAL)
+ void *virtual; /* Kernel virtual address (NULL if
+ not kmapped, ie. highmem) */
+-#endif /* CONFIG_HIGMEM || WANT_PAGE_VIRTUAL */
++#endif /* WANT_PAGE_VIRTUAL */
+ };
+
+ /*
+@@ -323,7 +323,6 @@ static inline void put_page(struct page
+ * The zone field is never updated after free_area_init_core()
+ * sets it, so none of the operations on it need to be atomic.
+ */
+-#define NODE_SHIFT 4
+ #define ZONE_SHIFT (BITS_PER_LONG - 8)
+
+ struct zone;
+--- linux-2.6.0-test6/include/linux/mmzone.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/mmzone.h 2003-10-05 00:34:41.000000000 -0700
+@@ -10,13 +10,8 @@
+ #include <linux/wait.h>
+ #include <linux/cache.h>
+ #include <linux/threads.h>
++#include <linux/numa.h>
+ #include <asm/atomic.h>
+-#ifdef CONFIG_DISCONTIGMEM
+-#include <asm/numnodes.h>
+-#endif
+-#ifndef MAX_NUMNODES
+-#define MAX_NUMNODES 1
+-#endif
+
+ /* Free memory management - zoned buddy allocator. */
+ #ifndef CONFIG_FORCE_MAX_ZONEORDER
+@@ -303,19 +298,34 @@ extern void setup_per_zone_pages_min(voi
+ #define numa_node_id() (cpu_to_node(smp_processor_id()))
+
+ #ifndef CONFIG_DISCONTIGMEM
++
+ extern struct pglist_data contig_page_data;
+ #define NODE_DATA(nid) (&contig_page_data)
+ #define NODE_MEM_MAP(nid) mem_map
+-#define MAX_NR_NODES 1
++#define MAX_NODES_SHIFT 0
++
+ #else /* CONFIG_DISCONTIGMEM */
+
+ #include <asm/mmzone.h>
+
+-/* page->zone is currently 8 bits ... */
+-#define MAX_NR_NODES (255 / MAX_NR_ZONES)
++#if BITS_PER_LONG == 32
++/*
++ * with 32 bit flags field, page->zone is currently 8 bits.
++ * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
++ */
++#define MAX_NODES_SHIFT 6
++#elif BITS_PER_LONG == 64
++/*
++ * with 64 bit flags field, there's plenty of room.
++ */
++#define MAX_NODES_SHIFT 10
++#endif
+
+ #endif /* !CONFIG_DISCONTIGMEM */
+
++#if NODES_SHIFT > MAX_NODES_SHIFT
++#error NODES_SHIFT > MAX_NODES_SHIFT
++#endif
+
+ extern DECLARE_BITMAP(node_online_map, MAX_NUMNODES);
+ extern DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS);
+--- linux-2.6.0-test6/include/linux/moduleparam.h 2003-06-16 22:32:21.000000000 -0700
++++ 25/include/linux/moduleparam.h 2003-10-05 00:33:24.000000000 -0700
+@@ -3,6 +3,7 @@
+ /* (C) Copyright 2001, 2002 Rusty Russell IBM Corporation */
+ #include <linux/init.h>
+ #include <linux/stringify.h>
++#include <linux/kernel.h>
+
+ /* You can override this manually, but generally this should match the
+ module name. */
+@@ -33,6 +34,17 @@ struct kparam_string {
+ char *string;
+ };
+
++/* Special one for arrays */
++struct kparam_array
++{
++ unsigned int max;
++ unsigned int *num;
++ param_set_fn set;
++ param_get_fn get;
++ unsigned int elemsize;
++ void *elem;
++};
++
+ /* This is the fundamental function for registering boot/module
+ parameters. perm sets the visibility in driverfs: 000 means it's
+ not there, read bits mean it's readable, write bits mean it's
+@@ -112,10 +124,16 @@ extern int param_set_invbool(const char
+ extern int param_get_invbool(char *buffer, struct kernel_param *kp);
+ #define param_check_invbool(name, p) __param_check(name, p, int)
+
+-/* First two elements are the max and min array length (which don't change) */
+-extern int param_set_intarray(const char *val, struct kernel_param *kp);
+-extern int param_get_intarray(char *buffer, struct kernel_param *kp);
+-#define param_check_intarray(name, p) __param_check(name, p, int *)
++/* Comma-separated array: num is set to number they actually specified. */
++#define module_param_array(name, type, num, perm) \
++ static struct kparam_array __param_arr_##name \
++ = { ARRAY_SIZE(name), &num, param_set_##type, param_get_##type, \
++ sizeof(name[0]), name }; \
++ module_param_call(name, param_array_set, param_array_get, \
++ &__param_arr_##name, perm)
++
++extern int param_array_set(const char *val, struct kernel_param *kp);
++extern int param_array_get(char *buffer, struct kernel_param *kp);
+
+ extern int param_set_copystring(const char *val, struct kernel_param *kp);
+
+@@ -123,5 +141,6 @@ int param_array(const char *name,
+ const char *val,
+ unsigned int min, unsigned int max,
+ void *elem, int elemsize,
+- int (*set)(const char *, struct kernel_param *kp));
++ int (*set)(const char *, struct kernel_param *kp),
++ int *num);
+ #endif /* _LINUX_MODULE_PARAM_TYPES_H */
+--- linux-2.6.0-test6/include/linux/netdevice.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/netdevice.h 2003-10-05 00:33:46.000000000 -0700
+@@ -456,6 +456,13 @@ struct net_device
+ /* bridge stuff */
+ struct net_bridge_port *br_port;
+
++#ifdef CONFIG_KGDB
++ int kgdb_is_trapped;
++#endif
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ void (*poll_controller)(struct net_device *);
++#endif
++
+ #ifdef CONFIG_NET_FASTROUTE
+ #define NETDEV_FASTROUTE_HMASK 0xF
+ /* Semi-private data. Keep it at the end of device struct. */
+@@ -530,6 +537,11 @@ extern int dev_new_index(void);
+ extern struct net_device *dev_get_by_index(int ifindex);
+ extern struct net_device *__dev_get_by_index(int ifindex);
+ extern int dev_restart(struct net_device *dev);
++#ifdef CONFIG_KGDB
++extern int kgdb_eth_is_trapped(void);
++extern int kgdb_net_interrupt(struct sk_buff *skb);
++extern void kgdb_send_arp_request(void);
++#endif
+
+ typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
+ extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf);
+@@ -588,12 +600,22 @@ static inline void netif_start_queue(str
+
+ static inline void netif_wake_queue(struct net_device *dev)
+ {
++#ifdef CONFIG_KGDB
++ if (kgdb_eth_is_trapped()) {
++ return;
++ }
++#endif
+ if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
+ __netif_schedule(dev);
+ }
+
+ static inline void netif_stop_queue(struct net_device *dev)
+ {
++#ifdef CONFIG_KGDB
++ if (kgdb_eth_is_trapped()) {
++ return;
++ }
++#endif
+ set_bit(__LINK_STATE_XOFF, &dev->state);
+ }
+
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/netfilter_bridge/ebt_limit.h 2003-10-05 00:33:24.000000000 -0700
+@@ -0,0 +1,23 @@
++#ifndef __LINUX_BRIDGE_EBT_LIMIT_H
++#define __LINUX_BRIDGE_EBT_LIMIT_H
++
++#define EBT_LIMIT_MATCH "limit"
++
++/* timings are in milliseconds. */
++#define EBT_LIMIT_SCALE 10000
++
++/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
++ seconds, or one every 59 hours. */
++
++struct ebt_limit_info
++{
++ u_int32_t avg; /* Average secs between packets * scale */
++ u_int32_t burst; /* Period multiplier for upper limit. */
++
++ /* Used internally by the kernel */
++ unsigned long prev;
++ u_int32_t credit;
++ u_int32_t credit_cap, cost;
++};
++
++#endif
+--- linux-2.6.0-test6/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-06-14 12:18:29.000000000 -0700
++++ 25/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2003-10-05 00:33:24.000000000 -0700
+@@ -62,6 +62,14 @@ struct ip_conntrack_tuple
+ } dst;
+ };
+
++/* This is optimized opposed to a memset of the whole structure. Everything we
++ * really care about is the source/destination unions */
++#define IP_CT_TUPLE_U_BLANK(tuple) \
++ do { \
++ (tuple)->src.u.all = 0; \
++ (tuple)->dst.u.all = 0; \
++ } while (0)
++
+ enum ip_conntrack_dir
+ {
+ IP_CT_DIR_ORIGINAL,
+--- linux-2.6.0-test6/include/linux/netfilter_ipv4/ip_nat_rule.h 2003-06-14 12:18:33.000000000 -0700
++++ 25/include/linux/netfilter_ipv4/ip_nat_rule.h 2003-10-05 00:33:24.000000000 -0700
+@@ -14,5 +14,10 @@ extern int ip_nat_rule_find(struct sk_bu
+ const struct net_device *out,
+ struct ip_conntrack *ct,
+ struct ip_nat_info *info);
++
++extern unsigned int
++alloc_null_binding(struct ip_conntrack *conntrack,
++ struct ip_nat_info *info,
++ unsigned int hooknum);
+ #endif
+ #endif /* _IP_NAT_RULE_H */
+--- linux-2.6.0-test6/include/linux/nfs_fs.h 2003-07-27 12:14:40.000000000 -0700
++++ 25/include/linux/nfs_fs.h 2003-10-05 00:36:42.000000000 -0700
+@@ -271,7 +271,7 @@ nfs_file_cred(struct file *file)
+ /*
+ * linux/fs/nfs/direct.c
+ */
+-extern int nfs_direct_IO(int, struct file *, const struct iovec *, loff_t,
++extern int nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
+ unsigned long);
+
+ /*
+--- linux-2.6.0-test6/include/linux/nfs_page.h 2003-06-26 22:07:26.000000000 -0700
++++ 25/include/linux/nfs_page.h 2003-10-05 00:36:43.000000000 -0700
+@@ -46,7 +46,6 @@ extern struct nfs_page *nfs_create_reque
+ unsigned int, unsigned int);
+ extern void nfs_clear_request(struct nfs_page *req);
+ extern void nfs_release_request(struct nfs_page *req);
+-extern void nfs_release_list(struct list_head *list);
+
+
+ extern void nfs_list_add_request(struct nfs_page *, struct list_head *);
+@@ -56,7 +55,6 @@ extern int nfs_scan_list(struct list_hea
+ extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
+ unsigned int);
+ extern int nfs_wait_on_request(struct nfs_page *);
+-extern int nfs_wait_for_reads(struct list_head *);
+
+ extern spinlock_t nfs_wreq_lock;
+
+--- linux-2.6.0-test6/include/linux/nfs_xdr.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/nfs_xdr.h 2003-10-05 00:36:45.000000000 -0700
+@@ -591,6 +591,7 @@ struct nfs4_compound {
+ #endif /* CONFIG_NFS_V4 */
+
+ struct nfs_read_data {
++ int flags;
+ struct rpc_task task;
+ struct inode *inode;
+ struct rpc_cred *cred;
+@@ -605,6 +606,7 @@ struct nfs_read_data {
+ };
+
+ struct nfs_write_data {
++ int flags;
+ struct rpc_task task;
+ struct inode *inode;
+ struct rpc_cred *cred;
+@@ -634,16 +636,9 @@ struct nfs_rpc_ops {
+ struct nfs_fh *, struct nfs_fattr *);
+ int (*access) (struct inode *, struct rpc_cred *, int);
+ int (*readlink)(struct inode *, struct page *);
+- int (*read) (struct inode *, struct rpc_cred *,
+- struct nfs_fattr *,
+- int, unsigned int, unsigned int,
+- struct page *, int *eofp);
+- int (*write) (struct inode *, struct rpc_cred *,
+- struct nfs_fattr *,
+- int, unsigned int, unsigned int,
+- struct page *, struct nfs_writeverf *verfp);
+- int (*commit) (struct inode *, struct nfs_fattr *,
+- unsigned long, unsigned int);
++ int (*read) (struct nfs_read_data *);
++ int (*write) (struct nfs_write_data *);
++ int (*commit) (struct nfs_write_data *);
+ int (*create) (struct inode *, struct qstr *, struct iattr *,
+ int, struct nfs_fh *, struct nfs_fattr *);
+ int (*remove) (struct inode *, struct qstr *);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/numa.h 2003-10-05 00:34:41.000000000 -0700
+@@ -0,0 +1,16 @@
++#ifndef _LINUX_NUMA_H
++#define _LINUX_NUMA_H
++
++#include <linux/config.h>
++
++#ifdef CONFIG_DISCONTIGMEM
++#include <asm/numnodes.h>
++#endif
++
++#ifndef NODES_SHIFT
++#define NODES_SHIFT 0
++#endif
++
++#define MAX_NUMNODES (1 << NODES_SHIFT)
++
++#endif /* _LINUX_NUMA_H */
+--- linux-2.6.0-test6/include/linux/pagemap.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/pagemap.h 2003-10-05 00:37:03.000000000 -0700
+@@ -71,7 +71,7 @@ extern struct page * find_trylock_page(s
+ extern struct page * find_or_create_page(struct address_space *mapping,
+ unsigned long index, unsigned int gfp_mask);
+ extern unsigned int find_get_pages(struct address_space *mapping,
+- pgoff_t start, unsigned int nr_pages,
++ pgoff_t *next, unsigned int nr_pages,
+ struct page **pages);
+
+ /*
+@@ -153,17 +153,27 @@ static inline void ___add_to_page_cache(
+ extern void FASTCALL(__lock_page(struct page *page));
+ extern void FASTCALL(unlock_page(struct page *page));
+
+-static inline void lock_page(struct page *page)
++
++extern int FASTCALL(__lock_page_wq(struct page *page, wait_queue_t *wait));
++static inline int lock_page_wq(struct page *page, wait_queue_t *wait)
+ {
+ if (TestSetPageLocked(page))
+- __lock_page(page);
++ return __lock_page_wq(page, wait);
++ else
++ return 0;
++}
++
++static inline void lock_page(struct page *page)
++{
++ lock_page_wq(page, NULL);
+ }
+
+ /*
+ * This is exported only for wait_on_page_locked/wait_on_page_writeback.
+ * Never use this directly!
+ */
+-extern void FASTCALL(wait_on_page_bit(struct page *page, int bit_nr));
++extern int FASTCALL(wait_on_page_bit_wq(struct page *page, int bit_nr,
++ wait_queue_t *wait));
+
+ /*
+ * Wait for a page to be unlocked.
+@@ -172,19 +182,33 @@ extern void FASTCALL(wait_on_page_bit(st
+ * ie with increased "page->count" so that the page won't
+ * go away during the wait..
+ */
+-static inline void wait_on_page_locked(struct page *page)
++static inline int wait_on_page_locked_wq(struct page *page, wait_queue_t *wait)
+ {
+ if (PageLocked(page))
+- wait_on_page_bit(page, PG_locked);
++ return wait_on_page_bit_wq(page, PG_locked, wait);
++ return 0;
++}
++
++static inline int wait_on_page_writeback_wq(struct page *page,
++ wait_queue_t *wait)
++{
++ if (PageWriteback(page))
++ return wait_on_page_bit_wq(page, PG_writeback, wait);
++ return 0;
++}
++
++static inline void wait_on_page_locked(struct page *page)
++{
++ wait_on_page_locked_wq(page, NULL);
+ }
+
+ /*
+ * Wait for a page to complete writeback
+ */
++
+ static inline void wait_on_page_writeback(struct page *page)
+ {
+- if (PageWriteback(page))
+- wait_on_page_bit(page, PG_writeback);
++ wait_on_page_writeback_wq(page, NULL);
+ }
+
+ extern void end_page_writeback(struct page *page);
+--- linux-2.6.0-test6/include/linux/pagevec.h 2003-06-14 12:18:51.000000000 -0700
++++ 25/include/linux/pagevec.h 2003-10-05 00:37:03.000000000 -0700
+@@ -23,7 +23,7 @@ void __pagevec_lru_add(struct pagevec *p
+ void __pagevec_lru_add_active(struct pagevec *pvec);
+ void pagevec_strip(struct pagevec *pvec);
+ unsigned int pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
+- pgoff_t start, unsigned int nr_pages);
++ pgoff_t *next, unsigned int nr_pages);
+
+ static inline void pagevec_init(struct pagevec *pvec, int cold)
+ {
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/parser.h 2003-10-05 00:33:24.000000000 -0700
+@@ -0,0 +1,21 @@
++struct match_token {
++ int token;
++ char *pattern;
++};
++
++typedef struct match_token match_table_t[];
++
++enum {MAX_OPT_ARGS = 3};
++
++typedef struct {
++ char *from;
++ char *to;
++} substring_t;
++
++int match_token(char *s, match_table_t table, substring_t args[]);
++
++int match_int(substring_t *, int *result);
++int match_octal(substring_t *, int *result);
++int match_hex(substring_t *, int *result);
++void match_strcpy(char *, substring_t *);
++char *match_strdup(substring_t *);
+--- linux-2.6.0-test6/include/linux/pci.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/pci.h 2003-10-05 00:36:20.000000000 -0700
+@@ -36,6 +36,7 @@
+ #define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+ #define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+ #define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
++#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+ #define PCI_STATUS 0x06 /* 16 bits */
+ #define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+@@ -198,6 +199,8 @@
+ #define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+ #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+ #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
++#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
++#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+ #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+ #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+ #define PCI_CAP_SIZEOF 4
+@@ -275,11 +278,13 @@
+ #define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+ #define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+ #define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
++#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */
+ #define PCI_MSI_RFU 3 /* Rest of capability flags */
+ #define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+ #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+ #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+ #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
++#define PCI_MSI_MASK_BIT 16 /* Mask bits register */
+
+ /* CompactPCI Hotswap Register */
+
+@@ -515,7 +520,6 @@ struct pci_driver {
+ const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
+ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
+ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
+- int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */
+ int (*suspend) (struct pci_dev *dev, u32 state); /* Device suspended */
+ int (*resume) (struct pci_dev *dev); /* Device woken up */
+ int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */
+@@ -696,6 +700,18 @@ void pci_pool_free (struct pci_pool *poo
+ extern struct pci_dev *isa_bridge;
+ #endif
+
++#ifndef CONFIG_PCI_USE_VECTOR
++static inline void pci_scan_msi_device(struct pci_dev *dev) {}
++static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
++static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
++#else
++extern void pci_scan_msi_device(struct pci_dev *dev);
++extern int pci_enable_msi(struct pci_dev *dev);
++extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
++extern int msi_alloc_vectors(struct pci_dev* dev, int *vector, int nvec);
++extern int msi_free_vectors(struct pci_dev* dev, int *vector, int nvec);
++#endif
++
+ #endif /* CONFIG_PCI */
+
+ /* Include architecture-dependent settings and functions */
+--- linux-2.6.0-test6/include/linux/pci_ids.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/pci_ids.h 2003-10-05 00:36:28.000000000 -0700
+@@ -519,6 +519,7 @@
+ #define PCI_DEVICE_ID_CT_65550 0x00e0
+ #define PCI_DEVICE_ID_CT_65554 0x00e4
+ #define PCI_DEVICE_ID_CT_65555 0x00e5
++#define PCI_DEVICE_ID_CT_69000 0x00c0
+
+ #define PCI_VENDOR_ID_MIRO 0x1031
+ #define PCI_DEVICE_ID_MIRO_36050 0x5601
+@@ -896,6 +897,7 @@
+
+ #define PCI_VENDOR_ID_SGI 0x10a9
+ #define PCI_DEVICE_ID_SGI_IOC3 0x0003
++#define PCI_DEVICE_ID_SGI_IOC4 0x100a
+ #define PCI_VENDOR_ID_SGI_LITHIUM 0x1002
+
+ #define PCI_VENDOR_ID_ACC 0x10aa
+@@ -1060,6 +1062,16 @@
+ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
+ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
+ #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4280 0x0281
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_SE 0x0282
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO 0x0286
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_U 0x0301
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800 0x0302
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_U 0x0311
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600 0x0312
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_U 0x0321
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200 0x0322
+
+ #define PCI_VENDOR_ID_IMS 0x10e0
+ #define PCI_DEVICE_ID_IMS_8849 0x8849
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/linux/pci_msi.h 2003-10-05 00:36:20.000000000 -0700
+@@ -0,0 +1,193 @@
++/*
++ * ../include/linux/pci_msi.h
++ *
++ */
++
++#ifndef _ASM_PCI_MSI_H
++#define _ASM_PCI_MSI_H
++
++#include <linux/pci.h>
++
++#define MSI_AUTO -1
++#define NR_REPEATS 23
++#define NR_RESERVED_VECTORS 3 /*FIRST_DEVICE_VECTOR,FIRST_SYSTEM_VECTOR,0x80 */
++
++/*
++ * Assume the maximum number of hot plug slots supported by the system is about
++ * ten. The worstcase is that each of these slots is hot-added with a device,
++ * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which
++ * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined
++ * as below to ensure at least one message is assigned to each detected MSI/
++ * MSI-X device function.
++ */
++#define NR_HP_RESERVED_VECTORS 20
++
++extern int vector_irq[NR_IRQS];
++extern cpumask_t pending_irq_balance_cpumask[NR_IRQS];
++extern void (*interrupt[NR_IRQS])(void);
++
++#ifdef CONFIG_SMP
++#define set_msi_irq_affinity set_msi_affinity
++#else
++#define set_msi_irq_affinity NULL
++static inline void move_msi(int vector) {}
++#endif
++
++#ifndef CONFIG_X86_IO_APIC
++static inline int get_ioapic_vector(struct pci_dev *dev) { return -1;}
++static inline void restore_ioapic_irq_handler(int irq) {}
++#else
++extern void restore_ioapic_irq_handler(int irq);
++#endif
++
++/*
++ * MSI-X Address Register
++ */
++#define PCI_MSIX_FLAGS_QSIZE 0x7FF
++#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
++#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
++#define PCI_MSIX_FLAGS_BITMASK (1 << 0)
++
++#define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0
++#define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4
++#define PCI_MSIX_ENTRY_DATA_OFFSET 8
++#define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12
++#define PCI_MSIX_ENTRY_SIZE 16
++
++#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
++#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
++#define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI)
++#define msi_data_reg(base, is64bit) \
++ ( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
++#define msi_mask_bits_reg(base, is64bit) \
++ ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
++#define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE
++#define multi_msi_capable(control) \
++ (1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1))
++#define multi_msi_enable(control, num) \
++ control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE);
++#define is_64bit_address(control) (control & PCI_MSI_FLAGS_64BIT)
++#define is_mask_bit_support(control) (control & PCI_MSI_FLAGS_MASKBIT)
++#define msi_enable(control, num) multi_msi_enable(control, num); \
++ control |= PCI_MSI_FLAGS_ENABLE
++
++#define msix_control_reg msi_control_reg
++#define msix_table_offset_reg(base) (base + 0x04)
++#define msix_pba_offset_reg(base) (base + 0x08)
++#define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE
++#define msix_disable(control) control &= ~PCI_MSIX_FLAGS_ENABLE
++#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1)
++#define multi_msix_capable msix_table_size
++#define msix_unmask(address) (address & ~PCI_MSIX_FLAGS_BITMASK)
++#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
++#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
++
++extern char __dbg_str_buf[256];
++#define _DEFINE_DBG_BUFFER char __dbg_str_buf[256];
++#define _DBG_K_TRACE_ENTRY ((unsigned int)0x00000001)
++#define _DBG_K_TRACE_EXIT ((unsigned int)0x00000002)
++#define _DBG_K_INFO ((unsigned int)0x00000004)
++#define _DBG_K_ERROR ((unsigned int)0x00000008)
++#define _DBG_K_TRACE (_DBG_K_TRACE_ENTRY | _DBG_K_TRACE_EXIT)
++
++#define _DEBUG_LEVEL (_DBG_K_INFO | _DBG_K_ERROR | _DBG_K_TRACE)
++#define _DBG_PRINT( dbg_flags, args... ) \
++if ( _DEBUG_LEVEL & (dbg_flags) ) \
++{ \
++ int len; \
++ len = sprintf(__dbg_str_buf, "%s:%d: %s ", \
++ __FILE__, __LINE__, __FUNCTION__ ); \
++ sprintf(__dbg_str_buf + len, args); \
++ printk(KERN_INFO "%s\n", __dbg_str_buf); \
++}
++
++#define MSI_FUNCTION_TRACE_ENTER \
++ _DBG_PRINT (_DBG_K_TRACE_ENTRY, "%s", "[Entry]");
++#define MSI_FUNCTION_TRACE_EXIT \
++ _DBG_PRINT (_DBG_K_TRACE_EXIT, "%s", "[Entry]");
++
++/*
++ * MSI Defined Data Structures
++ */
++#define MSI_ADDRESS_HEADER 0xfee
++#define MSI_ADDRESS_HEADER_SHIFT 12
++#define MSI_ADDRESS_HEADER_MASK 0xfff000
++#define MSI_TARGET_CPU_SHIFT 4
++#define MSI_TARGET_CPU_MASK 0xff
++#define MSI_DELIVERY_MODE 0
++#define MSI_LEVEL_MODE 1 /* Edge always assert */
++#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */
++#define MSI_LOGICAL_MODE 1
++#define MSI_REDIRECTION_HINT_MODE 0
++#ifdef CONFIG_SMP
++#define MSI_TARGET_CPU logical_smp_processor_id()
++#else
++#define MSI_TARGET_CPU TARGET_CPUS
++#endif
++
++struct msg_data {
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++ __u32 vector : 8;
++ __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
++ __u32 reserved_1 : 3;
++ __u32 level : 1; /* 0: deassert | 1: assert */
++ __u32 trigger : 1; /* 0: edge | 1: level */
++ __u32 reserved_2 : 16;
++#elif defined(__BIG_ENDIAN_BITFIELD)
++ __u32 reserved_2 : 16;
++ __u32 trigger : 1; /* 0: edge | 1: level */
++ __u32 level : 1; /* 0: deassert | 1: assert */
++ __u32 reserved_1 : 3;
++ __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
++ __u32 vector : 8;
++#else
++#error "Bitfield endianness not defined! Check your byteorder.h"
++#endif
++} __attribute__ ((packed));
++
++struct msg_address {
++ union {
++ struct {
++#if defined(__LITTLE_ENDIAN_BITFIELD)
++ __u32 reserved_1 : 2;
++ __u32 dest_mode : 1; /*0:physic | 1:logic */
++ __u32 redirection_hint: 1; /*0: dedicated CPU
++ 1: lowest priority */
++ __u32 reserved_2 : 4;
++ __u32 dest_id : 24; /* Destination ID */
++#elif defined(__BIG_ENDIAN_BITFIELD)
++ __u32 dest_id : 24; /* Destination ID */
++ __u32 reserved_2 : 4;
++ __u32 redirection_hint: 1; /*0: dedicated CPU
++ 1: lowest priority */
++ __u32 dest_mode : 1; /*0:physic | 1:logic */
++ __u32 reserved_1 : 2;
++#else
++#error "Bitfield endianness not defined! Check your byteorder.h"
++#endif
++ }u;
++ __u32 value;
++ }lo_address;
++ __u32 hi_address;
++} __attribute__ ((packed));
++
++struct msi_desc {
++ struct {
++ __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
++ __u8 maskbit : 1; /* mask-pending bit supported ? */
++ __u8 reserved: 2; /* reserved */
++ __u8 entry_nr; /* specific enabled entry */
++ __u8 default_vector; /* default pre-assigned vector */
++ __u8 current_cpu; /* current destination cpu */
++ }msi_attrib;
++
++ struct {
++ __u16 head;
++ __u16 tail;
++ }link;
++
++ unsigned long mask_base;
++ struct pci_dev *dev;
++};
++
++#endif /* _ASM_PCI_MSI_H */
+--- linux-2.6.0-test6/include/linux/raw.h 2003-06-14 12:18:25.000000000 -0700
++++ 25/include/linux/raw.h 2003-10-05 00:33:24.000000000 -0700
+@@ -13,4 +13,6 @@ struct raw_config_request
+ __u64 block_minor;
+ };
+
++#define MAX_RAW_MINORS CONFIG_MAX_RAW_DEVS
++
+ #endif /* __LINUX_RAW_H */
+--- linux-2.6.0-test6/include/linux/rcupdate.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/linux/rcupdate.h 2003-10-05 00:33:24.000000000 -0700
+@@ -15,7 +15,7 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+- * Copyright (c) IBM Corporation, 2001
++ * Copyright (C) IBM Corporation, 2001
+ *
+ * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ *
+--- linux-2.6.0-test6/include/linux/sched.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/sched.h 2003-10-05 00:36:54.000000000 -0700
+@@ -151,6 +151,7 @@ extern void init_idle(task_t *idle, int
+
+ extern void show_state(void);
+ extern void show_regs(struct pt_regs *);
++extern void show_trace_task(task_t *tsk);
+
+ /*
+ * TASK is a pointer to the task whose backtrace we want to see (or NULL for current
+@@ -207,6 +208,8 @@ struct mm_struct {
+ cpumask_t cpu_vm_mask;
+ unsigned long swap_address;
+
++ unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
++
+ unsigned dumpable:1;
+ #ifdef CONFIG_HUGETLB_PAGE
+ int used_hugetlb;
+@@ -262,6 +265,15 @@ struct signal_struct {
+
+ /* thread group stop support, overloads group_exit_code too */
+ int group_stop_count;
++
++ /* job control IDs */
++ pid_t pgrp;
++ pid_t tty_old_pgrp;
++ pid_t session;
++ /* boolean value for session group leader */
++ int leader;
++
++ struct tty_struct *tty; /* NULL if no tty */
+ };
+
+ /*
+@@ -364,12 +376,7 @@ struct task_struct {
+ unsigned long personality;
+ int did_exec:1;
+ pid_t pid;
+- pid_t __pgrp; /* Accessed via process_group() */
+- pid_t tty_old_pgrp;
+- pid_t session;
+ pid_t tgid;
+- /* boolean value for session group leader */
+- int leader;
+ /*
+ * pointers to (original) parent process, youngest child, younger sibling,
+ * older sibling, respectively. (p->father can be replaced with
+@@ -413,7 +420,6 @@ struct task_struct {
+ char comm[16];
+ /* file system info */
+ int link_count, total_link_count;
+- struct tty_struct *tty; /* NULL if no tty */
+ unsigned int locks; /* How many file locks are being held */
+ /* ipc stuff */
+ struct sysv_sem sysvsem;
+@@ -463,11 +469,33 @@ struct task_struct {
+
+ unsigned long ptrace_message;
+ siginfo_t *last_siginfo; /* For ptrace use. */
++/*
++ * current io wait handle: wait queue entry to use for io waits
++ * If this thread is processing aio, this points at the waitqueue
++ * inside the currently handled kiocb. It may be NULL (i.e. default
++ * to a stack based synchronous wait) if its doing sync IO.
++ */
++ wait_queue_t *io_wait;
+ };
+
+ static inline pid_t process_group(struct task_struct *tsk)
+ {
+- return tsk->group_leader->__pgrp;
++ return tsk->signal->pgrp;
++}
++
++static inline pid_t process_session(struct task_struct *tsk)
++{
++ return tsk->signal->session;
++}
++
++static inline int process_session_leader(struct task_struct *tsk)
++{
++ return tsk->signal->leader;
++}
++
++static inline struct tty_struct *process_tty(struct task_struct *tsk)
++{
++ return tsk->signal->tty;
+ }
+
+ extern void __put_task_struct(struct task_struct *tsk);
+--- linux-2.6.0-test6/include/linux/sctp.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/sctp.h 2003-10-05 00:33:24.000000000 -0700
+@@ -524,113 +524,4 @@ typedef struct sctp_addip_chunk {
+ sctp_addiphdr_t addip_hdr;
+ } sctp_addip_chunk_t __attribute__((packed));
+
+-/* FIXME: Cleanup needs to continue below this line. */
+-
+-
+-/* ADDIP Section 3.1.1
+- *
+- * ASCONF-Request Correlation ID: 32 bits (unsigned integer)
+- *
+- * This is an opaque integer assigned by the sender to identify each
+- * request parameter. It is in host byte order and is only meaningful
+- * to the sender. The receiver of the ASCONF Chunk will copy this 32
+- * bit value into the ASCONF Correlation ID field of the
+- * ASCONF-ACK. The sender of the ASCONF can use this same value in the
+- * ASCONF-ACK to find which request the response is for.
+- *
+- * ASCONF Parameter: TLV format
+- *
+- * Each Address configuration change is represented by a TLV parameter
+- * as defined in Section 3.2. One or more requests may be present in
+- * an ASCONF Chunk.
+- */
+-typedef struct {
+- __u32 correlation;
+- sctp_paramhdr_t p;
+- __u8 payload[0];
+-} sctpAsconfReq_t;
+-
+-/* ADDIP
+- * 3.1.1 Address/Stream Configuration Change Chunk (ASCONF)
+- *
+- * This chunk is used to communicate to the remote endpoint one of the
+- * configuration change requests that MUST be acknowledged. The
+- * information carried in the ASCONF Chunk uses the form of a
+- * Tag-Length-Value (TLV), as described in "3.2.1
+- * Optional/Variable-length Parameter Format" in [RFC2960], for all
+- * variable parameters.
+- */
+-typedef struct {
+- __u32 serial;
+- __u8 reserved[3];
+- __u8 addr_type;
+- __u32 addr[4];
+- sctpAsconfReq_t requests[0];
+-} sctpAsconf_t;
+-
+-/* ADDIP
+- * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
+- *
+- * ASCONF-Request Correlation ID: 32 bits (unsigned integer)
+- *
+- * This value is copied from the ASCONF Correlation ID received in the
+- * ASCONF Chunk. It is used by the receiver of the ASCONF-ACK to identify
+- * which ASCONF parameter this response is associated with.
+- *
+- * ASCONF Parameter Response : TLV format
+- *
+- * The ASCONF Parameter Response is used in the ASCONF-ACK to report
+- * status of ASCONF processing. By default, if a responding endpoint
+- * does not include any Error Cause, a success is indicated. Thus a
+- * sender of an ASCONF-ACK MAY indicate complete success of all TLVs in
+- * an ASCONF by returning only the Chunk Type, Chunk Flags, Chunk Length
+- * (set to 8) and the Serial Number.
+- */
+-typedef union {
+- struct {
+- __u32 correlation;
+- sctp_paramhdr_t header; /* success report */
+- } success;
+- struct {
+- __u32 correlation;
+- sctp_paramhdr_t header; /* error cause indication */
+- sctp_paramhdr_t errcause;
+- uint8_t request[0]; /* original request from ASCONF */
+- } error;
+-#define __correlation success.correlation
+-#define __header success.header
+-#define __cause error.errcause
+-#define __request error.request
+-} sctpAsconfAckRsp_t;
+-
+-/* ADDIP
+- * 3.1.2 Address/Stream Configuration Acknowledgment Chunk (ASCONF-ACK)
+- *
+- * This chunk is used by the receiver of an ASCONF Chunk to
+- * acknowledge the reception. It carries zero or more results for any
+- * ASCONF Parameters that were processed by the receiver.
+- */
+-typedef struct {
+- __u32 serial;
+- sctpAsconfAckRsp_t responses[0];
+-} sctpAsconfAck_t;
+-
+-/*********************************************************************
+- * Internal structures
+- *
+- * These are data structures which never go out on the wire.
+- *********************************************************************/
+-
+-/* What is this data structure for? The TLV isn't one--it is just a
+- * value. Perhaps this data structure ought to have a type--otherwise
+- * it is not unambigiously parseable. --piggy
+- */
+-typedef struct {
+- struct list_head hook;
+- int length; /* length of the TLV */
+-
+- /* the actually TLV to be copied into ASCONF_ACK */
+- sctpAsconfAckRsp_t TLV;
+-} sctpAsconfAckRspNode_t;
+-
+ #endif /* __LINUX_SCTP_H__ */
+--- linux-2.6.0-test6/include/linux/security.h 2003-07-10 18:50:32.000000000 -0700
++++ 25/include/linux/security.h 2003-10-05 00:33:24.000000000 -0700
+@@ -334,6 +334,7 @@ struct swap_info_struct;
+ * called when the actual read/write operations are performed.
+ * @inode contains the inode structure to check.
+ * @mask contains the permission mask.
++ * @nd contains the nameidata (may be NULL).
+ * Return 0 if permission is granted.
+ * @inode_setattr:
+ * Check permission before setting file attributes. Note that the kernel
+@@ -1055,7 +1056,7 @@ struct security_operations {
+ struct dentry *new_dentry);
+ int (*inode_readlink) (struct dentry *dentry);
+ int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
+- int (*inode_permission) (struct inode *inode, int mask);
++ int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
+ int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
+ int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
+ void (*inode_delete) (struct inode *inode);
+@@ -1474,9 +1475,10 @@ static inline int security_inode_follow_
+ return security_ops->inode_follow_link (dentry, nd);
+ }
+
+-static inline int security_inode_permission (struct inode *inode, int mask)
++static inline int security_inode_permission (struct inode *inode, int mask,
++ struct nameidata *nd)
+ {
+- return security_ops->inode_permission (inode, mask);
++ return security_ops->inode_permission (inode, mask, nd);
+ }
+
+ static inline int security_inode_setattr (struct dentry *dentry,
+@@ -2110,7 +2112,8 @@ static inline int security_inode_follow_
+ return 0;
+ }
+
+-static inline int security_inode_permission (struct inode *inode, int mask)
++static inline int security_inode_permission (struct inode *inode, int mask,
++ struct nameidata *nd)
+ {
+ return 0;
+ }
+--- linux-2.6.0-test6/include/linux/serial_core.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/serial_core.h 2003-10-05 00:33:38.000000000 -0700
+@@ -158,7 +158,9 @@ struct uart_port {
+ unsigned char x_char; /* xon/xoff char */
+ unsigned char regshift; /* reg offset shift */
+ unsigned char iotype; /* io access style */
+-
++#ifdef CONFIG_KGDB
++ int kgdb; /* in use by kgdb */
++#endif
+ #define UPIO_PORT (0)
+ #define UPIO_HUB6 (1)
+ #define UPIO_MEM (2)
+--- linux-2.6.0-test6/include/linux/serialP.h 2003-06-14 12:17:57.000000000 -0700
++++ 25/include/linux/serialP.h 2003-10-05 00:33:25.000000000 -0700
+@@ -19,6 +19,7 @@
+ * For definitions of the flags field, see tty.h
+ */
+
++#include <linux/version.h>
+ #include <linux/config.h>
+ #include <linux/termios.h>
+ #include <linux/workqueue.h>
+--- linux-2.6.0-test6/include/linux/serio.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/serio.h 2003-10-05 00:34:15.000000000 -0700
+@@ -53,6 +53,7 @@ struct serio_dev {
+ irqreturn_t (*interrupt)(struct serio *, unsigned char,
+ unsigned int, struct pt_regs *);
+ void (*connect)(struct serio *, struct serio_dev *dev);
++ int (*reconnect)(struct serio *);
+ void (*disconnect)(struct serio *);
+ void (*cleanup)(struct serio *);
+
+@@ -62,12 +63,13 @@ struct serio_dev {
+ int serio_open(struct serio *serio, struct serio_dev *dev);
+ void serio_close(struct serio *serio);
+ void serio_rescan(struct serio *serio);
++void serio_reconnect(struct serio *serio);
+ irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
+
+ void serio_register_port(struct serio *serio);
+-void serio_register_slave_port(struct serio *serio);
++void __serio_register_port(struct serio *serio);
+ void serio_unregister_port(struct serio *serio);
+-void serio_unregister_slave_port(struct serio *serio);
++void __serio_unregister_port(struct serio *serio);
+ void serio_register_device(struct serio_dev *dev);
+ void serio_unregister_device(struct serio_dev *dev);
+
+--- linux-2.6.0-test6/include/linux/skbuff.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/skbuff.h 2003-10-05 00:36:10.000000000 -0700
+@@ -152,6 +152,7 @@ struct skb_shared_info {
+ * @sk: Socket we are owned by
+ * @stamp: Time we arrived
+ * @dev: Device we arrived on/are leaving by
++ * @real_dev: The real device we are using
+ * @h: Transport layer header
+ * @nh: Network layer header
+ * @mac: Link layer header
+@@ -179,6 +180,7 @@ struct skb_shared_info {
+ * @nfct: Associated connection, if any
+ * @nf_debug: Netfilter debugging
+ * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
++ * @private: Data which is private to the HIPPI implementation
+ * @tc_index: Traffic control index
+ */
+
+@@ -885,7 +887,7 @@ static inline char *__skb_pull(struct sk
+ */
+ static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
+ {
+- return (len > skb->len) ? NULL : __skb_pull(skb, len);
++ return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
+ }
+
+ extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta);
+@@ -901,7 +903,7 @@ static inline char *__pskb_pull(struct s
+
+ static inline unsigned char *pskb_pull(struct sk_buff *skb, unsigned int len)
+ {
+- return (len > skb->len) ? NULL : __pskb_pull(skb, len);
++ return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len);
+ }
+
+ static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
+@@ -1052,7 +1054,7 @@ static inline struct sk_buff *__dev_allo
+ int gfp_mask)
+ {
+ struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
+- if (skb)
++ if (likely(skb))
+ skb_reserve(skb, 16);
+ return skb;
+ }
+--- linux-2.6.0-test6/include/linux/spinlock.h 2003-07-02 14:53:18.000000000 -0700
++++ 25/include/linux/spinlock.h 2003-10-05 00:36:40.000000000 -0700
+@@ -15,6 +15,12 @@
+
+ #include <asm/processor.h> /* for cpu relax */
+ #include <asm/system.h>
++#ifdef CONFIG_KGDB
++#include <asm/current.h>
++#define SET_WHO(x, him) (x)->who = him;
++#else
++#define SET_WHO(x, him)
++#endif
+
+ /*
+ * Must define these before including other files, inline functions need them
+@@ -55,6 +61,9 @@ typedef struct {
+ const char *module;
+ char *owner;
+ int oline;
++#ifdef CONFIG_KGDB
++ struct task_struct *who;
++#endif
+ } spinlock_t;
+ #define SPIN_LOCK_UNLOCKED (spinlock_t) { SPINLOCK_MAGIC, 0, 10, __FILE__ , NULL, 0}
+
+@@ -66,6 +75,7 @@ typedef struct {
+ (x)->module = __FILE__; \
+ (x)->owner = NULL; \
+ (x)->oline = 0; \
++ SET_WHO(x, NULL) \
+ } while (0)
+
+ #define CHECK_LOCK(x) \
+@@ -88,6 +98,7 @@ typedef struct {
+ (x)->lock = 1; \
+ (x)->owner = __FILE__; \
+ (x)->oline = __LINE__; \
++ SET_WHO(x, current) \
+ } while (0)
+
+ /* without debugging, spin_is_locked on UP always says
+@@ -118,6 +129,7 @@ typedef struct {
+ (x)->lock = 1; \
+ (x)->owner = __FILE__; \
+ (x)->oline = __LINE__; \
++ SET_WHO(x, current) \
+ 1; \
+ })
+
+@@ -184,6 +196,17 @@ typedef struct {
+
+ #endif /* !SMP */
+
++#ifdef CONFIG_LOCKMETER
++extern void _metered_spin_lock (spinlock_t *lock);
++extern void _metered_spin_unlock (spinlock_t *lock);
++extern int _metered_spin_trylock(spinlock_t *lock);
++extern void _metered_read_lock (rwlock_t *lock);
++extern void _metered_read_unlock (rwlock_t *lock);
++extern void _metered_write_lock (rwlock_t *lock);
++extern void _metered_write_unlock (rwlock_t *lock);
++extern int _metered_write_trylock(rwlock_t *lock);
++#endif
++
+ /*
+ * Define the various spin_lock and rw_lock methods. Note we define these
+ * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
+@@ -389,6 +412,141 @@ do { \
+ _raw_spin_trylock(lock) ? 1 : \
+ ({preempt_enable(); local_bh_enable(); 0;});})
+
++#ifdef CONFIG_LOCKMETER
++#undef spin_lock
++#undef spin_trylock
++#undef spin_unlock
++#undef spin_lock_irqsave
++#undef spin_lock_irq
++#undef spin_lock_bh
++#undef read_lock
++#undef read_unlock
++#undef write_lock
++#undef write_unlock
++#undef write_trylock
++#undef spin_unlock_bh
++#undef read_lock_irqsave
++#undef read_lock_irq
++#undef read_lock_bh
++#undef read_unlock_bh
++#undef write_lock_irqsave
++#undef write_lock_irq
++#undef write_lock_bh
++#undef write_unlock_bh
++
++#define spin_lock(lock) \
++do { \
++ preempt_disable(); \
++ _metered_spin_lock(lock); \
++} while(0)
++
++#define spin_trylock(lock) ({preempt_disable(); _metered_spin_trylock(lock) ? \
++ 1 : ({preempt_enable(); 0;});})
++#define spin_unlock(lock) \
++do { \
++ _metered_spin_unlock(lock); \
++ preempt_enable(); \
++} while (0)
++
++#define spin_lock_irqsave(lock, flags) \
++do { \
++ local_irq_save(flags); \
++ preempt_disable(); \
++ _metered_spin_lock(lock); \
++} while (0)
++
++#define spin_lock_irq(lock) \
++do { \
++ local_irq_disable(); \
++ preempt_disable(); \
++ _metered_spin_lock(lock); \
++} while (0)
++
++#define spin_lock_bh(lock) \
++do { \
++ local_bh_disable(); \
++ preempt_disable(); \
++ _metered_spin_lock(lock); \
++} while (0)
++
++#define spin_unlock_bh(lock) \
++do { \
++ _metered_spin_unlock(lock); \
++ preempt_enable(); \
++ local_bh_enable(); \
++} while (0)
++
++
++#define read_lock(lock) ({preempt_disable(); _metered_read_lock(lock);})
++#define read_unlock(lock) ({_metered_read_unlock(lock); preempt_enable();})
++#define write_lock(lock) ({preempt_disable(); _metered_write_lock(lock);})
++#define write_unlock(lock) ({_metered_write_unlock(lock); preempt_enable();})
++#define write_trylock(lock) ({preempt_disable();_metered_write_trylock(lock) ? \
++ 1 : ({preempt_enable(); 0;});})
++#define spin_unlock_no_resched(lock) \
++do { \
++ _metered_spin_unlock(lock); \
++ preempt_enable_no_resched(); \
++} while (0)
++
++#define read_lock_irqsave(lock, flags) \
++do { \
++ local_irq_save(flags); \
++ preempt_disable(); \
++ _metered_read_lock(lock); \
++} while (0)
++
++#define read_lock_irq(lock) \
++do { \
++ local_irq_disable(); \
++ preempt_disable(); \
++ _metered_read_lock(lock); \
++} while (0)
++
++#define read_lock_bh(lock) \
++do { \
++ local_bh_disable(); \
++ preempt_disable(); \
++ _metered_read_lock(lock); \
++} while (0)
++
++#define read_unlock_bh(lock) \
++do { \
++ _metered_read_unlock(lock); \
++ preempt_enable(); \
++ local_bh_enable(); \
++} while (0)
++
++#define write_lock_irqsave(lock, flags) \
++do { \
++ local_irq_save(flags); \
++ preempt_disable(); \
++ _metered_write_lock(lock); \
++} while (0)
++
++#define write_lock_irq(lock) \
++do { \
++ local_irq_disable(); \
++ preempt_disable(); \
++ _metered_write_lock(lock); \
++} while (0)
++
++#define write_lock_bh(lock) \
++do { \
++ local_bh_disable(); \
++ preempt_disable(); \
++ _metered_write_lock(lock); \
++} while (0)
++
++#define write_unlock_bh(lock) \
++do { \
++ _metered_write_unlock(lock); \
++ preempt_enable(); \
++ local_bh_enable(); \
++} while (0)
++
++#endif /* !CONFIG_LOCKMETER */
++
+ /* "lock on reference count zero" */
+ #ifndef ATOMIC_DEC_AND_LOCK
+ #include <asm/atomic.h>
+--- linux-2.6.0-test6/include/linux/stallion.h 2003-06-14 12:18:32.000000000 -0700
++++ 25/include/linux/stallion.h 2003-10-05 00:33:25.000000000 -0700
+@@ -21,6 +21,8 @@
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
++#include <linux/version.h>
++
+ /*****************************************************************************/
+ #ifndef _STALLION_H
+ #define _STALLION_H
+--- linux-2.6.0-test6/include/linux/sysctl.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/sysctl.h 2003-10-05 00:33:25.000000000 -0700
+@@ -244,6 +244,7 @@ enum
+ NET_IPV4_NEIGH=17,
+ NET_IPV4_ROUTE=18,
+ NET_IPV4_FIB_HASH=19,
++ NET_IPV4_NETFILTER=20,
+
+ NET_IPV4_TCP_TIMESTAMPS=33,
+ NET_IPV4_TCP_WINDOW_SCALING=34,
+@@ -358,6 +359,24 @@ enum
+ NET_IPV4_CONF_NOPOLICY=16,
+ };
+
++/* /proc/sys/net/ipv4/netfilter */
++enum
++{
++ NET_IPV4_NF_CONNTRACK_MAX=1,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT=2,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV=3,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED=4,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT=5,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT=6,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK=7,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT=8,
++ NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE=9,
++ NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT=10,
++ NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
++ NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
++ NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
++};
++
+ /* /proc/sys/net/ipv6 */
+ enum {
+ NET_IPV6_CONF=16,
+--- linux-2.6.0-test6/include/linux/toshiba.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/toshiba.h 2003-10-05 00:33:25.000000000 -0700
+@@ -33,4 +33,13 @@ typedef struct {
+ unsigned int edi __attribute__ ((packed));
+ } SMMRegisters;
+
++#ifdef CONFIG_PROC_FS
++static int tosh_get_info(char *, char **, off_t, int);
++#else /* !CONFIG_PROC_FS */
++inline int tosh_get_info(char *buffer, char **start, off_t fpos, int lenght)
++{
++ return 0;
++}
++#endif /* CONFIG_PROC_FS */
++
+ #endif
+--- linux-2.6.0-test6/include/linux/usb.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/usb.h 2003-10-05 00:33:25.000000000 -0700
+@@ -1038,9 +1038,9 @@ void usb_show_string(struct usb_device *
+ #define dbg(format, arg...) do {} while (0)
+ #endif
+
+-#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
+-#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
+-#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
++#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
++#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
++#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
+
+
+ #endif /* __KERNEL__ */
+--- linux-2.6.0-test6/include/linux/wait.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/linux/wait.h 2003-10-05 00:36:54.000000000 -0700
+@@ -80,6 +80,15 @@ static inline int waitqueue_active(wait_
+ return !list_empty(&q->task_list);
+ }
+
++/*
++ * Used to distinguish between sync and async io wait context:
++ * sync i/o typically specifies a NULL wait queue entry or a wait
++ * queue entry bound to a task (current task) to wake up.
++ * aio specifies a wait queue entry with an async notification
++ * callback routine, not associated with any task.
++ */
++#define is_sync_wait(wait) (!(wait) || ((wait)->task))
++
+ extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
+ extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
+ extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
+--- linux-2.6.0-test6/include/linux/writeback.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/include/linux/writeback.h 2003-10-05 00:37:01.000000000 -0700
+@@ -84,9 +84,13 @@ int dirty_writeback_centisecs_handler(st
+ void __user *, size_t *);
+
+ void page_writeback_init(void);
+-void balance_dirty_pages_ratelimited(struct address_space *mapping);
++int balance_dirty_pages_ratelimited(struct address_space *mapping);
+ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
+ int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
++ssize_t sync_page_range(struct inode *inode, struct address_space *mapping,
++ loff_t pos, size_t count);
++ssize_t sync_page_range_nolock(struct inode *inode, struct address_space
++ *mapping, loff_t pos, size_t count);
+
+ /* pdflush.c */
+ extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
+--- linux-2.6.0-test6/include/net/irda/irda_device.h 2003-08-22 19:23:42.000000000 -0700
++++ 25/include/net/irda/irda_device.h 2003-10-05 00:33:25.000000000 -0700
+@@ -128,6 +128,7 @@ struct dongle_reg {
+ void (*close)(dongle_t *dongle);
+ int (*reset)(struct irda_task *task);
+ int (*change_speed)(struct irda_task *task);
++ struct module *owner;
+ };
+
+ /*
+@@ -223,6 +224,7 @@ int irda_device_set_raw_mode(struct net
+ int irda_device_set_dtr_rts(struct net_device *dev, int dtr, int rts);
+ int irda_device_change_speed(struct net_device *dev, __u32 speed);
+ void irda_device_setup(struct net_device *dev);
++struct net_device *alloc_irdadev(int sizeof_priv);
+
+ /* Dongle interface */
+ void irda_device_unregister_dongle(struct dongle_reg *dongle);
+--- linux-2.6.0-test6/include/net/pkt_sched.h 2003-08-08 22:55:14.000000000 -0700
++++ 25/include/net/pkt_sched.h 2003-10-05 00:33:25.000000000 -0700
+@@ -8,6 +8,7 @@
+ #define PSCHED_CLOCK_SOURCE PSCHED_JIFFIES
+
+ #include <linux/config.h>
++#include <linux/netdevice.h>
+ #include <linux/types.h>
+ #include <linux/pkt_sched.h>
+ #include <net/pkt_cls.h>
+--- linux-2.6.0-test6/include/net/scm.h 2003-06-14 12:18:20.000000000 -0700
++++ 25/include/net/scm.h 2003-10-05 00:33:25.000000000 -0700
+@@ -39,7 +39,7 @@ static __inline__ int scm_send(struct so
+ memset(scm, 0, sizeof(*scm));
+ scm->creds.uid = current->uid;
+ scm->creds.gid = current->gid;
+- scm->creds.pid = current->pid;
++ scm->creds.pid = current->tgid;
+ if (msg->msg_controllen <= 0)
+ return 0;
+ return __scm_send(sock, msg, scm);
+--- linux-2.6.0-test6/include/net/sctp/command.h 2003-08-08 22:55:14.000000000 -0700
++++ 25/include/net/sctp/command.h 2003-10-05 00:33:25.000000000 -0700
+@@ -1,5 +1,6 @@
+-/* SCTP kernel reference Implementation Copyright (C) 1999-2001
+- * Cisco, Motorola, and IBM
++/* SCTP kernel reference Implementation
++ * (C) Copyright IBM Corp. 2001, 2003
++ * Copyright (C) 1999-2001 Cisco, Motorola
+ *
+ * This file is part of the SCTP kernel reference Implementation
+ *
+@@ -88,6 +89,7 @@ typedef enum {
+ SCTP_CMD_PART_DELIVER, /* Partial data delivery considerations. */
+ SCTP_CMD_RENEGE, /* Renege data on an association. */
+ SCTP_CMD_SETUP_T4, /* ADDIP, setup T4 RTO timer parms. */
++ SCTP_CMD_PROCESS_OPERR, /* Process an ERROR chunk. */
+ SCTP_CMD_LAST
+ } sctp_verb_t;
+
+--- linux-2.6.0-test6/include/net/sctp/sctp.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/net/sctp/sctp.h 2003-10-05 00:33:25.000000000 -0700
+@@ -116,6 +116,9 @@
+ #define SCTP_STATIC static
+ #endif
+
++#define MSECS_TO_JIFFIES(msec) (msec * HZ / 1000)
++#define JIFFIES_TO_MSECS(jiff) (jiff * 1000 / HZ)
++
+ /*
+ * Function declarations.
+ */
+@@ -495,22 +498,19 @@ for (err = (sctp_errhdr_t *)((void *)chu
+ #define tv_lt(s, t) \
+ (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec))
+
+-/* Stolen from net/profile.h. Using it from there is more grief than
+- * it is worth.
+- */
+-static inline void tv_add(const struct timeval *entered, struct timeval *leaved)
+-{
+- time_t usecs = leaved->tv_usec + entered->tv_usec;
+- time_t secs = leaved->tv_sec + entered->tv_sec;
+-
+- if (usecs >= 1000000) {
+- usecs -= 1000000;
+- secs++;
+- }
+- leaved->tv_sec = secs;
+- leaved->tv_usec = usecs;
+-}
+-
++/* Add tv1 to tv2. */
++#define TIMEVAL_ADD(tv1, tv2) \
++({ \
++ suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \
++ time_t secs = (tv2).tv_sec + (tv1).tv_sec; \
++\
++ if (usecs >= 1000000) { \
++ usecs -= 1000000; \
++ secs++; \
++ } \
++ (tv2).tv_sec = secs; \
++ (tv2).tv_usec = usecs; \
++})
+
+ /* External references. */
+
+--- linux-2.6.0-test6/include/net/sctp/sm.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/net/sctp/sm.h 2003-10-05 00:33:25.000000000 -0700
+@@ -265,13 +265,19 @@ struct sctp_chunk *sctp_make_op_error(co
+ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
+ union sctp_addr *addr,
+ int vparam_len);
++struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
++ union sctp_addr *,
++ struct sockaddr *,
++ int, int);
++struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
++ union sctp_addr *addr);
++struct sctp_chunk *sctp_make_asconf_ack(struct sctp_association *asoc,
++ int serial, int vparam_len);
++
+ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+ struct sctp_chunk *asconf,
+ int vparam_len);
+
+-struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
+- union sctp_addr *addr);
+-
+ void sctp_chunk_assign_tsn(struct sctp_chunk *);
+ void sctp_chunk_assign_ssn(struct sctp_chunk *);
+
+--- linux-2.6.0-test6/include/net/sctp/structs.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/net/sctp/structs.h 2003-10-05 00:33:25.000000000 -0700
+@@ -1085,6 +1085,10 @@ int sctp_add_bind_addr(struct sctp_bind_
+ int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
+ int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
+ struct sctp_opt *);
++union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
++ const union sctp_addr *addrs,
++ int addrcnt,
++ struct sctp_opt *opt);
+ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
+ int *addrs_len, int gfp);
+ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
+@@ -1389,6 +1393,10 @@ struct sctp_association {
+ __u8 ipv4_address; /* Peer understands IPv4 addresses? */
+ __u8 ipv6_address; /* Peer understands IPv6 addresses? */
+ __u8 hostname_address;/* Peer understands DNS addresses? */
++
++ /* Does peer support ADDIP? */
++ __u8 asconf_capable;
++
+ struct sctp_inithdr i;
+ int cookie_len;
+ void *cookie;
+--- linux-2.6.0-test6/include/sound/sndmagic.h 2003-06-14 12:18:06.000000000 -0700
++++ 25/include/sound/sndmagic.h 2003-10-05 00:33:25.000000000 -0700
+@@ -198,6 +198,8 @@ static inline int _snd_magic_bad(void *o
+ #define vx_pipe_t_magic 0xa15a4112
+ #define azf3328_t_magic 0xa15a4200
+
++#define snd_card_harmony_t_magic 0xa15a4300
++
+ #else
+
+ #define snd_magic_kcalloc(type, extra, flags) (type *) snd_kcalloc(sizeof(type) + extra, flags)
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/include/video/epson1355.h 2003-10-05 00:34:22.000000000 -0700
+@@ -0,0 +1,64 @@
++/*
++ * include/video/epson13xx.h -- Epson 13xx frame buffer
++ *
++ * Copyright (C) Hewlett-Packard Company. All rights reserved.
++ *
++ * Written by Christopher Hoover <ch@hpl.hp.com>
++ *
++ */
++
++#ifndef _EPSON13XX_H_
++#define _EPSON13XX_H_
++
++#define REG_REVISION_CODE 0x00
++#define REG_MEMORY_CONFIG 0x01
++#define REG_PANEL_TYPE 0x02
++#define REG_MOD_RATE 0x03
++#define REG_HORZ_DISP_WIDTH 0x04
++#define REG_HORZ_NONDISP_PERIOD 0x05
++#define REG_HRTC_START_POSITION 0x06
++#define REG_HRTC_PULSE_WIDTH 0x07
++#define REG_VERT_DISP_HEIGHT0 0x08
++#define REG_VERT_DISP_HEIGHT1 0x09
++#define REG_VERT_NONDISP_PERIOD 0x0A
++#define REG_VRTC_START_POSITION 0x0B
++#define REG_VRTC_PULSE_WIDTH 0x0C
++#define REG_DISPLAY_MODE 0x0D
++#define REG_SCRN1_LINE_COMPARE0 0x0E
++#define REG_SCRN1_LINE_COMPARE1 0x0F
++#define REG_SCRN1_DISP_START_ADDR0 0x10
++#define REG_SCRN1_DISP_START_ADDR1 0x11
++#define REG_SCRN1_DISP_START_ADDR2 0x12
++#define REG_SCRN2_DISP_START_ADDR0 0x13
++#define REG_SCRN2_DISP_START_ADDR1 0x14
++#define REG_SCRN2_DISP_START_ADDR2 0x15
++#define REG_MEM_ADDR_OFFSET0 0x16
++#define REG_MEM_ADDR_OFFSET1 0x17
++#define REG_PIXEL_PANNING 0x18
++#define REG_CLOCK_CONFIG 0x19
++#define REG_POWER_SAVE_CONFIG 0x1A
++#define REG_MISC 0x1B
++#define REG_MD_CONFIG_READBACK0 0x1C
++#define REG_MD_CONFIG_READBACK1 0x1D
++#define REG_GPIO_CONFIG0 0x1E
++#define REG_GPIO_CONFIG1 0x1F
++#define REG_GPIO_CONTROL0 0x20
++#define REG_GPIO_CONTROL1 0x21
++#define REG_PERF_ENHANCEMENT0 0x22
++#define REG_PERF_ENHANCEMENT1 0x23
++#define REG_LUT_ADDR 0x24
++#define REG_RESERVED_1 0x25
++#define REG_LUT_DATA 0x26
++#define REG_INK_CURSOR_CONTROL 0x27
++#define REG_CURSOR_X_POSITION0 0x28
++#define REG_CURSOR_X_POSITION1 0x29
++#define REG_CURSOR_Y_POSITION0 0x2A
++#define REG_CURSOR_Y_POSITION1 0x2B
++#define REG_INK_CURSOR_COLOR0_0 0x2C
++#define REG_INK_CURSOR_COLOR0_1 0x2D
++#define REG_INK_CURSOR_COLOR1_0 0x2E
++#define REG_INK_CURSOR_COLOR1_1 0x2F
++#define REG_INK_CURSOR_START_ADDR 0x30
++#define REG_ALTERNATE_FRM 0x31
++
++#endif
+--- linux-2.6.0-test6/include/video/neomagic.h 2003-06-14 12:18:07.000000000 -0700
++++ 25/include/video/neomagic.h 2003-10-05 00:34:22.000000000 -0700
+@@ -55,6 +55,20 @@
+ #define NEO_MODE1_X_1600 0x1c00
+ #define NEO_MODE1_BLT_ON_ADDR 0x2000
+
++/* These are offseted in MMIO space by par->CursorOff */
++#define NEOREG_CURSCNTL 0x00
++#define NEOREG_CURSX 0x04
++#define NEOREG_CURSY 0x08
++#define NEOREG_CURSBGCOLOR 0x0C
++#define NEOREG_CURSFGCOLOR 0x10
++#define NEOREG_CURSMEMPOS 0x14
++
++#define NEO_CURS_DISABLE 0x00000000
++#define NEO_CURS_ENABLE 0x00000001
++#define NEO_ICON64_ENABLE 0x00000008
++#define NEO_ICON128_ENABLE 0x0000000C
++#define NEO_ICON_BLANK 0x00000010
++
+ #ifdef __KERNEL__
+
+ #ifdef NEOFB_DEBUG
+@@ -75,45 +89,45 @@
+
+
+ struct xtimings {
+- unsigned int pixclock;
+- unsigned int HDisplay;
+- unsigned int HSyncStart;
+- unsigned int HSyncEnd;
+- unsigned int HTotal;
+- unsigned int VDisplay;
+- unsigned int VSyncStart;
+- unsigned int VSyncEnd;
+- unsigned int VTotal;
+- unsigned int sync;
+- int dblscan;
+- int interlaced;
++ unsigned int pixclock;
++ unsigned int HDisplay;
++ unsigned int HSyncStart;
++ unsigned int HSyncEnd;
++ unsigned int HTotal;
++ unsigned int VDisplay;
++ unsigned int VSyncStart;
++ unsigned int VSyncEnd;
++ unsigned int VTotal;
++ unsigned int sync;
++ int dblscan;
++ int interlaced;
+ };
+
+
+ /* --------------------------------------------------------------------- */
+
+ typedef volatile struct {
+- __u32 bltStat;
+- __u32 bltCntl;
+- __u32 xpColor;
+- __u32 fgColor;
+- __u32 bgColor;
+- __u32 pitch;
+- __u32 clipLT;
+- __u32 clipRB;
+- __u32 srcBitOffset;
+- __u32 srcStart;
+- __u32 reserved0;
+- __u32 dstStart;
+- __u32 xyExt;
+-
+- __u32 reserved1[19];
+-
+- __u32 pageCntl;
+- __u32 pageBase;
+- __u32 postBase;
+- __u32 postPtr;
+- __u32 dataPtr;
++ __u32 bltStat;
++ __u32 bltCntl;
++ __u32 xpColor;
++ __u32 fgColor;
++ __u32 bgColor;
++ __u32 pitch;
++ __u32 clipLT;
++ __u32 clipRB;
++ __u32 srcBitOffset;
++ __u32 srcStart;
++ __u32 reserved0;
++ __u32 dstStart;
++ __u32 xyExt;
++
++ __u32 reserved1[19];
++
++ __u32 pageCntl;
++ __u32 pageBase;
++ __u32 postBase;
++ __u32 postPtr;
++ __u32 dataPtr;
+ } Neo2200;
+
+ #define NR_PALETTE 256
+@@ -124,142 +138,69 @@ typedef volatile struct {
+ #define NEO_EXT_GR_MAX 0xC7
+
+ struct neofb_par {
+-
+- unsigned char MiscOutReg; /* Misc */
+- unsigned char CRTC[25]; /* Crtc Controller */
+- unsigned char Sequencer[5]; /* Video Sequencer */
+- unsigned char Graphics[9]; /* Video Graphics */
+- unsigned char Attribute[21]; /* Video Atribute */
+-
+- unsigned char GeneralLockReg;
+- unsigned char ExtCRTDispAddr;
+- unsigned char ExtCRTOffset;
+- unsigned char SysIfaceCntl1;
+- unsigned char SysIfaceCntl2;
+- unsigned char ExtColorModeSelect;
+- unsigned char biosMode;
+-
+- unsigned char PanelDispCntlReg1;
+- unsigned char PanelDispCntlReg2;
+- unsigned char PanelDispCntlReg3;
+- unsigned char PanelVertCenterReg1;
+- unsigned char PanelVertCenterReg2;
+- unsigned char PanelVertCenterReg3;
+- unsigned char PanelVertCenterReg4;
+- unsigned char PanelVertCenterReg5;
+- unsigned char PanelHorizCenterReg1;
+- unsigned char PanelHorizCenterReg2;
+- unsigned char PanelHorizCenterReg3;
+- unsigned char PanelHorizCenterReg4;
+- unsigned char PanelHorizCenterReg5;
+-
+- int ProgramVCLK;
+- unsigned char VCLK3NumeratorLow;
+- unsigned char VCLK3NumeratorHigh;
+- unsigned char VCLK3Denominator;
+- unsigned char VerticalExt;
++ struct vgastate state;
++ atomic_t ref_count;
++
++ unsigned char MiscOutReg; /* Misc */
++ unsigned char CRTC[25]; /* Crtc Controller */
++ unsigned char Sequencer[5]; /* Video Sequencer */
++ unsigned char Graphics[9]; /* Video Graphics */
++ unsigned char Attribute[21]; /* Video Atribute */
++
++ unsigned char GeneralLockReg;
++ unsigned char ExtCRTDispAddr;
++ unsigned char ExtCRTOffset;
++ unsigned char SysIfaceCntl1;
++ unsigned char SysIfaceCntl2;
++ unsigned char ExtColorModeSelect;
++ unsigned char biosMode;
++
++ unsigned char PanelDispCntlReg1;
++ unsigned char PanelDispCntlReg2;
++ unsigned char PanelDispCntlReg3;
++ unsigned char PanelVertCenterReg1;
++ unsigned char PanelVertCenterReg2;
++ unsigned char PanelVertCenterReg3;
++ unsigned char PanelVertCenterReg4;
++ unsigned char PanelVertCenterReg5;
++ unsigned char PanelHorizCenterReg1;
++ unsigned char PanelHorizCenterReg2;
++ unsigned char PanelHorizCenterReg3;
++ unsigned char PanelHorizCenterReg4;
++ unsigned char PanelHorizCenterReg5;
++
++ int ProgramVCLK;
++ unsigned char VCLK3NumeratorLow;
++ unsigned char VCLK3NumeratorHigh;
++ unsigned char VCLK3Denominator;
++ unsigned char VerticalExt;
+
+ #ifdef CONFIG_MTRR
+- int mtrr;
++ int mtrr;
+ #endif
+- u8 *mmio_vbase;
+-
+- Neo2200 *neo2200;
+-
+- /* Panels size */
+- int NeoPanelWidth;
+- int NeoPanelHeight;
+-
+- int maxClock;
+-
+- int pci_burst;
+- int lcd_stretch;
+- int internal_display;
+- int external_display;
+- int libretto;
++ u8 *mmio_vbase;
++ u8 cursorOff;
++ u8 *cursorPad; /* Must die !! */
++
++ Neo2200 *neo2200;
++
++ /* Panels size */
++ int NeoPanelWidth;
++ int NeoPanelHeight;
++
++ int maxClock;
++
++ int pci_burst;
++ int lcd_stretch;
++ int internal_display;
++ int external_display;
++ int libretto;
+ };
+
+ typedef struct {
+- int x_res;
+- int y_res;
+- int mode;
++ int x_res;
++ int y_res;
++ int mode;
+ } biosMode;
+
+-/* vga IO functions */
+-static inline u8 VGArCR (u8 index)
+-{
+- outb (index, 0x3d4);
+- return inb (0x3d5);
+-}
+-
+-static inline void VGAwCR (u8 index, u8 val)
+-{
+- outb (index, 0x3d4);
+- outb (val, 0x3d5);
+-}
+-
+-static inline u8 VGArGR (u8 index)
+-{
+- outb (index, 0x3ce);
+- return inb (0x3cf);
+-}
+-
+-static inline void VGAwGR (u8 index, u8 val)
+-{
+- outb (index, 0x3ce);
+- outb (val, 0x3cf);
+-}
+-
+-static inline u8 VGArSEQ (u8 index)
+-{
+- outb (index, 0x3c4);
+- return inb (0x3c5);
+-}
+-
+-static inline void VGAwSEQ (u8 index, u8 val)
+-{
+- outb (index, 0x3c4);
+- outb (val, 0x3c5);
+-}
+-
+-
+-static int paletteEnabled = 0;
+-
+-static inline void VGAenablePalette (void)
+-{
+- u8 tmp;
+-
+- tmp = inb (0x3da);
+- outb (0x00, 0x3c0);
+- paletteEnabled = 1;
+-}
+-
+-static inline void VGAdisablePalette (void)
+-{
+- u8 tmp;
+-
+- tmp = inb (0x3da);
+- outb (0x20, 0x3c0);
+- paletteEnabled = 0;
+-}
+-
+-static inline void VGAwATTR (u8 index, u8 value)
+-{
+- u8 tmp;
+-
+- if (paletteEnabled)
+- index &= ~0x20;
+- else
+- index |= 0x20;
+-
+- tmp = inb (0x3da);
+- outb (index, 0x3c0);
+- outb (value, 0x3c0);
+-}
+-
+-static inline void VGAwMISC (u8 value)
+-{
+- outb (value, 0x3c2);
+-}
+ #endif
+-
+--- linux-2.6.0-test6/include/video/sisfb.h 2003-09-08 13:58:59.000000000 -0700
++++ 25/include/video/sisfb.h 2003-10-05 00:34:22.000000000 -0700
+@@ -6,6 +6,53 @@
+ #include <asm/ioctl.h>
+ #include <asm/types.h>
+
++/* TW: vbflags */
++#define CRT2_DEFAULT 0x00000001
++#define CRT2_LCD 0x00000002 /* TW: Never change the order of the CRT2_XXX entries */
++#define CRT2_TV 0x00000004 /* (see SISCycleCRT2Type()) */
++#define CRT2_VGA 0x00000008
++#define CRT2_ENABLE (CRT2_LCD | CRT2_TV | CRT2_VGA)
++#define VB_DISPTYPE_DISP2 CRT2_ENABLE
++#define VB_DISPTYPE_CRT2 CRT2_ENABLE
++#define TV_NTSC 0x00000010
++#define TV_PAL 0x00000020
++#define TV_HIVISION 0x00000040
++#define TV_HIVISION_LV 0x00000080
++#define TV_TYPE (TV_NTSC | TV_PAL | TV_HIVISION | TV_HIVISION_LV)
++#define TV_AVIDEO 0x00000100
++#define TV_SVIDEO 0x00000200
++#define TV_SCART 0x00000400
++#define TV_INTERFACE (TV_AVIDEO | TV_SVIDEO | TV_SCART | TV_CHSCART | TV_CHHDTV)
++#define VB_USELCDA 0x00000800
++#define TV_PALM 0x00001000
++#define TV_PALN 0x00002000
++#define TV_CHSCART 0x00008000
++#define TV_CHHDTV 0x00010000
++#define VGA2_CONNECTED 0x00040000
++#define VB_DISPTYPE_CRT1 0x00080000 /* CRT1 connected and used */
++#define VBDISPTYPE_DISP1 VB_DISPTYPE_CRT1
++#define VB_301 0x00100000 /* Video bridge type */
++#define VB_301B 0x00200000
++#define VB_302B 0x00400000
++#define VB_30xBDH 0x00800000 /* 30xB DH version (w/o LCD support) */
++#define VB_LVDS 0x01000000
++#define VB_CHRONTEL 0x02000000
++#define VB_301LV 0x04000000
++#define VB_302LV 0x08000000
++#define VB_TRUMPION 0x10000000
++#define VB_VIDEOBRIDGE (VB_301|VB_301B|VB_302B|VB_301LV|VB_302LV| \
++ VB_LVDS|VB_CHRONTEL|VB_TRUMPION)
++#define VB_SISBRIDGE (VB_301|VB_301B|VB_302B|VB_301LV|VB_302LV)
++#define VB_SINGLE_MODE 0x20000000 /* CRT1 or CRT2; determined by VB_DISPTYPE_CRTx */
++#define VB_DISPMODE_SINGLE VB_SINGLE_MODE
++#define VB_MIRROR_MODE 0x40000000 /* CRT1 + CRT2 identical (mirror mode) */
++#define VB_DISPMODE_MIRROR VB_MIRROR_MODE
++#define VB_DUALVIEW_MODE 0x80000000 /* CRT1 + CRT2 independent (dual head mode) */
++#define VB_DISPMODE_DUAL VB_DUALVIEW_MODE
++#define VB_DISPLAY_MODE (VB_SINGLE_MODE | VB_MIRROR_MODE | VB_DUALVIEW_MODE)
++
++
++/* entries for disp_state - deprecated as of 1.6.02 */
+ #define DISPTYPE_CRT1 0x00000008L
+ #define DISPTYPE_CRT2 0x00000004L
+ #define DISPTYPE_LCD 0x00000002L
+@@ -16,6 +63,7 @@
+ #define DISPMODE_MIRROR 0x00000010L
+ #define DISPMODE_DUALVIEW 0x00000040L
+
++/* Deprecated as of 1.6.02 - use vbflags instead */
+ #define HASVB_NONE 0x00
+ #define HASVB_301 0x01
+ #define HASVB_LVDS 0x02
+@@ -39,6 +87,8 @@ typedef enum _SIS_CHIP_TYPE {
+ SIS_650,
+ SIS_740,
+ SIS_330,
++ SIS_660,
++ SIS_760,
+ MAX_SIS_CHIP
+ } SIS_CHIP_TYPE;
+
+@@ -83,13 +133,15 @@ struct ap_data {
+ struct mode_info minfo;
+ unsigned long iobase;
+ unsigned int mem_size;
+- unsigned long disp_state;
++ unsigned long disp_state; /* deprecated */
+ SIS_CHIP_TYPE chip;
+ unsigned char hasVB;
+- SIS_TV_TYPE TV_type;
+- SIS_TV_PLUG TV_plug;
++ SIS_TV_TYPE TV_type; /* deprecated */
++ SIS_TV_PLUG TV_plug; /* deprecated */
+ unsigned long version;
+- char reserved[256];
++ unsigned long vbflags; /* replaces deprecated entries above */
++ unsigned long currentvbflags;
++ char reserved[248];
+ };
+
+ struct video_info {
+@@ -114,10 +166,10 @@ struct video_info {
+ int video_linelength;
+ unsigned int refresh_rate;
+
+- unsigned long disp_state;
+- unsigned char hasVB;
+- unsigned char TV_type;
+- unsigned char TV_plug;
++ unsigned long disp_state; /* DEPRECATED */
++ unsigned char hasVB; /* DEPRECATED */
++ unsigned char TV_type; /* DEPRECATED */
++ unsigned char TV_plug; /* DEPRECATED */
+
+ SIS_CHIP_TYPE chip;
+ unsigned char revision_id;
+@@ -137,7 +189,18 @@ struct video_info {
+ unsigned short subsysvendor;
+ unsigned short subsysdevice;
+
+- char reserved[236];
++ unsigned long vbflags; /* Replacing deprecated stuff from above */
++ unsigned long currentvbflags;
++
++ int current_bpp;
++ int current_width;
++ int current_height;
++ int current_htotal;
++ int current_vtotal;
++ __u32 current_pixclock;
++ int current_refresh_rate;
++
++ char reserved[200];
+ };
+
+
+@@ -185,7 +248,13 @@ struct _SISFB_INFO {
+
+ unsigned char sisfb_lcda; /* Detected status of LCDA for low res/text modes */
+
+- char reserved[235]; /* for future use */
++ unsigned long sisfb_vbflags;
++ unsigned long sisfb_currentvbflags;
++
++ int sisfb_scalelcd;
++ unsigned long sisfb_specialtiming;
++
++ char reserved[219]; /* for future use */
+ };
+
+ #ifdef __KERNEL__
+--- linux-2.6.0-test6/init/do_mounts.h 2003-09-27 18:57:47.000000000 -0700
++++ 25/init/do_mounts.h 2003-10-05 00:33:25.000000000 -0700
+@@ -104,4 +104,3 @@ void md_run_setup(void);
+ static inline void md_run_setup(void) {}
+
+ #endif
+-
+--- linux-2.6.0-test6/init/do_mounts_initrd.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/init/do_mounts_initrd.c 2003-10-05 00:33:53.000000000 -0700
+@@ -9,6 +9,8 @@
+
+ #include "do_mounts.h"
+
++unsigned long initrd_start, initrd_end;
++int initrd_below_start_ok;
+ unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
+ static int __initdata old_fd, root_fd;
+ static int __initdata mount_initrd = 1;
+@@ -99,18 +101,20 @@ static void __init handle_initrd(void)
+
+ int __init initrd_load(void)
+ {
+- if (!mount_initrd)
+- return 0;
+-
+- create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL);
+- create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL);
+- /* Load the initrd data into /dev/ram0. Execute it as initrd unless
+- * /dev/ram0 is supposed to be our actual root device, in
+- * that case the ram disk is just set up here, and gets
+- * mounted in the normal path. */
+- if (rd_load_image("/dev/initrd") && ROOT_DEV != Root_RAM0) {
+- handle_initrd();
+- return 1;
++ if (mount_initrd) {
++ create_dev("/dev/ram", Root_RAM0, NULL);
++ /*
++ * Load the initrd data into /dev/ram0. Execute it as initrd
++ * unless /dev/ram0 is supposed to be our actual root device,
++ * in that case the ram disk is just set up here, and gets
++ * mounted in the normal path.
++ */
++ if (rd_load_image("/dev/initrd") && ROOT_DEV != Root_RAM0) {
++ sys_unlink("/dev/initrd");
++ handle_initrd();
++ return 1;
++ }
+ }
++ sys_unlink("/dev/initrd");
+ return 0;
+ }
+--- linux-2.6.0-test6/init/initramfs.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/init/initramfs.c 2003-10-05 00:33:53.000000000 -0700
+@@ -8,9 +8,11 @@
+ #include <linux/delay.h>
+ #include <linux/string.h>
+
++static __initdata char *message;
+ static void __init error(char *x)
+ {
+- panic("populate_root: %s\n", x);
++ if (!message)
++ message = x;
+ }
+
+ static void __init *malloc(int size)
+@@ -63,7 +65,7 @@ static char __init *find_link(int major,
+ }
+ q = (struct hash *)malloc(sizeof(struct hash));
+ if (!q)
+- error("can't allocate link hash entry");
++ panic("can't allocate link hash entry");
+ q->ino = ino;
+ q->minor = minor;
+ q->major = major;
+@@ -119,7 +121,7 @@ static void __init parse_header(char *s)
+
+ /* FSM */
+
+-enum state {
++static __initdata enum state {
+ Start,
+ Collect,
+ GotHeader,
+@@ -130,9 +132,11 @@ enum state {
+ Reset
+ } state, next_state;
+
+-char *victim;
+-unsigned count;
+-loff_t this_header, next_header;
++static __initdata char *victim;
++static __initdata unsigned count;
++static __initdata loff_t this_header, next_header;
++
++static __initdata int dry_run;
+
+ static inline void eat(unsigned n)
+ {
+@@ -185,23 +189,30 @@ static int __init do_collect(void)
+
+ static int __init do_header(void)
+ {
++ if (memcmp(collected, "070701", 6)) {
++ error("no cpio magic");
++ return 1;
++ }
+ parse_header(collected);
+ next_header = this_header + N_ALIGN(name_len) + body_len;
+ next_header = (next_header + 3) & ~3;
++ if (dry_run) {
++ read_into(name_buf, N_ALIGN(name_len), GotName);
++ return 0;
++ }
++ state = SkipIt;
+ if (name_len <= 0 || name_len > PATH_MAX)
+- state = SkipIt;
+- else if (S_ISLNK(mode)) {
++ return 0;
++ if (S_ISLNK(mode)) {
+ if (body_len > PATH_MAX)
+- state = SkipIt;
+- else {
+- collect = collected = symlink_buf;
+- remains = N_ALIGN(name_len) + body_len;
+- next_state = GotSymlink;
+- state = Collect;
+- }
+- } else if (body_len && !S_ISREG(mode))
+- state = SkipIt;
+- else
++ return 0;
++ collect = collected = symlink_buf;
++ remains = N_ALIGN(name_len) + body_len;
++ next_state = GotSymlink;
++ state = Collect;
++ return 0;
++ }
++ if (S_ISREG(mode) || !body_len)
+ read_into(name_buf, N_ALIGN(name_len), GotName);
+ return 0;
+ }
+@@ -248,6 +259,8 @@ static int __init do_name(void)
+ next_state = Reset;
+ return 0;
+ }
++ if (dry_run)
++ return 0;
+ if (S_ISREG(mode)) {
+ if (maybe_link() >= 0) {
+ wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
+@@ -268,8 +281,7 @@ static int __init do_name(void)
+ sys_chown(collected, uid, gid);
+ sys_chmod(collected, mode);
+ }
+- } else
+- panic("populate_root: bogus mode: %o\n", mode);
++ }
+ return 0;
+ }
+
+@@ -323,13 +335,14 @@ static int __init write_buffer(char *buf
+ static void __init flush_buffer(char *buf, unsigned len)
+ {
+ int written;
+- while ((written = write_buffer(buf, len)) < len) {
++ if (message)
++ return;
++ while ((written = write_buffer(buf, len)) < len && !message) {
+ char c = buf[written];
+ if (c == '0') {
+ buf += written;
+ len -= written;
+ state = Start;
+- continue;
+ } else
+ error("junk in compressed archive");
+ }
+@@ -408,18 +421,20 @@ static void __init flush_window(void)
+ outcnt = 0;
+ }
+
+-static void __init unpack_to_rootfs(char *buf, unsigned len)
++char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
+ {
+ int written;
++ dry_run = check_only;
+ header_buf = malloc(110);
+ symlink_buf = malloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1);
+ name_buf = malloc(N_ALIGN(PATH_MAX));
+ window = malloc(WSIZE);
+ if (!window || !header_buf || !symlink_buf || !name_buf)
+- error("can't allocate buffers");
++ panic("can't allocate buffers");
+ state = Start;
+ this_header = 0;
+- while (len) {
++ message = NULL;
++ while (!message && len) {
+ loff_t saved_offset = this_header;
+ if (*buf == '0' && !(this_header & 3)) {
+ state = Start;
+@@ -427,7 +442,8 @@ static void __init unpack_to_rootfs(char
+ buf += written;
+ len -= written;
+ continue;
+- } else if (!*buf) {
++ }
++ if (!*buf) {
+ buf++;
+ len--;
+ this_header++;
+@@ -442,7 +458,7 @@ static void __init unpack_to_rootfs(char
+ crc = (ulg)0xffffffffL; /* shift register contents */
+ makecrc();
+ if (gunzip())
+- error("ungzip failed");
++ message = "ungzip failed";
+ if (state != Reset)
+ error("junk in gzipped archive");
+ this_header = saved_offset + inptr;
+@@ -453,12 +469,41 @@ static void __init unpack_to_rootfs(char
+ free(name_buf);
+ free(symlink_buf);
+ free(header_buf);
++ return message;
+ }
+
+ extern char __initramfs_start, __initramfs_end;
++#ifdef CONFIG_BLK_DEV_INITRD
++#include <linux/initrd.h>
++#endif
+
+ void __init populate_rootfs(void)
+ {
+- unpack_to_rootfs(&__initramfs_start,
+- &__initramfs_end - &__initramfs_start);
++ char *err = unpack_to_rootfs(&__initramfs_start,
++ &__initramfs_end - &__initramfs_start, 0);
++ if (err)
++ panic(err);
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (initrd_start) {
++ int fd;
++ printk(KERN_INFO "checking if image is initramfs...");
++ err = unpack_to_rootfs((char *)initrd_start,
++ initrd_end - initrd_start, 1);
++ if (!err) {
++ printk(" it is\n");
++ unpack_to_rootfs((char *)initrd_start,
++ initrd_end - initrd_start, 0);
++ free_initrd_mem(initrd_start, initrd_end);
++ return;
++ }
++ printk("it isn't (%s); looks like an initrd\n", err);
++ fd = sys_open("/dev/initrd", O_WRONLY|O_CREAT, 700);
++ if (fd >= 0) {
++ sys_write(fd, (char *)initrd_start,
++ initrd_end - initrd_start);
++ sys_close(fd);
++ free_initrd_mem(initrd_start, initrd_end);
++ }
++ }
++#endif
+ }
+--- linux-2.6.0-test6/init/main.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/init/main.c 2003-10-05 00:36:25.000000000 -0700
+@@ -37,6 +37,7 @@
+ #include <linux/moduleparam.h>
+ #include <linux/writeback.h>
+ #include <linux/cpu.h>
++#include <linux/efi.h>
+
+ #include <asm/io.h>
+ #include <asm/bugs.h>
+@@ -436,6 +437,10 @@ asmlinkage void __init start_kernel(void
+ pidmap_init();
+ pgtable_cache_init();
+ pte_chain_init();
++#ifdef CONFIG_X86
++ if (efi_enabled)
++ efi_enter_virtual_mode();
++#endif
+ fork_init(num_physpages);
+ proc_caches_init();
+ buffer_init();
+--- linux-2.6.0-test6/kernel/acct.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/acct.c 2003-10-05 00:36:15.000000000 -0700
+@@ -343,7 +343,7 @@ static void do_acct_process(long exitcod
+ /* we really need to bite the bullet and change layout */
+ ac.ac_uid = current->uid;
+ ac.ac_gid = current->gid;
+- ac.ac_tty = current->tty ? old_encode_dev(tty_devnum(current->tty)) : 0;
++ ac.ac_tty = process_tty(current) ? old_encode_dev(tty_devnum(process_tty(current))) : 0;
+
+ ac.ac_flag = 0;
+ if (current->flags & PF_FORKNOEXEC)
+--- linux-2.6.0-test6/kernel/exit.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/exit.c 2003-10-05 00:36:15.000000000 -0700
+@@ -119,13 +119,13 @@ int session_of_pgrp(int pgrp)
+
+ read_lock(&tasklist_lock);
+ for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid)
+- if (p->session > 0) {
+- sid = p->session;
++ if (process_session(p) > 0) {
++ sid = process_session(p);
+ goto out;
+ }
+ p = find_task_by_pid(pgrp);
+ if (p)
+- sid = p->session;
++ sid = process_session(p);
+ out:
+ read_unlock(&tasklist_lock);
+
+@@ -153,7 +153,7 @@ static int will_become_orphaned_pgrp(int
+ || p->real_parent->pid == 1)
+ continue;
+ if (process_group(p->real_parent) != pgrp
+- && p->real_parent->session == p->session) {
++ && process_session(p->real_parent) == process_session(p)) {
+ ret = 0;
+ break;
+ }
+@@ -242,14 +242,14 @@ void __set_special_pids(pid_t session, p
+ {
+ struct task_struct *curr = current;
+
+- if (curr->session != session) {
++ if (process_session(curr) != session) {
+ detach_pid(curr, PIDTYPE_SID);
+- curr->session = session;
++ curr->signal->session = session;
+ attach_pid(curr, PIDTYPE_SID, session);
+ }
+ if (process_group(curr) != pgrp) {
+ detach_pid(curr, PIDTYPE_PGID);
+- curr->group_leader->__pgrp = pgrp;
++ curr->signal->pgrp = pgrp;
+ attach_pid(curr, PIDTYPE_PGID, pgrp);
+ }
+ }
+@@ -303,7 +303,7 @@ void daemonize(const char *name, ...)
+ exit_mm(current);
+
+ set_special_pids(1, 1);
+- current->tty = NULL;
++ current->signal->tty = NULL;
+
+ /* Block and flush all signals */
+ sigfillset(&blocked);
+@@ -509,7 +509,7 @@ static inline void reparent_thread(task_
+ * outside, so the child pgrp is now orphaned.
+ */
+ if ((process_group(p) != process_group(father)) &&
+- (p->session == father->session)) {
++ (process_session(p) == process_session(father))) {
+ int pgrp = process_group(p);
+
+ if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) {
+@@ -619,7 +619,7 @@ static void exit_notify(struct task_stru
+ t = tsk->real_parent;
+
+ if ((process_group(t) != process_group(tsk)) &&
+- (t->session == tsk->session) &&
++ (process_session(t) == process_session(tsk)) &&
+ will_become_orphaned_pgrp(process_group(tsk), tsk) &&
+ has_stopped_jobs(process_group(tsk))) {
+ __kill_pg_info(SIGHUP, (void *)1, process_group(tsk));
+@@ -714,7 +714,7 @@ NORET_TYPE void do_exit(long code)
+ exit_itimers(tsk);
+ exit_thread();
+
+- if (tsk->leader)
++ if (process_session_leader(tsk))
+ disassociate_ctty(1);
+
+ module_put(tsk->thread_info->exec_domain->module);
+--- linux-2.6.0-test6/kernel/fork.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/fork.c 2003-10-05 00:36:54.000000000 -0700
+@@ -121,7 +121,12 @@ void prepare_to_wait(wait_queue_head_t *
+ {
+ unsigned long flags;
+
+- __set_current_state(state);
++ /*
++ * don't alter the task state if this is just going to
++ * queue an async wait queue callback
++ */
++ if (is_sync_wait(wait))
++ __set_current_state(state);
+ wait->flags &= ~WQ_FLAG_EXCLUSIVE;
+ spin_lock_irqsave(&q->lock, flags);
+ if (list_empty(&wait->task_list))
+@@ -134,7 +139,12 @@ prepare_to_wait_exclusive(wait_queue_hea
+ {
+ unsigned long flags;
+
+- __set_current_state(state);
++ /*
++ * don't alter the task state if this is just going to
++ * queue an async wait queue callback
++ */
++ if (is_sync_wait(wait))
++ __set_current_state(state);
+ wait->flags |= WQ_FLAG_EXCLUSIVE;
+ spin_lock_irqsave(&q->lock, flags);
+ if (list_empty(&wait->task_list))
+@@ -274,9 +284,9 @@ static inline int dup_mmap(struct mm_str
+ atomic_dec(&inode->i_writecount);
+
+ /* insert tmp into the share list, just after mpnt */
+- down(&inode->i_mapping->i_shared_sem);
++ down(&file->f_mapping->i_shared_sem);
+ list_add_tail(&tmp->shared, &mpnt->shared);
+- up(&inode->i_mapping->i_shared_sem);
++ up(&file->f_mapping->i_shared_sem);
+ }
+
+ /*
+@@ -725,6 +735,12 @@ static inline int copy_signal(unsigned l
+ sig->curr_target = NULL;
+ init_sigpending(&sig->shared_pending);
+
++ sig->tty = process_tty(current);
++ sig->pgrp = process_group(current);
++ sig->session = process_session(current);
++ sig->leader = 0; /* session leadership doesn't inherit */
++ sig->tty_old_pgrp = 0;
++
+ return 0;
+ }
+
+@@ -771,7 +787,9 @@ struct task_struct *copy_process(unsigne
+ * Thread groups must share signals as well, and detached threads
+ * can only be started up within the thread group.
+ */
+- if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
++ if ((clone_flags & CLONE_THREAD) &&
++ (clone_flags & (CLONE_SIGHAND|CLONE_DETACHED)) !=
++ (CLONE_SIGHAND|CLONE_DETACHED))
+ return ERR_PTR(-EINVAL);
+
+ /*
+@@ -876,8 +894,6 @@ struct task_struct *copy_process(unsigne
+ init_timer(&p->real_timer);
+ p->real_timer.data = (unsigned long) p;
+
+- p->leader = 0; /* session leadership doesn't inherit */
+- p->tty_old_pgrp = 0;
+ p->utime = p->stime = 0;
+ p->cutime = p->cstime = 0;
+ p->array = NULL;
+@@ -885,6 +901,7 @@ struct task_struct *copy_process(unsigne
+ p->start_time = get_jiffies_64();
+ p->security = NULL;
+ p->io_context = NULL;
++ p->io_wait = NULL;
+
+ retval = -ENOMEM;
+ if ((retval = security_task_alloc(p)))
+@@ -1022,7 +1039,7 @@ struct task_struct *copy_process(unsigne
+ if (thread_group_leader(p)) {
+ attach_pid(p, PIDTYPE_TGID, p->tgid);
+ attach_pid(p, PIDTYPE_PGID, process_group(p));
+- attach_pid(p, PIDTYPE_SID, p->session);
++ attach_pid(p, PIDTYPE_SID, process_session(p));
+ if (p->pid)
+ __get_cpu_var(process_counts)++;
+ } else
+--- linux-2.6.0-test6/kernel/futex.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/futex.c 2003-10-05 00:34:38.000000000 -0700
+@@ -45,6 +45,9 @@
+ * Futexes are matched on equal values of this key.
+ * The key type depends on whether it's a shared or private mapping.
+ * Don't rearrange members without looking at hash_futex().
++ *
++ * offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
++ * We set bit 0 to indicate if it's an inode-based key.
+ */
+ union futex_key {
+ struct {
+@@ -66,12 +69,20 @@ union futex_key {
+
+ /*
+ * We use this hashed waitqueue instead of a normal wait_queue_t, so
+- * we can wake only the relevant ones (hashed queues may be shared):
++ * we can wake only the relevant ones (hashed queues may be shared).
++ *
++ * A futex_q has a woken state, just like tasks have TASK_RUNNING.
++ * It is considered woken when list_empty(&q->list) || q->lock_ptr == 0.
++ * The order of wakup is always to make the first condition true, then
++ * wake up q->waiters, then make the second condition true.
+ */
+ struct futex_q {
+ struct list_head list;
+ wait_queue_head_t waiters;
+
++ /* Which hash list lock to use. */
++ spinlock_t *lock_ptr;
++
+ /* Key which the futex is hashed on. */
+ union futex_key key;
+
+@@ -124,8 +135,7 @@ static inline int match_futex(union fute
+ * Returns: 0, or negative error code.
+ * The key words are stored in *key on success.
+ *
+- * Should be called with ¤t->mm->mmap_sem,
+- * but NOT &futex_lock or ¤t->mm->page_table_lock.
++ * Should be called with ¤t->mm->mmap_sem but NOT any spinlocks.
+ */
+ static int get_futex_key(unsigned long uaddr, union futex_key *key)
+ {
+@@ -172,9 +182,10 @@ static int get_futex_key(unsigned long u
+ }
+
+ /*
+- * Linear mappings are also simple.
++ * Linear file mappings are also simple.
+ */
+ key->shared.inode = vma->vm_file->f_dentry->d_inode;
++ key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
+ if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
+ key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT)
+ + vma->vm_pgoff);
+@@ -214,16 +225,68 @@ static int get_futex_key(unsigned long u
+ return err;
+ }
+
++/*
++ * Take a reference to the resource addressed by a key.
++ * Can be called while holding spinlocks.
++ *
++ * NOTE: mmap_sem MUST be held between get_futex_key() and calling this
++ * function, if it is called at all. mmap_sem keeps key->shared.inode valid.
++ */
++static inline void get_key_refs(union futex_key *key)
++{
++ if (key->both.ptr != 0) {
++ if (key->both.offset & 1)
++ atomic_inc(&key->shared.inode->i_count);
++ else
++ atomic_inc(&key->private.mm->mm_count);
++ }
++}
++
++/*
++ * Drop a reference to the resource addressed by a key.
++ * The hash bucket spinlock must not be held.
++ */
++static void drop_key_refs(union futex_key *key)
++{
++ if (key->both.ptr != 0) {
++ if (key->both.offset & 1)
++ iput(key->shared.inode);
++ else
++ mmdrop(key->private.mm);
++ }
++}
++
++/*
++ * The hash bucket lock must be held when this is called.
++ * Afterwards, the futex_q must not be accessed.
++ */
++static void wake_futex(struct futex_q *q)
++{
++ list_del_init(&q->list);
++ if (q->filp)
++ send_sigio(&q->filp->f_owner, q->fd, POLL_IN);
++ /*
++ * The lock in wake_up_all() is a crucial memory barrier after the
++ * list_del_init() and also before assigning to q->lock_ptr.
++ */
++ wake_up_all(&q->waiters);
++ /*
++ * The waiting task can free the futex_q as soon as this is written,
++ * without taking any locks. This must come last.
++ */
++ q->lock_ptr = 0;
++}
+
+ /*
+ * Wake up all waiters hashed on the physical page that is mapped
+ * to this virtual address:
+ */
+-static int futex_wake(unsigned long uaddr, int num)
++static int futex_wake(unsigned long uaddr, int nr_wake)
+ {
+- struct list_head *i, *next, *head;
+- struct futex_hash_bucket *bh;
+ union futex_key key;
++ struct futex_hash_bucket *bh;
++ struct list_head *head;
++ struct futex_q *this, *next;
+ int ret;
+
+ down_read(¤t->mm->mmap_sem);
+@@ -236,21 +299,15 @@ static int futex_wake(unsigned long uadd
+ spin_lock(&bh->lock);
+ head = &bh->chain;
+
+- list_for_each_safe(i, next, head) {
+- struct futex_q *this = list_entry(i, struct futex_q, list);
+-
++ list_for_each_entry_safe(this, next, head, list) {
+ if (match_futex (&this->key, &key)) {
+- list_del_init(i);
+- wake_up_all(&this->waiters);
+- if (this->filp)
+- send_sigio(&this->filp->f_owner, this->fd, POLL_IN);
+- ret++;
+- if (ret >= num)
++ wake_futex(this);
++ if (++ret >= nr_wake)
+ break;
+ }
+ }
+- spin_unlock(&bh->lock);
+
++ spin_unlock(&bh->lock);
+ out:
+ up_read(¤t->mm->mmap_sem);
+ return ret;
+@@ -263,10 +320,11 @@ out:
+ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
+ int nr_wake, int nr_requeue)
+ {
+- struct list_head *i, *next, *head1, *head2;
+- struct futex_hash_bucket *bh1, *bh2;
+ union futex_key key1, key2;
+- int ret;
++ struct futex_hash_bucket *bh1, *bh2;
++ struct list_head *head1;
++ struct futex_q *this, *next;
++ int ret, drop_count = 0;
+
+ down_read(¤t->mm->mmap_sem);
+
+@@ -279,78 +337,107 @@ static int futex_requeue(unsigned long u
+
+ bh1 = hash_futex(&key1);
+ bh2 = hash_futex(&key2);
+- if (bh1 < bh2) {
++
++ if (bh1 < bh2)
++ spin_lock(&bh1->lock);
++ spin_lock(&bh2->lock);
++ if (bh1 > bh2)
+ spin_lock(&bh1->lock);
+- spin_lock(&bh2->lock);
+- } else {
+- spin_lock(&bh2->lock);
+- if (bh1 > bh2)
+- spin_lock(&bh1->lock);
+- }
+- head1 = &bh1->chain;
+- head2 = &bh2->chain;
+
+- list_for_each_safe(i, next, head1) {
+- struct futex_q *this = list_entry(i, struct futex_q, list);
++ head1 = &bh1->chain;
++ list_for_each_entry_safe(this, next, head1, list) {
++ if (!match_futex (&this->key, &key1))
++ continue;
++ if (++ret <= nr_wake) {
++ wake_futex(this);
++ } else {
++ list_move_tail(&this->list, &bh2->chain);
++ this->lock_ptr = &bh2->lock;
++ this->key = key2;
++ get_key_refs(&key2);
++ drop_count++;
+
+- if (match_futex (&this->key, &key1)) {
+- list_del_init(i);
+- if (++ret <= nr_wake) {
+- wake_up_all(&this->waiters);
+- if (this->filp)
+- send_sigio(&this->filp->f_owner,
+- this->fd, POLL_IN);
+- } else {
+- list_add_tail(i, head2);
+- this->key = key2;
+- if (ret - nr_wake >= nr_requeue)
+- break;
+- /* Make sure to stop if key1 == key2 */
+- if (head1 == head2 && head1 != next)
+- head1 = i;
+- }
++ if (ret - nr_wake >= nr_requeue)
++ break;
++ /* Make sure to stop if key1 == key2 */
++ if (head1 == &bh2->chain && head1 != &next->list)
++ head1 = &this->list;
+ }
+ }
+- if (bh1 < bh2) {
+- spin_unlock(&bh2->lock);
+- spin_unlock(&bh1->lock);
+- } else {
+- if (bh1 > bh2)
+- spin_unlock(&bh1->lock);
++
++ spin_unlock(&bh1->lock);
++ if (bh1 != bh2)
+ spin_unlock(&bh2->lock);
+- }
++
++ /* drop_key_refs() must be called outside the spinlocks. */
++ while (--drop_count >= 0)
++ drop_key_refs(&key1);
++
+ out:
+ up_read(¤t->mm->mmap_sem);
+ return ret;
+ }
+
+-static inline void queue_me(struct futex_q *q, union futex_key *key,
+- int fd, struct file *filp)
++/*
++ * queue_me and unqueue_me must be called as a pair, each
++ * exactly once. They are called with the hashed spinlock held.
++ */
++
++/* The key must be already stored in q->key. */
++static void queue_me(struct futex_q *q, int fd, struct file *filp)
+ {
+- struct futex_hash_bucket *bh = hash_futex(key);
+- struct list_head *head = &bh->chain;
++ struct futex_hash_bucket *bh;
+
+- q->key = *key;
+ q->fd = fd;
+ q->filp = filp;
+
++ init_waitqueue_head(&q->waiters);
++
++ get_key_refs(&q->key);
++ bh = hash_futex(&q->key);
++ q->lock_ptr = &bh->lock;
++
+ spin_lock(&bh->lock);
+- list_add_tail(&q->list, head);
++ list_add_tail(&q->list, &bh->chain);
+ spin_unlock(&bh->lock);
+ }
+
+ /* Return 1 if we were still queued (ie. 0 means we were woken) */
+-static inline int unqueue_me(struct futex_q *q)
++static int unqueue_me(struct futex_q *q)
+ {
+- struct futex_hash_bucket *bh = hash_futex(&q->key);
+ int ret = 0;
++ spinlock_t *lock_ptr;
+
+- spin_lock(&bh->lock);
+- if (!list_empty(&q->list)) {
+- list_del(&q->list);
+- ret = 1;
++ /* In the common case we don't take the spinlock, which is nice. */
++ retry:
++ lock_ptr = q->lock_ptr;
++ if (lock_ptr != 0) {
++ spin_lock(lock_ptr);
++ /*
++ * q->lock_ptr can change between reading it and
++ * spin_lock(), causing us to take the wrong lock. This
++ * corrects the race condition.
++ *
++ * Reasoning goes like this: if we have the wrong lock,
++ * q->lock_ptr must have changed (maybe several times)
++ * between reading it and the spin_lock(). It can
++ * change again after the spin_lock() but only if it was
++ * already changed before the spin_lock(). It cannot,
++ * however, change back to the original value. Therefore
++ * we can detect whether we acquired the correct lock.
++ */
++ if (unlikely(lock_ptr != q->lock_ptr)) {
++ spin_unlock(lock_ptr);
++ goto retry;
++ }
++ if (likely(!list_empty(&q->list))) {
++ list_del(&q->list);
++ ret = 1;
++ }
++ spin_unlock(lock_ptr);
+ }
+- spin_unlock(&bh->lock);
++
++ drop_key_refs(&q->key);
+ return ret;
+ }
+
+@@ -358,19 +445,15 @@ static int futex_wait(unsigned long uadd
+ {
+ DECLARE_WAITQUEUE(wait, current);
+ int ret, curval;
+- union futex_key key;
+ struct futex_q q;
+- struct futex_hash_bucket *bh = NULL;
+-
+- init_waitqueue_head(&q.waiters);
+
+ down_read(¤t->mm->mmap_sem);
+
+- ret = get_futex_key(uaddr, &key);
++ ret = get_futex_key(uaddr, &q.key);
+ if (unlikely(ret != 0))
+ goto out_release_sem;
+
+- queue_me(&q, &key, -1, NULL);
++ queue_me(&q, -1, NULL);
+
+ /*
+ * Access the page after the futex is queued.
+@@ -400,23 +483,17 @@ static int futex_wait(unsigned long uadd
+ * rely on the futex_wake() code removing us from hash when it
+ * wakes us up.
+ */
+- add_wait_queue(&q.waiters, &wait);
+- bh = hash_futex(&key);
+- spin_lock(&bh->lock);
+- set_current_state(TASK_INTERRUPTIBLE);
+-
+- if (unlikely(list_empty(&q.list))) {
+- /*
+- * We were woken already.
+- */
+- spin_unlock(&bh->lock);
+- set_current_state(TASK_RUNNING);
+- return 0;
+- }
+
+- spin_unlock(&bh->lock);
+- time = schedule_timeout(time);
+- set_current_state(TASK_RUNNING);
++ /* add_wait_queue is the barrier after __set_current_state. */
++ __set_current_state(TASK_INTERRUPTIBLE);
++ add_wait_queue(&q.waiters, &wait);
++ /*
++ * !list_empty() is safe here without any lock.
++ * q.lock_ptr != 0 is not safe, because of ordering against wakeup.
++ */
++ if (likely(!list_empty(&q.list)))
++ time = schedule_timeout(time);
++ __set_current_state(TASK_RUNNING);
+
+ /*
+ * NOTE: we don't remove ourselves from the waitqueue because
+@@ -446,7 +523,7 @@ static int futex_close(struct inode *ino
+ struct futex_q *q = filp->private_data;
+
+ unqueue_me(q);
+- kfree(filp->private_data);
++ kfree(q);
+ return 0;
+ }
+
+@@ -455,14 +532,16 @@ static unsigned int futex_poll(struct fi
+ struct poll_table_struct *wait)
+ {
+ struct futex_q *q = filp->private_data;
+- struct futex_hash_bucket *bh = hash_futex(&q->key);
+ int ret = 0;
+
+ poll_wait(filp, &q->waiters, wait);
+- spin_lock(&bh->lock);
++
++ /*
++ * list_empty() is safe here without any lock.
++ * q->lock_ptr != 0 is not safe, because of ordering against wakeup.
++ */
+ if (list_empty(&q->list))
+ ret = POLLIN | POLLRDNORM;
+- spin_unlock(&bh->lock);
+
+ return ret;
+ }
+@@ -472,12 +551,13 @@ static struct file_operations futex_fops
+ .poll = futex_poll,
+ };
+
+-/* Signal allows caller to avoid the race which would occur if they
+- set the sigio stuff up afterwards. */
++/*
++ * Signal allows caller to avoid the race which would occur if they
++ * set the sigio stuff up afterwards.
++ */
+ static int futex_fd(unsigned long uaddr, int signal)
+ {
+ struct futex_q *q;
+- union futex_key key;
+ struct file *filp;
+ int ret, err;
+
+@@ -497,6 +577,7 @@ static int futex_fd(unsigned long uaddr,
+ filp->f_op = &futex_fops;
+ filp->f_vfsmnt = mntget(futex_mnt);
+ filp->f_dentry = dget(futex_mnt->mnt_root);
++ filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+
+ if (signal) {
+ int err;
+@@ -519,20 +600,24 @@ static int futex_fd(unsigned long uaddr,
+ }
+
+ down_read(¤t->mm->mmap_sem);
+- err = get_futex_key(uaddr, &key);
+- up_read(¤t->mm->mmap_sem);
++ err = get_futex_key(uaddr, &q->key);
+
+ if (unlikely(err != 0)) {
++ up_read(¤t->mm->mmap_sem);
+ put_unused_fd(ret);
+ put_filp(filp);
+ kfree(q);
+ return err;
+ }
+
+- init_waitqueue_head(&q->waiters);
++ /*
++ * queue_me() must be called before releasing mmap_sem, because
++ * key->shared.inode needs to be referenced while holding it.
++ */
+ filp->private_data = q;
+
+- queue_me(q, &key, ret, filp);
++ queue_me(q, ret, filp);
++ up_read(¤t->mm->mmap_sem);
+
+ /* Now we map fd to filp, so userspace can access it */
+ fd_install(ret, filp);
+--- linux-2.6.0-test6/kernel/kmod.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/kernel/kmod.c 2003-10-05 00:36:10.000000000 -0700
+@@ -47,7 +47,8 @@ char modprobe_path[256] = "/sbin/modprob
+
+ /**
+ * request_module - try to load a kernel module
+- * @module_name: Name of module
++ * @fmt: printf style format string for the name of the module
++ * @varargs: arguements as specified in the format string
+ *
+ * Load a module using the user mode module loader. The function returns
+ * zero on success or a negative errno code on failure. Note that a
+@@ -184,14 +185,19 @@ static int wait_for_helper(void *data)
+
+ sub_info->retval = 0;
+ pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD);
+- if (pid < 0)
++ if (pid < 0) {
+ sub_info->retval = pid;
+- else
++ } else {
+ /* We don't have a SIGCHLD signal handler, so this
+ * always returns -ECHILD, but the important thing is
+ * that it blocks. */
+- sys_wait4(pid, NULL, 0, NULL);
++ mm_segment_t fs;
+
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++ sys_wait4(pid, &sub_info->retval, 0, NULL);
++ set_fs(fs);
++ }
+ complete(sub_info->complete);
+ return 0;
+ }
+@@ -209,7 +215,7 @@ static void __call_usermodehelper(void *
+ * until that is done. */
+ if (sub_info->wait)
+ pid = kernel_thread(wait_for_helper, sub_info,
+- CLONE_KERNEL | SIGCHLD);
++ CLONE_FS | CLONE_FILES | SIGCHLD);
+ else
+ pid = kernel_thread(____call_usermodehelper, sub_info,
+ CLONE_VFORK | SIGCHLD);
+--- linux-2.6.0-test6/kernel/ksyms.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/ksyms.c 2003-10-05 00:36:58.000000000 -0700
+@@ -45,8 +45,6 @@
+ #include <linux/uio.h>
+ #include <linux/tty.h>
+ #include <linux/in6.h>
+-#include <linux/completion.h>
+-#include <linux/seq_file.h>
+ #include <linux/binfmts.h>
+ #include <linux/namei.h>
+ #include <linux/buffer_head.h>
+@@ -126,11 +124,11 @@ EXPORT_SYMBOL(get_unmapped_area);
+ EXPORT_SYMBOL(init_mm);
+ EXPORT_SYMBOL(blk_queue_bounce);
+ EXPORT_SYMBOL(blk_congestion_wait);
++EXPORT_SYMBOL(blk_congestion_wait_wq);
+ #ifdef CONFIG_HIGHMEM
+ EXPORT_SYMBOL(kmap_high);
+ EXPORT_SYMBOL(kunmap_high);
+ EXPORT_SYMBOL(highmem_start_page);
+-EXPORT_SYMBOL(kmap_prot);
+ EXPORT_SYMBOL(kmap_pte);
+ #endif
+ #ifdef HASHED_PAGE_VIRTUAL
+@@ -139,49 +137,12 @@ EXPORT_SYMBOL(page_address);
+ EXPORT_SYMBOL(get_user_pages);
+
+ /* filesystem internal functions */
+-EXPORT_SYMBOL(def_blk_fops);
+-EXPORT_SYMBOL(update_atime);
+ EXPORT_SYMBOL(get_fs_type);
+-EXPORT_SYMBOL(user_get_super);
+-EXPORT_SYMBOL(get_super);
+-EXPORT_SYMBOL(drop_super);
+-EXPORT_SYMBOL(getname);
+-EXPORT_SYMBOL(names_cachep);
+ EXPORT_SYMBOL(fput);
+ EXPORT_SYMBOL(fget);
+-EXPORT_SYMBOL(igrab);
+-EXPORT_SYMBOL(iunique);
+-EXPORT_SYMBOL(iput);
+-EXPORT_SYMBOL(inode_init_once);
+-EXPORT_SYMBOL(follow_up);
+-EXPORT_SYMBOL(follow_down);
+ EXPORT_SYMBOL(lookup_mnt);
+-EXPORT_SYMBOL(lookup_create);
+-EXPORT_SYMBOL(path_lookup);
+-EXPORT_SYMBOL(path_walk);
+-EXPORT_SYMBOL(path_release);
+-EXPORT_SYMBOL(__user_walk);
+-EXPORT_SYMBOL(lookup_one_len);
+-EXPORT_SYMBOL(lookup_hash);
+ EXPORT_SYMBOL(sys_close);
+ EXPORT_SYMBOL(dcache_lock);
+-EXPORT_SYMBOL(d_alloc_root);
+-EXPORT_SYMBOL(d_delete);
+-EXPORT_SYMBOL(dget_locked);
+-EXPORT_SYMBOL(d_validate);
+-EXPORT_SYMBOL(d_rehash);
+-EXPORT_SYMBOL(d_invalidate); /* May be it will be better in dcache.h? */
+-EXPORT_SYMBOL(d_move);
+-EXPORT_SYMBOL(d_instantiate);
+-EXPORT_SYMBOL(d_alloc);
+-EXPORT_SYMBOL(d_alloc_anon);
+-EXPORT_SYMBOL(d_splice_alias);
+-EXPORT_SYMBOL(d_lookup);
+-EXPORT_SYMBOL(d_path);
+-EXPORT_SYMBOL(mark_buffer_dirty);
+-EXPORT_SYMBOL(end_buffer_read_sync);
+-EXPORT_SYMBOL(end_buffer_write_sync);
+-EXPORT_SYMBOL(end_buffer_async_write);
+ EXPORT_SYMBOL(__mark_inode_dirty);
+ EXPORT_SYMBOL(get_empty_filp);
+ EXPORT_SYMBOL(open_private_file);
+@@ -190,79 +151,20 @@ EXPORT_SYMBOL(filp_open);
+ EXPORT_SYMBOL(filp_close);
+ EXPORT_SYMBOL(put_filp);
+ EXPORT_SYMBOL(files_lock);
+-EXPORT_SYMBOL(check_disk_change);
+-EXPORT_SYMBOL(invalidate_bdev);
+-EXPORT_SYMBOL(invalidate_inodes);
+-EXPORT_SYMBOL(__invalidate_device);
+ EXPORT_SYMBOL(invalidate_inode_pages);
+ EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
+ EXPORT_SYMBOL(truncate_inode_pages);
+-EXPORT_SYMBOL(fsync_bdev);
+-EXPORT_SYMBOL(permission);
+-EXPORT_SYMBOL(vfs_permission);
+ EXPORT_SYMBOL(inode_setattr);
+ EXPORT_SYMBOL(inode_change_ok);
+ EXPORT_SYMBOL(write_inode_now);
+ EXPORT_SYMBOL(notify_change);
+-EXPORT_SYMBOL(set_blocksize);
+-EXPORT_SYMBOL(sb_set_blocksize);
+-EXPORT_SYMBOL(sb_min_blocksize);
+-EXPORT_SYMBOL(bdget);
+-EXPORT_SYMBOL(bdput);
+-EXPORT_SYMBOL(bd_claim);
+-EXPORT_SYMBOL(bd_release);
+-EXPORT_SYMBOL(open_bdev_excl);
+-EXPORT_SYMBOL(close_bdev_excl);
+-EXPORT_SYMBOL(open_by_devnum);
+-EXPORT_SYMBOL(__brelse);
+-EXPORT_SYMBOL(__bforget);
+-EXPORT_SYMBOL(ll_rw_block);
+-EXPORT_SYMBOL(sync_dirty_buffer);
+-EXPORT_SYMBOL(submit_bh);
+-EXPORT_SYMBOL(unlock_buffer);
+-EXPORT_SYMBOL(__wait_on_buffer);
+-EXPORT_SYMBOL(blockdev_direct_IO);
+-EXPORT_SYMBOL(block_write_full_page);
+-EXPORT_SYMBOL(block_read_full_page);
+-EXPORT_SYMBOL(block_prepare_write);
+-EXPORT_SYMBOL(block_sync_page);
+-EXPORT_SYMBOL(generic_cont_expand);
+-EXPORT_SYMBOL(cont_prepare_write);
+-EXPORT_SYMBOL(generic_commit_write);
+-EXPORT_SYMBOL(block_commit_write);
+-EXPORT_SYMBOL(block_truncate_page);
+-EXPORT_SYMBOL(generic_block_bmap);
+-EXPORT_SYMBOL(generic_file_read);
+-EXPORT_SYMBOL(generic_file_sendfile);
+-EXPORT_SYMBOL(do_generic_mapping_read);
+ EXPORT_SYMBOL(file_ra_state_init);
+-EXPORT_SYMBOL(generic_file_write);
+-EXPORT_SYMBOL(generic_file_write_nolock);
+-EXPORT_SYMBOL(generic_file_mmap);
+-EXPORT_SYMBOL(generic_file_readonly_mmap);
+ EXPORT_SYMBOL(generic_ro_fops);
+-EXPORT_SYMBOL(dput);
+-EXPORT_SYMBOL(have_submounts);
+-EXPORT_SYMBOL(d_find_alias);
+-EXPORT_SYMBOL(d_prune_aliases);
+-EXPORT_SYMBOL(shrink_dcache_sb);
+-EXPORT_SYMBOL(shrink_dcache_parent);
+-EXPORT_SYMBOL(shrink_dcache_anon);
+-EXPORT_SYMBOL(find_inode_number);
+-EXPORT_SYMBOL(is_subdir);
+ EXPORT_SYMBOL(get_unused_fd);
+ EXPORT_SYMBOL(vfs_read);
+ EXPORT_SYMBOL(vfs_readv);
+ EXPORT_SYMBOL(vfs_write);
+ EXPORT_SYMBOL(vfs_writev);
+-EXPORT_SYMBOL(vfs_create);
+-EXPORT_SYMBOL(vfs_mkdir);
+-EXPORT_SYMBOL(vfs_mknod);
+-EXPORT_SYMBOL(vfs_symlink);
+-EXPORT_SYMBOL(vfs_link);
+-EXPORT_SYMBOL(vfs_rmdir);
+-EXPORT_SYMBOL(vfs_unlink);
+-EXPORT_SYMBOL(vfs_rename);
+ EXPORT_SYMBOL(vfs_statfs);
+ EXPORT_SYMBOL(vfs_fstat);
+ EXPORT_SYMBOL(vfs_stat);
+@@ -272,9 +174,6 @@ EXPORT_SYMBOL(inode_add_bytes);
+ EXPORT_SYMBOL(inode_sub_bytes);
+ EXPORT_SYMBOL(inode_get_bytes);
+ EXPORT_SYMBOL(inode_set_bytes);
+-EXPORT_SYMBOL(lock_rename);
+-EXPORT_SYMBOL(unlock_rename);
+-EXPORT_SYMBOL(generic_read_dir);
+ EXPORT_SYMBOL(generic_fillattr);
+ EXPORT_SYMBOL(generic_file_llseek);
+ EXPORT_SYMBOL(remote_llseek);
+@@ -282,70 +181,21 @@ EXPORT_SYMBOL(no_llseek);
+ EXPORT_SYMBOL(poll_initwait);
+ EXPORT_SYMBOL(poll_freewait);
+ EXPORT_SYMBOL(ROOT_DEV);
+-EXPORT_SYMBOL(find_get_page);
+-EXPORT_SYMBOL(find_lock_page);
+-EXPORT_SYMBOL(find_trylock_page);
+-EXPORT_SYMBOL(find_or_create_page);
+-EXPORT_SYMBOL(grab_cache_page_nowait);
+-EXPORT_SYMBOL(read_cache_page);
+ EXPORT_SYMBOL(read_cache_pages);
+ EXPORT_SYMBOL(mark_page_accessed);
+-EXPORT_SYMBOL(vfs_readlink);
+-EXPORT_SYMBOL(vfs_follow_link);
+-EXPORT_SYMBOL(page_readlink);
+-EXPORT_SYMBOL(page_follow_link);
+-EXPORT_SYMBOL(page_symlink_inode_operations);
+-EXPORT_SYMBOL(page_symlink);
+ EXPORT_SYMBOL(vfs_readdir);
+ EXPORT_SYMBOL(__break_lease);
+ EXPORT_SYMBOL(lease_get_mtime);
+ EXPORT_SYMBOL(lock_may_read);
+ EXPORT_SYMBOL(lock_may_write);
+-EXPORT_SYMBOL(dcache_dir_open);
+-EXPORT_SYMBOL(dcache_dir_close);
+-EXPORT_SYMBOL(dcache_dir_lseek);
+-EXPORT_SYMBOL(dcache_readdir);
+-EXPORT_SYMBOL(simple_getattr);
+-EXPORT_SYMBOL(simple_statfs);
+-EXPORT_SYMBOL(simple_lookup);
+-EXPORT_SYMBOL(simple_dir_operations);
+-EXPORT_SYMBOL(simple_dir_inode_operations);
+-EXPORT_SYMBOL(simple_link);
+-EXPORT_SYMBOL(simple_unlink);
+-EXPORT_SYMBOL(simple_rmdir);
+-EXPORT_SYMBOL(simple_rename);
+-EXPORT_SYMBOL(simple_sync_file);
+-EXPORT_SYMBOL(simple_readpage);
+-EXPORT_SYMBOL(simple_prepare_write);
+-EXPORT_SYMBOL(simple_commit_write);
+-EXPORT_SYMBOL(simple_empty);
+-EXPORT_SYMBOL(simple_fill_super);
+-EXPORT_SYMBOL(simple_pin_fs);
+-EXPORT_SYMBOL(simple_release_fs);
+ EXPORT_SYMBOL(fd_install);
+ EXPORT_SYMBOL(put_unused_fd);
+-EXPORT_SYMBOL(get_sb_bdev);
+-EXPORT_SYMBOL(kill_block_super);
+-EXPORT_SYMBOL(get_sb_nodev);
+-EXPORT_SYMBOL(get_sb_single);
+-EXPORT_SYMBOL(kill_anon_super);
+-EXPORT_SYMBOL(kill_litter_super);
+-EXPORT_SYMBOL(generic_shutdown_super);
+-EXPORT_SYMBOL(deactivate_super);
+-EXPORT_SYMBOL(sget);
+-EXPORT_SYMBOL(set_anon_super);
+ EXPORT_SYMBOL(do_select);
+
+ /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
+ EXPORT_SYMBOL(default_llseek);
+ EXPORT_SYMBOL(dentry_open);
+-#ifdef CONFIG_MMU
+-EXPORT_SYMBOL(filemap_nopage);
+-#endif
+-EXPORT_SYMBOL(filemap_fdatawrite);
+-EXPORT_SYMBOL(filemap_fdatawait);
+ EXPORT_SYMBOL(lock_page);
+-EXPORT_SYMBOL(unlock_page);
+
+ /* device registration */
+ EXPORT_SYMBOL(register_blkdev);
+@@ -355,16 +205,7 @@ EXPORT_SYMBOL(tty_unregister_driver);
+ EXPORT_SYMBOL(tty_std_termios);
+
+ /* block device driver support */
+-EXPORT_SYMBOL(bmap);
+-EXPORT_SYMBOL(blkdev_open);
+-EXPORT_SYMBOL(blkdev_get);
+-EXPORT_SYMBOL(blkdev_put);
+-EXPORT_SYMBOL(ioctl_by_bdev);
+ EXPORT_SYMBOL(read_dev_sector);
+-EXPORT_SYMBOL(init_buffer);
+-EXPORT_SYMBOL_GPL(generic_file_direct_IO);
+-EXPORT_SYMBOL(generic_file_readv);
+-EXPORT_SYMBOL(generic_file_writev);
+ EXPORT_SYMBOL(iov_shorten);
+ EXPORT_SYMBOL_GPL(default_backing_dev_info);
+
+@@ -375,32 +216,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
+ /* filesystem registration */
+ EXPORT_SYMBOL(register_filesystem);
+ EXPORT_SYMBOL(unregister_filesystem);
+-EXPORT_SYMBOL(kern_mount);
+ EXPORT_SYMBOL(__mntput);
+ EXPORT_SYMBOL(may_umount);
+
+-/* executable format registration */
+-EXPORT_SYMBOL(register_binfmt);
+-EXPORT_SYMBOL(unregister_binfmt);
+-EXPORT_SYMBOL(search_binary_handler);
+-EXPORT_SYMBOL(prepare_binprm);
+-EXPORT_SYMBOL(compute_creds);
+-EXPORT_SYMBOL(remove_arg_zero);
+-EXPORT_SYMBOL(set_binfmt);
+-
+-/* sysctl table registration */
+-EXPORT_SYMBOL(register_sysctl_table);
+-EXPORT_SYMBOL(unregister_sysctl_table);
+-EXPORT_SYMBOL(sysctl_string);
+-EXPORT_SYMBOL(sysctl_intvec);
+-EXPORT_SYMBOL(sysctl_jiffies);
+-EXPORT_SYMBOL(proc_dostring);
+-EXPORT_SYMBOL(proc_dointvec);
+-EXPORT_SYMBOL(proc_dointvec_jiffies);
+-EXPORT_SYMBOL(proc_dointvec_minmax);
+-EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
+-EXPORT_SYMBOL(proc_doulongvec_minmax);
+-
+ /* interrupt handling */
+ EXPORT_SYMBOL(request_irq);
+ EXPORT_SYMBOL(free_irq);
+@@ -414,10 +232,6 @@ EXPORT_SYMBOL(prepare_to_wait_exclusive)
+ EXPORT_SYMBOL(finish_wait);
+ EXPORT_SYMBOL(autoremove_wake_function);
+
+-/* completion handling */
+-EXPORT_SYMBOL(wait_for_completion);
+-EXPORT_SYMBOL(complete);
+-
+ /* The notion of irq probe/assignment is foreign to S/390 */
+
+ #if !defined(CONFIG_ARCH_S390)
+@@ -449,30 +263,11 @@ EXPORT_SYMBOL(iomem_resource);
+
+ /* process management */
+ EXPORT_SYMBOL(complete_and_exit);
+-EXPORT_SYMBOL(default_wake_function);
+-EXPORT_SYMBOL(__wake_up);
+ #ifdef CONFIG_SMP
+ EXPORT_SYMBOL_GPL(__wake_up_sync); /* internal use only */
+ #endif
+-EXPORT_SYMBOL(wake_up_process);
+-EXPORT_SYMBOL(sleep_on);
+-EXPORT_SYMBOL(sleep_on_timeout);
+-EXPORT_SYMBOL(interruptible_sleep_on);
+-EXPORT_SYMBOL(interruptible_sleep_on_timeout);
+-EXPORT_SYMBOL(schedule);
+-#ifdef CONFIG_PREEMPT
+-EXPORT_SYMBOL(preempt_schedule);
+-#endif
+ EXPORT_SYMBOL(schedule_timeout);
+-EXPORT_SYMBOL(yield);
+-EXPORT_SYMBOL(io_schedule);
+-EXPORT_SYMBOL(__cond_resched);
+-EXPORT_SYMBOL(set_user_nice);
+-EXPORT_SYMBOL(task_nice);
+ EXPORT_SYMBOL_GPL(idle_cpu);
+-#ifdef CONFIG_SMP
+-EXPORT_SYMBOL_GPL(set_cpus_allowed);
+-#endif
+ #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ EXPORT_SYMBOL(kernel_flag);
+ #endif
+@@ -485,18 +280,10 @@ EXPORT_SYMBOL(do_settimeofday);
+ #if (BITS_PER_LONG < 64)
+ EXPORT_SYMBOL(get_jiffies_64);
+ #endif
+-#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+-EXPORT_SYMBOL(__might_sleep);
+-#endif
+-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+-EXPORT_SYMBOL(__preempt_spin_lock);
+-EXPORT_SYMBOL(__preempt_write_lock);
+-#endif
+ #if !defined(__ia64__)
+ EXPORT_SYMBOL(loops_per_jiffy);
+ #endif
+
+-
+ /* misc */
+ EXPORT_SYMBOL(panic);
+ EXPORT_SYMBOL(panic_notifier_list);
+@@ -524,45 +311,16 @@ EXPORT_SYMBOL(securebits);
+ EXPORT_SYMBOL(cap_bset);
+ EXPORT_SYMBOL(daemonize);
+ EXPORT_SYMBOL(csum_partial); /* for networking and md */
+-EXPORT_SYMBOL(seq_escape);
+-EXPORT_SYMBOL(seq_printf);
+-EXPORT_SYMBOL(seq_path);
+-EXPORT_SYMBOL(seq_open);
+-EXPORT_SYMBOL(seq_release);
+-EXPORT_SYMBOL(seq_read);
+-EXPORT_SYMBOL(seq_lseek);
+-EXPORT_SYMBOL(single_open);
+-EXPORT_SYMBOL(single_release);
+-EXPORT_SYMBOL(seq_release_private);
+-
+-/* Program loader interfaces */
+-#ifdef CONFIG_MMU
+-EXPORT_SYMBOL(setup_arg_pages);
+-#endif
+-EXPORT_SYMBOL(copy_strings_kernel);
+-EXPORT_SYMBOL(do_execve);
+-EXPORT_SYMBOL(flush_old_exec);
+-EXPORT_SYMBOL(kernel_read);
+-EXPORT_SYMBOL(open_exec);
+
+ /* Miscellaneous access points */
+ EXPORT_SYMBOL(si_meminfo);
+
+ /* Added to make file system as module */
+ EXPORT_SYMBOL(sys_tz);
+-EXPORT_SYMBOL(file_fsync);
+-EXPORT_SYMBOL(fsync_buffers_list);
+-EXPORT_SYMBOL(clear_inode);
+-EXPORT_SYMBOL(init_special_inode);
+-EXPORT_SYMBOL(new_inode);
+-EXPORT_SYMBOL(__insert_inode_hash);
+-EXPORT_SYMBOL(remove_inode_hash);
+-EXPORT_SYMBOL(buffer_insert_list);
+ EXPORT_SYMBOL(make_bad_inode);
+ EXPORT_SYMBOL(is_bad_inode);
+ EXPORT_SYMBOL(__inode_dir_notify);
+ EXPORT_SYMBOL(generic_osync_inode);
+-EXPORT_SYMBOL(remove_suid);
+
+ #ifdef CONFIG_UID16
+ EXPORT_SYMBOL(overflowuid);
+@@ -575,9 +333,6 @@ EXPORT_SYMBOL(fs_overflowgid);
+ EXPORT_SYMBOL(fasync_helper);
+ EXPORT_SYMBOL(kill_fasync);
+
+-/* binfmt_aout */
+-EXPORT_SYMBOL(get_write_access);
+-
+ /* library functions */
+ EXPORT_SYMBOL(strnicmp);
+ EXPORT_SYMBOL(strspn);
+@@ -607,6 +362,16 @@ EXPORT_SYMBOL(__per_cpu_offset);
+ EXPORT_SYMBOL(set_fs_pwd);
+ EXPORT_SYMBOL(set_fs_root);
+
++#if defined(CONFIG_LOCKMETER)
++EXPORT_SYMBOL(_metered_spin_lock);
++EXPORT_SYMBOL(_metered_spin_unlock);
++EXPORT_SYMBOL(_metered_spin_trylock);
++EXPORT_SYMBOL(_metered_read_lock);
++EXPORT_SYMBOL(_metered_read_unlock);
++EXPORT_SYMBOL(_metered_write_lock);
++EXPORT_SYMBOL(_metered_write_unlock);
++#endif
++
+ /* debug */
+ EXPORT_SYMBOL(dump_stack);
+ EXPORT_SYMBOL(ptrace_notify);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/kernel/lockmeter.c 2003-10-05 00:36:40.000000000 -0700
+@@ -0,0 +1,1169 @@
++/*
++ * Copyright (C) 1999,2000 Silicon Graphics, Inc.
++ *
++ * Written by John Hawkes (hawkes@sgi.com)
++ * Based on klstat.c by Jack Steiner (steiner@sgi.com)
++ *
++ * Modified by Ray Bryant (raybry@us.ibm.com)
++ * Changes Copyright (C) 2000 IBM, Inc.
++ * Added save of index in spinlock_t to improve efficiency
++ * of "hold" time reporting for spinlocks
++ * Added support for hold time statistics for read and write
++ * locks.
++ */
++
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/threads.h>
++#include <linux/version.h>
++#include <linux/vmalloc.h>
++#include <linux/spinlock.h>
++#include <linux/utsname.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++
++#include <linux/lockmeter.h>
++
++#define ASSERT(cond)
++#define bzero(loc,size) memset(loc,0,size)
++
++/*<---------------------------------------------------*/
++/* lockmeter.c */
++/*>---------------------------------------------------*/
++
++static lstat_control_t lstat_control __cacheline_aligned =
++ { LSTAT_OFF, SPIN_LOCK_UNLOCKED, SPIN_LOCK_UNLOCKED,
++ 19 * 0, NR_CPUS * 0, 0, NR_CPUS * 0 };
++
++static ushort lstat_make_dir_entry(void *, void *);
++
++/*
++ * lstat_lookup
++ *
++ * Given a RA, locate the directory entry for the lock.
++ */
++static ushort
++lstat_lookup(void *lock_ptr, void *caller_ra)
++{
++ ushort index;
++ lstat_directory_entry_t *dirp;
++
++ dirp = lstat_control.dir;
++
++ index = lstat_control.hashtab[DIRHASH(caller_ra)];
++ while (dirp[index].caller_ra != caller_ra) {
++ if (index == 0) {
++ return lstat_make_dir_entry(lock_ptr, caller_ra);
++ }
++ index = dirp[index].next_stat_index;
++ }
++
++ if (dirp[index].lock_ptr != NULL && dirp[index].lock_ptr != lock_ptr) {
++ dirp[index].lock_ptr = NULL;
++ }
++
++ return index;
++}
++
++/*
++ * lstat_make_dir_entry
++ * Called to add a new lock to the lock directory.
++ */
++static ushort
++lstat_make_dir_entry(void *lock_ptr, void *caller_ra)
++{
++ lstat_directory_entry_t *dirp;
++ ushort index, hindex;
++ unsigned long flags;
++
++ /* lock the table without recursively reentering this metering code */
++ local_irq_save(flags);
++ _raw_spin_lock(&lstat_control.directory_lock);
++
++ hindex = DIRHASH(caller_ra);
++ index = lstat_control.hashtab[hindex];
++ dirp = lstat_control.dir;
++ while (index && dirp[index].caller_ra != caller_ra)
++ index = dirp[index].next_stat_index;
++
++ if (index == 0) {
++ if (lstat_control.next_free_dir_index < LSTAT_MAX_STAT_INDEX) {
++ index = lstat_control.next_free_dir_index++;
++ lstat_control.dir[index].caller_ra = caller_ra;
++ lstat_control.dir[index].lock_ptr = lock_ptr;
++ lstat_control.dir[index].next_stat_index =
++ lstat_control.hashtab[hindex];
++ lstat_control.hashtab[hindex] = index;
++ } else {
++ lstat_control.dir_overflow++;
++ }
++ }
++ _raw_spin_unlock(&lstat_control.directory_lock);
++ local_irq_restore(flags);
++ return index;
++}
++
++int
++lstat_update(void *lock_ptr, void *caller_ra, int action)
++{
++ int index;
++ int cpu;
++
++ ASSERT(action < LSTAT_ACT_MAX_VALUES);
++
++ if (lstat_control.state == LSTAT_OFF)
++ return 0;
++
++ index = lstat_lookup(lock_ptr, caller_ra);
++ cpu = THIS_CPU_NUMBER;
++ (*lstat_control.counts[cpu])[index].count[action]++;
++ (*lstat_control.counts[cpu])[index].acquire_time = get_cycles();
++
++ return index;
++}
++
++int
++lstat_update_time(void *lock_ptr, void *caller_ra, int action, uint32_t ticks)
++{
++ ushort index;
++ int cpu;
++
++ ASSERT(action < LSTAT_ACT_MAX_VALUES);
++
++ if (lstat_control.state == LSTAT_OFF)
++ return 0;
++
++ index = lstat_lookup(lock_ptr, caller_ra);
++ cpu = THIS_CPU_NUMBER;
++ (*lstat_control.counts[cpu])[index].count[action]++;
++ (*lstat_control.counts[cpu])[index].cum_wait_ticks += (uint64_t) ticks;
++ if ((*lstat_control.counts[cpu])[index].max_wait_ticks < ticks)
++ (*lstat_control.counts[cpu])[index].max_wait_ticks = ticks;
++
++ (*lstat_control.counts[cpu])[index].acquire_time = get_cycles();
++
++ return index;
++}
++
++void
++_metered_spin_lock(spinlock_t * lock_ptr)
++{
++ if (lstat_control.state == LSTAT_OFF) {
++ _raw_spin_lock(lock_ptr); /* do the real lock */
++ PUT_INDEX(lock_ptr, 0); /* clean index in case lockmetering */
++ /* gets turned on before unlock */
++ } else {
++ void *this_pc = LSTAT_RA(LSTAT_RA_SPIN);
++ int index;
++
++ if (_raw_spin_trylock(lock_ptr)) {
++ index = lstat_update(lock_ptr, this_pc,
++ LSTAT_ACT_NO_WAIT);
++ } else {
++ uint32_t start_cycles = get_cycles();
++ _raw_spin_lock(lock_ptr); /* do the real lock */
++ index = lstat_update_time(lock_ptr, this_pc,
++ LSTAT_ACT_SPIN, get_cycles() - start_cycles);
++ }
++ /* save the index in the lock itself for use in spin unlock */
++ PUT_INDEX(lock_ptr, index);
++ }
++}
++
++int
++_metered_spin_trylock(spinlock_t * lock_ptr)
++{
++ if (lstat_control.state == LSTAT_OFF) {
++ return _raw_spin_trylock(lock_ptr);
++ } else {
++ int retval;
++ void *this_pc = LSTAT_RA(LSTAT_RA_SPIN);
++
++ if ((retval = _raw_spin_trylock(lock_ptr))) {
++ int index = lstat_update(lock_ptr, this_pc,
++ LSTAT_ACT_NO_WAIT);
++ /*
++ * save the index in the lock itself for use in spin
++ * unlock
++ */
++ PUT_INDEX(lock_ptr, index);
++ } else {
++ lstat_update(lock_ptr, this_pc, LSTAT_ACT_REJECT);
++ }
++
++ return retval;
++ }
++}
++
++void
++_metered_spin_unlock(spinlock_t * lock_ptr)
++{
++ int index = -1;
++
++ if (lstat_control.state != LSTAT_OFF) {
++ index = GET_INDEX(lock_ptr);
++ /*
++ * If statistics were turned off when we set the lock,
++ * then the index can be zero. If that is the case,
++ * then collect no stats on this call.
++ */
++ if (index > 0) {
++ uint32_t hold_time;
++ int cpu = THIS_CPU_NUMBER;
++ hold_time = get_cycles() -
++ (*lstat_control.counts[cpu])[index].acquire_time;
++ (*lstat_control.counts[cpu])[index].cum_hold_ticks +=
++ (uint64_t) hold_time;
++ if ((*lstat_control.counts[cpu])[index].max_hold_ticks <
++ hold_time)
++ (*lstat_control.counts[cpu])[index].
++ max_hold_ticks = hold_time;
++ }
++ }
++
++ /* make sure we don't have a stale index value saved */
++ PUT_INDEX(lock_ptr, 0);
++ _raw_spin_unlock(lock_ptr); /* do the real unlock */
++}
++
++/*
++ * allocate the next global read lock structure and store its index
++ * in the rwlock at "lock_ptr".
++ */
++uint32_t
++alloc_rwlock_struct(rwlock_t * rwlock_ptr)
++{
++ int index;
++ unsigned long flags;
++ int cpu = THIS_CPU_NUMBER;
++
++ /* If we've already overflowed, then do a quick exit */
++ if (lstat_control.next_free_read_lock_index >
++ LSTAT_MAX_READ_LOCK_INDEX) {
++ lstat_control.rwlock_overflow++;
++ return 0;
++ }
++
++ local_irq_save(flags);
++ _raw_spin_lock(&lstat_control.directory_lock);
++
++ /* It is possible this changed while we were waiting for the directory_lock */
++ if (lstat_control.state == LSTAT_OFF) {
++ index = 0;
++ goto unlock;
++ }
++
++ /* It is possible someone else got here first and set the index */
++ if ((index = GET_RWINDEX(rwlock_ptr)) == 0) {
++ /*
++ * we can't turn on read stats for this lock while there are
++ * readers (this would mess up the running hold time sum at
++ * unlock time)
++ */
++ if (RWLOCK_READERS(rwlock_ptr) != 0) {
++ index = 0;
++ goto unlock;
++ }
++
++ /*
++ * if stats are turned on after being off, we may need to
++ * return an old index from when the statistics were on last
++ * time.
++ */
++ for (index = 1; index < lstat_control.next_free_read_lock_index;
++ index++)
++ if ((*lstat_control.read_lock_counts[cpu])[index].
++ lock_ptr == rwlock_ptr)
++ goto put_index_and_unlock;
++
++ /* allocate the next global read lock structure */
++ if (lstat_control.next_free_read_lock_index >=
++ LSTAT_MAX_READ_LOCK_INDEX) {
++ lstat_control.rwlock_overflow++;
++ index = 0;
++ goto unlock;
++ }
++ index = lstat_control.next_free_read_lock_index++;
++
++ /*
++ * initialize the global read stats data structure for each
++ * cpu
++ */
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ (*lstat_control.read_lock_counts[cpu])[index].lock_ptr =
++ rwlock_ptr;
++ }
++put_index_and_unlock:
++ /* store the index for the read lock structure into the lock */
++ PUT_RWINDEX(rwlock_ptr, index);
++ }
++
++unlock:
++ _raw_spin_unlock(&lstat_control.directory_lock);
++ local_irq_restore(flags);
++ return index;
++}
++
++void
++_metered_read_lock(rwlock_t * rwlock_ptr)
++{
++ void *this_pc;
++ uint32_t start_cycles;
++ int index;
++ int cpu;
++ unsigned long flags;
++ int readers_before, readers_after;
++ uint64_t cycles64;
++
++ if (lstat_control.state == LSTAT_OFF) {
++ _raw_read_lock(rwlock_ptr);
++ /* clean index in case lockmetering turns on before an unlock */
++ PUT_RWINDEX(rwlock_ptr, 0);
++ return;
++ }
++
++ this_pc = LSTAT_RA(LSTAT_RA_READ);
++ cpu = THIS_CPU_NUMBER;
++ index = GET_RWINDEX(rwlock_ptr);
++
++ /* allocate the global stats entry for this lock, if needed */
++ if (index == 0)
++ index = alloc_rwlock_struct(rwlock_ptr);
++
++ readers_before = RWLOCK_READERS(rwlock_ptr);
++ if (_raw_read_trylock(rwlock_ptr)) {
++ /*
++ * We have decremented the lock to count a new reader,
++ * and have confirmed that no writer has it locked.
++ */
++ /* update statistics if enabled */
++ if (index > 0) {
++ local_irq_save(flags);
++ lstat_update((void *) rwlock_ptr, this_pc,
++ LSTAT_ACT_NO_WAIT);
++ /* preserve value of TSC so cum_hold_ticks and start_busy use same value */
++ cycles64 = get_cycles64();
++ (*lstat_control.read_lock_counts[cpu])[index].
++ cum_hold_ticks -= cycles64;
++
++ /* record time and cpu of start of busy period */
++ /* this is not perfect (some race conditions are possible) */
++ if (readers_before == 0) {
++ (*lstat_control.read_lock_counts[cpu])[index].
++ start_busy = cycles64;
++ PUT_RW_CPU(rwlock_ptr, cpu);
++ }
++ readers_after = RWLOCK_READERS(rwlock_ptr);
++ if (readers_after >
++ (*lstat_control.read_lock_counts[cpu])[index].
++ max_readers)
++ (*lstat_control.read_lock_counts[cpu])[index].
++ max_readers = readers_after;
++ local_irq_restore(flags);
++ }
++
++ return;
++ }
++ /* If we get here, then we could not quickly grab the read lock */
++
++ start_cycles = get_cycles(); /* start counting the wait time */
++
++ /* Now spin until read_lock is successful */
++ _raw_read_lock(rwlock_ptr);
++
++ lstat_update_time((void *) rwlock_ptr, this_pc, LSTAT_ACT_SPIN,
++ get_cycles() - start_cycles);
++
++ /* update statistics if they are enabled for this lock */
++ if (index > 0) {
++ local_irq_save(flags);
++ cycles64 = get_cycles64();
++ (*lstat_control.read_lock_counts[cpu])[index].cum_hold_ticks -=
++ cycles64;
++
++ /* this is not perfect (some race conditions are possible) */
++ if (readers_before == 0) {
++ (*lstat_control.read_lock_counts[cpu])[index].
++ start_busy = cycles64;
++ PUT_RW_CPU(rwlock_ptr, cpu);
++ }
++ readers_after = RWLOCK_READERS(rwlock_ptr);
++ if (readers_after >
++ (*lstat_control.read_lock_counts[cpu])[index].max_readers)
++ (*lstat_control.read_lock_counts[cpu])[index].
++ max_readers = readers_after;
++ local_irq_restore(flags);
++ }
++}
++
++void
++_metered_read_unlock(rwlock_t * rwlock_ptr)
++{
++ int index;
++ int cpu;
++ unsigned long flags;
++ uint64_t busy_length;
++ uint64_t cycles64;
++
++ if (lstat_control.state == LSTAT_OFF) {
++ _raw_read_unlock(rwlock_ptr);
++ return;
++ }
++
++ index = GET_RWINDEX(rwlock_ptr);
++ cpu = THIS_CPU_NUMBER;
++
++ if (index > 0) {
++ local_irq_save(flags);
++ /*
++ * preserve value of TSC so cum_hold_ticks and busy_ticks are
++ * consistent.
++ */
++ cycles64 = get_cycles64();
++ (*lstat_control.read_lock_counts[cpu])[index].cum_hold_ticks +=
++ cycles64;
++ (*lstat_control.read_lock_counts[cpu])[index].read_lock_count++;
++
++ /*
++ * once again, this is not perfect (some race conditions are
++ * possible)
++ */
++ if (RWLOCK_READERS(rwlock_ptr) == 1) {
++ int cpu1 = GET_RW_CPU(rwlock_ptr);
++ uint64_t last_start_busy =
++ (*lstat_control.read_lock_counts[cpu1])[index].
++ start_busy;
++ (*lstat_control.read_lock_counts[cpu])[index].
++ busy_periods++;
++ if (cycles64 > last_start_busy) {
++ busy_length = cycles64 - last_start_busy;
++ (*lstat_control.read_lock_counts[cpu])[index].
++ busy_ticks += busy_length;
++ if (busy_length >
++ (*lstat_control.
++ read_lock_counts[cpu])[index].
++ max_busy)
++ (*lstat_control.
++ read_lock_counts[cpu])[index].
++ max_busy = busy_length;
++ }
++ }
++ local_irq_restore(flags);
++ }
++ _raw_read_unlock(rwlock_ptr);
++}
++
++void
++_metered_write_lock(rwlock_t * rwlock_ptr)
++{
++ uint32_t start_cycles;
++ void *this_pc;
++ uint32_t spin_ticks = 0; /* in anticipation of a potential wait */
++ int index;
++ int write_index = 0;
++ int cpu;
++ enum {
++ writer_writer_conflict,
++ writer_reader_conflict
++ } why_wait = writer_writer_conflict;
++
++ if (lstat_control.state == LSTAT_OFF) {
++ _raw_write_lock(rwlock_ptr);
++ /* clean index in case lockmetering turns on before an unlock */
++ PUT_RWINDEX(rwlock_ptr, 0);
++ return;
++ }
++
++ this_pc = LSTAT_RA(LSTAT_RA_WRITE);
++ cpu = THIS_CPU_NUMBER;
++ index = GET_RWINDEX(rwlock_ptr);
++
++ /* allocate the global stats entry for this lock, if needed */
++ if (index == 0) {
++ index = alloc_rwlock_struct(rwlock_ptr);
++ }
++
++ if (_raw_write_trylock(rwlock_ptr)) {
++ /* We acquired the lock on the first try */
++ write_index = lstat_update((void *) rwlock_ptr, this_pc,
++ LSTAT_ACT_NO_WAIT);
++ /* save the write_index for use in unlock if stats enabled */
++ if (index > 0)
++ (*lstat_control.read_lock_counts[cpu])[index].
++ write_index = write_index;
++ return;
++ }
++
++ /* If we get here, then we could not quickly grab the write lock */
++ start_cycles = get_cycles(); /* start counting the wait time */
++
++ why_wait = RWLOCK_READERS(rwlock_ptr) ?
++ writer_reader_conflict : writer_writer_conflict;
++
++ /* Now set the lock and wait for conflicts to disappear */
++ _raw_write_lock(rwlock_ptr);
++
++ spin_ticks = get_cycles() - start_cycles;
++
++ /* update stats -- if enabled */
++ if (index > 0 && spin_ticks) {
++ if (why_wait == writer_reader_conflict) {
++ /* waited due to a reader holding the lock */
++ write_index = lstat_update_time((void *)rwlock_ptr,
++ this_pc, LSTAT_ACT_SPIN, spin_ticks);
++ } else {
++ /*
++ * waited due to another writer holding the lock
++ */
++ write_index = lstat_update_time((void *)rwlock_ptr,
++ this_pc, LSTAT_ACT_WW_SPIN, spin_ticks);
++ (*lstat_control.counts[cpu])[write_index].
++ cum_wait_ww_ticks += spin_ticks;
++ if (spin_ticks >
++ (*lstat_control.counts[cpu])[write_index].
++ max_wait_ww_ticks) {
++ (*lstat_control.counts[cpu])[write_index].
++ max_wait_ww_ticks = spin_ticks;
++ }
++ }
++
++ /* save the directory index for use on write_unlock */
++ (*lstat_control.read_lock_counts[cpu])[index].
++ write_index = write_index;
++ }
++}
++
++void
++_metered_write_unlock(rwlock_t * rwlock_ptr)
++{
++ int index;
++ int cpu;
++ int write_index;
++ uint32_t hold_time;
++
++ if (lstat_control.state == LSTAT_OFF) {
++ _raw_write_unlock(rwlock_ptr);
++ return;
++ }
++
++ cpu = THIS_CPU_NUMBER;
++ index = GET_RWINDEX(rwlock_ptr);
++
++ /* update statistics if stats enabled for this lock */
++ if (index > 0) {
++ write_index =
++ (*lstat_control.read_lock_counts[cpu])[index].write_index;
++
++ hold_time = get_cycles() -
++ (*lstat_control.counts[cpu])[write_index].acquire_time;
++ (*lstat_control.counts[cpu])[write_index].cum_hold_ticks +=
++ (uint64_t) hold_time;
++ if ((*lstat_control.counts[cpu])[write_index].max_hold_ticks <
++ hold_time)
++ (*lstat_control.counts[cpu])[write_index].
++ max_hold_ticks = hold_time;
++ }
++ _raw_write_unlock(rwlock_ptr);
++}
++
++int
++_metered_write_trylock(rwlock_t * rwlock_ptr)
++{
++ int retval;
++ void *this_pc = LSTAT_RA(LSTAT_RA_WRITE);
++
++ if ((retval = _raw_write_trylock(rwlock_ptr))) {
++ lstat_update(rwlock_ptr, this_pc, LSTAT_ACT_NO_WAIT);
++ } else {
++ lstat_update(rwlock_ptr, this_pc, LSTAT_ACT_REJECT);
++ }
++
++ return retval;
++}
++
++static void
++init_control_space(void)
++{
++ /* Set all control space pointers to null and indices to "empty" */
++ int cpu;
++
++ /*
++ * Access CPU_CYCLE_FREQUENCY at the outset, which in some
++ * architectures may trigger a runtime calculation that uses a
++ * spinlock. Let's do this before lockmetering is turned on.
++ */
++ if (CPU_CYCLE_FREQUENCY == 0)
++ BUG();
++
++ lstat_control.hashtab = NULL;
++ lstat_control.dir = NULL;
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ lstat_control.counts[cpu] = NULL;
++ lstat_control.read_lock_counts[cpu] = NULL;
++ }
++}
++
++static int
++reset_lstat_data(void)
++{
++ int cpu, flags;
++
++ flags = 0;
++ lstat_control.next_free_dir_index = 1; /* 0 is for overflows */
++ lstat_control.next_free_read_lock_index = 1;
++ lstat_control.dir_overflow = 0;
++ lstat_control.rwlock_overflow = 0;
++
++ lstat_control.started_cycles64 = 0;
++ lstat_control.ending_cycles64 = 0;
++ lstat_control.enabled_cycles64 = 0;
++ lstat_control.first_started_time = 0;
++ lstat_control.started_time = 0;
++ lstat_control.ending_time = 0;
++ lstat_control.intervals = 0;
++
++ /*
++ * paranoia -- in case someone does a "lockstat reset" before
++ * "lockstat on"
++ */
++ if (lstat_control.hashtab) {
++ bzero(lstat_control.hashtab,
++ LSTAT_HASH_TABLE_SIZE * sizeof (short));
++ bzero(lstat_control.dir, LSTAT_MAX_STAT_INDEX *
++ sizeof (lstat_directory_entry_t));
++
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ bzero(lstat_control.counts[cpu],
++ sizeof (lstat_cpu_counts_t));
++ bzero(lstat_control.read_lock_counts[cpu],
++ sizeof (lstat_read_lock_cpu_counts_t));
++ }
++ }
++#ifdef NOTDEF
++ _raw_spin_unlock(&lstat_control.directory_lock);
++ local_irq_restore(flags);
++#endif
++ return 1;
++}
++
++static void
++release_control_space(void)
++{
++ /*
++ * Called when either (1) allocation of kmem
++ * or (2) when user writes LSTAT_RELEASE to /pro/lockmeter.
++ * Assume that all pointers have been initialized to zero,
++ * i.e., nonzero pointers are valid addresses.
++ */
++ int cpu;
++
++ if (lstat_control.hashtab) {
++ kfree(lstat_control.hashtab);
++ lstat_control.hashtab = NULL;
++ }
++
++ if (lstat_control.dir) {
++ vfree(lstat_control.dir);
++ lstat_control.dir = NULL;
++ }
++
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ if (lstat_control.counts[cpu]) {
++ vfree(lstat_control.counts[cpu]);
++ lstat_control.counts[cpu] = NULL;
++ }
++ if (lstat_control.read_lock_counts[cpu]) {
++ kfree(lstat_control.read_lock_counts[cpu]);
++ lstat_control.read_lock_counts[cpu] = NULL;
++ }
++ }
++}
++
++int
++get_lockmeter_info_size(void)
++{
++ return sizeof (lstat_user_request_t)
++ + num_online_cpus() * sizeof (lstat_cpu_counts_t)
++ + num_online_cpus() * sizeof (lstat_read_lock_cpu_counts_t)
++ + (LSTAT_MAX_STAT_INDEX * sizeof (lstat_directory_entry_t));
++}
++
++ssize_t
++get_lockmeter_info(char *buffer, size_t max_len, loff_t * last_index)
++{
++ lstat_user_request_t req;
++ struct timeval tv;
++ ssize_t next_ret_bcount;
++ ssize_t actual_ret_bcount = 0;
++ int cpu;
++
++ *last_index = 0; /* a one-shot read */
++
++ req.lstat_version = LSTAT_VERSION;
++ req.state = lstat_control.state;
++ req.maxcpus = num_online_cpus();
++ req.cycleval = CPU_CYCLE_FREQUENCY;
++#ifdef notyet
++ req.kernel_magic_addr = (void *) &_etext;
++ req.kernel_end_addr = (void *) &_etext;
++#endif
++ req.uts = system_utsname;
++ req.intervals = lstat_control.intervals;
++
++ req.first_started_time = lstat_control.first_started_time;
++ req.started_time = lstat_control.started_time;
++ req.started_cycles64 = lstat_control.started_cycles64;
++
++ req.next_free_dir_index = lstat_control.next_free_dir_index;
++ req.next_free_read_lock_index = lstat_control.next_free_read_lock_index;
++ req.dir_overflow = lstat_control.dir_overflow;
++ req.rwlock_overflow = lstat_control.rwlock_overflow;
++
++ if (lstat_control.state == LSTAT_OFF) {
++ if (req.intervals == 0) {
++ /* mesasurement is off and no valid data present */
++ next_ret_bcount = sizeof (lstat_user_request_t);
++ req.enabled_cycles64 = 0;
++
++ if ((actual_ret_bcount + next_ret_bcount) > max_len)
++ return actual_ret_bcount;
++
++ copy_to_user(buffer, (void *) &req, next_ret_bcount);
++ actual_ret_bcount += next_ret_bcount;
++ return actual_ret_bcount;
++ } else {
++ /*
++ * measurement is off but valid data present
++ * fetch time info from lstat_control
++ */
++ req.ending_time = lstat_control.ending_time;
++ req.ending_cycles64 = lstat_control.ending_cycles64;
++ req.enabled_cycles64 = lstat_control.enabled_cycles64;
++ }
++ } else {
++ /*
++ * this must be a read while data active--use current time,
++ * etc
++ */
++ do_gettimeofday(&tv);
++ req.ending_time = tv.tv_sec;
++ req.ending_cycles64 = get_cycles64();
++ req.enabled_cycles64 = req.ending_cycles64 -
++ req.started_cycles64 + lstat_control.enabled_cycles64;
++ }
++
++ next_ret_bcount = sizeof (lstat_user_request_t);
++ if ((actual_ret_bcount + next_ret_bcount) > max_len)
++ return actual_ret_bcount;
++
++ copy_to_user(buffer, (void *) &req, next_ret_bcount);
++ actual_ret_bcount += next_ret_bcount;
++
++ if (!lstat_control.counts[0]) /* not initialized? */
++ return actual_ret_bcount;
++
++ next_ret_bcount = sizeof (lstat_cpu_counts_t);
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ if ((actual_ret_bcount + next_ret_bcount) > max_len)
++ return actual_ret_bcount; /* leave early */
++ copy_to_user(buffer + actual_ret_bcount,
++ lstat_control.counts[cpu], next_ret_bcount);
++ actual_ret_bcount += next_ret_bcount;
++ }
++
++ next_ret_bcount = LSTAT_MAX_STAT_INDEX *
++ sizeof (lstat_directory_entry_t);
++ if (((actual_ret_bcount + next_ret_bcount) > max_len)
++ || !lstat_control.dir)
++ return actual_ret_bcount; /* leave early */
++
++ copy_to_user(buffer + actual_ret_bcount, lstat_control.dir,
++ next_ret_bcount);
++ actual_ret_bcount += next_ret_bcount;
++
++ next_ret_bcount = sizeof (lstat_read_lock_cpu_counts_t);
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ if (actual_ret_bcount + next_ret_bcount > max_len)
++ return actual_ret_bcount;
++ copy_to_user(buffer + actual_ret_bcount,
++ lstat_control.read_lock_counts[cpu],
++ next_ret_bcount);
++ actual_ret_bcount += next_ret_bcount;
++ }
++
++ return actual_ret_bcount;
++}
++
++/*
++ * Writing to the /proc lockmeter node enables or disables metering.
++ * based upon the first byte of the "written" data.
++ * The following values are defined:
++ * LSTAT_ON: 1st call: allocates storage, intializes and turns on measurement
++ * subsequent calls just turn on measurement
++ * LSTAT_OFF: turns off measurement
++ * LSTAT_RESET: resets statistics
++ * LSTAT_RELEASE: releases statistics storage
++ *
++ * This allows one to accumulate statistics over several lockstat runs:
++ *
++ * lockstat on
++ * lockstat off
++ * ...repeat above as desired...
++ * lockstat get
++ * ...now start a new set of measurements...
++ * lockstat reset
++ * lockstat on
++ * ...
++ *
++ */
++ssize_t
++put_lockmeter_info(const char *buffer, size_t len)
++{
++ int error = 0;
++ int dirsize, countsize, read_lock_countsize, hashsize;
++ int cpu;
++ char put_char;
++ int i, read_lock_blocks;
++ unsigned long flags;
++ rwlock_t *lock_ptr;
++ struct timeval tv;
++
++ if (len <= 0)
++ return -EINVAL;
++
++ _raw_spin_lock(&lstat_control.control_lock);
++
++ get_user(put_char, buffer);
++ switch (put_char) {
++
++ case LSTAT_OFF:
++ if (lstat_control.state != LSTAT_OFF) {
++ /*
++ * To avoid seeing read lock hold times in an
++ * inconsisent state, we have to follow this protocol
++ * to turn off statistics
++ */
++ local_irq_save(flags);
++ /*
++ * getting this lock will stop any read lock block
++ * allocations
++ */
++ _raw_spin_lock(&lstat_control.directory_lock);
++ /*
++ * keep any more read lock blocks from being
++ * allocated
++ */
++ lstat_control.state = LSTAT_OFF;
++ /* record how may read lock blocks there are */
++ read_lock_blocks =
++ lstat_control.next_free_read_lock_index;
++ _raw_spin_unlock(&lstat_control.directory_lock);
++ /* now go through the list of read locks */
++ cpu = THIS_CPU_NUMBER;
++ for (i = 1; i < read_lock_blocks; i++) {
++ lock_ptr =
++ (*lstat_control.read_lock_counts[cpu])[i].
++ lock_ptr;
++ /* is this saved lock address still valid? */
++ if (GET_RWINDEX(lock_ptr) == i) {
++ /*
++ * lock address appears to still be
++ * valid because we only hold one lock
++ * at a time, this can't cause a
++ * deadlock unless this is a lock held
++ * as part of the current system call
++ * path. At the moment there
++ * are no READ mode locks held to get
++ * here from user space, so we solve
++ * this by skipping locks held in
++ * write mode.
++ */
++ if (RWLOCK_IS_WRITE_LOCKED(lock_ptr)) {
++ PUT_RWINDEX(lock_ptr, 0);
++ continue;
++ }
++ /*
++ * now we know there are no read
++ * holders of this lock! stop
++ * statistics collection for this
++ * lock
++ */
++ _raw_write_lock(lock_ptr);
++ PUT_RWINDEX(lock_ptr, 0);
++ _raw_write_unlock(lock_ptr);
++ }
++ /*
++ * it may still be possible for the hold time
++ * sum to be negative e.g. if a lock is
++ * reallocated while "busy" we will have to fix
++ * this up in the data reduction program.
++ */
++ }
++ local_irq_restore(flags);
++ lstat_control.intervals++;
++ lstat_control.ending_cycles64 = get_cycles64();
++ lstat_control.enabled_cycles64 +=
++ lstat_control.ending_cycles64 -
++ lstat_control.started_cycles64;
++ do_gettimeofday(&tv);
++ lstat_control.ending_time = tv.tv_sec;
++ /*
++ * don't deallocate the structures -- we may do a
++ * lockstat on to add to the data that is already
++ * there. Use LSTAT_RELEASE to release storage
++ */
++ } else {
++ error = -EBUSY; /* already OFF */
++ }
++ break;
++
++ case LSTAT_ON:
++ if (lstat_control.state == LSTAT_OFF) {
++#ifdef DEBUG_LOCKMETER
++ printk("put_lockmeter_info(cpu=%d): LSTAT_ON\n",
++ THIS_CPU_NUMBER);
++#endif
++ lstat_control.next_free_dir_index = 1; /* 0 is for overflows */
++
++ dirsize = LSTAT_MAX_STAT_INDEX *
++ sizeof (lstat_directory_entry_t);
++ hashsize =
++ (1 + LSTAT_HASH_TABLE_SIZE) * sizeof (ushort);
++ countsize = sizeof (lstat_cpu_counts_t);
++ read_lock_countsize =
++ sizeof (lstat_read_lock_cpu_counts_t);
++#ifdef DEBUG_LOCKMETER
++ printk(" dirsize:%d", dirsize);
++ printk(" hashsize:%d", hashsize);
++ printk(" countsize:%d", countsize);
++ printk(" read_lock_countsize:%d\n",
++ read_lock_countsize);
++#endif
++#ifdef DEBUG_LOCKMETER
++ {
++ int secs;
++ unsigned long cycles;
++ uint64_t cycles64;
++
++ do_gettimeofday(&tv);
++ secs = tv.tv_sec;
++ do {
++ do_gettimeofday(&tv);
++ } while (secs == tv.tv_sec);
++ cycles = get_cycles();
++ cycles64 = get_cycles64();
++ secs = tv.tv_sec;
++ do {
++ do_gettimeofday(&tv);
++ } while (secs == tv.tv_sec);
++ cycles = get_cycles() - cycles;
++ cycles64 = get_cycles64() - cycles;
++ printk("lockmeter: cycleFrequency:%d "
++ "cycles:%d cycles64:%d\n",
++ CPU_CYCLE_FREQUENCY, cycles, cycles64);
++ }
++#endif
++
++ /*
++ * if this is the first call, allocate storage and
++ * initialize
++ */
++ if (!lstat_control.hashtab) {
++
++ spin_lock_init(&lstat_control.directory_lock);
++
++ /* guarantee all pointers at zero */
++ init_control_space();
++
++ lstat_control.hashtab =
++ kmalloc(hashsize, GFP_KERNEL);
++ if (!lstat_control.hashtab) {
++ error = -ENOSPC;
++#ifdef DEBUG_LOCKMETER
++ printk("!!error kmalloc of hashtab\n");
++#endif
++ }
++ lstat_control.dir = vmalloc(dirsize);
++ if (!lstat_control.dir) {
++ error = -ENOSPC;
++#ifdef DEBUG_LOCKMETER
++ printk("!!error kmalloc of dir\n");
++#endif
++ }
++
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ lstat_control.counts[cpu] =
++ vmalloc(countsize);
++ if (!lstat_control.counts[cpu]) {
++ error = -ENOSPC;
++#ifdef DEBUG_LOCKMETER
++ printk("!!error vmalloc of "
++ "counts[%d]\n", cpu);
++#endif
++ }
++ lstat_control.read_lock_counts[cpu] =
++ (lstat_read_lock_cpu_counts_t *)
++ kmalloc(read_lock_countsize,
++ GFP_KERNEL);
++ if (!lstat_control.
++ read_lock_counts[cpu]) {
++ error = -ENOSPC;
++#ifdef DEBUG_LOCKMETER
++ printk("!!error kmalloc of "
++ "read_lock_counts[%d]\n",
++ cpu);
++#endif
++ }
++ }
++ }
++
++ if (error) {
++ /*
++ * One or more kmalloc failures -- free
++ * everything
++ */
++ release_control_space();
++ } else {
++
++ if (!reset_lstat_data()) {
++ error = -EINVAL;
++ break;
++ };
++
++ /*
++ * record starting and ending times and the
++ * like
++ */
++ if (lstat_control.intervals == 0) {
++ do_gettimeofday(&tv);
++ lstat_control.first_started_time =
++ tv.tv_sec;
++ }
++ lstat_control.started_cycles64 = get_cycles64();
++ do_gettimeofday(&tv);
++ lstat_control.started_time = tv.tv_sec;
++
++ lstat_control.state = LSTAT_ON;
++ }
++ } else {
++ error = -EBUSY; /* already ON */
++ }
++ break;
++
++ case LSTAT_RESET:
++ if (lstat_control.state == LSTAT_OFF) {
++ if (!reset_lstat_data())
++ error = -EINVAL;
++ } else {
++ error = -EBUSY; /* still on; can't reset */
++ }
++ break;
++
++ case LSTAT_RELEASE:
++ if (lstat_control.state == LSTAT_OFF) {
++ release_control_space();
++ lstat_control.intervals = 0;
++ lstat_control.enabled_cycles64 = 0;
++ } else {
++ error = -EBUSY;
++ }
++ break;
++
++ default:
++ error = -EINVAL;
++ } /* switch */
++
++ _raw_spin_unlock(&lstat_control.control_lock);
++ return error ? error : len;
++}
++
++#ifdef USER_MODE_TESTING
++/* following used for user mode testing */
++void
++lockmeter_init()
++{
++ int dirsize, hashsize, countsize, read_lock_countsize, cpu;
++
++ printf("lstat_control is at %x size=%d\n", &lstat_control,
++ sizeof (lstat_control));
++ printf("sizeof(spinlock_t)=%d\n", sizeof (spinlock_t));
++ lstat_control.state = LSTAT_ON;
++
++ lstat_control.directory_lock = SPIN_LOCK_UNLOCKED;
++ lstat_control.next_free_dir_index = 1; /* 0 is for overflows */
++ lstat_control.next_free_read_lock_index = 1;
++
++ dirsize = LSTAT_MAX_STAT_INDEX * sizeof (lstat_directory_entry_t);
++ hashsize = (1 + LSTAT_HASH_TABLE_SIZE) * sizeof (ushort);
++ countsize = sizeof (lstat_cpu_counts_t);
++ read_lock_countsize = sizeof (lstat_read_lock_cpu_counts_t);
++
++ lstat_control.hashtab = (ushort *) malloc(hashsize);
++
++ if (lstat_control.hashtab == 0) {
++ printf("malloc failure for at line %d in lockmeter.c\n",
++ __LINE__);
++ exit(0);
++ }
++
++ lstat_control.dir = (lstat_directory_entry_t *) malloc(dirsize);
++
++ if (lstat_control.dir == 0) {
++ printf("malloc failure for at line %d in lockmeter.c\n", cpu,
++ __LINE__);
++ exit(0);
++ }
++
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ int j, k;
++ j = (int) (lstat_control.counts[cpu] =
++ (lstat_cpu_counts_t *) malloc(countsize));
++ k = (int) (lstat_control.read_lock_counts[cpu] =
++ (lstat_read_lock_cpu_counts_t *)
++ malloc(read_lock_countsize));
++ if (j * k == 0) {
++ printf("malloc failure for cpu=%d at line %d in "
++ "lockmeter.c\n", cpu, __LINE__);
++ exit(0);
++ }
++ }
++
++ memset(lstat_control.hashtab, 0, hashsize);
++ memset(lstat_control.dir, 0, dirsize);
++
++ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
++ memset(lstat_control.counts[cpu], 0, countsize);
++ memset(lstat_control.read_lock_counts[cpu], 0,
++ read_lock_countsize);
++ }
++}
++
++asm(" \
++.align 4 \
++.globl __write_lock_failed \
++__write_lock_failed: \
++ " LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax) \
++1: cmpl $" RW_LOCK_BIAS_STR ",(%eax) \
++ jne 1b \
++\
++ " LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax) \
++ jnz __write_lock_failed \
++ ret \
++\
++\
++.align 4 \
++.globl __read_lock_failed \
++__read_lock_failed: \
++ lock ; incl (%eax) \
++1: cmpl $1,(%eax) \
++ js 1b \
++\
++ lock ; decl (%eax) \
++ js __read_lock_failed \
++ ret \
++");
++#endif
+--- linux-2.6.0-test6/kernel/Makefile 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/Makefile 2003-10-05 00:36:40.000000000 -0700
+@@ -11,6 +11,7 @@ obj-y = sched.o fork.o exec_domain.o
+ obj-$(CONFIG_FUTEX) += futex.o
+ obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
+ obj-$(CONFIG_SMP) += cpu.o
++obj-$(CONFIG_LOCKMETER) += lockmeter.o
+ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += ksyms.o module.o
+ obj-$(CONFIG_KALLSYMS) += kallsyms.o
+--- linux-2.6.0-test6/kernel/module.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/kernel/module.c 2003-10-05 00:33:25.000000000 -0700
+@@ -844,6 +844,7 @@ int set_obsolete(const char *val, struct
+ {
+ unsigned int min, max;
+ unsigned int size, maxsize;
++ int dummy;
+ char *endp;
+ const char *p;
+ struct obsolete_modparm *obsparm = kp->arg;
+@@ -866,19 +867,19 @@ int set_obsolete(const char *val, struct
+ switch (*endp) {
+ case 'b':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- 1, param_set_byte);
++ 1, param_set_byte, &dummy);
+ case 'h':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- sizeof(short), param_set_short);
++ sizeof(short), param_set_short, &dummy);
+ case 'i':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- sizeof(int), param_set_int);
++ sizeof(int), param_set_int, &dummy);
+ case 'l':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- sizeof(long), param_set_long);
++ sizeof(long), param_set_long, &dummy);
+ case 's':
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- sizeof(char *), param_set_charp);
++ sizeof(char *), param_set_charp, &dummy);
+
+ case 'c':
+ /* Undocumented: 1-5c50 means 1-5 strings of up to 49 chars,
+@@ -895,7 +896,7 @@ int set_obsolete(const char *val, struct
+ if (size >= maxsize)
+ goto oversize;
+ return param_array(kp->name, val, min, max, obsparm->addr,
+- maxsize, obsparm_copy_string);
++ maxsize, obsparm_copy_string, &dummy);
+ }
+ printk(KERN_ERR "Unknown obsolete parameter type %s\n", obsparm->type);
+ return -EINVAL;
+--- linux-2.6.0-test6/kernel/params.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/kernel/params.c 2003-10-05 00:33:25.000000000 -0700
+@@ -242,10 +242,10 @@ int param_array(const char *name,
+ const char *val,
+ unsigned int min, unsigned int max,
+ void *elem, int elemsize,
+- int (*set)(const char *, struct kernel_param *kp))
++ int (*set)(const char *, struct kernel_param *kp),
++ int *num)
+ {
+ int ret;
+- unsigned int count = 0;
+ struct kernel_param kp;
+ char save;
+
+@@ -259,11 +259,12 @@ int param_array(const char *name,
+ return -EINVAL;
+ }
+
++ *num = 0;
+ /* We expect a comma-separated list of values. */
+ do {
+ int len;
+
+- if (count > max) {
++ if (*num == max) {
+ printk(KERN_ERR "%s: can only take %i arguments\n",
+ name, max);
+ return -EINVAL;
+@@ -279,10 +280,10 @@ int param_array(const char *name,
+ return ret;
+ kp.arg += elemsize;
+ val += len+1;
+- count++;
++ (*num)++;
+ } while (save == ',');
+
+- if (count < min) {
++ if (*num < min) {
+ printk(KERN_ERR "%s: needs at least %i arguments\n",
+ name, min);
+ return -EINVAL;
+@@ -290,29 +291,32 @@ int param_array(const char *name,
+ return 0;
+ }
+
+-/* First two elements are the max and min array length (which don't change) */
+-int param_set_intarray(const char *val, struct kernel_param *kp)
++int param_array_set(const char *val, struct kernel_param *kp)
+ {
+- int *array;
++ struct kparam_array *arr = kp->arg;
+
+- /* Grab min and max as first two elements */
+- array = kp->arg;
+- return param_array(kp->name, val, array[0], array[1], &array[2],
+- sizeof(int), param_set_int);
++ return param_array(kp->name, val, 1, arr->max, arr->elem,
++ arr->elemsize, arr->set, arr->num);
+ }
+
+-int param_get_intarray(char *buffer, struct kernel_param *kp)
++int param_array_get(char *buffer, struct kernel_param *kp)
+ {
+- int max;
+- int *array;
+- unsigned int i;
+-
+- array = kp->arg;
+- max = array[1];
+-
+- for (i = 2; i < max + 2; i++)
+- sprintf(buffer, "%s%i", i > 2 ? "," : "", array[i]);
+- return strlen(buffer);
++ int i, off, ret;
++ struct kparam_array *arr = kp->arg;
++ struct kernel_param p;
++
++ p = *kp;
++ for (i = off = 0; i < *arr->num; i++) {
++ if (i)
++ buffer[off++] = ',';
++ p.arg = arr->elem + arr->elemsize * i;
++ ret = arr->get(buffer + off, &p);
++ if (ret < 0)
++ return ret;
++ off += ret;
++ }
++ buffer[off] = '\0';
++ return off;
+ }
+
+ int param_set_copystring(const char *val, struct kernel_param *kp)
+@@ -346,6 +350,6 @@ EXPORT_SYMBOL(param_set_bool);
+ EXPORT_SYMBOL(param_get_bool);
+ EXPORT_SYMBOL(param_set_invbool);
+ EXPORT_SYMBOL(param_get_invbool);
+-EXPORT_SYMBOL(param_set_intarray);
+-EXPORT_SYMBOL(param_get_intarray);
++EXPORT_SYMBOL(param_array_set);
++EXPORT_SYMBOL(param_array_get);
+ EXPORT_SYMBOL(param_set_copystring);
+--- linux-2.6.0-test6/kernel/pid.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/pid.c 2003-10-05 00:36:15.000000000 -0700
+@@ -250,14 +250,14 @@ void switch_exec_pids(task_t *leader, ta
+
+ attach_pid(thread, PIDTYPE_PID, thread->pid);
+ attach_pid(thread, PIDTYPE_TGID, thread->tgid);
+- attach_pid(thread, PIDTYPE_PGID, leader->__pgrp);
+- attach_pid(thread, PIDTYPE_SID, thread->session);
++ attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp);
++ attach_pid(thread, PIDTYPE_SID, thread->signal->session);
+ list_add_tail(&thread->tasks, &init_task.tasks);
+
+ attach_pid(leader, PIDTYPE_PID, leader->pid);
+ attach_pid(leader, PIDTYPE_TGID, leader->tgid);
+- attach_pid(leader, PIDTYPE_PGID, leader->__pgrp);
+- attach_pid(leader, PIDTYPE_SID, leader->session);
++ attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp);
++ attach_pid(leader, PIDTYPE_SID, leader->signal->session);
+ }
+
+ /*
+@@ -265,6 +265,9 @@ void switch_exec_pids(task_t *leader, ta
+ * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
+ * more.
+ */
++#ifdef CONFIG_KGDB
++int kgdb_pid_init_done; /* so we don't call prior to... */
++#endif
+ void __init pidhash_init(void)
+ {
+ int i, j, pidhash_size;
+@@ -286,6 +289,9 @@ void __init pidhash_init(void)
+ for (j = 0; j < pidhash_size; j++)
+ INIT_LIST_HEAD(&pid_hash[i][j]);
+ }
++#ifdef CONFIG_KGDB
++ kgdb_pid_init_done++;
++#endif
+ }
+
+ void __init pidmap_init(void)
+--- linux-2.6.0-test6/kernel/printk.c 2003-07-02 14:53:18.000000000 -0700
++++ 25/kernel/printk.c 2003-10-05 00:36:41.000000000 -0700
+@@ -29,11 +29,11 @@
+ #include <linux/delay.h>
+ #include <linux/smp.h>
+ #include <linux/security.h>
++#include <linux/bootmem.h>
+
+ #include <asm/uaccess.h>
+
+-#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
+-#define LOG_BUF_MASK (LOG_BUF_LEN-1)
++#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
+
+ /* printk's without a loglevel use this.. */
+ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
+@@ -68,17 +68,21 @@ struct console *console_drivers;
+ */
+ static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
+
+-static char log_buf[LOG_BUF_LEN];
++static char __log_buf[__LOG_BUF_LEN];
++static char *log_buf = __log_buf;
++static int log_buf_len = __LOG_BUF_LEN;
++
++#define LOG_BUF_MASK (log_buf_len-1)
+ #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
+
+ /*
+- * The indices into log_buf are not constrained to LOG_BUF_LEN - they
++ * The indices into log_buf are not constrained to log_buf_len - they
+ * must be masked before subscripting
+ */
+-static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
+-static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
+-static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
+-static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
++static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
++static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
++static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
++static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
+
+ struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
+ static int preferred_console = -1;
+@@ -141,6 +145,45 @@ static int __init console_setup(char *st
+
+ __setup("console=", console_setup);
+
++static int __init log_buf_len_setup(char *str)
++{
++ unsigned long size = memparse(str, &str);
++
++ if (size > log_buf_len) {
++ unsigned long start, dest_idx, offset;
++ char * new_log_buf;
++
++ new_log_buf = alloc_bootmem(size);
++ if (!new_log_buf) {
++ printk("log_buf_len: allocation failed\n");
++ goto out;
++ }
++
++ spin_lock_irq(&logbuf_lock);
++ log_buf_len = size;
++ log_buf = new_log_buf;
++
++ offset = start = min(con_start, log_start);
++ dest_idx = 0;
++ while (start != log_end) {
++ log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)];
++ start++;
++ dest_idx++;
++ }
++ log_start -= offset;
++ con_start -= offset;
++ log_end -= offset;
++ spin_unlock_irq(&logbuf_lock);
++
++ printk("log_buf_len: %d\n", log_buf_len);
++ }
++out:
++
++ return 1;
++}
++
++__setup("log_buf_len=", log_buf_len_setup);
++
+ /*
+ * Commands to do_syslog:
+ *
+@@ -213,8 +256,8 @@ int do_syslog(int type, char __user * bu
+ if (error)
+ goto out;
+ count = len;
+- if (count > LOG_BUF_LEN)
+- count = LOG_BUF_LEN;
++ if (count > log_buf_len)
++ count = log_buf_len;
+ spin_lock_irq(&logbuf_lock);
+ if (count > logged_chars)
+ count = logged_chars;
+@@ -229,7 +272,7 @@ int do_syslog(int type, char __user * bu
+ */
+ for(i = 0; i < count && !error; i++) {
+ j = limit-1-i;
+- if (j+LOG_BUF_LEN < log_end)
++ if (j + log_buf_len < log_end)
+ break;
+ c = LOG_BUF(j);
+ spin_unlock_irq(&logbuf_lock);
+@@ -302,12 +345,15 @@ static void __call_console_drivers(unsig
+ /*
+ * Write out chars from start to end - 1 inclusive
+ */
+-static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
++static void _call_console_drivers(unsigned long start,
++ unsigned long end, int msg_log_level)
+ {
+- if (msg_log_level < console_loglevel && console_drivers && start != end) {
++ if (msg_log_level < console_loglevel &&
++ console_drivers && start != end) {
+ if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
+ /* wrapped write */
+- __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
++ __call_console_drivers(start & LOG_BUF_MASK,
++ log_buf_len);
+ __call_console_drivers(0, end & LOG_BUF_MASK);
+ } else {
+ __call_console_drivers(start, end);
+@@ -370,11 +416,11 @@ static void emit_log_char(char c)
+ {
+ LOG_BUF(log_end) = c;
+ log_end++;
+- if (log_end - log_start > LOG_BUF_LEN)
+- log_start = log_end - LOG_BUF_LEN;
+- if (log_end - con_start > LOG_BUF_LEN)
+- con_start = log_end - LOG_BUF_LEN;
+- if (logged_chars < LOG_BUF_LEN)
++ if (log_end - log_start > log_buf_len)
++ log_start = log_end - log_buf_len;
++ if (log_end - con_start > log_buf_len)
++ con_start = log_end - log_buf_len;
++ if (logged_chars < log_buf_len)
+ logged_chars++;
+ }
+
+@@ -399,9 +445,13 @@ asmlinkage int printk(const char *fmt, .
+ char *p;
+ static char printk_buf[1024];
+ static int log_level_unknown = 1;
++ static int printk_cpu = -1;
+
+- if (oops_in_progress) {
+- /* If a crash is occurring, make sure we can't deadlock */
++ if (oops_in_progress && printk_cpu == smp_processor_id()) {
++ /*
++ * If a crash is occurring during printk() on this CPU, make
++ * sure we can't deadlock
++ */
+ spin_lock_init(&logbuf_lock);
+ /* And make sure that we print immediately */
+ init_MUTEX(&console_sem);
+@@ -409,6 +459,7 @@ asmlinkage int printk(const char *fmt, .
+
+ /* This stops the holder of console_sem just where we want him */
+ spin_lock_irqsave(&logbuf_lock, flags);
++ printk_cpu = smp_processor_id();
+
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+--- linux-2.6.0-test6/kernel/ptrace.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/kernel/ptrace.c 2003-10-05 00:33:25.000000000 -0700
+@@ -179,19 +179,14 @@ int access_process_vm(struct task_struct
+
+ flush_cache_page(vma, addr);
+
+- /*
+- * FIXME! We used to have flush_page_to_ram() in here, but
+- * that was wrong. davem says we need a new per-arch primitive
+- * to handle this correctly.
+- */
+-
+ maddr = kmap(page);
+ if (write) {
+- memcpy(maddr + offset, buf, bytes);
+- flush_icache_user_range(vma, page, addr, bytes);
++ copy_to_user_page(vma, page, addr,
++ maddr + offset, buf, bytes);
+ set_page_dirty_lock(page);
+ } else {
+- memcpy(buf, maddr + offset, bytes);
++ copy_from_user_page(vma, page, addr,
++ buf, maddr + offset, bytes);
+ }
+ kunmap(page);
+ page_cache_release(page);
+--- linux-2.6.0-test6/kernel/rcupdate.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/kernel/rcupdate.c 2003-10-05 00:33:25.000000000 -0700
+@@ -15,7 +15,7 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+- * Copyright (c) IBM Corporation, 2001
++ * Copyright (C) IBM Corporation, 2001
+ *
+ * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ *
+--- linux-2.6.0-test6/kernel/sched.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/sched.c 2003-10-05 00:36:39.000000000 -0700
+@@ -18,6 +18,7 @@
+ */
+
+ #include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/nmi.h>
+ #include <linux/init.h>
+ #include <asm/uaccess.h>
+@@ -642,6 +643,8 @@ int wake_up_process(task_t * p)
+ return try_to_wake_up(p, TASK_STOPPED | TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0, 0);
+ }
+
++EXPORT_SYMBOL(wake_up_process);
++
+ int wake_up_process_kick(task_t * p)
+ {
+ return try_to_wake_up(p, TASK_STOPPED | TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0, 1);
+@@ -1585,6 +1588,8 @@ switch_tasks:
+ goto need_resched;
+ }
+
++EXPORT_SYMBOL(schedule);
++
+ #ifdef CONFIG_PREEMPT
+ /*
+ * this is is the entry point to schedule() from in-kernel preemption
+@@ -1612,6 +1617,8 @@ need_resched:
+ if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
+ goto need_resched;
+ }
++
++EXPORT_SYMBOL(preempt_schedule);
+ #endif /* CONFIG_PREEMPT */
+
+ int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
+@@ -1620,6 +1627,8 @@ int default_wake_function(wait_queue_t *
+ return try_to_wake_up(p, mode, sync, 0);
+ }
+
++EXPORT_SYMBOL(default_wake_function);
++
+ /*
+ * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just
+ * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve
+@@ -1660,6 +1669,8 @@ void __wake_up(wait_queue_head_t *q, uns
+ spin_unlock_irqrestore(&q->lock, flags);
+ }
+
++EXPORT_SYMBOL(__wake_up);
++
+ /*
+ * Same as __wake_up but called with the spinlock in wait_queue_head_t held.
+ */
+@@ -1696,6 +1707,8 @@ void __wake_up_sync(wait_queue_head_t *q
+ spin_unlock_irqrestore(&q->lock, flags);
+ }
+
++EXPORT_SYMBOL(__wake_up_sync);
++
+ void complete(struct completion *x)
+ {
+ unsigned long flags;
+@@ -1706,6 +1719,8 @@ void complete(struct completion *x)
+ spin_unlock_irqrestore(&x->wait.lock, flags);
+ }
+
++EXPORT_SYMBOL(complete);
++
+ void complete_all(struct completion *x)
+ {
+ unsigned long flags;
+@@ -1737,6 +1752,8 @@ void wait_for_completion(struct completi
+ spin_unlock_irq(&x->wait.lock);
+ }
+
++EXPORT_SYMBOL(wait_for_completion);
++
+ #define SLEEP_ON_VAR \
+ unsigned long flags; \
+ wait_queue_t wait; \
+@@ -1763,6 +1780,8 @@ void interruptible_sleep_on(wait_queue_h
+ SLEEP_ON_TAIL
+ }
+
++EXPORT_SYMBOL(interruptible_sleep_on);
++
+ long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+ {
+ SLEEP_ON_VAR
+@@ -1776,6 +1795,8 @@ long interruptible_sleep_on_timeout(wait
+ return timeout;
+ }
+
++EXPORT_SYMBOL(interruptible_sleep_on_timeout);
++
+ void sleep_on(wait_queue_head_t *q)
+ {
+ SLEEP_ON_VAR
+@@ -1787,6 +1808,8 @@ void sleep_on(wait_queue_head_t *q)
+ SLEEP_ON_TAIL
+ }
+
++EXPORT_SYMBOL(sleep_on);
++
+ long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+ {
+ SLEEP_ON_VAR
+@@ -1800,6 +1823,8 @@ long sleep_on_timeout(wait_queue_head_t
+ return timeout;
+ }
+
++EXPORT_SYMBOL(sleep_on_timeout);
++
+ void scheduling_functions_end_here(void) { }
+
+ void set_user_nice(task_t *p, long nice)
+@@ -1849,6 +1874,15 @@ out_unlock:
+ task_rq_unlock(rq, &flags);
+ }
+
++EXPORT_SYMBOL(set_user_nice);
++
++#if defined( CONFIG_KGDB)
++struct task_struct * kgdb_get_idle(int this_cpu)
++{
++ return cpu_rq(this_cpu)->idle;
++}
++#endif
++
+ #ifndef __alpha__
+
+ /*
+@@ -1915,6 +1949,8 @@ int task_nice(task_t *p)
+ return TASK_NICE(p);
+ }
+
++EXPORT_SYMBOL(task_nice);
++
+ /**
+ * task_curr - is this task currently executing on a CPU?
+ * @p: the task in question.
+@@ -1933,6 +1969,8 @@ int idle_cpu(int cpu)
+ return cpu_curr(cpu) == cpu_rq(cpu)->idle;
+ }
+
++EXPORT_SYMBOL(idle_cpu);
++
+ /**
+ * find_process_by_pid - find a process with a matching PID value.
+ * @pid: the pid in question.
+@@ -2260,6 +2298,8 @@ void __cond_resched(void)
+ schedule();
+ }
+
++EXPORT_SYMBOL(__cond_resched);
++
+ /**
+ * yield - yield the current processor to other threads.
+ *
+@@ -2272,6 +2312,8 @@ void yield(void)
+ sys_sched_yield();
+ }
+
++EXPORT_SYMBOL(yield);
++
+ /*
+ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
+ * that process accounting knows that this is a task in IO wait state.
+@@ -2288,6 +2330,8 @@ void io_schedule(void)
+ atomic_dec(&rq->nr_iowait);
+ }
+
++EXPORT_SYMBOL(io_schedule);
++
+ long io_schedule_timeout(long timeout)
+ {
+ struct runqueue *rq = this_rq();
+@@ -2402,17 +2446,16 @@ static inline struct task_struct *younge
+
+ static void show_task(task_t * p)
+ {
+- unsigned long free = 0;
+ task_t *relative;
+- int state;
+- static const char * stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
++ unsigned state;
++ static const char *stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
+
+ printk("%-13.13s ", p->comm);
+ state = p->state ? __ffs(p->state) + 1 : 0;
+- if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *))
++ if (state < ARRAY_SIZE(stat_nam))
+ printk(stat_nam[state]);
+ else
+- printk(" ");
++ printk("?");
+ #if (BITS_PER_LONG == 32)
+ if (p == current)
+ printk(" current ");
+@@ -2424,13 +2467,7 @@ static void show_task(task_t * p)
+ else
+ printk(" %016lx ", thread_saved_pc(p));
+ #endif
+- {
+- unsigned long * n = (unsigned long *) (p->thread_info+1);
+- while (!*n)
+- n++;
+- free = (unsigned long) n - (unsigned long)(p+1);
+- }
+- printk("%5lu %5d %6d ", free, p->pid, p->parent->pid);
++ printk("%5d %6d ", p->pid, p->parent->pid);
+ if ((relative = eldest_child(p)))
+ printk("%5d ", relative->pid);
+ else
+@@ -2457,12 +2494,12 @@ void show_state(void)
+
+ #if (BITS_PER_LONG == 32)
+ printk("\n"
+- " free sibling\n");
+- printk(" task PC stack pid father child younger older\n");
++ " sibling\n");
++ printk(" task PC pid father child younger older\n");
+ #else
+ printk("\n"
+- " free sibling\n");
+- printk(" task PC stack pid father child younger older\n");
++ " sibling\n");
++ printk(" task PC pid father child younger older\n");
+ #endif
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+@@ -2574,6 +2611,8 @@ int set_cpus_allowed(task_t *p, cpumask_
+ return 0;
+ }
+
++EXPORT_SYMBOL_GPL(set_cpus_allowed);
++
+ /* Move (not current) task off this cpu, onto dest cpu. */
+ static void move_task_away(struct task_struct *p, int dest_cpu)
+ {
+@@ -2819,6 +2858,7 @@ void __might_sleep(char *file, int line)
+ }
+ #endif
+ }
++EXPORT_SYMBOL(__might_sleep);
+ #endif
+
+
+@@ -2847,6 +2887,8 @@ void __preempt_spin_lock(spinlock_t *loc
+ } while (!_raw_spin_trylock(lock));
+ }
+
++EXPORT_SYMBOL(__preempt_spin_lock);
++
+ void __preempt_write_lock(rwlock_t *lock)
+ {
+ if (preempt_count() > 1) {
+@@ -2861,4 +2903,6 @@ void __preempt_write_lock(rwlock_t *lock
+ preempt_disable();
+ } while (!_raw_write_trylock(lock));
+ }
+-#endif
++
++EXPORT_SYMBOL(__preempt_write_lock);
++#endif /* defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) */
+--- linux-2.6.0-test6/kernel/signal.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/signal.c 2003-10-05 00:36:15.000000000 -0700
+@@ -593,7 +593,8 @@ static int check_kill_permission(int sig
+ error = -EPERM;
+ if ((!info || ((unsigned long)info != 1 &&
+ (unsigned long)info != 2 && SI_FROMUSER(info)))
+- && ((sig != SIGCONT) || (current->session != t->session))
++ && ((sig != SIGCONT) ||
++ (process_session(current) != process_session(t)))
+ && (current->euid ^ t->suid) && (current->euid ^ t->uid)
+ && (current->uid ^ t->suid) && (current->uid ^ t->uid)
+ && !capable(CAP_KILL))
+@@ -1102,7 +1103,7 @@ kill_sl_info(int sig, struct siginfo *in
+ retval = -ESRCH;
+ read_lock(&tasklist_lock);
+ for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) {
+- if (!p->leader)
++ if (!process_session_leader(p))
+ continue;
+ err = group_send_sig_info(sig, info, p);
+ if (retval)
+--- linux-2.6.0-test6/kernel/sys.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/sys.c 2003-10-05 00:36:15.000000000 -0700
+@@ -951,7 +951,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
+
+ if (p->parent == current || p->real_parent == current) {
+ err = -EPERM;
+- if (p->session != current->session)
++ if (process_session(p) != process_session(current))
+ goto out;
+ err = -EACCES;
+ if (p->did_exec)
+@@ -963,7 +963,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
+ }
+
+ err = -EPERM;
+- if (p->leader)
++ if (process_session_leader(p))
+ goto out;
+
+ if (pgid != pid) {
+@@ -972,7 +972,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
+ struct list_head *l;
+
+ for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid)
+- if (p->session == current->session)
++ if (process_session(p) == process_session(current))
+ goto ok_pgid;
+ goto out;
+ }
+@@ -984,7 +984,7 @@ ok_pgid:
+
+ if (process_group(p) != pgid) {
+ detach_pid(p, PIDTYPE_PGID);
+- p->group_leader->__pgrp = pgid;
++ p->signal->pgrp = pgid;
+ attach_pid(p, PIDTYPE_PGID, pgid);
+ }
+
+@@ -1026,7 +1026,7 @@ asmlinkage long sys_getpgrp(void)
+ asmlinkage long sys_getsid(pid_t pid)
+ {
+ if (!pid) {
+- return current->session;
++ return process_session(current);
+ } else {
+ int retval;
+ struct task_struct *p;
+@@ -1038,7 +1038,7 @@ asmlinkage long sys_getsid(pid_t pid)
+ if(p) {
+ retval = security_task_getsid(p);
+ if (!retval)
+- retval = p->session;
++ retval = process_session(p);
+ }
+ read_unlock(&tasklist_lock);
+ return retval;
+@@ -1059,10 +1059,10 @@ asmlinkage long sys_setsid(void)
+ if (pid)
+ goto out;
+
+- current->leader = 1;
++ current->signal->leader = 1;
+ __set_special_pids(current->pid, current->pid);
+- current->tty = NULL;
+- current->tty_old_pgrp = 0;
++ current->signal->tty = NULL;
++ current->signal->tty_old_pgrp = 0;
+ err = process_group(current);
+ out:
+ write_unlock_irq(&tasklist_lock);
+--- linux-2.6.0-test6/kernel/sysctl.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/kernel/sysctl.c 2003-10-05 00:33:25.000000000 -0700
+@@ -19,6 +19,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/swap.h>
+ #include <linux/slab.h>
+@@ -136,17 +137,14 @@ extern ctl_table random_table[];
+
+ static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
+ static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
+-static int proc_sys_permission(struct inode *, int, struct nameidata *);
++static int proc_opensys(struct inode *, struct file *);
+
+ struct file_operations proc_sys_file_operations = {
++ .open = proc_opensys,
+ .read = proc_readsys,
+ .write = proc_writesys,
+ };
+
+-static struct inode_operations proc_sys_inode_operations = {
+- .permission = proc_sys_permission,
+-};
+-
+ extern struct proc_dir_entry *proc_sys_root;
+
+ static void register_proc_table(ctl_table *, struct proc_dir_entry *);
+@@ -1140,10 +1138,8 @@ static void register_proc_table(ctl_tabl
+ if (!de)
+ continue;
+ de->data = (void *) table;
+- if (table->proc_handler) {
++ if (table->proc_handler)
+ de->proc_fops = &proc_sys_file_operations;
+- de->proc_iops = &proc_sys_inode_operations;
+- }
+ }
+ table->de = de;
+ if (de->mode & S_IFDIR)
+@@ -1212,6 +1208,20 @@ static ssize_t do_rw_proc(int write, str
+ return res;
+ }
+
++static int proc_opensys(struct inode *inode, struct file *file)
++{
++ if (file->f_mode & FMODE_WRITE) {
++ /*
++ * sysctl entries that are not writable,
++ * are _NOT_ writable, capabilities or not.
++ */
++ if (!(inode->i_mode & S_IWUSR))
++ return -EPERM;
++ }
++
++ return 0;
++}
++
+ static ssize_t proc_readsys(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -1224,11 +1234,6 @@ static ssize_t proc_writesys(struct file
+ return do_rw_proc(1, file, (char __user *) buf, count, ppos);
+ }
+
+-static int proc_sys_permission(struct inode *inode, int op, struct nameidata *nd)
+-{
+- return test_perm(inode->i_mode, op);
+-}
+-
+ /**
+ * proc_dostring - read a string sysctl
+ * @table: the sysctl table
+@@ -1994,3 +1999,19 @@ void unregister_sysctl_table(struct ctl_
+ }
+
+ #endif /* CONFIG_SYSCTL */
++
++/*
++ * No sense putting this after each symbol definition, twice,
++ * exception granted :-)
++ */
++EXPORT_SYMBOL(proc_dointvec);
++EXPORT_SYMBOL(proc_dointvec_jiffies);
++EXPORT_SYMBOL(proc_dointvec_minmax);
++EXPORT_SYMBOL(proc_dostring);
++EXPORT_SYMBOL(proc_doulongvec_minmax);
++EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
++EXPORT_SYMBOL(register_sysctl_table);
++EXPORT_SYMBOL(sysctl_intvec);
++EXPORT_SYMBOL(sysctl_jiffies);
++EXPORT_SYMBOL(sysctl_string);
++EXPORT_SYMBOL(unregister_sysctl_table);
+--- linux-2.6.0-test6/lib/kobject.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/lib/kobject.c 2003-10-05 00:34:36.000000000 -0700
+@@ -236,8 +236,6 @@ static void unlink(struct kobject * kobj
+ list_del_init(&kobj->entry);
+ up_write(&kobj->kset->subsys->rwsem);
+ }
+- if (kobj->parent)
+- kobject_put(kobj->parent);
+ kobject_put(kobj);
+ }
+
+@@ -448,6 +446,8 @@ void kobject_cleanup(struct kobject * ko
+ if (kobj->k_name != kobj->name)
+ kfree(kobj->k_name);
+ kobj->k_name = NULL;
++ if (kobj->parent)
++ kobject_put(kobj->parent);
+ if (t && t->release)
+ t->release(kobj);
+ if (s)
+--- linux-2.6.0-test6/lib/Makefile 2003-09-27 18:57:47.000000000 -0700
++++ 25/lib/Makefile 2003-10-05 00:33:25.000000000 -0700
+@@ -5,7 +5,7 @@
+
+ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
+ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
+- kobject.o idr.o div64.o
++ kobject.o idr.o div64.o parser.o
+
+ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
+ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/lib/parser.c 2003-10-05 00:33:25.000000000 -0700
+@@ -0,0 +1,138 @@
++/*
++ * lib/parser.c - simple parser for mount, etc. options.
++ *
++ * This source code is licensed under the GNU General Public License,
++ * Version 2. See the file COPYING for more details.
++ */
++
++#include <linux/ctype.h>
++#include <linux/module.h>
++#include <linux/parser.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++
++static int match_one(char *s, char *p, substring_t args[])
++{
++ char *meta;
++ int argc = 0;
++
++ if (!p)
++ return 1;
++
++ while(1) {
++ int len = -1;
++ meta = strchr(p, '%');
++ if (!meta)
++ return strcmp(p, s) == 0;
++
++ if (strncmp(p, s, meta-p))
++ return 0;
++
++ s += meta - p;
++ p = meta + 1;
++
++ if (isdigit(*p))
++ len = simple_strtoul(p, &p, 10);
++ else if (*p == '%') {
++ if (*s++ != '%')
++ return 0;
++ continue;
++ }
++
++ if (argc >= MAX_OPT_ARGS)
++ return 0;
++
++ args[argc].from = s;
++ switch (*p++) {
++ case 's':
++ if (len == -1 || len > strlen(s))
++ len = strlen(s);
++ args[argc].to = s + len;
++ break;
++ case 'd':
++ simple_strtol(s, &args[argc].to, 0);
++ goto num;
++ case 'u':
++ simple_strtoul(s, &args[argc].to, 0);
++ goto num;
++ case 'o':
++ simple_strtoul(s, &args[argc].to, 8);
++ goto num;
++ case 'x':
++ simple_strtoul(s, &args[argc].to, 16);
++ num:
++ if (args[argc].to == args[argc].from)
++ return 0;
++ break;
++ default:
++ return 0;
++ }
++ s = args[argc].to;
++ argc++;
++ }
++}
++
++int match_token(char *s, match_table_t table, substring_t args[])
++{
++ struct match_token *p;
++
++ for (p = table; !match_one(s, p->pattern, args) ; p++)
++ ;
++
++ return p->token;
++}
++
++static int match_number(substring_t *s, int *result, int base)
++{
++ char *endp;
++ char *buf;
++ int ret;
++
++ buf = kmalloc(s->to - s->from + 1, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++ memcpy(buf, s->from, s->to - s->from);
++ buf[s->to - s->from] = '\0';
++ *result = simple_strtol(buf, &endp, base);
++ ret = 0;
++ if (endp == buf)
++ ret = -EINVAL;
++ kfree(buf);
++ return ret;
++}
++
++int match_int(substring_t *s, int *result)
++{
++ return match_number(s, result, 0);
++}
++
++int match_octal(substring_t *s, int *result)
++{
++ return match_number(s, result, 8);
++}
++
++int match_hex(substring_t *s, int *result)
++{
++ return match_number(s, result, 16);
++}
++
++void match_strcpy(char *to, substring_t *s)
++{
++ memcpy(to, s->from, s->to - s->from);
++ to[s->to - s->from] = '\0';
++}
++
++char *match_strdup(substring_t *s)
++{
++ char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL);
++ if (p)
++ match_strcpy(p, s);
++ return p;
++}
++
++EXPORT_SYMBOL(match_token);
++EXPORT_SYMBOL(match_int);
++EXPORT_SYMBOL(match_octal);
++EXPORT_SYMBOL(match_hex);
++EXPORT_SYMBOL(match_strcpy);
++EXPORT_SYMBOL(match_strdup);
+--- linux-2.6.0-test6/MAINTAINERS 2003-09-27 18:57:43.000000000 -0700
++++ 25/MAINTAINERS 2003-10-05 00:34:22.000000000 -0700
+@@ -114,8 +114,8 @@ W: http://sourceforge.net/projects/gkern
+ S: Maintained
+
+ 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+-P: Theodore Ts'o
+-M: tytso@mit.edu
++P: Russell King
++M: rmk+serial@arm.linux.org.uk
+ L: linux-serial@vger.kernel.org
+ W: http://serial.sourceforge.net
+ S: Maintained
+@@ -284,6 +284,16 @@ P: Jonathan Layes
+ L: linux-net@vger.kernel.org
+ S: Maintained
+
++ASUS ACPI EXTRAS DRIVER
++P: Karol Kozimor
++M: sziwan@users.sourceforge.net
++P: Julien Lerouge
++M: julien.lerouge@free.fr
++L: acpi4asus-user@lists.sourceforge.net
++W: http://sourceforge.net/projects/acpi4asus
++W: http://julien.lerouge.free.fr
++S: Maintained
++
+ ATM
+ P: Chas Williams
+ M: chas@cmf.nrl.navy.mil
+@@ -509,7 +519,7 @@ S: Maintained
+
+ CRYPTO API
+ P: James Morris
+-M: jmorris@intercode.com.au
++M: jmorris@redhat.com
+ P: David S. Miller
+ M: davem@redhat.com
+ W http://samba.org/~jamesm/crypto/
+@@ -624,7 +634,7 @@ DIGIBOARD PC/XE AND PC/XI DRIVER
+ P: Christoph Lameter
+ M: christoph@lameter.com
+ W: http://www.digi.com
+-L: digilnux@dgii.com
++L: digilnux@digi.com
+ S: Orphaned
+
+ DIRECTORY NOTIFICATION
+@@ -669,6 +679,12 @@ M: romieu@cogenit.fr
+ M: romieu@ensta.fr
+ S: Maintained
+
++DVB SUBSYSTEM AND DRIVERS
++P: LinuxTV.org Project
++L: linux-dvb@linuxtv.org
++W: http://linuxtv.org/developer/dvb.xml
++S: Supported
++
+ EATA-DMA SCSI DRIVER
+ P: Michael Neuffer
+ L: linux-eata@i-connect.net, linux-scsi@vger.kernel.org
+@@ -706,6 +722,11 @@ L: emu10k1-devel@lists.sourceforge.net
+ W: http://sourceforge.net/projects/emu10k1/
+ S: Maintained
+
++EPSON 1355 FRAMEBUFFER DRIVER
++P: Christopher Hoover
++M: ch@murgatroid.com, ch@hpl.hp.com
++S: Maintained
++
+ ETHEREXPRESS-16 NETWORK DRIVER
+ P: Philip Blundell
+ M: Philip.Blundell@pobox.com
+@@ -1139,6 +1160,12 @@ W: http://sf.net/projects/kernel-janitor
+ W: http://developer.osdl.org/rddunlap/kj-patches/
+ S: Maintained
+
++KGDB FOR I386 PLATFORM
++P: George Anzinger
++M: george@mvista.com
++L: linux-net@vger.kernel.org
++S: Supported
++
+ KERNEL NFSD
+ P: Neil Brown
+ M: neilb@cse.unsw.edu.au
+@@ -1386,7 +1413,7 @@ M: kuznet@ms2.inr.ac.ru
+ P: Pekka Savola (ipv6)
+ M: pekkas@netcore.fi
+ P: James Morris
+-M: jmorris@intercode.com.au
++M: jmorris@redhat.com
+ P: Hideaki YOSHIFUJI
+ M: yoshfuji@linux-ipv6.org
+ L: netdev@oss.sgi.com
+@@ -1658,6 +1685,12 @@ L: linux-390@vm.marist.edu
+ W: http://oss.software.ibm.com/developerworks/opensource/linux390
+ S: Supported
+
++SAA7146 VIDEO4LINUX-2 DRIVER
++P: Michael Hunold
++M: michael@mihu.de
++W: http://www.mihu.de/linux/saa7146
++S: Maintained
++
+ SA1100 SUPPORT
+ P: Nicolas Pitre
+ M: nico@cam.org
+--- linux-2.6.0-test6/Makefile 2003-09-27 18:57:43.000000000 -0700
++++ 25/Makefile 2003-10-05 00:37:37.000000000 -0700
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 0
+-EXTRAVERSION = -test6
++EXTRAVERSION = -test6-mm4
+
+ # *DOCUMENTATION*
+ # To see a list of typical targets execute "make help"
+@@ -37,7 +37,7 @@ ifdef V
+ endif
+ endif
+ ifndef KBUILD_VERBOSE
+- KBUILD_VERBOSE = 0
++ KBUILD_VERBOSE = 0
+ endif
+
+ # Call sparse as part of compilation of C files
+@@ -79,16 +79,24 @@ ifdef O
+ endif
+ endif
+
++# That's our default target when none is given on the command line
++.PHONY: all
++all:
++
+ ifneq ($(KBUILD_OUTPUT),)
+ # Invoke a second make in the output directory, passing relevant variables
+- KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT); /bin/pwd)
++# check that the output directory actually exists
++saved-output := $(KBUILD_OUTPUT)
++KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
++$(if $(wildcard $(KBUILD_OUTPUT)),, \
++ $(error output directory "$(saved-output)" does not exist))
+
+-.PHONY: $(MAKECMDGOALS) all
++.PHONY: $(MAKECMDGOALS)
+
+-$(MAKECMDGOALS) all:
++$(filter-out all,$(MAKECMDGOALS)) all:
+ $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
+ KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
+- KBUILD_CHECK=$(KBUILD_CHECK) -f $(CURDIR)/Makefile $(MAKECMDGOALS)
++ KBUILD_CHECK=$(KBUILD_CHECK) -f $(CURDIR)/Makefile $@
+
+ # Leave processing to above invocation of make
+ skip-makefile := 1
+@@ -156,13 +164,6 @@ HOSTCXX = g++
+ HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+ HOSTCXXFLAGS = -O2
+
+-
+-# That's our default target when none is given on the command line
+-# Note that 'modules' will be added as a prerequisite as well,
+-# in the CONFIG_MODULES part below
+-
+-all: vmlinux
+-
+ # Decide whether to build built-in, modular, or both.
+ # Normally, just do built-in.
+
+@@ -366,6 +367,12 @@ else
+ # Build targets only - this includes vmlinux, arch specific targets, clean
+ # targets and others. In general all targets except *config targets.
+
++# That's our default target when none is given on the command line
++# Note that 'modules' will be added as a prerequisite as well,
++# in the CONFIG_MODULES part below
++
++all: vmlinux
++
+ # Objects we will link into vmlinux / subdirs we need to visit
+ init-y := init/
+ drivers-y := drivers/ sound/
+@@ -753,7 +760,7 @@ MRPROPER_FILES += \
+ .menuconfig.log \
+ include/asm \
+ .hdepend include/linux/modversions.h \
+- tags TAGS cscope.out kernel.spec \
++ tags TAGS cscope* kernel.spec \
+ .tmp*
+
+ # Directories removed with 'make mrproper'
+@@ -877,7 +884,7 @@ help:
+ @echo ' mrproper - remove all generated files + config + various backup files'
+ @echo ''
+ @echo 'Configuration targets:'
+- @$(MAKE) -f scripts/kconfig/Makefile help
++ @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
+ @echo ''
+ @echo 'Other generic targets:'
+ @echo ' all - Build all targets marked with [*]'
+@@ -890,7 +897,7 @@ help:
+ @echo ' tags/TAGS - Generate tags file for editors'
+ @echo ''
+ @echo 'Documentation targets:'
+- @$(MAKE) -f Documentation/DocBook/Makefile dochelp
++ @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
+ @echo ''
+ @echo 'Architecture specific targets ($(ARCH)):'
+ @$(if $(archhelp),$(archhelp),\
+--- linux-2.6.0-test6/mm/bootmem.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/mm/bootmem.c 2003-10-05 00:33:25.000000000 -0700
+@@ -146,7 +146,7 @@ static void __init free_bootmem_core(boo
+ * We 'merge' subsequent allocations to save space. We might 'lose'
+ * some fraction of a page if allocations cannot be satisfied due to
+ * size constraints on boxes where there is physical RAM space
+- * fragmentation - in these cases * (mostly large memory boxes) this
++ * fragmentation - in these cases (mostly large memory boxes) this
+ * is not a problem.
+ *
+ * On low memory boxes we get it right in 100% of the cases.
+--- linux-2.6.0-test6/mm/fadvise.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/fadvise.c 2003-10-05 00:34:08.000000000 -0700
+@@ -23,7 +23,6 @@
+ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
+ {
+ struct file *file = fget(fd);
+- struct inode *inode;
+ struct address_space *mapping;
+ struct backing_dev_info *bdi;
+ pgoff_t start_index;
+@@ -33,8 +32,7 @@ asmlinkage long sys_fadvise64_64(int fd,
+ if (!file)
+ return -EBADF;
+
+- inode = file->f_dentry->d_inode;
+- mapping = inode->i_mapping;
++ mapping = file->f_mapping;
+ if (!mapping) {
+ ret = -EINVAL;
+ goto out;
+--- linux-2.6.0-test6/mm/filemap.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/filemap.c 2003-10-05 00:37:07.000000000 -0700
+@@ -61,6 +61,9 @@
+ * ->swap_device_lock (exclusive_swap_page, others)
+ * ->mapping->page_lock
+ *
++ * ->i_sem
++ * ->i_shared_sem (truncate->invalidate_mmap_range)
++ *
+ * ->mmap_sem
+ * ->i_shared_sem (various places)
+ *
+@@ -70,6 +73,9 @@
+ * ->mmap_sem
+ * ->i_sem (msync)
+ *
++ * ->i_sem
++ * ->i_alloc_sem (various)
++ *
+ * ->inode_lock
+ * ->sb_lock (fs/fs-writeback.c)
+ * ->mapping->page_lock (__sync_single_inode)
+@@ -151,6 +157,8 @@ int filemap_fdatawrite(struct address_sp
+ return __filemap_fdatawrite(mapping, WB_SYNC_ALL);
+ }
+
++EXPORT_SYMBOL(filemap_fdatawrite);
++
+ /*
+ * This is a mostly non-blocking flush. Not suitable for data-integrity
+ * purposes.
+@@ -216,6 +224,20 @@ restart:
+ return ret;
+ }
+
++EXPORT_SYMBOL(filemap_fdatawait);
++
++int filemap_write_and_wait(struct address_space *mapping)
++{
++ int retval = 0;
++
++ if (mapping->nrpages) {
++ retval = filemap_fdatawrite(mapping);
++ if (retval == 0)
++ retval = filemap_fdatawait(mapping);
++ }
++ return retval;
++}
++
+ /*
+ * This adds a page to the page cache, starting out as locked, unreferenced,
+ * not uptodate and with no errors.
+@@ -253,6 +275,7 @@ int add_to_page_cache(struct page *page,
+ }
+ return error;
+ }
++
+ EXPORT_SYMBOL(add_to_page_cache);
+
+ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
+@@ -281,21 +304,42 @@ static wait_queue_head_t *page_waitqueue
+ return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
+ }
+
+-void wait_on_page_bit(struct page *page, int bit_nr)
++/*
++ * wait for the specified page bit to be cleared
++ * this could be a synchronous wait or could just queue an async
++ * notification callback depending on the wait queue entry parameter
++ *
++ * A NULL wait queue parameter defaults to sync behaviour
++ */
++int wait_on_page_bit_wq(struct page *page, int bit_nr, wait_queue_t *wait)
+ {
+ wait_queue_head_t *waitqueue = page_waitqueue(page);
+- DEFINE_WAIT(wait);
++ DEFINE_WAIT(local_wait);
++
++ if (!wait)
++ wait = &local_wait; /* default to a sync wait entry */
+
+ do {
+- prepare_to_wait(waitqueue, &wait, TASK_UNINTERRUPTIBLE);
++ prepare_to_wait(waitqueue, wait, TASK_UNINTERRUPTIBLE);
+ if (test_bit(bit_nr, &page->flags)) {
+ sync_page(page);
++ if (!is_sync_wait(wait)) {
++ /*
++ * if we've queued an async wait queue
++ * callback do not block; just tell the
++ * caller to return and retry later when
++ * the callback is notified
++ */
++ return -EIOCBRETRY;
++ }
+ io_schedule();
+ }
+ } while (test_bit(bit_nr, &page->flags));
+- finish_wait(waitqueue, &wait);
++ finish_wait(waitqueue, wait);
++
++ return 0;
+ }
+-EXPORT_SYMBOL(wait_on_page_bit);
++EXPORT_SYMBOL(wait_on_page_bit_wq);
+
+ /**
+ * unlock_page() - unlock a locked page
+@@ -305,7 +349,9 @@ EXPORT_SYMBOL(wait_on_page_bit);
+ * Unlocks the page and wakes up sleepers in ___wait_on_page_locked().
+ * Also wakes sleepers in wait_on_page_writeback() because the wakeup
+ * mechananism between PageLocked pages and PageWriteback pages is shared.
+- * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep.
++ * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep,
++ * or in case the wakeup notifies async wait queue entries, as in the case
++ * of aio, retries would be triggered and may re-queue their callbacks.
+ *
+ * The first mb is necessary to safely close the critical section opened by the
+ * TestSetPageLocked(), the second mb is necessary to enforce ordering between
+@@ -323,6 +369,8 @@ void unlock_page(struct page *page)
+ wake_up_all(waitqueue);
+ }
+
++EXPORT_SYMBOL(unlock_page);
++
+ /*
+ * End writeback against a page.
+ */
+@@ -339,30 +387,57 @@ void end_page_writeback(struct page *pag
+ if (waitqueue_active(waitqueue))
+ wake_up_all(waitqueue);
+ }
++
+ EXPORT_SYMBOL(end_page_writeback);
+
+ /*
+- * Get a lock on the page, assuming we need to sleep to get it.
++ * Get a lock on the page, assuming we need to either sleep to get it
++ * or to queue an async notification callback to try again when its
++ * available.
++ *
++ * A NULL wait queue parameter defaults to sync behaviour. Otherwise
++ * it specifies the wait queue entry to be used for async notification
++ * or waiting.
+ *
+ * Ugly: running sync_page() in state TASK_UNINTERRUPTIBLE is scary. If some
+ * random driver's requestfn sets TASK_RUNNING, we could busywait. However
+ * chances are that on the second loop, the block layer's plug list is empty,
+ * so sync_page() will then return in state TASK_UNINTERRUPTIBLE.
+ */
+-void __lock_page(struct page *page)
++int __lock_page_wq(struct page *page, wait_queue_t *wait)
+ {
+ wait_queue_head_t *wqh = page_waitqueue(page);
+- DEFINE_WAIT(wait);
++ DEFINE_WAIT(local_wait);
++
++ if (!wait)
++ wait = &local_wait;
+
+ while (TestSetPageLocked(page)) {
+- prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
++ prepare_to_wait(wqh, wait, TASK_UNINTERRUPTIBLE);
+ if (PageLocked(page)) {
+ sync_page(page);
++ if (!is_sync_wait(wait)) {
++ /*
++ * if we've queued an async wait queue
++ * callback do not block; just tell the
++ * caller to return and retry later when
++ * the callback is notified
++ */
++ return -EIOCBRETRY;
++ }
+ io_schedule();
+ }
+ }
+- finish_wait(wqh, &wait);
++ finish_wait(wqh, wait);
++ return 0;
++}
++EXPORT_SYMBOL(__lock_page_wq);
++
++void __lock_page(struct page *page)
++{
++ __lock_page_wq(page, NULL);
+ }
++
+ EXPORT_SYMBOL(__lock_page);
+
+ /*
+@@ -385,6 +460,8 @@ struct page * find_get_page(struct addre
+ return page;
+ }
+
++EXPORT_SYMBOL(find_get_page);
++
+ /*
+ * Same as above, but trylock it instead of incrementing the count.
+ */
+@@ -400,6 +477,8 @@ struct page *find_trylock_page(struct ad
+ return page;
+ }
+
++EXPORT_SYMBOL(find_trylock_page);
++
+ /**
+ * find_lock_page - locate, pin and lock a pagecache page
+ *
+@@ -411,8 +490,8 @@ struct page *find_trylock_page(struct ad
+ *
+ * Returns zero if the page was not present. find_lock_page() may sleep.
+ */
+-struct page *find_lock_page(struct address_space *mapping,
+- unsigned long offset)
++struct page *find_lock_page_wq(struct address_space *mapping,
++ unsigned long offset, wait_queue_t *wait)
+ {
+ struct page *page;
+
+@@ -423,7 +502,10 @@ repeat:
+ page_cache_get(page);
+ if (TestSetPageLocked(page)) {
+ spin_unlock(&mapping->page_lock);
+- lock_page(page);
++ if (-EIOCBRETRY == lock_page_wq(page, wait)) {
++ page_cache_release(page);
++ return ERR_PTR(-EIOCBRETRY);
++ }
+ spin_lock(&mapping->page_lock);
+
+ /* Has the page been truncated while we slept? */
+@@ -438,6 +520,14 @@ repeat:
+ return page;
+ }
+
++EXPORT_SYMBOL(find_lock_page);
++
++struct page *find_lock_page(struct address_space *mapping,
++ unsigned long offset)
++{
++ return find_lock_page_wq(mapping, offset, NULL);
++}
++
+ /**
+ * find_or_create_page - locate or add a pagecache page
+ *
+@@ -482,6 +572,8 @@ repeat:
+ return page;
+ }
+
++EXPORT_SYMBOL(find_or_create_page);
++
+ /**
+ * find_get_pages - gang pagecache lookup
+ * @mapping: The address_space to search
+@@ -496,9 +588,12 @@ repeat:
+ * The search returns a group of mapping-contiguous pages with ascending
+ * indexes. There may be holes in the indices due to not-present pages.
+ *
+- * find_get_pages() returns the number of pages which were found.
++ * find_get_pages() returns the number of pages which were found
++ * and also atomically sets the next offset to continue looking up
++ * mapping contiguous pages from (useful when doing a range of
++ * pagevec lookups in chunks of PAGEVEC_SIZE).
+ */
+-unsigned int find_get_pages(struct address_space *mapping, pgoff_t start,
++unsigned int find_get_pages(struct address_space *mapping, pgoff_t *next,
+ unsigned int nr_pages, struct page **pages)
+ {
+ unsigned int i;
+@@ -506,9 +601,12 @@ unsigned int find_get_pages(struct addre
+
+ spin_lock(&mapping->page_lock);
+ ret = radix_tree_gang_lookup(&mapping->page_tree,
+- (void **)pages, start, nr_pages);
++ (void **)pages, *next, nr_pages);
+ for (i = 0; i < ret; i++)
+ page_cache_get(pages[i]);
++ if (ret)
++ *next = pages[ret - 1]->index + 1;
++
+ spin_unlock(&mapping->page_lock);
+ return ret;
+ }
+@@ -543,6 +641,8 @@ grab_cache_page_nowait(struct address_sp
+ return page;
+ }
+
++EXPORT_SYMBOL(grab_cache_page_nowait);
++
+ /*
+ * This is a generic file read routine, and uses the
+ * inode->i_op->readpage() function for the actual low-level
+@@ -560,21 +660,47 @@ void do_generic_mapping_read(struct addr
+ read_actor_t actor)
+ {
+ struct inode *inode = mapping->host;
+- unsigned long index, offset;
++ unsigned long index, offset, first, last, end_index;
+ struct page *cached_page;
++ loff_t isize = i_size_read(inode);
+ int error;
+
+ cached_page = NULL;
+- index = *ppos >> PAGE_CACHE_SHIFT;
++ first = *ppos >> PAGE_CACHE_SHIFT;
+ offset = *ppos & ~PAGE_CACHE_MASK;
+
++ last = (*ppos + desc->count) >> PAGE_CACHE_SHIFT;
++ end_index = isize >> PAGE_CACHE_SHIFT;
++ if (last > end_index)
++ last = end_index;
++
++ /* Don't repeat the readahead if we are executing aio retries */
++ if (in_aio()) {
++ if (is_retried_kiocb(io_wait_to_kiocb(current->io_wait)))
++ goto done_readahead;
++ }
++
++ /*
++ * Let the readahead logic know upfront about all
++ * the pages we'll need to satisfy this request
++ */
++ for (index = first ; index < last; index++)
++ page_cache_readahead(mapping, ra, filp, index);
++
++ if (ra->next_size == -1UL) {
++ /* the readahead window was maximally shrunk */
++ /* explicitly readahead at least what is needed now */
++ for (index = first; index < last; index++)
++ handle_ra_miss(mapping, ra, index);
++ do_page_cache_readahead(mapping, filp, first, last - first);
++ }
++
++done_readahead:
++ index = first;
+ for (;;) {
+ struct page *page;
+- unsigned long end_index, nr, ret;
+- loff_t isize = i_size_read(inode);
++ unsigned long nr, ret;
+
+- end_index = isize >> PAGE_CACHE_SHIFT;
+-
+ if (index > end_index)
+ break;
+ nr = PAGE_CACHE_SIZE;
+@@ -585,7 +711,6 @@ void do_generic_mapping_read(struct addr
+ }
+
+ cond_resched();
+- page_cache_readahead(mapping, ra, filp, index);
+
+ nr = nr - offset;
+ find_page:
+@@ -635,7 +760,12 @@ page_not_up_to_date:
+ goto page_ok;
+
+ /* Get exclusive access to the page ... */
+- lock_page(page);
++
++ if (lock_page_wq(page, current->io_wait)) {
++ pr_debug("queued lock page \n");
++ error = -EIOCBRETRY;
++ goto sync_error;
++ }
+
+ /* Did it get unhashed before we got the lock? */
+ if (!page->mapping) {
+@@ -657,13 +787,23 @@ readpage:
+ if (!error) {
+ if (PageUptodate(page))
+ goto page_ok;
+- wait_on_page_locked(page);
++ if (wait_on_page_locked_wq(page, current->io_wait)) {
++ pr_debug("queued wait_on_page \n");
++ error = -EIOCBRETRY;
++ goto sync_error;
++ }
++
+ if (PageUptodate(page))
+ goto page_ok;
+ error = -EIO;
+ }
+
+- /* UHHUH! A synchronous read error occurred. Report it */
++sync_error:
++ /* We don't have uptodate data in the page yet */
++ /* Could be due to an error or because we need to
++ * retry when we get an async i/o notification.
++ * Report the reason.
++ */
+ desc->error = error;
+ page_cache_release(page);
+ break;
+@@ -699,6 +839,8 @@ no_cached_page:
+ update_atime(inode);
+ }
+
++EXPORT_SYMBOL(do_generic_mapping_read);
++
+ int file_read_actor(read_descriptor_t *desc, struct page *page,
+ unsigned long offset, unsigned long size)
+ {
+@@ -775,7 +917,7 @@ __generic_file_aio_read(struct kiocb *io
+ struct address_space *mapping;
+ struct inode *inode;
+
+- mapping = filp->f_dentry->d_inode->i_mapping;
++ mapping = filp->f_mapping;
+ inode = mapping->host;
+ retval = 0;
+ if (!count)
+@@ -815,20 +957,19 @@ __generic_file_aio_read(struct kiocb *io
+ out:
+ return retval;
+ }
++EXPORT_SYMBOL(__generic_file_aio_read);
+
+-ssize_t
+-generic_file_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
++ssize_t generic_file_aio_read(struct kiocb *iocb, char __user *buf,
++ size_t count, loff_t pos)
+ {
+ struct iovec local_iov = { .iov_base = buf, .iov_len = count };
+
+- BUG_ON(iocb->ki_pos != pos);
+ return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
+ }
+ EXPORT_SYMBOL(generic_file_aio_read);
+-EXPORT_SYMBOL(__generic_file_aio_read);
+
+-ssize_t
+-generic_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
++ssize_t generic_file_read(struct file *filp, char __user *buf,
++ size_t count, loff_t *ppos)
+ {
+ struct iovec local_iov = { .iov_base = buf, .iov_len = count };
+ struct kiocb kiocb;
+@@ -840,8 +981,10 @@ generic_file_read(struct file *filp, cha
+ ret = wait_on_sync_kiocb(&kiocb);
+ return ret;
+ }
++EXPORT_SYMBOL(generic_file_read);
+
+-int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
++int file_send_actor(read_descriptor_t * desc, struct page *page,
++ unsigned long offset, unsigned long size)
+ {
+ ssize_t written;
+ unsigned long count = desc->count;
+@@ -880,6 +1023,8 @@ ssize_t generic_file_sendfile(struct fil
+ return desc.error;
+ }
+
++EXPORT_SYMBOL(generic_file_sendfile);
++
+ static ssize_t
+ do_readahead(struct address_space *mapping, struct file *filp,
+ unsigned long index, unsigned long nr)
+@@ -901,7 +1046,7 @@ asmlinkage ssize_t sys_readahead(int fd,
+ file = fget(fd);
+ if (file) {
+ if (file->f_mode & FMODE_READ) {
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ unsigned long start = offset >> PAGE_CACHE_SHIFT;
+ unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
+ unsigned long len = end - start + 1;
+@@ -920,7 +1065,7 @@ asmlinkage ssize_t sys_readahead(int fd,
+ static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
+ static int page_cache_read(struct file * file, unsigned long offset)
+ {
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct page *page;
+ int error;
+
+@@ -959,7 +1104,7 @@ struct page * filemap_nopage(struct vm_a
+ {
+ int error;
+ struct file *file = area->vm_file;
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct file_ra_state *ra = &file->f_ra;
+ struct inode *inode = mapping->host;
+ struct page *page;
+@@ -1126,10 +1271,12 @@ page_not_uptodate:
+ return NULL;
+ }
+
++EXPORT_SYMBOL(filemap_nopage);
++
+ static struct page * filemap_getpage(struct file *file, unsigned long pgoff,
+ int nonblock)
+ {
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct page *page;
+ int error;
+
+@@ -1241,7 +1388,7 @@ static int filemap_populate(struct vm_ar
+ int nonblock)
+ {
+ struct file *file = vma->vm_file;
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ unsigned long size;
+ struct mm_struct *mm = vma->vm_mm;
+@@ -1300,7 +1447,7 @@ static struct vm_operations_struct gener
+
+ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
+ {
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+
+ if (!mapping->a_ops->readpage)
+@@ -1330,6 +1477,9 @@ int generic_file_readonly_mmap(struct fi
+ }
+ #endif /* CONFIG_MMU */
+
++EXPORT_SYMBOL(generic_file_mmap);
++EXPORT_SYMBOL(generic_file_readonly_mmap);
++
+ static inline struct page *__read_cache_page(struct address_space *mapping,
+ unsigned long index,
+ int (*filler)(void *,struct page*),
+@@ -1406,6 +1556,8 @@ retry:
+ return page;
+ }
+
++EXPORT_SYMBOL(read_cache_page);
++
+ /*
+ * If the page was newly created, increment its refcount and add it to the
+ * caller's lru-buffering pagevec. This function is specifically for
+@@ -1418,7 +1570,9 @@ __grab_cache_page(struct address_space *
+ int err;
+ struct page *page;
+ repeat:
+- page = find_lock_page(mapping, index);
++ page = find_lock_page_wq(mapping, index, current->io_wait);
++ if (IS_ERR(page))
++ return page;
+ if (!page) {
+ if (!*cached_page) {
+ *cached_page = page_cache_alloc(mapping);
+@@ -1456,6 +1610,8 @@ void remove_suid(struct dentry *dentry)
+ }
+ }
+
++EXPORT_SYMBOL(remove_suid);
++
+ /*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were sucessfully copied. If a fault is encountered then clear the page
+@@ -1561,9 +1717,9 @@ filemap_set_next_iovec(const struct iove
+ * Returns appropriate error code that caller should return or
+ * zero in case that write should be allowed.
+ */
+-inline int generic_write_checks(struct inode *inode,
+- struct file *file, loff_t *pos, size_t *count, int isblk)
++inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk)
+ {
++ struct inode *inode = file->f_mapping->host;
+ unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+
+ if (unlikely(*pos < 0))
+@@ -1625,7 +1781,7 @@ inline int generic_write_checks(struct i
+ *count = inode->i_sb->s_maxbytes - *pos;
+ } else {
+ loff_t isize;
+- if (bdev_read_only(inode->i_bdev))
++ if (bdev_read_only(I_BDEV(inode)))
+ return -EPERM;
+ isize = i_size_read(inode);
+ if (*pos >= isize) {
+@@ -1638,10 +1794,12 @@ inline int generic_write_checks(struct i
+ }
+ return 0;
+ }
++
+ EXPORT_SYMBOL(generic_write_checks);
+
+ /*
+ * Write to a file through the page cache.
++ * Called under i_sem for S_ISREG files.
+ *
+ * We put everything into the page cache prior to writing it. This is not a
+ * problem when writing full pages. With partial pages, however, we first have
+@@ -1650,11 +1808,11 @@ EXPORT_SYMBOL(generic_write_checks);
+ * okir@monad.swb.de
+ */
+ ssize_t
+-generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
++__generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
+ {
+ struct file *file = iocb->ki_filp;
+- struct address_space * mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space * mapping = file->f_mapping;
+ struct address_space_operations *a_ops = mapping->a_ops;
+ size_t ocount; /* original count */
+ size_t count; /* after file limit checks */
+@@ -1701,11 +1859,10 @@ generic_file_aio_write_nolock(struct kio
+ current->backing_dev_info = mapping->backing_dev_info;
+ written = 0;
+
+- err = generic_write_checks(inode, file, &pos, &count, isblk);
++ err = generic_write_checks(file, &pos, &count, isblk);
+ if (err)
+ goto out;
+
+-
+ if (count == 0)
+ goto out;
+
+@@ -1730,12 +1887,19 @@ generic_file_aio_write_nolock(struct kio
+ /*
+ * Sync the fs metadata but not the minor inode changes and
+ * of course not the data as we did direct DMA for the IO.
++ * i_sem is held, which protects generic_osync_inode() from
++ * livelocking.
+ */
+ if (written >= 0 && file->f_flags & O_SYNC)
+- status = generic_osync_inode(inode, OSYNC_METADATA);
++ status = generic_osync_inode(inode, mapping, OSYNC_METADATA);
+ if (written >= 0 && !is_sync_kiocb(iocb))
+ written = -EIOCBQUEUED;
+- goto out_status;
++ if (written != -ENOTBLK)
++ goto out_status;
++ /*
++ * direct-io write to a hole: fall through to buffered I/O
++ */
++ written = 0;
+ }
+
+ buf = iov->iov_base;
+@@ -1759,6 +1923,10 @@ generic_file_aio_write_nolock(struct kio
+ fault_in_pages_readable(buf, bytes);
+
+ page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
++ if (IS_ERR(page)) {
++ status = PTR_ERR(page);
++ break;
++ }
+ if (!page) {
+ status = -ENOMEM;
+ break;
+@@ -1807,7 +1975,11 @@ generic_file_aio_write_nolock(struct kio
+ page_cache_release(page);
+ if (status < 0)
+ break;
+- balance_dirty_pages_ratelimited(mapping);
++ status = balance_dirty_pages_ratelimited(mapping);
++ if (status < 0) {
++ pr_debug("async balance_dirty_pages\n");
++ break;
++ }
+ cond_resched();
+ } while (count);
+ *ppos = pos;
+@@ -1818,12 +1990,22 @@ generic_file_aio_write_nolock(struct kio
+ /*
+ * For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
+ */
+- if (status >= 0) {
+- if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
+- status = generic_osync_inode(inode,
+- OSYNC_METADATA|OSYNC_DATA);
+- }
++ if (likely(status >= 0)) {
++ if (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ if (!a_ops->writepage)
++ status = generic_osync_inode(inode, mapping,
++ OSYNC_METADATA|OSYNC_DATA);
++ }
++ }
+
++ /*
++ * If we get here for O_DIRECT writes then we must have fallen through
++ * to buffered writes (block instantiation inside i_size). So we sync
++ * the file data here, to try to honour O_DIRECT expectations.
++ */
++ if (unlikely(file->f_flags & O_DIRECT) && written)
++ status = filemap_write_and_wait(mapping);
++
+ out_status:
+ err = written ? written : status;
+ out:
+@@ -1832,6 +2014,57 @@ out:
+ return err;
+ }
+
++EXPORT_SYMBOL(generic_file_aio_write_nolock);
++
++ssize_t
++generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
++ unsigned long nr_segs, loff_t *ppos)
++{
++ struct file *file = iocb->ki_filp;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ ssize_t ret;
++ loff_t pos = *ppos;
++
++ if (!iov->iov_base && !is_sync_kiocb(iocb)) {
++ /* nothing to transfer, may just need to sync data */
++ ret = iov->iov_len; /* vector AIO not supported yet */
++ goto osync;
++ }
++
++ ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs, ppos);
++
++ /*
++ * Avoid doing a sync in parts for aio - its more efficient to
++ * call in again after all the data has been copied
++ */
++ if (!is_sync_kiocb(iocb))
++ return ret;
++
++osync:
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ ret = sync_page_range_nolock(inode, mapping, pos, ret);
++ if (ret >= 0)
++ *ppos = pos + ret;
++ }
++ return ret;
++}
++
++
++ssize_t
++__generic_file_write_nolock(struct file *file, const struct iovec *iov,
++ unsigned long nr_segs, loff_t *ppos)
++{
++ struct kiocb kiocb;
++ ssize_t ret;
++
++ init_sync_kiocb(&kiocb, file);
++ ret = __generic_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
++ if (-EIOCBQUEUED == ret)
++ ret = wait_on_sync_kiocb(&kiocb);
++ return ret;
++}
++
+ ssize_t
+ generic_file_write_nolock(struct file *file, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
+@@ -1846,39 +2079,69 @@ generic_file_write_nolock(struct file *f
+ return ret;
+ }
+
++EXPORT_SYMBOL(generic_file_write_nolock);
++
+ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
+ size_t count, loff_t pos)
+ {
+ struct file *file = iocb->ki_filp;
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+- ssize_t err;
+- struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ ssize_t ret;
++ struct iovec local_iov = { .iov_base = (void __user *)buf,
++ .iov_len = count };
+
+- BUG_ON(iocb->ki_pos != pos);
++ if (!buf && !is_sync_kiocb(iocb)) {
++ /* nothing to transfer, may just need to sync data */
++ ret = count;
++ goto osync;
++ }
+
+ down(&inode->i_sem);
+- err = generic_file_aio_write_nolock(iocb, &local_iov, 1,
++ ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
+ &iocb->ki_pos);
+ up(&inode->i_sem);
+
+- return err;
++ /*
++ * Avoid doing a sync in parts for aio - its more efficient to
++ * call in again after all the data has been copied
++ */
++ if (!is_sync_kiocb(iocb))
++ return ret;
++
++osync:
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ ret = sync_page_range(inode, mapping, pos, ret);
++ if (ret >= 0)
++ iocb->ki_pos = pos + ret;
++ }
++ return ret;
+ }
+ EXPORT_SYMBOL(generic_file_aio_write);
+-EXPORT_SYMBOL(generic_file_aio_write_nolock);
+
+ ssize_t generic_file_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+- ssize_t err;
+- struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
++ ssize_t ret;
++ struct iovec local_iov = { .iov_base = (void __user *)buf,
++ .iov_len = count };
+
+ down(&inode->i_sem);
+- err = generic_file_write_nolock(file, &local_iov, 1, ppos);
++ ret = __generic_file_write_nolock(file, &local_iov, 1, ppos);
+ up(&inode->i_sem);
+
+- return err;
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ ssize_t err;
++
++ err = sync_page_range(inode, mapping, *ppos - ret, ret);
++ if (err < 0)
++ ret = err;
++ }
++ return ret;
+ }
++EXPORT_SYMBOL(generic_file_write);
+
+ ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
+@@ -1893,37 +2156,50 @@ ssize_t generic_file_readv(struct file *
+ return ret;
+ }
+
++EXPORT_SYMBOL(generic_file_readv);
++
+ ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
+- unsigned long nr_segs, loff_t * ppos)
++ unsigned long nr_segs, loff_t *ppos)
+ {
+- struct inode *inode = file->f_dentry->d_inode;
++ struct address_space *mapping = file->f_mapping;
++ struct inode *inode = mapping->host;
+ ssize_t ret;
+
+ down(&inode->i_sem);
+- ret = generic_file_write_nolock(file, iov, nr_segs, ppos);
++ ret = __generic_file_write_nolock(file, iov, nr_segs, ppos);
+ up(&inode->i_sem);
++
++ if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
++ ssize_t err;
++
++ err = sync_page_range(inode, mapping, *ppos - ret, ret);
++ if (err < 0)
++ ret = err;
++ }
+ return ret;
+ }
+
++EXPORT_SYMBOL(generic_file_writev);
++
++/*
++ * Called under i_sem for writes to S_ISREG files
++ */
+ ssize_t
+ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs)
+ {
+ struct file *file = iocb->ki_filp;
+- struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+ ssize_t retval;
+
+- if (mapping->nrpages) {
+- retval = filemap_fdatawrite(mapping);
+- if (retval == 0)
+- retval = filemap_fdatawait(mapping);
+- if (retval)
+- goto out;
++ retval = filemap_write_and_wait(mapping);
++ if (retval == 0) {
++ retval = mapping->a_ops->direct_IO(rw, iocb, iov,
++ offset, nr_segs);
++ if (rw == WRITE && mapping->nrpages)
++ invalidate_inode_pages2(mapping);
+ }
+-
+- retval = mapping->a_ops->direct_IO(rw, iocb, iov, offset, nr_segs);
+- if (rw == WRITE && mapping->nrpages)
+- invalidate_inode_pages2(mapping);
+-out:
+ return retval;
+ }
++
++EXPORT_SYMBOL_GPL(generic_file_direct_IO);
+--- linux-2.6.0-test6/mm/highmem.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/mm/highmem.c 2003-10-05 00:33:25.000000000 -0700
+@@ -24,6 +24,7 @@
+ #include <linux/blkdev.h>
+ #include <linux/init.h>
+ #include <linux/hash.h>
++#include <linux/highmem.h>
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+
+@@ -62,7 +63,7 @@ static void flush_all_zero_pkmaps(void)
+ {
+ int i;
+
+- flush_cache_all();
++ flush_cache_kmaps();
+
+ for (i = 0; i < LAST_PKMAP; i++) {
+ struct page *page;
+--- linux-2.6.0-test6/mm/madvise.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/mm/madvise.c 2003-10-05 00:34:07.000000000 -0700
+@@ -65,7 +65,7 @@ static long madvise_willneed(struct vm_a
+ end = vma->vm_end;
+ end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+
+- force_page_cache_readahead(file->f_dentry->d_inode->i_mapping,
++ force_page_cache_readahead(file->f_mapping,
+ file, start, max_sane_readahead(end - start));
+ return 0;
+ }
+--- linux-2.6.0-test6/mm/Makefile 2003-09-08 13:58:59.000000000 -0700
++++ 25/mm/Makefile 2003-10-05 00:36:48.000000000 -0700
+@@ -12,3 +12,6 @@ obj-y := bootmem.o filemap.o mempool.o
+ slab.o swap.o truncate.o vmscan.o $(mmu-y)
+
+ obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o
++
++obj-$(CONFIG_X86_4G) += usercopy.o
++
+--- linux-2.6.0-test6/mm/memory.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/memory.c 2003-10-05 00:36:48.000000000 -0700
+@@ -100,7 +100,8 @@ static inline void free_one_pmd(struct m
+ pte_free_tlb(tlb, page);
+ }
+
+-static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir)
++static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir,
++ int pgd_idx)
+ {
+ int j;
+ pmd_t * pmd;
+@@ -114,8 +115,11 @@ static inline void free_one_pgd(struct m
+ }
+ pmd = pmd_offset(dir, 0);
+ pgd_clear(dir);
+- for (j = 0; j < PTRS_PER_PMD ; j++)
++ for (j = 0; j < PTRS_PER_PMD ; j++) {
++ if (pgd_idx * PGDIR_SIZE + j * PMD_SIZE >= TASK_SIZE)
++ break;
+ free_one_pmd(tlb, pmd+j);
++ }
+ pmd_free_tlb(tlb, pmd);
+ }
+
+@@ -128,11 +132,13 @@ static inline void free_one_pgd(struct m
+ void clear_page_tables(struct mmu_gather *tlb, unsigned long first, int nr)
+ {
+ pgd_t * page_dir = tlb->mm->pgd;
++ int pgd_idx = first;
+
+ page_dir += first;
+ do {
+- free_one_pgd(tlb, page_dir);
++ free_one_pgd(tlb, page_dir, pgd_idx);
+ page_dir++;
++ pgd_idx++;
+ } while (--nr);
+ }
+
+@@ -430,7 +436,7 @@ zap_pmd_range(struct mmu_gather *tlb, pg
+ unsigned long address, unsigned long size)
+ {
+ pmd_t * pmd;
+- unsigned long end;
++ unsigned long end, pgd_boundary;
+
+ if (pgd_none(*dir))
+ return;
+@@ -441,8 +447,9 @@ zap_pmd_range(struct mmu_gather *tlb, pg
+ }
+ pmd = pmd_offset(dir, address);
+ end = address + size;
+- if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
+- end = ((address + PGDIR_SIZE) & PGDIR_MASK);
++ pgd_boundary = ((address + PGDIR_SIZE) & PGDIR_MASK);
++ if (pgd_boundary && (end > pgd_boundary))
++ end = pgd_boundary;
+ do {
+ zap_pte_range(tlb, pmd, address, end - address);
+ address = (address + PMD_SIZE) & PMD_MASK;
+@@ -518,7 +525,7 @@ int unmap_vmas(struct mmu_gather **tlbp,
+ unsigned long end_addr, unsigned long *nr_accounted)
+ {
+ unsigned long zap_bytes = ZAP_BLOCK_SIZE;
+- unsigned long tlb_start; /* For tlb_finish_mmu */
++ unsigned long tlb_start = 0; /* For tlb_finish_mmu */
+ int tlb_start_valid = 0;
+ int ret = 0;
+
+@@ -596,6 +603,11 @@ void zap_page_range(struct vm_area_struc
+ might_sleep();
+
+ if (is_vm_hugetlb_page(vma)) {
++ static int x;
++ if (x < 10) {
++ x++;
++ dump_stack();
++ }
+ zap_hugepage_range(vma, address, size);
+ return;
+ }
+@@ -678,6 +690,7 @@ int get_user_pages(struct task_struct *t
+ struct page **pages, struct vm_area_struct **vmas)
+ {
+ int i;
++ int vm_io;
+ unsigned int flags;
+
+ /*
+@@ -734,8 +747,10 @@ int get_user_pages(struct task_struct *t
+ }
+ #endif
+
+- if (!vma || (pages && (vma->vm_flags & VM_IO))
+- || !(flags & vma->vm_flags))
++ if (!vma)
++ return i ? : -EFAULT;
++ vm_io = vma->vm_flags & VM_IO;
++ if ((pages && vm_io) || !(flags & vma->vm_flags))
+ return i ? : -EFAULT;
+
+ if (is_vm_hugetlb_page(vma)) {
+@@ -743,9 +758,17 @@ int get_user_pages(struct task_struct *t
+ &start, &len, i);
+ continue;
+ }
++
+ spin_lock(&mm->page_table_lock);
+ do {
+- struct page *map;
++ struct page *map = NULL;
++
++ /*
++ * We don't follow pagetables for VM_IO regions - they
++ * may have no pageframes.
++ */
++ if (vm_io)
++ goto no_follow;
+ while (!(map = follow_page(mm, start, write))) {
+ spin_unlock(&mm->page_table_lock);
+ switch (handle_mm_fault(mm,vma,start,write)) {
+@@ -777,6 +800,7 @@ int get_user_pages(struct task_struct *t
+ if (!PageReserved(pages[i]))
+ page_cache_get(pages[i]);
+ }
++no_follow:
+ if (vmas)
+ vmas[i] = vma;
+ i++;
+@@ -1398,7 +1422,7 @@ do_no_page(struct mm_struct *mm, struct
+ spin_unlock(&mm->page_table_lock);
+
+ if (vma->vm_file) {
+- mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
++ mapping = vma->vm_file->f_mapping;
+ sequence = atomic_read(&mapping->truncate_count);
+ }
+ smp_rmb(); /* Prevent CPU from reordering lock-free ->nopage() */
+@@ -1441,6 +1465,7 @@ retry:
+ sequence = atomic_read(&mapping->truncate_count);
+ spin_unlock(&mm->page_table_lock);
+ page_cache_release(new_page);
++ pte_chain_free(pte_chain);
+ goto retry;
+ }
+ page_table = pte_offset_map(pmd, address);
+--- linux-2.6.0-test6/mm/mincore.c 2003-06-14 12:18:48.000000000 -0700
++++ 25/mm/mincore.c 2003-10-05 00:34:07.000000000 -0700
+@@ -26,7 +26,7 @@ static unsigned char mincore_page(struct
+ unsigned long pgoff)
+ {
+ unsigned char present = 0;
+- struct address_space * as = vma->vm_file->f_dentry->d_inode->i_mapping;
++ struct address_space * as = vma->vm_file->f_mapping;
+ struct page * page;
+
+ page = find_get_page(as, pgoff);
+--- linux-2.6.0-test6/mm/mmap.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/mmap.c 2003-10-05 00:36:32.000000000 -0700
+@@ -79,11 +79,10 @@ static void remove_shared_vm_struct(stru
+ struct file *file = vma->vm_file;
+
+ if (file) {
+- struct inode *inode = file->f_dentry->d_inode;
+-
+- down(&inode->i_mapping->i_shared_sem);
+- __remove_shared_vm_struct(vma, inode);
+- up(&inode->i_mapping->i_shared_sem);
++ struct address_space *mapping = file->f_mapping;
++ down(&mapping->i_shared_sem);
++ __remove_shared_vm_struct(vma, file->f_dentry->d_inode);
++ up(&mapping->i_shared_sem);
+ }
+ }
+
+@@ -234,11 +233,10 @@ static inline void __vma_link_file(struc
+
+ file = vma->vm_file;
+ if (file) {
+- struct inode * inode = file->f_dentry->d_inode;
+- struct address_space *mapping = inode->i_mapping;
++ struct address_space *mapping = file->f_mapping;
+
+ if (vma->vm_flags & VM_DENYWRITE)
+- atomic_dec(&inode->i_writecount);
++ atomic_dec(&file->f_dentry->d_inode->i_writecount);
+
+ if (vma->vm_flags & VM_SHARED)
+ list_add_tail(&vma->shared, &mapping->i_mmap_shared);
+@@ -264,7 +262,7 @@ static void vma_link(struct mm_struct *m
+ struct address_space *mapping = NULL;
+
+ if (vma->vm_file)
+- mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
++ mapping = vma->vm_file->f_mapping;
+
+ if (mapping)
+ down(&mapping->i_shared_sem);
+@@ -280,6 +278,26 @@ static void vma_link(struct mm_struct *m
+ }
+
+ /*
++ * Insert vm structure into process list sorted by address and into the inode's
++ * i_mmap ring. The caller should hold mm->page_table_lock and
++ * ->f_mappping->i_shared_sem if vm_file is non-NULL.
++ */
++static void
++__insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
++{
++ struct vm_area_struct * __vma, * prev;
++ struct rb_node ** rb_link, * rb_parent;
++
++ __vma = find_vma_prepare(mm, vma->vm_start,&prev, &rb_link, &rb_parent);
++ if (__vma && __vma->vm_start < vma->vm_end)
++ BUG();
++ __vma_link(mm, vma, prev, rb_link, rb_parent);
++ mark_mm_hugetlb(mm, vma);
++ mm->map_count++;
++ validate_mm(mm);
++}
++
++/*
+ * If the vma has a ->close operation then the driver probably needs to release
+ * per-vma resources, so we don't attempt to merge those.
+ */
+@@ -351,7 +369,8 @@ static int vma_merge(struct mm_struct *m
+ unsigned long end, unsigned long vm_flags,
+ struct file *file, unsigned long pgoff)
+ {
+- spinlock_t * lock = &mm->page_table_lock;
++ spinlock_t *lock = &mm->page_table_lock;
++ struct semaphore *i_shared_sem;
+
+ /*
+ * We later require that vma->vm_flags == vm_flags, so this tests
+@@ -360,6 +379,8 @@ static int vma_merge(struct mm_struct *m
+ if (vm_flags & VM_SPECIAL)
+ return 0;
+
++ i_shared_sem = file ? &file->f_mapping->i_shared_sem : NULL;
++
+ if (!prev) {
+ prev = rb_entry(rb_parent, struct vm_area_struct, vm_rb);
+ goto merge_next;
+@@ -377,7 +398,7 @@ static int vma_merge(struct mm_struct *m
+
+ if (unlikely(file && prev->vm_next &&
+ prev->vm_next->vm_file == file)) {
+- down(&inode->i_mapping->i_shared_sem);
++ down(i_shared_sem);
+ need_up = 1;
+ }
+ spin_lock(lock);
+@@ -395,7 +416,7 @@ static int vma_merge(struct mm_struct *m
+ __remove_shared_vm_struct(next, inode);
+ spin_unlock(lock);
+ if (need_up)
+- up(&inode->i_mapping->i_shared_sem);
++ up(i_shared_sem);
+ if (file)
+ fput(file);
+
+@@ -405,7 +426,7 @@ static int vma_merge(struct mm_struct *m
+ }
+ spin_unlock(lock);
+ if (need_up)
+- up(&inode->i_mapping->i_shared_sem);
++ up(i_shared_sem);
+ return 1;
+ }
+
+@@ -419,14 +440,17 @@ static int vma_merge(struct mm_struct *m
+ pgoff, (end - addr) >> PAGE_SHIFT))
+ return 0;
+ if (end == prev->vm_start) {
++ if (file)
++ down(i_shared_sem); /* invalidate_mmap_range */
+ spin_lock(lock);
+ prev->vm_start = addr;
+ prev->vm_pgoff -= (end - addr) >> PAGE_SHIFT;
+ spin_unlock(lock);
++ if (file)
++ up(i_shared_sem);
+ return 1;
+ }
+ }
+-
+ return 0;
+ }
+
+@@ -1136,6 +1160,7 @@ int split_vma(struct mm_struct * mm, str
+ unsigned long addr, int new_below)
+ {
+ struct vm_area_struct *new;
++ struct address_space *mapping = NULL;
+
+ if (mm->map_count >= MAX_MAP_COUNT)
+ return -ENOMEM;
+@@ -1149,12 +1174,9 @@ int split_vma(struct mm_struct * mm, str
+
+ INIT_LIST_HEAD(&new->shared);
+
+- if (new_below) {
++ if (new_below)
+ new->vm_end = addr;
+- vma->vm_start = addr;
+- vma->vm_pgoff += ((addr - new->vm_start) >> PAGE_SHIFT);
+- } else {
+- vma->vm_end = addr;
++ else {
+ new->vm_start = addr;
+ new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT);
+ }
+@@ -1165,7 +1187,25 @@ int split_vma(struct mm_struct * mm, str
+ if (new->vm_ops && new->vm_ops->open)
+ new->vm_ops->open(new);
+
+- insert_vm_struct(mm, new);
++ if (vma->vm_file)
++ mapping = vma->vm_file->f_mapping;
++
++ if (mapping)
++ down(&mapping->i_shared_sem);
++ spin_lock(&mm->page_table_lock);
++
++ if (new_below) {
++ vma->vm_start = addr;
++ vma->vm_pgoff += ((addr - new->vm_start) >> PAGE_SHIFT);
++ } else
++ vma->vm_end = addr;
++
++ __insert_vm_struct(mm, new);
++
++ spin_unlock(&mm->page_table_lock);
++ if (mapping)
++ up(&mapping->i_shared_sem);
++
+ return 0;
+ }
+
+--- linux-2.6.0-test6/mm/msync.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/mm/msync.c 2003-10-05 00:34:08.000000000 -0700
+@@ -146,20 +146,20 @@ static int msync_interval(struct vm_area
+ ret = filemap_sync(vma, start, end-start, flags);
+
+ if (!ret && (flags & MS_SYNC)) {
+- struct inode *inode = file->f_dentry->d_inode;
++ struct address_space *mapping = file->f_mapping;
+ int err;
+
+- down(&inode->i_sem);
+- ret = filemap_fdatawrite(inode->i_mapping);
++ down(&mapping->host->i_sem);
++ ret = filemap_fdatawrite(mapping);
+ if (file->f_op && file->f_op->fsync) {
+ err = file->f_op->fsync(file,file->f_dentry,1);
+ if (err && !ret)
+ ret = err;
+ }
+- err = filemap_fdatawait(inode->i_mapping);
++ err = filemap_fdatawait(mapping);
+ if (!ret)
+ ret = err;
+- up(&inode->i_sem);
++ up(&mapping->host->i_sem);
+ }
+ }
+ return ret;
+--- linux-2.6.0-test6/mm/page_alloc.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/page_alloc.c 2003-10-05 00:34:39.000000000 -0700
+@@ -50,7 +50,7 @@ EXPORT_SYMBOL(nr_swap_pages);
+ * Used by page_zone() to look up the address of the struct zone whose
+ * id is encoded in the upper bits of page->flags
+ */
+-struct zone *zone_table[MAX_NR_ZONES*MAX_NR_NODES];
++struct zone *zone_table[MAX_NR_ZONES*MAX_NUMNODES];
+ EXPORT_SYMBOL(zone_table);
+
+ static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
+--- linux-2.6.0-test6/mm/page-writeback.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/page-writeback.c 2003-10-05 00:37:06.000000000 -0700
+@@ -28,6 +28,7 @@
+ #include <linux/smp.h>
+ #include <linux/sysctl.h>
+ #include <linux/cpu.h>
++#include <linux/pagevec.h>
+
+ /*
+ * The maximum number of pages to writeout in a single bdflush/kupdate
+@@ -146,7 +147,7 @@ get_dirty_limits(struct page_state *ps,
+ * If we're over `background_thresh' then pdflush is woken to perform some
+ * writeout.
+ */
+-static void balance_dirty_pages(struct address_space *mapping)
++static int balance_dirty_pages(struct address_space *mapping)
+ {
+ struct page_state ps;
+ long nr_reclaimable;
+@@ -163,6 +164,7 @@ static void balance_dirty_pages(struct a
+ .sync_mode = WB_SYNC_NONE,
+ .older_than_this = NULL,
+ .nr_to_write = write_chunk,
++ .nonblocking = !is_sync_wait(current->io_wait)
+ };
+
+ get_dirty_limits(&ps, &background_thresh, &dirty_thresh);
+@@ -189,7 +191,11 @@ static void balance_dirty_pages(struct a
+ if (pages_written >= write_chunk)
+ break; /* We've done our duty */
+ }
+- blk_congestion_wait(WRITE, HZ/10);
++ if (-EIOCBRETRY == blk_congestion_wait_wq(WRITE, HZ/10,
++ current->io_wait)) {
++ pr_debug("async blk congestion wait\n");
++ return -EIOCBRETRY;
++ }
+ }
+
+ if (nr_reclaimable + ps.nr_writeback <= dirty_thresh)
+@@ -197,6 +203,8 @@ static void balance_dirty_pages(struct a
+
+ if (!writeback_in_progress(bdi) && nr_reclaimable > background_thresh)
+ pdflush_operation(background_writeout, 0);
++
++ return 0;
+ }
+
+ /**
+@@ -212,7 +220,7 @@ static void balance_dirty_pages(struct a
+ * decrease the ratelimiting by a lot, to prevent individual processes from
+ * overshooting the limit by (ratelimit_pages) each.
+ */
+-void balance_dirty_pages_ratelimited(struct address_space *mapping)
++int balance_dirty_pages_ratelimited(struct address_space *mapping)
+ {
+ static DEFINE_PER_CPU(int, ratelimits) = 0;
+ long ratelimit;
+@@ -228,10 +236,10 @@ void balance_dirty_pages_ratelimited(str
+ if (get_cpu_var(ratelimits)++ >= ratelimit) {
+ __get_cpu_var(ratelimits) = 0;
+ put_cpu_var(ratelimits);
+- balance_dirty_pages(mapping);
+- return;
++ return balance_dirty_pages(mapping);
+ }
+ put_cpu_var(ratelimits);
++ return 0;
+ }
+
+ /*
+@@ -566,3 +574,152 @@ int test_clear_page_dirty(struct page *p
+ return 0;
+ }
+ EXPORT_SYMBOL(test_clear_page_dirty);
++
++
++static ssize_t operate_on_page_range(struct address_space *mapping,
++ loff_t pos, size_t count, int (*operator)(struct page *))
++{
++ pgoff_t first = pos >> PAGE_CACHE_SHIFT;
++ pgoff_t last = (pos + count - 1) >> PAGE_CACHE_SHIFT; /* inclusive */
++ pgoff_t next = first, curr = first;
++ struct pagevec pvec;
++ ssize_t ret = 0, bytes = 0;
++ int i, nr;
++
++ if (count == 0)
++ return 0;
++
++ pagevec_init(&pvec, 0);
++ while ((nr = pagevec_lookup(&pvec, mapping, &next,
++ min((pgoff_t)PAGEVEC_SIZE, last - next + 1)))) {
++ for (i = 0; i < pagevec_count(&pvec); i++) {
++ struct page *page = pvec.pages[i];
++
++ curr = page->index;
++ if (page->mapping != mapping) /* truncated ?*/ {
++ curr = next;
++ break;
++ } else {
++ ret = (*operator)(page);
++ if (ret == -EIOCBRETRY)
++ break;
++ if (PageError(page)) {
++ if (!ret)
++ ret = -EIO;
++ } else
++ curr++;
++ }
++ }
++ pagevec_release(&pvec);
++ if ((ret == -EIOCBRETRY) || (next > last))
++ break;
++ }
++ if (!nr)
++ curr = last + 1;
++
++ bytes = (curr << PAGE_CACHE_SHIFT) - pos;
++ if (bytes > count)
++ bytes = count;
++ return (bytes && (!ret || (ret == -EIOCBRETRY))) ? bytes : ret;
++}
++
++static int page_waiter(struct page *page)
++{
++ return wait_on_page_writeback_wq(page, current->io_wait);
++}
++
++static size_t
++wait_on_page_range(struct address_space *mapping, loff_t pos, size_t count)
++{
++ return operate_on_page_range(mapping, pos, count, page_waiter);
++}
++
++static int page_writer(struct page *page)
++{
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = 1,
++ };
++
++ lock_page(page);
++ if (!page->mapping) { /* truncated */
++ unlock_page(page);
++ return 0;
++ }
++ if (!test_clear_page_dirty(page)) {
++ unlock_page(page);
++ return 0;
++ }
++ wait_on_page_writeback(page);
++ return page->mapping->a_ops->writepage(page, &wbc);
++}
++
++static ssize_t
++write_out_page_range(struct address_space *mapping, loff_t pos, size_t count)
++{
++ return operate_on_page_range(mapping, pos, count, page_writer);
++}
++
++/*
++ * Write and wait upon all the pages in the passed range. This is a "data
++ * integrity" operation. It waits upon in-flight writeout before starting and
++ * waiting upon new writeout. If there was an IO error, return it.
++ *
++ * We need to re-take i_sem during the generic_osync_inode list walk because
++ * it is otherwise livelockable.
++ */
++ssize_t sync_page_range(struct inode *inode, struct address_space *mapping,
++ loff_t pos, size_t count)
++{
++ int ret = 0;
++
++ if (in_aio()) {
++ /* Already issued writeouts for this iocb ? */
++ if (kiocbTrySync(io_wait_to_kiocb(current->io_wait)))
++ goto do_wait; /* just need to check if done */
++ }
++ if (!mapping->a_ops->writepage)
++ return 0;
++ if (mapping->backing_dev_info->memory_backed)
++ return 0;
++ ret = write_out_page_range(mapping, pos, count);
++ if (ret >= 0) {
++ down(&inode->i_sem);
++ ret = generic_osync_inode(inode, mapping, OSYNC_METADATA);
++ up(&inode->i_sem);
++ }
++do_wait:
++ if (ret >= 0)
++ ret = wait_on_page_range(mapping, pos, count);
++ return ret;
++}
++
++/*
++ * It is really better to use sync_page_range, rather than call
++ * sync_page_range_nolock while holding i_sem, if you don't
++ * want to block parallel O_SYNC writes until the pages in this
++ * range are written out.
++ */
++ssize_t sync_page_range_nolock(struct inode *inode, struct address_space
++ *mapping, loff_t pos, size_t count)
++{
++ ssize_t ret = 0;
++
++ if (in_aio()) {
++ /* Already issued writeouts for this iocb ? */
++ if (kiocbTrySync(io_wait_to_kiocb(current->io_wait)))
++ goto do_wait; /* just need to check if done */
++ }
++ if (!mapping->a_ops->writepage)
++ return 0;
++ if (mapping->backing_dev_info->memory_backed)
++ return 0;
++ ret = write_out_page_range(mapping, pos, count);
++ if (ret >= 0) {
++ ret = generic_osync_inode(inode, mapping, OSYNC_METADATA);
++ }
++do_wait:
++ if (ret >= 0)
++ ret = wait_on_page_range(mapping, pos, count);
++ return ret;
++}
+--- linux-2.6.0-test6/mm/pdflush.c 2003-06-14 12:18:52.000000000 -0700
++++ 25/mm/pdflush.c 2003-10-05 00:34:35.000000000 -0700
+@@ -84,6 +84,8 @@ struct pdflush_work {
+ unsigned long when_i_went_to_sleep;
+ };
+
++static int wakeup_count = 100;
++
+ static int __pdflush(struct pdflush_work *my_work)
+ {
+ daemonize("pdflush");
+@@ -112,7 +114,10 @@ static int __pdflush(struct pdflush_work
+
+ spin_lock_irq(&pdflush_lock);
+ if (!list_empty(&my_work->list)) {
+- printk("pdflush: bogus wakeup!\n");
++ if (wakeup_count > 0) {
++ wakeup_count--;
++ printk("pdflush: bogus wakeup!\n");
++ }
+ my_work->fn = NULL;
+ continue;
+ }
+@@ -182,6 +187,7 @@ int pdflush_operation(void (*fn)(unsigne
+ {
+ unsigned long flags;
+ int ret = 0;
++ static int poke_count = 0;
+
+ if (fn == NULL)
+ BUG(); /* Hard to diagnose if it's deferred */
+@@ -190,9 +196,19 @@ int pdflush_operation(void (*fn)(unsigne
+ if (list_empty(&pdflush_list)) {
+ spin_unlock_irqrestore(&pdflush_lock, flags);
+ ret = -1;
++ if (wakeup_count < 100 && poke_count < 10) {
++ printk("%s: no threads\n", __FUNCTION__);
++ dump_stack();
++ poke_count++;
++ }
+ } else {
+ struct pdflush_work *pdf;
+
++ if (wakeup_count < 100 && poke_count < 10) {
++ printk("%s: found a thread\n", __FUNCTION__);
++ dump_stack();
++ poke_count++;
++ }
+ pdf = list_entry(pdflush_list.next, struct pdflush_work, list);
+ list_del_init(&pdf->list);
+ if (list_empty(&pdflush_list))
+--- linux-2.6.0-test6/mm/shmem.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/shmem.c 2003-10-05 00:34:11.000000000 -0700
+@@ -1147,7 +1147,7 @@ shmem_file_write(struct file *file, cons
+ pos = *ppos;
+ written = 0;
+
+- err = generic_write_checks(inode, file, &pos, &count, 0);
++ err = generic_write_checks(file, &pos, &count, 0);
+ if (err || !count)
+ goto out;
+
+@@ -1933,6 +1933,7 @@ struct file *shmem_file_setup(char *name
+ inode->i_nlink = 0; /* It is unlinked */
+ file->f_vfsmnt = mntget(shm_mnt);
+ file->f_dentry = dentry;
++ file->f_mapping = inode->i_mapping;
+ file->f_op = &shmem_file_operations;
+ file->f_mode = FMODE_WRITE | FMODE_READ;
+ return(file);
+--- linux-2.6.0-test6/mm/slab.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/mm/slab.c 2003-10-05 00:36:48.000000000 -0700
+@@ -250,7 +250,7 @@ struct kmem_cache_s {
+ unsigned int limit;
+ /* 2) touched by every alloc & free from the backend */
+ struct kmem_list3 lists;
+- /* NUMA: kmem_3list_t *nodelists[NR_NODES] */
++ /* NUMA: kmem_3list_t *nodelists[MAX_NUMNODES] */
+ unsigned int objsize;
+ unsigned int flags; /* constant flags */
+ unsigned int num; /* # of objs per slab */
+@@ -1178,7 +1178,8 @@ next:
+ cachep = NULL;
+ goto opps;
+ }
+- slab_size = L1_CACHE_ALIGN(cachep->num*sizeof(kmem_bufctl_t)+sizeof(struct slab));
++ slab_size = L1_CACHE_ALIGN(cachep->num*sizeof(kmem_bufctl_t) +
++ sizeof(struct slab));
+
+ /*
+ * If the slab has been placed off-slab, and we have enough space then
+@@ -1222,10 +1223,13 @@ next:
+ * the cache that's used by kmalloc(24), otherwise
+ * the creation of further caches will BUG().
+ */
+- cachep->array[smp_processor_id()] = &initarray_generic.cache;
++ cachep->array[smp_processor_id()] =
++ &initarray_generic.cache;
+ g_cpucache_up = PARTIAL;
+ } else {
+- cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init),GFP_KERNEL);
++ cachep->array[smp_processor_id()] =
++ kmalloc(sizeof(struct arraycache_init),
++ GFP_KERNEL);
+ }
+ BUG_ON(!ac_data(cachep));
+ ac_data(cachep)->avail = 0;
+@@ -1239,7 +1243,7 @@ next:
+ }
+
+ cachep->lists.next_reap = jiffies + REAPTIMEOUT_LIST3 +
+- ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
++ ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+
+ /* Need the semaphore to access the chain. */
+ down(&cache_chain_sem);
+@@ -1252,16 +1256,24 @@ next:
+ list_for_each(p, &cache_chain) {
+ kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
+ char tmp;
+- /* This happens when the module gets unloaded and doesn't
+- destroy its slab cache and noone else reuses the vmalloc
+- area of the module. Print a warning. */
+- if (__get_user(tmp,pc->name)) {
+- printk("SLAB: cache with size %d has lost its name\n",
+- pc->objsize);
++
++ /*
++ * This happens when the module gets unloaded and
++ * doesn't destroy its slab cache and noone else reuses
++ * the vmalloc area of the module. Print a warning.
++ */
++#ifdef CONFIG_X86_UACCESS_INDIRECT
++ if (__direct_get_user(tmp,pc->name)) {
++#else
++ if (__get_user(tmp,pc->name)) {
++#endif
++ printk("SLAB: cache with size %d has lost its "
++ "name\n", pc->objsize);
+ continue;
+ }
+ if (!strcmp(pc->name,name)) {
+- printk("kmem_cache_create: duplicate cache %s\n",name);
++ printk("kmem_cache_create: duplicate "
++ "cache %s\n",name);
+ up(&cache_chain_sem);
+ BUG();
+ }
+@@ -2675,8 +2687,8 @@ struct seq_operations slabinfo_op = {
+ * slabinfo_write - Tuning for the slab allocator
+ * @file: unused
+ * @buffer: user buffer
+- * @count: data len
+- * @data: unused
++ * @count: data length
++ * @ppos: unused
+ */
+ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+--- linux-2.6.0-test6/mm/swap.c 2003-07-10 18:50:32.000000000 -0700
++++ 25/mm/swap.c 2003-10-05 00:37:03.000000000 -0700
+@@ -339,12 +339,15 @@ void pagevec_strip(struct pagevec *pvec)
+ * The search returns a group of mapping-contiguous pages with ascending
+ * indexes. There may be holes in the indices due to not-present pages.
+ *
+- * pagevec_lookup() returns the number of pages which were found.
++ * pagevec_lookup() returns the number of pages which were found
++ * and also atomically sets the next offset to continue looking up
++ * mapping contiguous pages from (useful when doing a range of
++ * pagevec lookups in chunks of PAGEVEC_SIZE).
+ */
+ unsigned int pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
+- pgoff_t start, unsigned int nr_pages)
++ pgoff_t *next, unsigned int nr_pages)
+ {
+- pvec->nr = find_get_pages(mapping, start, nr_pages, pvec->pages);
++ pvec->nr = find_get_pages(mapping, next, nr_pages, pvec->pages);
+ return pagevec_count(pvec);
+ }
+
+--- linux-2.6.0-test6/mm/swapfile.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/mm/swapfile.c 2003-10-05 00:34:11.000000000 -0700
+@@ -912,7 +912,7 @@ static int setup_swap_extents(struct swa
+ sector_t last_block;
+ int ret;
+
+- inode = sis->swap_file->f_dentry->d_inode;
++ inode = sis->swap_file->f_mapping->host;
+ if (S_ISBLK(inode->i_mode)) {
+ ret = add_swap_extent(sis, 0, sis->max, 0);
+ goto done;
+@@ -1031,13 +1031,13 @@ asmlinkage long sys_swapoff(const char _
+ if (IS_ERR(victim))
+ goto out;
+
+- mapping = victim->f_dentry->d_inode->i_mapping;
++ mapping = victim->f_mapping;
+ prev = -1;
+ swap_list_lock();
+ for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
+ p = swap_info + type;
+ if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) {
+- if (p->swap_file->f_dentry->d_inode->i_mapping==mapping)
++ if (p->swap_file->f_mapping == mapping)
+ break;
+ }
+ prev = type;
+@@ -1099,13 +1099,12 @@ asmlinkage long sys_swapoff(const char _
+ swap_device_unlock(p);
+ swap_list_unlock();
+ vfree(swap_map);
+- if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) {
+- struct block_device *bdev;
+- bdev = swap_file->f_dentry->d_inode->i_bdev;
++ if (S_ISBLK(mapping->host->i_mode)) {
++ struct block_device *bdev = I_BDEV(mapping->host);
+ set_blocksize(bdev, p->old_block_size);
+ bd_release(bdev);
+ } else {
+- up(&swap_file->f_dentry->d_inode->i_mapping->host->i_sem);
++ up(&mapping->host->i_sem);
+ }
+ filp_close(swap_file, NULL);
+ err = 0;
+@@ -1231,8 +1230,8 @@ asmlinkage long sys_swapon(const char __
+ int swapfilesize;
+ unsigned short *swap_map;
+ struct page *page = NULL;
+- struct inode *inode;
+- struct inode *downed_inode = NULL;
++ struct inode *inode = NULL;
++ int did_down = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+@@ -1279,8 +1278,8 @@ asmlinkage long sys_swapon(const char __
+ }
+
+ p->swap_file = swap_file;
+- inode = swap_file->f_dentry->d_inode;
+- mapping = swap_file->f_dentry->d_inode->i_mapping;
++ mapping = swap_file->f_mapping;
++ inode = mapping->host;
+
+ error = -EBUSY;
+ for (i = 0; i < nr_swapfiles; i++) {
+@@ -1288,32 +1287,32 @@ asmlinkage long sys_swapon(const char __
+
+ if (i == type || !q->swap_file)
+ continue;
+- if (mapping == q->swap_file->f_dentry->d_inode->i_mapping)
++ if (mapping == q->swap_file->f_mapping)
+ goto bad_swap;
+ }
+
+ error = -EINVAL;
+ if (S_ISBLK(inode->i_mode)) {
+- bdev = inode->i_bdev;
++ bdev = I_BDEV(inode);
+ error = bd_claim(bdev, sys_swapon);
+ if (error < 0) {
+ bdev = NULL;
+ goto bad_swap;
+ }
+ p->old_block_size = block_size(bdev);
+- error = set_blocksize(inode->i_bdev, PAGE_SIZE);
++ error = set_blocksize(bdev, PAGE_SIZE);
+ if (error < 0)
+ goto bad_swap;
+ p->bdev = bdev;
+ } else if (S_ISREG(inode->i_mode)) {
+ p->bdev = inode->i_sb->s_bdev;
+- downed_inode = mapping->host;
+- down(&downed_inode->i_sem);
++ down(&inode->i_sem);
++ did_down = 1;
+ } else {
+ goto bad_swap;
+ }
+
+- swapfilesize = i_size_read(mapping->host) >> PAGE_SHIFT;
++ swapfilesize = i_size_read(inode) >> PAGE_SHIFT;
+
+ /*
+ * Read the swap header.
+@@ -1461,8 +1460,8 @@ out:
+ }
+ if (name)
+ putname(name);
+- if (error && downed_inode)
+- up(&downed_inode->i_sem);
++ if (error && did_down)
++ up(&inode->i_sem);
+ return error;
+ }
+
+--- linux-2.6.0-test6/mm/truncate.c 2003-06-14 12:18:34.000000000 -0700
++++ 25/mm/truncate.c 2003-10-05 00:37:03.000000000 -0700
+@@ -121,14 +121,10 @@ void truncate_inode_pages(struct address
+
+ pagevec_init(&pvec, 0);
+ next = start;
+- while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
++ while (pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ struct page *page = pvec.pages[i];
+- pgoff_t page_index = page->index;
+
+- if (page_index > next)
+- next = page_index;
+- next++;
+ if (TestSetPageLocked(page))
+ continue;
+ if (PageWriteback(page)) {
+@@ -154,7 +150,7 @@ void truncate_inode_pages(struct address
+
+ next = start;
+ for ( ; ; ) {
+- if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
++ if (!pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
+ if (next == start)
+ break;
+ next = start;
+@@ -165,9 +161,6 @@ void truncate_inode_pages(struct address
+
+ lock_page(page);
+ wait_on_page_writeback(page);
+- if (page->index > next)
+- next = page->index;
+- next++;
+ truncate_complete_page(mapping, page);
+ unlock_page(page);
+ }
+@@ -198,17 +191,13 @@ unsigned long invalidate_mapping_pages(s
+
+ pagevec_init(&pvec, 0);
+ while (next <= end &&
+- pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
++ pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ struct page *page = pvec.pages[i];
+
+ if (TestSetPageLocked(page)) {
+- next++;
+ continue;
+ }
+- if (page->index > next)
+- next = page->index;
+- next++;
+ if (PageDirty(page) || PageWriteback(page))
+ goto unlock;
+ if (page_mapped(page))
+@@ -245,14 +234,13 @@ void invalidate_inode_pages2(struct addr
+ int i;
+
+ pagevec_init(&pvec, 0);
+- while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
++ while (pagevec_lookup(&pvec, mapping, &next, PAGEVEC_SIZE)) {
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ struct page *page = pvec.pages[i];
+
+ lock_page(page);
+ if (page->mapping == mapping) { /* truncate race? */
+ wait_on_page_writeback(page);
+- next = page->index + 1;
+ if (page_mapped(page))
+ clear_page_dirty(page);
+ else
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/mm/usercopy.c 2003-10-05 00:36:48.000000000 -0700
+@@ -0,0 +1,279 @@
++/*
++ * linux/mm/usercopy.c
++ *
++ * (C) Copyright 2003 Ingo Molnar
++ *
++ * Generic implementation of all the user-VM access functions, without
++ * relying on being able to access the VM directly.
++ */
++
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/pagemap.h>
++#include <linux/smp_lock.h>
++#include <linux/ptrace.h>
++#include <linux/interrupt.h>
++
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
++#include <asm/atomic_kmap.h>
++
++/*
++ * Get kernel address of the user page and pin it.
++ */
++static inline struct page *pin_page(unsigned long addr, int write)
++{
++ struct mm_struct *mm = current->mm ? : &init_mm;
++ struct page *page = NULL;
++ int ret;
++
++ spin_lock(&mm->page_table_lock);
++ /*
++ * Do a quick atomic lookup first - this is the fastpath.
++ */
++ page = follow_page(mm, addr, write);
++ if (likely(page != NULL)) {
++ if (!PageReserved(page))
++ get_page(page);
++ spin_unlock(&mm->page_table_lock);
++ return page;
++ }
++
++ /*
++ * No luck - bad address or need to fault in the page:
++ */
++ spin_unlock(&mm->page_table_lock);
++
++ /*
++ * In the context of filemap_copy_from_user(), we are not allowed
++ * to sleep. We must fail this usercopy attempt and allow
++ * filemap_copy_from_user() to recover: drop its atomic kmap and use
++ * a sleeping kmap instead.
++ */
++ if (in_atomic())
++ return NULL;
++
++ down_read(&mm->mmap_sem);
++ ret = get_user_pages(current, mm, addr, 1, write, 0, &page, NULL);
++ up_read(&mm->mmap_sem);
++ if (ret <= 0)
++ return NULL;
++ return page;
++}
++
++static inline void unpin_page(struct page *page)
++{
++ put_page(page);
++}
++
++/*
++ * Access another process' address space.
++ * Source/target buffer must be kernel space,
++ * Do not walk the page table directly, use get_user_pages
++ */
++static int rw_vm(unsigned long addr, void *buf, int len, int write)
++{
++ if (!len)
++ return 0;
++
++ /* ignore errors, just check how much was sucessfully transfered */
++ while (len) {
++ struct page *page = NULL;
++ int bytes, offset;
++ void *maddr;
++
++ page = pin_page(addr, write);
++ if (!page)
++ break;
++
++ bytes = len;
++ offset = addr & (PAGE_SIZE-1);
++ if (bytes > PAGE_SIZE-offset)
++ bytes = PAGE_SIZE-offset;
++
++ maddr = kmap_atomic(page, KM_USER_COPY);
++
++#define HANDLE_TYPE(type) \
++ case sizeof(type): *(type *)(maddr+offset) = *(type *)(buf); break;
++
++ if (write) {
++ switch (bytes) {
++ HANDLE_TYPE(char);
++ HANDLE_TYPE(int);
++ HANDLE_TYPE(long long);
++ default:
++ memcpy(maddr + offset, buf, bytes);
++ }
++ } else {
++#undef HANDLE_TYPE
++#define HANDLE_TYPE(type) \
++ case sizeof(type): *(type *)(buf) = *(type *)(maddr+offset); break;
++ switch (bytes) {
++ HANDLE_TYPE(char);
++ HANDLE_TYPE(int);
++ HANDLE_TYPE(long long);
++ default:
++ memcpy(buf, maddr + offset, bytes);
++ }
++#undef HANDLE_TYPE
++ }
++ kunmap_atomic(maddr, KM_USER_COPY);
++ unpin_page(page);
++ len -= bytes;
++ buf += bytes;
++ addr += bytes;
++ }
++
++ return len;
++}
++
++static int str_vm(unsigned long addr, void *buf0, int len, int copy)
++{
++ struct mm_struct *mm = current->mm ? : &init_mm;
++ struct page *page;
++ void *buf = buf0;
++
++ if (!len)
++ return len;
++
++ down_read(&mm->mmap_sem);
++ /* ignore errors, just check how much was sucessfully transfered */
++ while (len) {
++ int bytes, ret, offset, left, copied;
++ char *maddr;
++
++ ret = get_user_pages(current, mm, addr, 1, copy == 2, 0, &page, NULL);
++ if (ret <= 0) {
++ up_read(&mm->mmap_sem);
++ return -EFAULT;
++ }
++
++ bytes = len;
++ offset = addr & (PAGE_SIZE-1);
++ if (bytes > PAGE_SIZE-offset)
++ bytes = PAGE_SIZE-offset;
++
++ maddr = kmap_atomic(page, KM_USER_COPY);
++ if (copy == 2) {
++ memset(maddr + offset, 0, bytes);
++ copied = bytes;
++ left = 0;
++ } else if (copy == 1) {
++ left = strncpy_count(buf, maddr + offset, bytes);
++ copied = bytes - left;
++ } else {
++ copied = strnlen(maddr + offset, bytes);
++ left = bytes - copied;
++ }
++ BUG_ON(bytes < 0 || copied < 0);
++ kunmap_atomic(maddr, KM_USER_COPY);
++ page_cache_release(page);
++ len -= copied;
++ buf += copied;
++ addr += copied;
++ if (left)
++ break;
++ }
++ up_read(&mm->mmap_sem);
++
++ return len;
++}
++
++/*
++ * Copies memory from userspace (ptr) into kernelspace (val).
++ *
++ * returns # of bytes not copied.
++ */
++int get_user_size(unsigned int size, void *val, const void *ptr)
++{
++ int ret;
++
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ __direct_copy_from_user(val, ptr, size);
++ return 0;
++ }
++ ret = rw_vm((unsigned long)ptr, val, size, 0);
++ if (ret)
++ /*
++ * Zero the rest:
++ */
++ memset(val + size - ret, 0, ret);
++ return ret;
++}
++
++/*
++ * Copies memory from kernelspace (val) into userspace (ptr).
++ *
++ * returns # of bytes not copied.
++ */
++int put_user_size(unsigned int size, const void *val, void *ptr)
++{
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ __direct_copy_to_user(ptr, val, size);
++ return 0;
++ }
++ return rw_vm((unsigned long)ptr, (void *)val, size, 1);
++}
++
++int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr)
++{
++ int copied, left;
++
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ left = strncpy_count(val, ptr, size);
++ copied = size - left;
++ BUG_ON(copied < 0);
++
++ return copied;
++ }
++ left = str_vm((unsigned long)ptr, val, size, 1);
++ if (left < 0)
++ return left;
++ copied = size - left;
++ BUG_ON(copied < 0);
++
++ return copied;
++}
++
++int strlen_fromuser_size(unsigned int size, const void *ptr)
++{
++ int copied, left;
++
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ copied = strnlen(ptr, size) + 1;
++ BUG_ON(copied < 0);
++
++ return copied;
++ }
++ left = str_vm((unsigned long)ptr, NULL, size, 0);
++ if (left < 0)
++ return 0;
++ copied = size - left + 1;
++ BUG_ON(copied < 0);
++
++ return copied;
++}
++
++int zero_user_size(unsigned int size, void *ptr)
++{
++ int left;
++
++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
++ memset(ptr, 0, size);
++ return 0;
++ }
++ left = str_vm((unsigned long)ptr, NULL, size, 2);
++ if (left < 0)
++ return size;
++ return left;
++}
++
++EXPORT_SYMBOL(get_user_size);
++EXPORT_SYMBOL(put_user_size);
++EXPORT_SYMBOL(zero_user_size);
++EXPORT_SYMBOL(copy_str_fromuser_size);
++EXPORT_SYMBOL(strlen_fromuser_size);
++
+--- linux-2.6.0-test6/mm/vmalloc.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/mm/vmalloc.c 2003-10-05 00:33:25.000000000 -0700
+@@ -135,23 +135,23 @@ static int map_area_pmd(pmd_t *pmd, unsi
+
+ void unmap_vm_area(struct vm_struct *area)
+ {
+- unsigned long address = VMALLOC_VMADDR(area->addr);
++ unsigned long address = (unsigned long) area->addr;
+ unsigned long end = (address + area->size);
+ pgd_t *dir;
+
+ dir = pgd_offset_k(address);
+- flush_cache_all();
++ flush_cache_vunmap(address, end);
+ do {
+ unmap_area_pmd(dir, address, end - address);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+- flush_tlb_kernel_range(VMALLOC_VMADDR(area->addr), end);
++ flush_tlb_kernel_range((unsigned long) area->addr, end);
+ }
+
+ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+ {
+- unsigned long address = VMALLOC_VMADDR(area->addr);
++ unsigned long address = (unsigned long) area->addr;
+ unsigned long end = address + (area->size-PAGE_SIZE);
+ pgd_t *dir;
+ int err = 0;
+@@ -174,7 +174,7 @@ int map_vm_area(struct vm_struct *area,
+ } while (address && (address < end));
+
+ spin_unlock(&init_mm.page_table_lock);
+- flush_cache_all();
++ flush_cache_vmap((unsigned long) area->addr, end);
+ return err;
+ }
+
+--- linux-2.6.0-test6/net/802/fddi.c 2003-06-14 12:18:30.000000000 -0700
++++ 25/net/802/fddi.c 2003-10-05 00:33:25.000000000 -0700
+@@ -27,6 +27,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <asm/system.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -163,3 +164,5 @@ unsigned short fddi_type_trans(struct sk
+
+ return(type);
+ }
++
++EXPORT_SYMBOL(fddi_type_trans);
+--- linux-2.6.0-test6/net/802/hippi.c 2003-06-14 12:18:21.000000000 -0700
++++ 25/net/802/hippi.c 2003-10-05 00:33:25.000000000 -0700
+@@ -20,6 +20,7 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -151,3 +152,5 @@ unsigned short hippi_type_trans(struct s
+
+ return hip->snap.ethertype;
+ }
++
++EXPORT_SYMBOL(hippi_type_trans);
+--- linux-2.6.0-test6/net/802/p8023.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/net/802/p8023.c 2003-10-05 00:33:25.000000000 -0700
+@@ -12,22 +12,24 @@
+ * running raw 802.3 on different devices. Thankfully nobody else
+ * has done anything like the old IPX.
+ */
+-
++
++#include <linux/in.h>
++#include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/skbuff.h>
++
+ #include <net/datalink.h>
+-#include <linux/mm.h>
+-#include <linux/in.h>
+
+ /*
+ * Place an 802.3 header on a packet. The driver will do the mac
+ * addresses, we just need to give it the buffer length.
+ */
+-
+-static int p8023_request(struct datalink_proto *dl,
+- struct sk_buff *skb, unsigned char *dest_node)
++static int p8023_request(struct datalink_proto *dl,
++ struct sk_buff *skb, unsigned char *dest_node)
+ {
+- struct net_device *dev = skb->dev;
++ struct net_device *dev = skb->dev;
++
+ dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
+ return dev_queue_xmit(skb);
+ }
+@@ -35,16 +37,13 @@ static int p8023_request(struct datalink
+ /*
+ * Create an 802.3 client. Note there can be only one 802.3 client
+ */
+-
+ struct datalink_proto *make_8023_client(void)
+ {
+- struct datalink_proto *proto;
++ struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+
+- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
+- if (proto != NULL)
+- {
++ if (proto) {
+ proto->header_length = 0;
+- proto->request = p8023_request;
++ proto->request = p8023_request;
+ }
+ return proto;
+ }
+@@ -52,10 +51,11 @@ struct datalink_proto *make_8023_client(
+ /*
+ * Destroy the 802.3 client.
+ */
+-
+ void destroy_8023_client(struct datalink_proto *dl)
+ {
+ if (dl)
+ kfree(dl);
+ }
+
++EXPORT_SYMBOL(destroy_8023_client);
++EXPORT_SYMBOL(make_8023_client);
+--- linux-2.6.0-test6/net/802/tr.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/802/tr.c 2003-10-05 00:33:25.000000000 -0700
+@@ -18,6 +18,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/jiffies.h>
+@@ -600,3 +601,6 @@ static int __init rif_init(void)
+ }
+
+ module_init(rif_init);
++
++EXPORT_SYMBOL(tr_source_route);
++EXPORT_SYMBOL(tr_type_trans);
+--- /dev/null 2002-08-30 16:31:37.000000000 -0700
++++ 25/net/bridge/netfilter/ebt_limit.c 2003-10-05 00:33:25.000000000 -0700
+@@ -0,0 +1,104 @@
++/*
++ * ebt_limit
++ *
++ * Authors:
++ * Tom Marshall <tommy@home.tig-grr.com>
++ *
++ * Mostly copied from netfilter's ipt_limit.c, see that file for
++ * more explanation
++ *
++ * September, 2003
++ *
++ */
++
++#include <linux/netfilter_bridge/ebtables.h>
++#include <linux/netfilter_bridge/ebt_limit.h>
++#include <linux/module.h>
++
++#include <linux/netdevice.h>
++#include <linux/spinlock.h>
++
++static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
++
++#define CREDITS_PER_JIFFY 128
++
++static int ebt_limit_match(const struct sk_buff *skb,
++ const struct net_device *in, const struct net_device *out,
++ const void *data, unsigned int datalen)
++{
++ struct ebt_limit_info *info = (struct ebt_limit_info *)data;
++ unsigned long now = jiffies;
++
++ spin_lock_bh(&limit_lock);
++ info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY;
++ if (info->credit > info->credit_cap)
++ info->credit = info->credit_cap;
++
++ if (info->credit >= info->cost) {
++ /* We're not limited. */
++ info->credit -= info->cost;
++ spin_unlock_bh(&limit_lock);
++ return EBT_MATCH;
++ }
++
++ spin_unlock_bh(&limit_lock);
++ return EBT_NOMATCH;
++}
++
++/* Precision saver. */
++static u_int32_t
++user2credits(u_int32_t user)
++{
++ /* If multiplying would overflow... */
++ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
++ /* Divide first. */
++ return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
++
++ return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
++}
++
++static int ebt_limit_check(const char *tablename, unsigned int hookmask,
++ const struct ebt_entry *e, void *data, unsigned int datalen)
++{
++ struct ebt_limit_info *info = (struct ebt_limit_info *)data;
++
++ if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info)))
++ return -EINVAL;
++
++ /* Check for overflow. */
++ if (info->burst == 0 ||
++ user2credits(info->avg * info->burst) < user2credits(info->avg)) {
++ printk("Overflow in ebt_limit: %u/%u\n",
++ info->avg, info->burst);
++ return -EINVAL;
++ }
++
++ /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
++ info->prev = jiffies;
++ info->credit = user2credits(info->avg * info->burst);
++ info->credit_cap = user2credits(info->avg * info->burst);
++ info->cost = user2credits(info->avg);
++ return 0;
++}
++
++static struct ebt_match ebt_limit_reg =
++{
++ .name = EBT_LIMIT_MATCH,
++ .match = ebt_limit_match,
++ .check = ebt_limit_check,
++ .me = THIS_MODULE,
++};
++
++static int __init init(void)
++{
++ return ebt_register_match(&ebt_limit_reg);
++}
++
++static void __exit fini(void)
++{
++ ebt_unregister_match(&ebt_limit_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+--- linux-2.6.0-test6/net/bridge/netfilter/ebt_vlan.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/net/bridge/netfilter/ebt_vlan.c 2003-10-05 00:33:25.000000000 -0700
+@@ -48,7 +48,7 @@ ebt_filter_vlan(const struct sk_buff *sk
+ const void *data, unsigned int datalen)
+ {
+ struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
+- struct vlan_ethhdr frame;
++ struct vlan_hdr frame;
+
+ unsigned short TCI; /* Whole TCI, given from parsed frame */
+ unsigned short id; /* VLAN ID, given from frame TCI */
+--- linux-2.6.0-test6/net/bridge/netfilter/Kconfig 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/bridge/netfilter/Kconfig 2003-10-05 00:33:25.000000000 -0700
+@@ -73,6 +73,17 @@ config BRIDGE_EBT_IP
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config BRIDGE_EBT_LIMIT
++ tristate "ebt: limit match support"
++ depends on BRIDGE_NF_EBTABLES
++ help
++ This option adds the limit match, which allows you to control
++ the rate at which a rule can be matched. This match is the
++ equivalent of the iptables limit match.
++
++ If you want to compile it as a module, say M here and read
++ <file:Documentation/modules.txt>. If unsure, say `N'.
++
+ config BRIDGE_EBT_MARK
+ tristate "ebt: mark filter support"
+ depends on BRIDGE_NF_EBTABLES
+--- linux-2.6.0-test6/net/bridge/netfilter/Makefile 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/bridge/netfilter/Makefile 2003-10-05 00:33:25.000000000 -0700
+@@ -13,6 +13,7 @@ obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtabl
+ obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o
+ obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o
+ obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o
++obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o
+ obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o
+ obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o
+ obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o
+--- linux-2.6.0-test6/net/core/datagram.c 2003-06-14 12:18:24.000000000 -0700
++++ 25/net/core/datagram.c 2003-10-05 00:33:25.000000000 -0700
+@@ -33,6 +33,7 @@
+ *
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <asm/uaccess.h>
+@@ -485,3 +486,10 @@ unsigned int datagram_poll(struct file *
+
+ return mask;
+ }
++
++EXPORT_SYMBOL(datagram_poll);
++EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
++EXPORT_SYMBOL(skb_copy_datagram);
++EXPORT_SYMBOL(skb_copy_datagram_iovec);
++EXPORT_SYMBOL(skb_free_datagram);
++EXPORT_SYMBOL(skb_recv_datagram);
+--- linux-2.6.0-test6/net/core/dev.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/core/dev.c 2003-10-05 00:36:10.000000000 -0700
+@@ -111,6 +111,10 @@
+ #endif /* CONFIG_NET_RADIO */
+ #include <asm/current.h>
+
++#ifdef CONFIG_KGDB
++#include <asm/kgdb.h>
++#endif
++
+ /* This define, if set, will randomly drop a packet when congestion
+ * is more than moderate. It helps fairness in the multi-interface
+ * case when one of them is a hog, but it kills performance for the
+@@ -915,6 +919,8 @@ int unregister_netdevice_notifier(struct
+
+ /**
+ * call_netdevice_notifiers - call all network notifier blocks
++ * @val: value passed unmodified to notifier function
++ * @v: pointer passed unmodified to notifier function
+ *
+ * Call all network notifier blocks. Parameters and return value
+ * are as for notifier_call_chain().
+@@ -1322,7 +1328,6 @@ static void sample_queue(unsigned long d
+ }
+ #endif
+
+-
+ /**
+ * netif_rx - post buffer to the network code
+ * @skb: buffer to post
+@@ -1347,6 +1352,21 @@ int netif_rx(struct sk_buff *skb)
+ struct softnet_data *queue;
+ unsigned long flags;
+
++#ifdef CONFIG_KGDB
++ /* See if kgdb_eth wants this packet */
++ if (!kgdb_net_interrupt(skb)) {
++ /* No.. if we're 'trapped' then junk it */
++ if (kgdb_eth_is_trapped()) {
++ kfree_skb(skb);
++ return NET_RX_DROP;
++ }
++ } else {
++ /* kgdb_eth ate the packet... drop it silently */
++ kfree_skb(skb);
++ return NET_RX_DROP;
++ }
++#endif
++
+ if (!skb->stamp.tv_sec)
+ do_gettimeofday(&skb->stamp);
+
+@@ -1488,6 +1508,18 @@ static void net_tx_action(struct softirq
+ }
+ }
+
++static __inline__ int deliver_skb(struct sk_buff *skb,
++ struct packet_type *pt_prev, int last)
++{
++ if (unlikely(!pt_prev->data))
++ return deliver_to_old_ones(pt_prev, skb, last);
++ else {
++ atomic_inc(&skb->users);
++ return pt_prev->func(skb, skb->dev, pt_prev);
++ }
++}
++
++
+ #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
+ int (*br_handle_frame_hook)(struct sk_buff *skb);
+
+@@ -1495,15 +1527,8 @@ static __inline__ int handle_bridge(stru
+ struct packet_type *pt_prev)
+ {
+ int ret = NET_RX_DROP;
+-
+- if (pt_prev) {
+- if (!pt_prev->data)
+- ret = deliver_to_old_ones(pt_prev, skb, 0);
+- else {
+- atomic_inc(&skb->users);
+- ret = pt_prev->func(skb, skb->dev, pt_prev);
+- }
+- }
++ if (pt_prev)
++ ret = deliver_skb(skb, pt_prev, 0);
+
+ return ret;
+ }
+@@ -1551,16 +1576,8 @@ int netif_receive_skb(struct sk_buff *sk
+ rcu_read_lock();
+ list_for_each_entry_rcu(ptype, &ptype_all, list) {
+ if (!ptype->dev || ptype->dev == skb->dev) {
+- if (pt_prev) {
+- if (!pt_prev->data) {
+- ret = deliver_to_old_ones(pt_prev,
+- skb, 0);
+- } else {
+- atomic_inc(&skb->users);
+- ret = pt_prev->func(skb, skb->dev,
+- pt_prev);
+- }
+- }
++ if (pt_prev)
++ ret = deliver_skb(skb, pt_prev, 0);
+ pt_prev = ptype;
+ }
+ }
+@@ -1573,16 +1590,8 @@ int netif_receive_skb(struct sk_buff *sk
+ list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
+ if (ptype->type == type &&
+ (!ptype->dev || ptype->dev == skb->dev)) {
+- if (pt_prev) {
+- if (!pt_prev->data) {
+- ret = deliver_to_old_ones(pt_prev,
+- skb, 0);
+- } else {
+- atomic_inc(&skb->users);
+- ret = pt_prev->func(skb, skb->dev,
+- pt_prev);
+- }
+- }
++ if (pt_prev)
++ ret = deliver_skb(skb, pt_prev, 0);
+ pt_prev = ptype;
+ }
+ }
+@@ -1637,8 +1646,8 @@ static int process_backlog(struct net_de
+ #ifdef CONFIG_NET_HW_FLOWCONTROL
+ if (queue->throttle &&
+ queue->input_pkt_queue.qlen < no_cong_thresh ) {
++ queue->throttle = 0;
+ if (atomic_dec_and_test(&netdev_dropping)) {
+- queue->throttle = 0;
+ netdev_wakeup();
+ break;
+ }
+@@ -3036,3 +3045,63 @@ out:
+ }
+
+ subsys_initcall(net_dev_init);
++
++EXPORT_SYMBOL(__dev_get);
++EXPORT_SYMBOL(__dev_get_by_flags);
++EXPORT_SYMBOL(__dev_get_by_index);
++EXPORT_SYMBOL(__dev_get_by_name);
++EXPORT_SYMBOL(__dev_remove_pack);
++EXPORT_SYMBOL(__skb_linearize);
++EXPORT_SYMBOL(call_netdevice_notifiers);
++EXPORT_SYMBOL(dev_add_pack);
++EXPORT_SYMBOL(dev_alloc);
++EXPORT_SYMBOL(dev_alloc_name);
++EXPORT_SYMBOL(dev_close);
++EXPORT_SYMBOL(dev_get_by_flags);
++EXPORT_SYMBOL(dev_get_by_index);
++EXPORT_SYMBOL(dev_get_by_name);
++EXPORT_SYMBOL(dev_getbyhwaddr);
++EXPORT_SYMBOL(dev_ioctl);
++EXPORT_SYMBOL(dev_new_index);
++EXPORT_SYMBOL(dev_open);
++EXPORT_SYMBOL(dev_queue_xmit);
++EXPORT_SYMBOL(dev_queue_xmit_nit);
++EXPORT_SYMBOL(dev_remove_pack);
++EXPORT_SYMBOL(dev_set_allmulti);
++EXPORT_SYMBOL(dev_set_promiscuity);
++EXPORT_SYMBOL(free_netdev);
++EXPORT_SYMBOL(netdev_boot_setup_check);
++EXPORT_SYMBOL(netdev_set_master);
++EXPORT_SYMBOL(netdev_state_change);
++EXPORT_SYMBOL(netif_receive_skb);
++EXPORT_SYMBOL(netif_rx);
++EXPORT_SYMBOL(register_gifconf);
++EXPORT_SYMBOL(register_netdevice);
++EXPORT_SYMBOL(register_netdevice_notifier);
++EXPORT_SYMBOL(skb_checksum_help);
++EXPORT_SYMBOL(synchronize_net);
++EXPORT_SYMBOL(unregister_netdevice);
++EXPORT_SYMBOL(unregister_netdevice_notifier);
++
++#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
++EXPORT_SYMBOL(br_handle_frame_hook);
++#endif
++/* for 801q VLAN support */
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++EXPORT_SYMBOL(dev_change_flags);
++#endif
++#ifdef CONFIG_KMOD
++EXPORT_SYMBOL(dev_load);
++#endif
++#ifdef CONFIG_NET_HW_FLOWCONTROL
++EXPORT_SYMBOL(netdev_dropping);
++EXPORT_SYMBOL(netdev_fc_xoff);
++EXPORT_SYMBOL(netdev_register_fc);
++EXPORT_SYMBOL(netdev_unregister_fc);
++#endif
++#ifdef CONFIG_NET_FASTROUTE
++EXPORT_SYMBOL(netdev_fastroute);
++EXPORT_SYMBOL(netdev_fastroute_obstacles);
++#endif
++
++EXPORT_PER_CPU_SYMBOL(softnet_data);
+--- linux-2.6.0-test6/net/core/dev_mcast.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/net/core/dev_mcast.c 2003-10-05 00:33:25.000000000 -0700
+@@ -22,6 +22,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
+@@ -273,3 +274,6 @@ void __init dev_mcast_init(void)
+ #endif
+ }
+
++EXPORT_SYMBOL(dev_mc_add);
++EXPORT_SYMBOL(dev_mc_delete);
++EXPORT_SYMBOL(dev_mc_upload);
+--- linux-2.6.0-test6/net/core/dst.c 2003-06-14 12:18:23.000000000 -0700
++++ 25/net/core/dst.c 2003-10-05 00:33:25.000000000 -0700
+@@ -6,15 +6,16 @@
+ */
+
+ #include <linux/bitops.h>
+-#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/init.h>
+ #include <linux/kernel.h>
+-#include <linux/sched.h>
+ #include <linux/mm.h>
+-#include <linux/string.h>
+-#include <linux/errno.h>
++#include <linux/module.h>
+ #include <linux/netdevice.h>
++#include <linux/sched.h>
+ #include <linux/skbuff.h>
+-#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/types.h>
+
+ #include <net/dst.h>
+
+@@ -257,3 +258,7 @@ void __init dst_init(void)
+ {
+ register_netdevice_notifier(&dst_dev_notifier);
+ }
++
++EXPORT_SYMBOL(__dst_free);
++EXPORT_SYMBOL(dst_alloc);
++EXPORT_SYMBOL(dst_destroy);
+--- linux-2.6.0-test6/net/core/dv.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/dv.c 2003-10-05 00:33:25.000000000 -0700
+@@ -10,6 +10,7 @@
+ * Dave Miller: improvement on the code (correctness, performance and source files)
+ *
+ */
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -237,7 +238,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -281,7 +282,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -301,7 +302,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -321,7 +322,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -337,7 +338,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -353,7 +354,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -373,7 +374,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -389,7 +390,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -405,7 +406,7 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+@@ -425,19 +426,19 @@ int divert_ioctl(unsigned int cmd, struc
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ break;
+
+ default:
+ return -EINVAL;
+- };
++ }
+
+ return 0;
+ }
+@@ -550,8 +551,8 @@ void divert_frame(struct sk_buff *skb)
+ }
+ }
+ break;
+- };
+-
+- return;
++ }
+ }
+
++EXPORT_SYMBOL(alloc_divert_blk);
++EXPORT_SYMBOL(free_divert_blk);
+--- linux-2.6.0-test6/net/core/ethtool.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/ethtool.c 2003-10-05 00:33:25.000000000 -0700
+@@ -9,6 +9,7 @@
+ * It's GPL, stupid.
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/ethtool.h>
+@@ -727,3 +728,11 @@ int dev_ethtool(struct ifreq *ifr)
+ return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
+ return -EOPNOTSUPP;
+ }
++
++EXPORT_SYMBOL(ethtool_op_get_link);
++EXPORT_SYMBOL(ethtool_op_get_sg);
++EXPORT_SYMBOL(ethtool_op_get_tso);
++EXPORT_SYMBOL(ethtool_op_get_tx_csum);
++EXPORT_SYMBOL(ethtool_op_set_sg);
++EXPORT_SYMBOL(ethtool_op_set_tso);
++EXPORT_SYMBOL(ethtool_op_set_tx_csum);
+--- linux-2.6.0-test6/net/core/filter.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/net/core/filter.c 2003-10-05 00:33:25.000000000 -0700
+@@ -424,3 +424,6 @@ int sk_attach_filter(struct sock_fprog *
+ sk_filter_release(sk, fp);
+ return err;
+ }
++
++EXPORT_SYMBOL(sk_chk_filter);
++EXPORT_SYMBOL(sk_run_filter);
+--- linux-2.6.0-test6/net/core/flow.c 2003-06-22 12:04:45.000000000 -0700
++++ 25/net/core/flow.c 2003-10-05 00:33:25.000000000 -0700
+@@ -5,6 +5,7 @@
+ */
+
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/list.h>
+ #include <linux/jhash.h>
+ #include <linux/interrupt.h>
+@@ -401,3 +402,6 @@ static int __init flow_cache_init(void)
+ }
+
+ module_init(flow_cache_init);
++
++EXPORT_SYMBOL(flow_cache_genid);
++EXPORT_SYMBOL(flow_cache_lookup);
+--- linux-2.6.0-test6/net/core/iovec.c 2003-06-14 12:18:52.000000000 -0700
++++ 25/net/core/iovec.c 2003-10-05 00:33:25.000000000 -0700
+@@ -16,8 +16,8 @@
+ * Andi Kleen : Fix csum*fromiovecend for IPv6.
+ */
+
+-
+ #include <linux/errno.h>
++#include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+@@ -254,3 +254,9 @@ out_fault:
+ err = -EFAULT;
+ goto out;
+ }
++
++EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
++EXPORT_SYMBOL(memcpy_fromiovec);
++EXPORT_SYMBOL(memcpy_fromiovecend);
++EXPORT_SYMBOL(memcpy_toiovec);
++EXPORT_SYMBOL(memcpy_tokerneliovec);
+--- linux-2.6.0-test6/net/core/link_watch.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/link_watch.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,5 +1,5 @@
+ /*
+- * Linux network device link state notifaction
++ * Linux network device link state notification
+ *
+ * Author:
+ * Stefan Rompf <sux@loplof.de>
+@@ -12,6 +12,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/if.h>
+ #include <linux/rtnetlink.h>
+@@ -132,3 +133,4 @@ void linkwatch_fire_event(struct net_dev
+ }
+ }
+
++EXPORT_SYMBOL(linkwatch_fire_event);
+--- linux-2.6.0-test6/net/core/neighbour.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/core/neighbour.c 2003-10-05 00:33:25.000000000 -0700
+@@ -17,6 +17,7 @@
+ #include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/socket.h>
+ #include <linux/sched.h>
+ #include <linux/netdevice.h>
+@@ -1683,3 +1684,34 @@ void neigh_sysctl_unregister(struct neig
+ }
+
+ #endif /* CONFIG_SYSCTL */
++
++EXPORT_SYMBOL(__neigh_event_send);
++EXPORT_SYMBOL(neigh_add);
++EXPORT_SYMBOL(neigh_changeaddr);
++EXPORT_SYMBOL(neigh_compat_output);
++EXPORT_SYMBOL(neigh_connected_output);
++EXPORT_SYMBOL(neigh_create);
++EXPORT_SYMBOL(neigh_delete);
++EXPORT_SYMBOL(neigh_destroy);
++EXPORT_SYMBOL(neigh_dump_info);
++EXPORT_SYMBOL(neigh_event_ns);
++EXPORT_SYMBOL(neigh_ifdown);
++EXPORT_SYMBOL(neigh_lookup);
++EXPORT_SYMBOL(neigh_parms_alloc);
++EXPORT_SYMBOL(neigh_parms_release);
++EXPORT_SYMBOL(neigh_rand_reach_time);
++EXPORT_SYMBOL(neigh_resolve_output);
++EXPORT_SYMBOL(neigh_table_clear);
++EXPORT_SYMBOL(neigh_table_init);
++EXPORT_SYMBOL(neigh_update);
++EXPORT_SYMBOL(neigh_update_hhs);
++EXPORT_SYMBOL(pneigh_enqueue);
++EXPORT_SYMBOL(pneigh_lookup);
++
++#ifdef CONFIG_ARPD
++EXPORT_SYMBOL(neigh_app_ns);
++#endif
++#ifdef CONFIG_SYSCTL
++EXPORT_SYMBOL(neigh_sysctl_register);
++EXPORT_SYMBOL(neigh_sysctl_unregister);
++#endif
+--- linux-2.6.0-test6/net/core/netfilter.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/netfilter.c 2003-10-05 00:33:25.000000000 -0700
+@@ -759,3 +759,17 @@ void __init netfilter_init(void)
+ INIT_LIST_HEAD(&nf_hooks[i][h]);
+ }
+ }
++
++EXPORT_SYMBOL(ip_ct_attach);
++EXPORT_SYMBOL(ip_route_me_harder);
++EXPORT_SYMBOL(nf_getsockopt);
++EXPORT_SYMBOL(nf_hook_slow);
++EXPORT_SYMBOL(nf_hooks);
++EXPORT_SYMBOL(nf_register_hook);
++EXPORT_SYMBOL(nf_register_queue_handler);
++EXPORT_SYMBOL(nf_register_sockopt);
++EXPORT_SYMBOL(nf_reinject);
++EXPORT_SYMBOL(nf_setsockopt);
++EXPORT_SYMBOL(nf_unregister_hook);
++EXPORT_SYMBOL(nf_unregister_queue_handler);
++EXPORT_SYMBOL(nf_unregister_sockopt);
+--- linux-2.6.0-test6/net/core/rtnetlink.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/rtnetlink.c 2003-10-05 00:33:25.000000000 -0700
+@@ -18,6 +18,7 @@
+
+ #include <linux/config.h>
+ #include <linux/errno.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/socket.h>
+ #include <linux/kernel.h>
+@@ -556,7 +557,6 @@ struct notifier_block rtnetlink_dev_noti
+ .notifier_call = rtnetlink_event,
+ };
+
+-
+ void __init rtnetlink_init(void)
+ {
+ rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
+@@ -567,3 +567,13 @@ void __init rtnetlink_init(void)
+ rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table;
+ rtnetlink_links[PF_PACKET] = link_rtnetlink_table;
+ }
++
++EXPORT_SYMBOL(__rta_fill);
++EXPORT_SYMBOL(rtattr_parse);
++EXPORT_SYMBOL(rtnetlink_dump_ifinfo);
++EXPORT_SYMBOL(rtnetlink_links);
++EXPORT_SYMBOL(rtnetlink_put_metrics);
++EXPORT_SYMBOL(rtnl);
++EXPORT_SYMBOL(rtnl_lock);
++EXPORT_SYMBOL(rtnl_sem);
++EXPORT_SYMBOL(rtnl_unlock);
+--- linux-2.6.0-test6/net/core/scm.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/scm.c 2003-10-05 00:33:25.000000000 -0700
+@@ -9,6 +9,7 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/module.h>
+ #include <linux/signal.h>
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+@@ -282,3 +283,9 @@ struct scm_fp_list *scm_fp_dup(struct sc
+ }
+ return new_fpl;
+ }
++
++EXPORT_SYMBOL(__scm_destroy);
++EXPORT_SYMBOL(__scm_send);
++EXPORT_SYMBOL(put_cmsg);
++EXPORT_SYMBOL(scm_detach_fds);
++EXPORT_SYMBOL(scm_fp_dup);
+--- linux-2.6.0-test6/net/core/skbuff.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/core/skbuff.c 2003-10-05 00:33:25.000000000 -0700
+@@ -39,6 +39,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -1103,3 +1104,22 @@ void __init skb_init(void)
+ if (!skbuff_head_cache)
+ panic("cannot create skbuff cache");
+ }
++
++EXPORT_SYMBOL(___pskb_trim);
++EXPORT_SYMBOL(__kfree_skb);
++EXPORT_SYMBOL(__pskb_pull_tail);
++EXPORT_SYMBOL(alloc_skb);
++EXPORT_SYMBOL(pskb_copy);
++EXPORT_SYMBOL(pskb_expand_head);
++EXPORT_SYMBOL(skb_checksum);
++EXPORT_SYMBOL(skb_clone);
++EXPORT_SYMBOL(skb_clone_fraglist);
++EXPORT_SYMBOL(skb_copy);
++EXPORT_SYMBOL(skb_copy_and_csum_bits);
++EXPORT_SYMBOL(skb_copy_and_csum_dev);
++EXPORT_SYMBOL(skb_copy_bits);
++EXPORT_SYMBOL(skb_copy_expand);
++EXPORT_SYMBOL(skb_over_panic);
++EXPORT_SYMBOL(skb_pad);
++EXPORT_SYMBOL(skb_realloc_headroom);
++EXPORT_SYMBOL(skb_under_panic);
+--- linux-2.6.0-test6/net/core/sock.c 2003-06-14 12:18:29.000000000 -0700
++++ 25/net/core/sock.c 2003-10-05 00:33:25.000000000 -0700
+@@ -98,6 +98,7 @@
+ #include <linux/in.h>
+ #include <linux/kernel.h>
+ #include <linux/major.h>
++#include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/timer.h>
+ #include <linux/string.h>
+@@ -1111,3 +1112,40 @@ void sock_init_data(struct socket *sock,
+
+ atomic_set(&sk->sk_refcnt, 1);
+ }
++
++EXPORT_SYMBOL(__lock_sock);
++EXPORT_SYMBOL(__release_sock);
++EXPORT_SYMBOL(sk_alloc);
++EXPORT_SYMBOL(sk_free);
++EXPORT_SYMBOL(sk_send_sigurg);
++EXPORT_SYMBOL(sock_alloc_send_pskb);
++EXPORT_SYMBOL(sock_alloc_send_skb);
++EXPORT_SYMBOL(sock_getsockopt);
++EXPORT_SYMBOL(sock_init_data);
++EXPORT_SYMBOL(sock_kfree_s);
++EXPORT_SYMBOL(sock_kmalloc);
++EXPORT_SYMBOL(sock_no_accept);
++EXPORT_SYMBOL(sock_no_bind);
++EXPORT_SYMBOL(sock_no_connect);
++EXPORT_SYMBOL(sock_no_getname);
++EXPORT_SYMBOL(sock_no_getsockopt);
++EXPORT_SYMBOL(sock_no_ioctl);
++EXPORT_SYMBOL(sock_no_listen);
++EXPORT_SYMBOL(sock_no_mmap);
++EXPORT_SYMBOL(sock_no_poll);
++EXPORT_SYMBOL(sock_no_recvmsg);
++EXPORT_SYMBOL(sock_no_release);
++EXPORT_SYMBOL(sock_no_sendmsg);
++EXPORT_SYMBOL(sock_no_sendpage);
++EXPORT_SYMBOL(sock_no_setsockopt);
++EXPORT_SYMBOL(sock_no_shutdown);
++EXPORT_SYMBOL(sock_no_socketpair);
++EXPORT_SYMBOL(sock_rfree);
++EXPORT_SYMBOL(sock_rmalloc);
++EXPORT_SYMBOL(sock_setsockopt);
++EXPORT_SYMBOL(sock_wfree);
++EXPORT_SYMBOL(sock_wmalloc);
++#ifdef CONFIG_SYSCTL
++EXPORT_SYMBOL(sysctl_rmem_max);
++EXPORT_SYMBOL(sysctl_wmem_max);
++#endif
+--- linux-2.6.0-test6/net/core/utils.c 2003-06-14 12:17:55.000000000 -0700
++++ 25/net/core/utils.c 2003-10-05 00:33:25.000000000 -0700
+@@ -13,13 +13,15 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/jiffies.h>
+-#include <linux/string.h>
++#include <linux/kernel.h>
+ #include <linux/mm.h>
++#include <linux/string.h>
++#include <linux/types.h>
++
++#include <asm/system.h>
++#include <asm/uaccess.h>
+
+ static unsigned long net_rand_seed = 152L;
+
+@@ -71,3 +73,7 @@ int net_ratelimit(void)
+ spin_unlock_irqrestore(&ratelimit_lock, flags);
+ return 0;
+ }
++
++EXPORT_SYMBOL(net_random);
++EXPORT_SYMBOL(net_ratelimit);
++EXPORT_SYMBOL(net_srandom);
+--- linux-2.6.0-test6/net/core/wireless.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/core/wireless.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1365,3 +1365,10 @@ void wireless_spy_update(struct net_devi
+ #endif /* IW_WIRELESS_THRSPY */
+ #endif /* IW_WIRELESS_SPY */
+ }
++
++EXPORT_SYMBOL(iw_handler_get_spy);
++EXPORT_SYMBOL(iw_handler_get_thrspy);
++EXPORT_SYMBOL(iw_handler_set_spy);
++EXPORT_SYMBOL(iw_handler_set_thrspy);
++EXPORT_SYMBOL(wireless_send_event);
++EXPORT_SYMBOL(wireless_spy_update);
+--- linux-2.6.0-test6/net/ethernet/eth.c 2003-06-22 12:04:45.000000000 -0700
++++ 25/net/ethernet/eth.c 2003-10-05 00:33:25.000000000 -0700
+@@ -37,6 +37,7 @@
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -241,3 +242,5 @@ void eth_header_cache_update(struct hh_c
+ memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
+ haddr, dev->addr_len);
+ }
++
++EXPORT_SYMBOL(eth_type_trans);
+--- linux-2.6.0-test6/net/ethernet/pe2.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/net/ethernet/pe2.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,27 +1,28 @@
++#include <linux/in.h>
++#include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/skbuff.h>
++
+ #include <net/datalink.h>
+-#include <linux/mm.h>
+-#include <linux/in.h>
+
+-static int pEII_request(struct datalink_proto *dl,
+- struct sk_buff *skb, unsigned char *dest_node)
++static int pEII_request(struct datalink_proto *dl,
++ struct sk_buff *skb, unsigned char *dest_node)
+ {
+- struct net_device *dev = skb->dev;
++ struct net_device *dev = skb->dev;
+
+- skb->protocol = htons (ETH_P_IPX);
+- if(dev->hard_header)
+- dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
++ skb->protocol = htons(ETH_P_IPX);
++ if (dev->hard_header)
++ dev->hard_header(skb, dev, ETH_P_IPX,
++ dest_node, NULL, skb->len);
+ return dev_queue_xmit(skb);
+ }
+
+-struct datalink_proto *
+-make_EII_client(void)
++struct datalink_proto *make_EII_client(void)
+ {
+- struct datalink_proto *proto;
++ struct datalink_proto *proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+
+- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
+- if (proto != NULL) {
++ if (proto) {
+ proto->header_length = 0;
+ proto->request = pEII_request;
+ }
+@@ -34,3 +35,6 @@ void destroy_EII_client(struct datalink_
+ if (dl)
+ kfree(dl);
+ }
++
++EXPORT_SYMBOL(destroy_EII_client);
++EXPORT_SYMBOL(make_EII_client);
+--- linux-2.6.0-test6/net/ipv4/af_inet.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/af_inet.c 2003-10-05 00:33:25.000000000 -0700
+@@ -74,6 +74,7 @@
+ #include <linux/in.h>
+ #include <linux/kernel.h>
+ #include <linux/major.h>
++#include <linux/module.h>
+ #include <linux/sched.h>
+ #include <linux/timer.h>
+ #include <linux/string.h>
+@@ -1246,4 +1247,33 @@ int __init ipv4_proc_init(void)
+ return 0;
+ }
+ #endif /* CONFIG_PROC_FS */
++
+ MODULE_ALIAS_NETPROTO(PF_INET);
++
++EXPORT_SYMBOL(inet_accept);
++EXPORT_SYMBOL(inet_bind);
++EXPORT_SYMBOL(inet_dgram_connect);
++EXPORT_SYMBOL(inet_dgram_ops);
++EXPORT_SYMBOL(inet_family_ops);
++EXPORT_SYMBOL(inet_getname);
++EXPORT_SYMBOL(inet_getsockopt);
++EXPORT_SYMBOL(inet_ioctl);
++EXPORT_SYMBOL(inet_listen);
++EXPORT_SYMBOL(inet_recvmsg);
++EXPORT_SYMBOL(inet_register_protosw);
++EXPORT_SYMBOL(inet_release);
++EXPORT_SYMBOL(inet_sendmsg);
++EXPORT_SYMBOL(inet_setsockopt);
++EXPORT_SYMBOL(inet_shutdown);
++EXPORT_SYMBOL(inet_sock_destruct);
++EXPORT_SYMBOL(inet_sock_release);
++EXPORT_SYMBOL(inet_stream_connect);
++EXPORT_SYMBOL(inet_stream_ops);
++EXPORT_SYMBOL(inet_unregister_protosw);
++EXPORT_SYMBOL(net_statistics);
++EXPORT_SYMBOL(tcp_protocol);
++EXPORT_SYMBOL(udp_protocol);
++
++#ifdef INET_REFCNT_DEBUG
++EXPORT_SYMBOL(inet_sock_nr);
++#endif
+--- linux-2.6.0-test6/net/ipv4/arp.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/arp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -69,6 +69,7 @@
+ * Arnaldo C. Melo : convert /proc/net/arp to seq_file
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+ #include <linux/kernel.h>
+@@ -630,12 +631,6 @@ int arp_process(struct sk_buff *skb)
+ if (in_dev == NULL)
+ goto out;
+
+- /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
+- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+- (2 * dev->addr_len) +
+- (2 * sizeof(u32)))))
+- goto out;
+-
+ arp = skb->nh.arph;
+
+ switch (dev_type) {
+@@ -835,8 +830,15 @@ out:
+
+ int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+ {
+- struct arphdr *arp = skb->nh.arph;
++ struct arphdr *arp;
++
++ /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
++ if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
++ (2 * dev->addr_len) +
++ (2 * sizeof(u32)))))
++ goto freeskb;
+
++ arp = skb->nh.arph;
+ if (arp->ar_hln != dev->addr_len ||
+ dev->flags & IFF_NOARP ||
+ skb->pkt_type == PACKET_OTHERHOST ||
+@@ -1429,3 +1431,13 @@ static int __init arp_proc_init(void)
+ }
+
+ #endif /* CONFIG_PROC_FS */
++
++EXPORT_SYMBOL(arp_broken_ops);
++EXPORT_SYMBOL(arp_find);
++EXPORT_SYMBOL(arp_rcv);
++EXPORT_SYMBOL(arp_send);
++EXPORT_SYMBOL(arp_tbl);
++
++#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
++EXPORT_SYMBOL(clip_tbl_hook);
++#endif
+--- linux-2.6.0-test6/net/ipv4/devinet.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/ipv4/devinet.c 2003-10-05 00:33:25.000000000 -0700
+@@ -32,6 +32,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -1354,3 +1355,11 @@ void __init devinet_init(void)
+ devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
+ #endif
+ }
++
++EXPORT_SYMBOL(devinet_ioctl);
++EXPORT_SYMBOL(in_dev_finish_destroy);
++EXPORT_SYMBOL(inet_select_addr);
++EXPORT_SYMBOL(inetdev_by_index);
++EXPORT_SYMBOL(inetdev_lock);
++EXPORT_SYMBOL(register_inetaddr_notifier);
++EXPORT_SYMBOL(unregister_inetaddr_notifier);
+--- linux-2.6.0-test6/net/ipv4/fib_frontend.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/net/ipv4/fib_frontend.c 2003-10-05 00:33:25.000000000 -0700
+@@ -16,6 +16,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
+@@ -605,3 +606,6 @@ void __init ip_fib_init(void)
+ register_inetaddr_notifier(&fib_inetaddr_notifier);
+ }
+
++EXPORT_SYMBOL(inet_addr_type);
++EXPORT_SYMBOL(ip_dev_find);
++EXPORT_SYMBOL(ip_rt_ioctl);
+--- linux-2.6.0-test6/net/ipv4/icmp.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/icmp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -65,6 +65,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/jiffies.h>
+ #include <linux/kernel.h>
+@@ -1126,3 +1127,8 @@ void __init icmp_init(struct net_proto_f
+ per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk);
+ }
+ }
++
++EXPORT_SYMBOL(icmp_err_convert);
++EXPORT_SYMBOL(icmp_send);
++EXPORT_SYMBOL(icmp_statistics);
++EXPORT_SYMBOL(xrlim_allow);
+--- linux-2.6.0-test6/net/ipv4/igmp.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/igmp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -72,8 +72,8 @@
+ * Vinay Kulkarni
+ */
+
+-
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <linux/types.h>
+@@ -2438,3 +2438,6 @@ int __init igmp_mc_proc_init(void)
+ }
+ #endif
+
++EXPORT_SYMBOL(ip_mc_dec_group);
++EXPORT_SYMBOL(ip_mc_inc_group);
++EXPORT_SYMBOL(ip_mc_join_group);
+--- linux-2.6.0-test6/net/ipv4/inetpeer.c 2003-06-14 12:18:33.000000000 -0700
++++ 25/net/ipv4/inetpeer.c 2003-10-05 00:33:25.000000000 -0700
+@@ -8,6 +8,7 @@
+ * Authors: Andrey V. Savochkin <saw@msu.ru>
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+@@ -452,3 +453,5 @@ static void peer_check_expire(unsigned l
+ peer_total / inet_peer_threshold * HZ;
+ add_timer(&peer_periodic_timer);
+ }
++
++EXPORT_SYMBOL(inet_peer_idlock);
+--- linux-2.6.0-test6/net/ipv4/ip_fragment.c 2003-06-14 12:18:05.000000000 -0700
++++ 25/net/ipv4/ip_fragment.c 2003-10-05 00:33:25.000000000 -0700
+@@ -23,6 +23,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/mm.h>
+ #include <linux/jiffies.h>
+@@ -675,3 +676,5 @@ void ipfrag_init(void)
+ ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
+ add_timer(&ipfrag_secret_timer);
+ }
++
++EXPORT_SYMBOL(ip_defrag);
+--- linux-2.6.0-test6/net/ipv4/ip_input.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ip_input.c 2003-10-05 00:33:25.000000000 -0700
+@@ -116,6 +116,7 @@
+ */
+
+ #include <asm/system.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+@@ -432,3 +433,5 @@ out:
+ return NET_RX_DROP;
+ }
+
++EXPORT_SYMBOL(ip_rcv);
++EXPORT_SYMBOL(ip_statistics);
+--- linux-2.6.0-test6/net/ipv4/ipip.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/ipv4/ipip.c 2003-10-05 00:33:25.000000000 -0700
+@@ -483,6 +483,11 @@ static int ipip_rcv(struct sk_buff *skb)
+
+ read_lock(&ipip_lock);
+ if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
++ kfree_skb(skb);
++ return 0;
++ }
++
+ tunnel->stat.rx_packets++;
+ tunnel->stat.rx_bytes += skb->len;
+ skb->dev = tunnel->dev;
+--- linux-2.6.0-test6/net/ipv4/ip_options.c 2003-06-14 12:18:28.000000000 -0700
++++ 25/net/ipv4/ip_options.c 2003-10-05 00:33:25.000000000 -0700
+@@ -11,6 +11,7 @@
+ *
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <asm/uaccess.h>
+ #include <linux/skbuff.h>
+@@ -617,3 +618,6 @@ int ip_options_rcv_srr(struct sk_buff *s
+ }
+ return 0;
+ }
++
++EXPORT_SYMBOL(ip_options_compile);
++EXPORT_SYMBOL(ip_options_undo);
+--- linux-2.6.0-test6/net/ipv4/ip_output.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ip_output.c 2003-10-05 00:33:25.000000000 -0700
+@@ -46,6 +46,7 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -1317,3 +1318,13 @@ void __init ip_init(void)
+ igmp_mc_proc_init();
+ #endif
+ }
++
++EXPORT_SYMBOL(ip_finish_output);
++EXPORT_SYMBOL(ip_fragment);
++EXPORT_SYMBOL(ip_generic_getfrag);
++EXPORT_SYMBOL(ip_queue_xmit);
++EXPORT_SYMBOL(ip_send_check);
++
++#ifdef CONFIG_SYSCTL
++EXPORT_SYMBOL(sysctl_ip_default_ttl);
++#endif
+--- linux-2.6.0-test6/net/ipv4/ip_sockglue.c 2003-06-14 12:18:06.000000000 -0700
++++ 25/net/ipv4/ip_sockglue.c 2003-10-05 00:33:25.000000000 -0700
+@@ -18,6 +18,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/mm.h>
+ #include <linux/sched.h>
+@@ -1055,3 +1056,10 @@ int ip_getsockopt(struct sock *sk, int l
+ }
+ return 0;
+ }
++
++EXPORT_SYMBOL(ip_cmsg_recv);
++
++#ifdef CONFIG_IP_SCTP_MODULE
++EXPORT_SYMBOL(ip_getsockopt);
++EXPORT_SYMBOL(ip_setsockopt);
++#endif
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_lblc.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_lblc.c 2003-10-05 00:33:25.000000000 -0700
+@@ -458,10 +458,11 @@ __ip_vs_wlc_schedule(struct ip_vs_servic
+ * The server with weight=0 is quiesced and will not receive any
+ * new connection.
+ */
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (least->flags & IP_VS_DEST_F_OVERLOAD)
++ list_for_each_entry(dest, &svc->destinations, n_list) {
++ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+- if (atomic_read(&least->weight) > 0) {
++ if (atomic_read(&dest->weight) > 0) {
++ least = dest;
+ loh = atomic_read(&least->activeconns) * 50
+ + atomic_read(&least->inactconns);
+ goto nextstage;
+@@ -473,7 +474,7 @@ __ip_vs_wlc_schedule(struct ip_vs_servic
+ * Find the destination with the least load.
+ */
+ nextstage:
+- list_for_each_entry(dest, &svc->destinations, n_list) {
++ list_for_each_entry_continue(dest, &svc->destinations, n_list) {
+ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_lblcr.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_lblcr.c 2003-10-05 00:33:25.000000000 -0700
+@@ -711,11 +711,12 @@ __ip_vs_wlc_schedule(struct ip_vs_servic
+ * The server with weight=0 is quiesced and will not receive any
+ * new connection.
+ */
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (least->flags & IP_VS_DEST_F_OVERLOAD)
++ list_for_each_entry(dest, &svc->destinations, n_list) {
++ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+
+- if (atomic_read(&least->weight) > 0) {
++ if (atomic_read(&dest->weight) > 0) {
++ least = dest;
+ loh = atomic_read(&least->activeconns) * 50
+ + atomic_read(&least->inactconns);
+ goto nextstage;
+@@ -727,7 +728,7 @@ __ip_vs_wlc_schedule(struct ip_vs_servic
+ * Find the destination with the least load.
+ */
+ nextstage:
+- list_for_each_entry(dest, &svc->destinations, n_list) {
++ list_for_each_entry_continue(dest, &svc->destinations, n_list) {
+ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_lc.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_lc.c 2003-10-05 00:33:25.000000000 -0700
+@@ -65,8 +65,8 @@ ip_vs_lc_dest_overhead(struct ip_vs_dest
+ static struct ip_vs_dest *
+ ip_vs_lc_schedule(struct ip_vs_service *svc, struct iphdr *iph)
+ {
+- struct ip_vs_dest *dest, *least;
+- unsigned int loh, doh;
++ struct ip_vs_dest *dest, *least = NULL;
++ unsigned int loh = 0, doh;
+
+ IP_VS_DBG(6, "ip_vs_lc_schedule(): Scheduling...\n");
+
+@@ -79,31 +79,18 @@ ip_vs_lc_schedule(struct ip_vs_service *
+ * served, but no new connection is assigned to the server.
+ */
+
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (least->flags & IP_VS_DEST_F_OVERLOAD)
+- continue;
+- if (atomic_read(&least->weight) > 0) {
+- loh = ip_vs_lc_dest_overhead(least);
+- goto nextstage;
+- }
+- }
+- return NULL;
+-
+- /*
+- * Find the destination with the least load.
+- */
+- nextstage:
+ list_for_each_entry(dest, &svc->destinations, n_list) {
+ if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
+ atomic_read(&dest->weight) == 0)
+ continue;
+ doh = ip_vs_lc_dest_overhead(dest);
+- if (doh < loh) {
++ if (!least || doh < loh) {
+ least = dest;
+ loh = doh;
+ }
+ }
+
++ if (least)
+ IP_VS_DBG(6, "LC: server %u.%u.%u.%u:%u activeconns %d inactconns %d\n",
+ NIPQUAD(least->addr), ntohs(least->port),
+ atomic_read(&least->activeconns),
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_nq.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_nq.c 2003-10-05 00:33:25.000000000 -0700
+@@ -81,8 +81,8 @@ ip_vs_nq_dest_overhead(struct ip_vs_dest
+ static struct ip_vs_dest *
+ ip_vs_nq_schedule(struct ip_vs_service *svc, struct iphdr *iph)
+ {
+- struct ip_vs_dest *dest, *least;
+- unsigned int loh, doh;
++ struct ip_vs_dest *dest, *least = NULL;
++ unsigned int loh = 0, doh;
+
+ IP_VS_DBG(6, "ip_vs_nq_schedule(): Scheduling...\n");
+
+@@ -99,27 +99,10 @@ ip_vs_nq_schedule(struct ip_vs_service *
+ * new connections.
+ */
+
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (!(least->flags & IP_VS_DEST_F_OVERLOAD) &&
+- atomic_read(&least->weight) > 0) {
+- loh = ip_vs_nq_dest_overhead(least);
+-
+- /* return the server directly if it is idle */
+- if (atomic_read(&least->activeconns) == 0)
+- goto out;
+-
+- goto nextstage;
+- }
+- }
+- return NULL;
+-
+- /*
+- * Find the destination with the least load.
+- */
+- nextstage:
+ list_for_each_entry(dest, &svc->destinations, n_list) {
+
+- if (dest->flags & IP_VS_DEST_F_OVERLOAD)
++ if (dest->flags & IP_VS_DEST_F_OVERLOAD ||
++ !atomic_read(&dest->weight))
+ continue;
+
+ doh = ip_vs_nq_dest_overhead(dest);
+@@ -127,16 +110,21 @@ ip_vs_nq_schedule(struct ip_vs_service *
+ /* return the server directly if it is idle */
+ if (atomic_read(&dest->activeconns) == 0) {
+ least = dest;
++ loh = doh;
+ goto out;
+ }
+
+- if (loh * atomic_read(&dest->weight) >
+- doh * atomic_read(&least->weight)) {
++ if (!least ||
++ (loh * atomic_read(&dest->weight) >
++ doh * atomic_read(&least->weight))) {
+ least = dest;
+ loh = doh;
+ }
+ }
+
++ if (!least)
++ return NULL;
++
+ out:
+ IP_VS_DBG(6, "NQ: server %u.%u.%u.%u:%u "
+ "activeconns %d refcnt %d weight %d overhead %d\n",
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_sed.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_sed.c 2003-10-05 00:33:25.000000000 -0700
+@@ -103,9 +103,10 @@ ip_vs_sed_schedule(struct ip_vs_service
+ * new connections.
+ */
+
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (!(least->flags & IP_VS_DEST_F_OVERLOAD) &&
+- atomic_read(&least->weight) > 0) {
++ list_for_each_entry(dest, &svc->destinations, n_list) {
++ if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
++ atomic_read(&dest->weight) > 0) {
++ least = dest;
+ loh = ip_vs_sed_dest_overhead(least);
+ goto nextstage;
+ }
+@@ -116,7 +117,7 @@ ip_vs_sed_schedule(struct ip_vs_service
+ * Find the destination with the least load.
+ */
+ nextstage:
+- list_for_each_entry(dest, &svc->destinations, n_list) {
++ list_for_each_entry_continue(dest, &svc->destinations, n_list) {
+ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+ doh = ip_vs_sed_dest_overhead(dest);
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_wlc.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_wlc.c 2003-10-05 00:33:25.000000000 -0700
+@@ -91,9 +91,10 @@ ip_vs_wlc_schedule(struct ip_vs_service
+ * new connections.
+ */
+
+- list_for_each_entry(least, &svc->destinations, n_list) {
+- if (!(least->flags & IP_VS_DEST_F_OVERLOAD) &&
+- atomic_read(&least->weight) > 0) {
++ list_for_each_entry(dest, &svc->destinations, n_list) {
++ if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
++ atomic_read(&dest->weight) > 0) {
++ least = dest;
+ loh = ip_vs_wlc_dest_overhead(least);
+ goto nextstage;
+ }
+@@ -104,7 +105,7 @@ ip_vs_wlc_schedule(struct ip_vs_service
+ * Find the destination with the least load.
+ */
+ nextstage:
+- list_for_each_entry(dest, &svc->destinations, n_list) {
++ list_for_each_entry_continue(dest, &svc->destinations, n_list) {
+ if (dest->flags & IP_VS_DEST_F_OVERLOAD)
+ continue;
+ doh = ip_vs_wlc_dest_overhead(dest);
+--- linux-2.6.0-test6/net/ipv4/ipvs/ip_vs_wrr.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/ipvs/ip_vs_wrr.c 2003-10-05 00:33:25.000000000 -0700
+@@ -58,26 +58,18 @@ static int ip_vs_wrr_gcd_weight(struct i
+ {
+ struct ip_vs_dest *dest;
+ int weight;
+- int g = 1;
++ int g = 0;
+
+ list_for_each_entry(dest, &svc->destinations, n_list) {
+ weight = atomic_read(&dest->weight);
+ if (weight > 0) {
+- g = weight;
+- goto search_gcd;
++ if (g > 0)
++ g = gcd(weight, g);
++ else
++ g = weight;
+ }
+ }
+-
+- return g;
+-
+- search_gcd:
+- list_for_each_entry(dest, &svc->destinations, n_list) {
+- weight = atomic_read(&dest->weight);
+- if (weight > 0)
+- g = gcd(weight, g);
+- }
+-
+- return g;
++ return g ? g : 1;
+ }
+
+
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_core.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_core.c 2003-10-05 00:33:25.000000000 -0700
+@@ -59,7 +59,7 @@ LIST_HEAD(ip_conntrack_expect_list);
+ LIST_HEAD(protocol_list);
+ static LIST_HEAD(helpers);
+ unsigned int ip_conntrack_htable_size = 0;
+-static int ip_conntrack_max;
++int ip_conntrack_max;
+ static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
+ struct list_head *ip_conntrack_hash;
+ static kmem_cache_t *ip_conntrack_cachep;
+@@ -301,7 +301,7 @@ clean_from_lists(struct ip_conntrack *ct
+ static void
+ destroy_conntrack(struct nf_conntrack *nfct)
+ {
+- struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
++ struct ip_conntrack *ct = (struct ip_conntrack *)nfct, *master = NULL;
+ struct ip_conntrack_protocol *proto;
+
+ DEBUGP("destroy_conntrack(%p)\n", ct);
+@@ -328,12 +328,15 @@ destroy_conntrack(struct nf_conntrack *n
+ /* can't call __unexpect_related here,
+ * since it would screw up expect_list */
+ list_del(&ct->master->expected_list);
+- ip_conntrack_put(ct->master->expectant);
++ master = ct->master->expectant;
+ }
+ kfree(ct->master);
+ }
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
++ if (master)
++ ip_conntrack_put(master);
++
+ DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
+ kmem_cache_free(ip_conntrack_cachep, ct);
+ atomic_dec(&ip_conntrack_count);
+@@ -1276,11 +1279,14 @@ getorigdst(struct sock *sk, int optval,
+ {
+ struct inet_opt *inet = inet_sk(sk);
+ struct ip_conntrack_tuple_hash *h;
+- struct ip_conntrack_tuple tuple = { { inet->rcv_saddr,
+- { .tcp = { inet->sport } } },
+- { inet->daddr,
+- { .tcp = { inet->dport } },
+- IPPROTO_TCP } };
++ struct ip_conntrack_tuple tuple;
++
++ IP_CT_TUPLE_U_BLANK(&tuple);
++ tuple.src.ip = inet->rcv_saddr;
++ tuple.src.u.tcp.port = inet->sport;
++ tuple.dst.ip = inet->daddr;
++ tuple.dst.u.tcp.port = inet->dport;
++ tuple.dst.protonum = IPPROTO_TCP;
+
+ /* We only do TCP at the moment: is there a better way? */
+ if (strcmp(sk->sk_prot->name, "TCP")) {
+@@ -1325,45 +1331,6 @@ static struct nf_sockopt_ops so_getorigd
+ .get = &getorigdst,
+ };
+
+-#define NET_IP_CONNTRACK_MAX 2089
+-#define NET_IP_CONNTRACK_MAX_NAME "ip_conntrack_max"
+-
+-#ifdef CONFIG_SYSCTL
+-static struct ctl_table_header *ip_conntrack_sysctl_header;
+-
+-static ctl_table ip_conntrack_table[] = {
+- {
+- .ctl_name = NET_IP_CONNTRACK_MAX,
+- .procname = NET_IP_CONNTRACK_MAX_NAME,
+- .data = &ip_conntrack_max,
+- .maxlen = sizeof(ip_conntrack_max),
+- .mode = 0644,
+- .proc_handler = proc_dointvec
+- },
+- { .ctl_name = 0 }
+-};
+-
+-static ctl_table ip_conntrack_dir_table[] = {
+- {
+- .ctl_name = NET_IPV4,
+- .procname = "ipv4",
+- .mode = 0555,
+- .child = ip_conntrack_table
+- },
+- { .ctl_name = 0 }
+-};
+-
+-static ctl_table ip_conntrack_root_table[] = {
+- {
+- .ctl_name = CTL_NET,
+- .procname = "net",
+- .mode = 0555,
+- .child = ip_conntrack_dir_table
+- },
+- { .ctl_name = 0 }
+-};
+-#endif /*CONFIG_SYSCTL*/
+-
+ static int kill_all(const struct ip_conntrack *i, void *data)
+ {
+ return 1;
+@@ -1373,9 +1340,6 @@ static int kill_all(const struct ip_conn
+ supposed to kill the mall. */
+ void ip_conntrack_cleanup(void)
+ {
+-#ifdef CONFIG_SYSCTL
+- unregister_sysctl_table(ip_conntrack_sysctl_header);
+-#endif
+ ip_ct_attach = NULL;
+ /* This makes sure all current packets have passed through
+ netfilter framework. Roll on, two-stage module
+@@ -1453,25 +1417,10 @@ int __init ip_conntrack_init(void)
+ for (i = 0; i < ip_conntrack_htable_size; i++)
+ INIT_LIST_HEAD(&ip_conntrack_hash[i]);
+
+-/* This is fucking braindead. There is NO WAY of doing this without
+- the CONFIG_SYSCTL unless you don't want to detect errors.
+- Grrr... --RR */
+-#ifdef CONFIG_SYSCTL
+- ip_conntrack_sysctl_header
+- = register_sysctl_table(ip_conntrack_root_table, 0);
+- if (ip_conntrack_sysctl_header == NULL) {
+- goto err_free_ct_cachep;
+- }
+-#endif /*CONFIG_SYSCTL*/
+-
+ /* For use by ipt_REJECT */
+ ip_ct_attach = ip_conntrack_attach;
+ return ret;
+
+-#ifdef CONFIG_SYSCTL
+-err_free_ct_cachep:
+- kmem_cache_destroy(ip_conntrack_cachep);
+-#endif /*CONFIG_SYSCTL*/
+ err_free_hash:
+ vfree(ip_conntrack_hash);
+ err_unreg_sockopt:
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_irc.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_irc.c 2003-10-05 00:33:25.000000000 -0700
+@@ -177,7 +177,10 @@ static int help(struct sk_buff *skb,
+ DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
+ HIPQUAD(dcc_ip), dcc_port);
+
+- if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)) {
++ /* dcc_ip can be the internal OR external (NAT'ed) IP
++ * Tiago Sousa <mirage@kaotik.org> */
++ if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)
++ && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != htonl(dcc_ip)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING
+ "Forged DCC command from "
+@@ -201,7 +204,7 @@ static int help(struct sk_buff *skb,
+
+ exp->tuple = ((struct ip_conntrack_tuple)
+ { { 0, { 0 } },
+- { htonl(dcc_ip), { .tcp = { htons(dcc_port) } },
++ { ct->tuplehash[dir].tuple.src.ip, { .tcp = { htons(dcc_port) } },
+ IPPROTO_TCP }});
+ exp->mask = ((struct ip_conntrack_tuple)
+ { { 0, { 0 } },
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2003-06-14 12:18:07.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2003-10-05 00:33:25.000000000 -0700
+@@ -4,7 +4,7 @@
+ #include <linux/netfilter.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+
+-#define GENERIC_TIMEOUT (600*HZ)
++unsigned long ip_ct_generic_timeout = 600*HZ;
+
+ static int generic_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+@@ -44,7 +44,7 @@ static int packet(struct ip_conntrack *c
+ const struct sk_buff *skb,
+ enum ip_conntrack_info conntrackinfo)
+ {
+- ip_ct_refresh(conntrack, GENERIC_TIMEOUT);
++ ip_ct_refresh(conntrack, ip_ct_generic_timeout);
+ return NF_ACCEPT;
+ }
+
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2003-06-14 12:17:56.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -6,7 +6,7 @@
+ #include <linux/icmp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+
+-#define ICMP_TIMEOUT (30*HZ)
++unsigned long ip_ct_icmp_timeout = 30*HZ;
+
+ #if 0
+ #define DEBUGP printk
+@@ -86,7 +86,7 @@ static int icmp_packet(struct ip_conntra
+ ct->timeout.function((unsigned long)ct);
+ } else {
+ atomic_inc(&ct->proto.icmp.count);
+- ip_ct_refresh(ct, ICMP_TIMEOUT);
++ ip_ct_refresh(ct, ip_ct_icmp_timeout);
+ }
+
+ return NF_ACCEPT;
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -49,20 +49,28 @@ static const char *tcp_conntrack_names[]
+ #define HOURS * 60 MINS
+ #define DAYS * 24 HOURS
+
+-
+-static unsigned long tcp_timeouts[]
+-= { 30 MINS, /* TCP_CONNTRACK_NONE, */
+- 5 DAYS, /* TCP_CONNTRACK_ESTABLISHED, */
+- 2 MINS, /* TCP_CONNTRACK_SYN_SENT, */
+- 60 SECS, /* TCP_CONNTRACK_SYN_RECV, */
+- 2 MINS, /* TCP_CONNTRACK_FIN_WAIT, */
+- 2 MINS, /* TCP_CONNTRACK_TIME_WAIT, */
+- 10 SECS, /* TCP_CONNTRACK_CLOSE, */
+- 60 SECS, /* TCP_CONNTRACK_CLOSE_WAIT, */
+- 30 SECS, /* TCP_CONNTRACK_LAST_ACK, */
+- 2 MINS, /* TCP_CONNTRACK_LISTEN, */
+-};
+-
++unsigned long ip_ct_tcp_timeout_syn_sent = 2 MINS;
++unsigned long ip_ct_tcp_timeout_syn_recv = 60 SECS;
++unsigned long ip_ct_tcp_timeout_established = 5 DAYS;
++unsigned long ip_ct_tcp_timeout_fin_wait = 2 MINS;
++unsigned long ip_ct_tcp_timeout_close_wait = 3 DAYS;
++unsigned long ip_ct_tcp_timeout_last_ack = 30 SECS;
++unsigned long ip_ct_tcp_timeout_time_wait = 2 MINS;
++unsigned long ip_ct_tcp_timeout_close = 10 SECS;
++
++static unsigned long * tcp_timeouts[]
++= { 0, /* TCP_CONNTRACK_NONE */
++ &ip_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */
++ &ip_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
++ &ip_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
++ &ip_ct_tcp_timeout_fin_wait, /* TCP_CONNTRACK_FIN_WAIT, */
++ &ip_ct_tcp_timeout_time_wait, /* TCP_CONNTRACK_TIME_WAIT, */
++ &ip_ct_tcp_timeout_close, /* TCP_CONNTRACK_CLOSE, */
++ &ip_ct_tcp_timeout_close_wait, /* TCP_CONNTRACK_CLOSE_WAIT, */
++ &ip_ct_tcp_timeout_last_ack, /* TCP_CONNTRACK_LAST_ACK, */
++ 0, /* TCP_CONNTRACK_LISTEN */
++ };
++
+ #define sNO TCP_CONNTRACK_NONE
+ #define sES TCP_CONNTRACK_ESTABLISHED
+ #define sSS TCP_CONNTRACK_SYN_SENT
+@@ -204,7 +212,7 @@ static int tcp_packet(struct ip_conntrac
+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
+
+ WRITE_UNLOCK(&tcp_lock);
+- ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);
++ ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
+ }
+
+ return NF_ACCEPT;
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-06-14 12:17:55.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -6,8 +6,8 @@
+ #include <linux/udp.h>
+ #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
+
+-#define UDP_TIMEOUT (30*HZ)
+-#define UDP_STREAM_TIMEOUT (180*HZ)
++unsigned long ip_ct_udp_timeout = 30*HZ;
++unsigned long ip_ct_udp_timeout_stream = 180*HZ;
+
+ static int udp_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+@@ -57,11 +57,11 @@ static int udp_packet(struct ip_conntrac
+ /* If we've seen traffic both ways, this is some kind of UDP
+ stream. Extend timeout. */
+ if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+- ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT);
++ ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
+ /* Also, more likely to be important, and not a probe */
+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
+ } else
+- ip_ct_refresh(conntrack, UDP_TIMEOUT);
++ ip_ct_refresh(conntrack, ip_ct_udp_timeout);
+
+ return NF_ACCEPT;
+ }
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-10-05 00:33:25.000000000 -0700
+@@ -7,6 +7,7 @@
+ /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
+ Public Licence. */
+
++#include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/ip.h>
+ #include <linux/netfilter.h>
+@@ -14,6 +15,9 @@
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/proc_fs.h>
++#ifdef CONFIG_SYSCTL
++#include <linux/sysctl.h>
++#endif
+ #include <net/checksum.h>
+
+ #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
+@@ -256,6 +260,98 @@ static struct nf_hook_ops ip_conntrack_l
+ .priority = NF_IP_PRI_LAST-1,
+ };
+
++/* Sysctl support */
++
++#ifdef CONFIG_SYSCTL
++
++/* From ip_conntrack_core.c */
++extern int ip_conntrack_max;
++
++/* From ip_conntrack_proto_tcp.c */
++extern unsigned long ip_ct_tcp_timeout_syn_sent;
++extern unsigned long ip_ct_tcp_timeout_syn_recv;
++extern unsigned long ip_ct_tcp_timeout_established;
++extern unsigned long ip_ct_tcp_timeout_fin_wait;
++extern unsigned long ip_ct_tcp_timeout_close_wait;
++extern unsigned long ip_ct_tcp_timeout_last_ack;
++extern unsigned long ip_ct_tcp_timeout_time_wait;
++extern unsigned long ip_ct_tcp_timeout_close;
++
++/* From ip_conntrack_proto_udp.c */
++extern unsigned long ip_ct_udp_timeout;
++extern unsigned long ip_ct_udp_timeout_stream;
++
++/* From ip_conntrack_proto_icmp.c */
++extern unsigned long ip_ct_icmp_timeout;
++
++/* From ip_conntrack_proto_icmp.c */
++extern unsigned long ip_ct_generic_timeout;
++
++static struct ctl_table_header *ip_ct_sysctl_header;
++
++static ctl_table ip_ct_sysctl_table[] = {
++ {NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
++ &ip_conntrack_max, sizeof(int), 0644, NULL,
++ &proc_dointvec},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
++ &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
++ &ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
++ &ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
++ &ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
++ &ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
++ &ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
++ &ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
++ &ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
++ &ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
++ &ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
++ &ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
++ &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
++ &proc_dointvec_jiffies},
++ {0}
++};
++
++#define NET_IP_CONNTRACK_MAX 2089
++
++static ctl_table ip_ct_netfilter_table[] = {
++ {NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
++ {NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
++ &ip_conntrack_max, sizeof(int), 0644, NULL,
++ &proc_dointvec},
++ {0}
++};
++
++static ctl_table ip_ct_ipv4_table[] = {
++ {NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
++ {0}
++};
++
++static ctl_table ip_ct_net_table[] = {
++ {CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
++ {0}
++};
++#endif
+ static int init_or_cleanup(int init)
+ {
+ struct proc_dir_entry *proc;
+@@ -291,10 +387,20 @@ static int init_or_cleanup(int init)
+ printk("ip_conntrack: can't register local in hook.\n");
+ goto cleanup_inoutandlocalops;
+ }
++#ifdef CONFIG_SYSCTL
++ ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
++ if (ip_ct_sysctl_header == NULL) {
++ printk("ip_conntrack: can't register to sysctl.\n");
++ goto cleanup;
++ }
++#endif
+
+ return ret;
+
+ cleanup:
++#ifdef CONFIG_SYSCTL
++ unregister_sysctl_table(ip_ct_sysctl_header);
++#endif
+ nf_unregister_hook(&ip_conntrack_local_in_ops);
+ cleanup_inoutandlocalops:
+ nf_unregister_hook(&ip_conntrack_out_ops);
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_nat_core.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_nat_core.c 2003-10-05 00:33:25.000000000 -0700
+@@ -516,12 +516,14 @@ ip_nat_setup_info(struct ip_conntrack *c
+ struct ip_conntrack_tuple new_tuple, inv_tuple, reply;
+ struct ip_conntrack_tuple orig_tp;
+ struct ip_nat_info *info = &conntrack->nat.info;
++ int in_hashes = info->initialized;
+
+ MUST_BE_WRITE_LOCKED(&ip_nat_lock);
+ IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
+ || hooknum == NF_IP_POST_ROUTING
+ || hooknum == NF_IP_LOCAL_OUT);
+ IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
++ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
+
+ /* What we've got will look like inverse of reply. Normally
+ this is what is in the conntrack, except for prior
+@@ -638,6 +640,14 @@ ip_nat_setup_info(struct ip_conntrack *c
+
+ /* It's done. */
+ info->initialized |= (1 << HOOK2MANIP(hooknum));
++
++ if (in_hashes) {
++ IP_NF_ASSERT(info->bysource.conntrack);
++ replace_in_hashes(conntrack, info);
++ } else {
++ place_in_hashes(conntrack, info);
++ }
++
+ return NF_ACCEPT;
+ }
+
+@@ -761,11 +771,6 @@ do_bindings(struct ip_conntrack *ct,
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+ int proto = (*pskb)->nh.iph->protocol;
+
+- /* Skip everything and don't call helpers if there are no
+- * manips for this connection */
+- if (info->num_manips == 0)
+- return NF_ACCEPT;
+-
+ /* Need nat lock to protect against modification, but neither
+ conntrack (referenced) and helper (deleted with
+ synchronize_bh()) can vanish. */
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_nat_helper.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_nat_helper.c 2003-10-05 00:33:25.000000000 -0700
+@@ -122,7 +122,6 @@ static void mangle_contents(struct sk_bu
+ /* fix IP hdr checksum information */
+ skb->nh.iph->tot_len = htons(skb->len);
+ ip_send_check(skb->nh.iph);
+- skb->csum = csum_partial(data, skb->len - dataoff, 0);
+ }
+
+ /* Unusual, but possible case. */
+@@ -167,6 +166,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff
+ {
+ struct iphdr *iph;
+ struct tcphdr *tcph;
++ int datalen;
+
+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ return 0;
+@@ -184,11 +184,11 @@ ip_nat_mangle_tcp_packet(struct sk_buff
+ mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
+ match_offset, match_len, rep_buffer, rep_len);
+
++ datalen = (*pskb)->len - iph->ihl*4;
+ tcph->check = 0;
+- tcph->check = tcp_v4_check(tcph, (*pskb)->len - iph->ihl*4,
+- iph->saddr, iph->daddr,
+- csum_partial((char *)tcph, tcph->doff*4,
+- (*pskb)->csum));
++ tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr,
++ csum_partial((char *)tcph, datalen, 0));
++
+ adjust_tcp_sequence(ntohl(tcph->seq),
+ (int)rep_len - (int)match_len,
+ ct, ctinfo);
+@@ -216,7 +216,12 @@ ip_nat_mangle_udp_packet(struct sk_buff
+ {
+ struct iphdr *iph;
+ struct udphdr *udph;
+- int need_csum = ((*pskb)->csum != 0);
++
++ /* UDP helpers might accidentally mangle the wrong packet */
++ iph = (*pskb)->nh.iph;
++ if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
++ match_offset + match_len)
++ return 0;
+
+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
+ return 0;
+@@ -235,17 +240,15 @@ ip_nat_mangle_udp_packet(struct sk_buff
+ udph->len = htons((*pskb)->len - iph->ihl*4);
+
+ /* fix udp checksum if udp checksum was previously calculated */
+- if (need_csum) {
++ if (udph->check) {
++ int datalen = (*pskb)->len - iph->ihl * 4;
+ udph->check = 0;
+- udph->check
+- = csum_tcpudp_magic(iph->saddr, iph->daddr,
+- (*pskb)->len - iph->ihl*4,
+- IPPROTO_UDP,
+- csum_partial((char *)udph,
+- sizeof(struct udphdr),
+- (*pskb)->csum));
+- } else
+- (*pskb)->csum = 0;
++ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
++ datalen, IPPROTO_UDP,
++ csum_partial((char *)udph,
++ datalen, 0));
++ }
++
+ return 1;
+ }
+
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_nat_rule.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_nat_rule.c 2003-10-05 00:33:25.000000000 -0700
+@@ -233,7 +233,7 @@ static int ipt_dnat_checkentry(const cha
+ return 1;
+ }
+
+-static inline unsigned int
++inline unsigned int
+ alloc_null_binding(struct ip_conntrack *conntrack,
+ struct ip_nat_info *info,
+ unsigned int hooknum)
+--- linux-2.6.0-test6/net/ipv4/netfilter/ip_nat_standalone.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ip_nat_standalone.c 2003-10-05 00:33:25.000000000 -0700
+@@ -119,7 +119,6 @@ ip_nat_fn(unsigned int hooknum,
+ /* Seen it before? This can happen for loopback, retrans,
+ or local packets.. */
+ if (!(info->initialized & (1 << maniptype))) {
+- int in_hashes = info->initialized;
+ unsigned int ret;
+
+ if (ct->master
+@@ -130,9 +129,10 @@ ip_nat_fn(unsigned int hooknum,
+ } else {
+ #ifdef CONFIG_IP_NF_NAT_LOCAL
+ /* LOCAL_IN hook doesn't have a chain! */
+- if (hooknum == NF_IP_LOCAL_IN) {
+- ret = NF_ACCEPT;
+- } else
++ if (hooknum == NF_IP_LOCAL_IN)
++ ret = alloc_null_binding(ct, info,
++ hooknum);
++ else
+ #endif
+ ret = ip_nat_rule_find(pskb, hooknum, in, out,
+ ct, info);
+@@ -142,13 +142,6 @@ ip_nat_fn(unsigned int hooknum,
+ WRITE_UNLOCK(&ip_nat_lock);
+ return ret;
+ }
+-
+- if (in_hashes) {
+- IP_NF_ASSERT(info->bysource.conntrack);
+- replace_in_hashes(ct, info);
+- } else {
+- place_in_hashes(ct, info);
+- }
+ } else
+ DEBUGP("Already setup manip %s for ct %p\n",
+ maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+@@ -199,6 +192,7 @@ ip_nat_out(unsigned int hooknum,
+ return ip_nat_fn(hooknum, pskb, in, out, okfn);
+ }
+
++#ifdef CONFIG_IP_NF_NAT_LOCAL
+ static unsigned int
+ ip_nat_local_fn(unsigned int hooknum,
+ struct sk_buff **pskb,
+@@ -224,6 +218,7 @@ ip_nat_local_fn(unsigned int hooknum,
+ return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+ return ret;
+ }
++#endif
+
+ /* We must be after connection tracking and before packet filtering. */
+
+@@ -245,6 +240,7 @@ static struct nf_hook_ops ip_nat_out_ops
+ .priority = NF_IP_PRI_NAT_SRC,
+ };
+
++#ifdef CONFIG_IP_NF_NAT_LOCAL
+ /* Before packet filtering, change destination */
+ static struct nf_hook_ops ip_nat_local_out_ops = {
+ .hook = ip_nat_local_fn,
+@@ -254,7 +250,7 @@ static struct nf_hook_ops ip_nat_local_o
+ .priority = NF_IP_PRI_NAT_DST,
+ };
+
+-#ifdef CONFIG_IP_NF_NAT_LOCAL
++/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
+ static struct nf_hook_ops ip_nat_local_in_ops = {
+ .hook = ip_nat_fn,
+ .owner = THIS_MODULE,
+@@ -324,12 +320,12 @@ static int init_or_cleanup(int init)
+ printk("ip_nat_init: can't register out hook.\n");
+ goto cleanup_inops;
+ }
++#ifdef CONFIG_IP_NF_NAT_LOCAL
+ ret = nf_register_hook(&ip_nat_local_out_ops);
+ if (ret < 0) {
+ printk("ip_nat_init: can't register local out hook.\n");
+ goto cleanup_outops;
+ }
+-#ifdef CONFIG_IP_NF_NAT_LOCAL
+ ret = nf_register_hook(&ip_nat_local_in_ops);
+ if (ret < 0) {
+ printk("ip_nat_init: can't register local in hook.\n");
+@@ -342,9 +338,9 @@ static int init_or_cleanup(int init)
+ #ifdef CONFIG_IP_NF_NAT_LOCAL
+ nf_unregister_hook(&ip_nat_local_in_ops);
+ cleanup_localoutops:
+-#endif
+ nf_unregister_hook(&ip_nat_local_out_ops);
+ cleanup_outops:
++#endif
+ nf_unregister_hook(&ip_nat_out_ops);
+ cleanup_inops:
+ nf_unregister_hook(&ip_nat_in_ops);
+--- linux-2.6.0-test6/net/ipv4/netfilter/ipt_owner.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/ipv4/netfilter/ipt_owner.c 2003-10-05 00:36:15.000000000 -0700
+@@ -90,7 +90,7 @@ match_sid(const struct sk_buff *skb, pid
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ struct files_struct *files;
+- if (p->session != sid)
++ if (process_session(p) != sid)
+ continue;
+
+ task_lock(p);
+--- linux-2.6.0-test6/net/ipv4/netfilter/ipt_REJECT.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/netfilter/ipt_REJECT.c 2003-10-05 00:33:25.000000000 -0700
+@@ -40,16 +40,17 @@ static void connection_attach(struct sk_
+ }
+ }
+
+-static inline struct rtable *route_reverse(struct sk_buff *skb, int local)
++static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
+ {
+ struct iphdr *iph = skb->nh.iph;
+ struct dst_entry *odst;
+ struct flowi fl = {};
+ struct rtable *rt;
+
+- if (local) {
++ if (hook != NF_IP_FORWARD) {
+ fl.nl_u.ip4_u.daddr = iph->saddr;
+- fl.nl_u.ip4_u.saddr = iph->daddr;
++ if (hook == NF_IP_LOCAL_IN)
++ fl.nl_u.ip4_u.saddr = iph->daddr;
+ fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+
+ if (ip_route_output_key(&rt, &fl) != 0)
+@@ -81,7 +82,7 @@ static inline struct rtable *route_rever
+ }
+
+ /* Send RST reply */
+-static void send_reset(struct sk_buff *oldskb, int local)
++static void send_reset(struct sk_buff *oldskb, int hook)
+ {
+ struct sk_buff *nskb;
+ struct tcphdr otcph, *tcph;
+@@ -104,7 +105,7 @@ static void send_reset(struct sk_buff *o
+ return;
+
+ /* FIXME: Check checksum --RR */
+- if ((rt = route_reverse(oldskb, local)) == NULL)
++ if ((rt = route_reverse(oldskb, hook)) == NULL)
+ return;
+
+ hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+@@ -390,7 +391,7 @@ static unsigned int reject(struct sk_buf
+ send_unreach(*pskb, ICMP_PKT_FILTERED);
+ break;
+ case IPT_TCP_RESET:
+- send_reset(*pskb, hooknum == NF_IP_LOCAL_IN);
++ send_reset(*pskb, hooknum);
+ case IPT_ICMP_ECHOREPLY:
+ /* Doesn't happen. */
+ break;
+--- linux-2.6.0-test6/net/ipv4/protocol.c 2003-06-14 12:17:58.000000000 -0700
++++ 25/net/ipv4/protocol.c 2003-10-05 00:33:25.000000000 -0700
+@@ -27,6 +27,7 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -95,3 +96,6 @@ int inet_del_protocol(struct inet_protoc
+
+ return ret;
+ }
++
++EXPORT_SYMBOL(inet_add_protocol);
++EXPORT_SYMBOL(inet_del_protocol);
+--- linux-2.6.0-test6/net/ipv4/route.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/route.c 2003-10-05 00:33:25.000000000 -0700
+@@ -62,6 +62,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
+@@ -2823,3 +2824,7 @@ out_enomem1:
+ rc = -ENOMEM;
+ goto out;
+ }
++
++EXPORT_SYMBOL(__ip_select_ident);
++EXPORT_SYMBOL(ip_route_input);
++EXPORT_SYMBOL(ip_route_output_key);
+--- linux-2.6.0-test6/net/ipv4/sysctl_net_ipv4.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/ipv4/sysctl_net_ipv4.c 2003-10-05 00:33:25.000000000 -0700
+@@ -8,6 +8,7 @@
+ */
+
+ #include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/sysctl.h>
+ #include <linux/config.h>
+ #include <net/snmp.h>
+@@ -587,3 +588,5 @@ ctl_table ipv4_table[] = {
+ };
+
+ #endif /* CONFIG_SYSCTL */
++
++EXPORT_SYMBOL(ipv4_config);
+--- linux-2.6.0-test6/net/ipv4/tcp.c 2003-06-22 12:04:45.000000000 -0700
++++ 25/net/ipv4/tcp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -248,6 +248,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/fcntl.h>
+ #include <linux/poll.h>
+@@ -2682,3 +2683,26 @@ void __init tcp_init(void)
+
+ tcpdiag_init();
+ }
++
++EXPORT_SYMBOL(__tcp_mem_reclaim);
++EXPORT_SYMBOL(sysctl_tcp_rmem);
++EXPORT_SYMBOL(sysctl_tcp_wmem);
++EXPORT_SYMBOL(tcp_accept);
++EXPORT_SYMBOL(tcp_close);
++EXPORT_SYMBOL(tcp_close_state);
++EXPORT_SYMBOL(tcp_destroy_sock);
++EXPORT_SYMBOL(tcp_disconnect);
++EXPORT_SYMBOL(tcp_getsockopt);
++EXPORT_SYMBOL(tcp_ioctl);
++EXPORT_SYMBOL(tcp_openreq_cachep);
++EXPORT_SYMBOL(tcp_poll);
++EXPORT_SYMBOL(tcp_read_sock);
++EXPORT_SYMBOL(tcp_recvmsg);
++EXPORT_SYMBOL(tcp_sendmsg);
++EXPORT_SYMBOL(tcp_sendpage);
++EXPORT_SYMBOL(tcp_setsockopt);
++EXPORT_SYMBOL(tcp_shutdown);
++EXPORT_SYMBOL(tcp_sockets_allocated);
++EXPORT_SYMBOL(tcp_statistics);
++EXPORT_SYMBOL(tcp_timewait_cachep);
++EXPORT_SYMBOL(tcp_write_space);
+--- linux-2.6.0-test6/net/ipv4/tcp_input.c 2003-07-27 12:14:40.000000000 -0700
++++ 25/net/ipv4/tcp_input.c 2003-10-05 00:33:25.000000000 -0700
+@@ -65,6 +65,7 @@
+
+ #include <linux/config.h>
+ #include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/sysctl.h>
+ #include <net/tcp.h>
+ #include <net/inet_common.h>
+@@ -4089,3 +4090,10 @@ discard:
+ }
+ return 0;
+ }
++
++EXPORT_SYMBOL(sysctl_tcp_ecn);
++EXPORT_SYMBOL(sysctl_tcp_reordering);
++EXPORT_SYMBOL(tcp_cwnd_application_limited);
++EXPORT_SYMBOL(tcp_parse_options);
++EXPORT_SYMBOL(tcp_rcv_established);
++EXPORT_SYMBOL(tcp_rcv_state_process);
+--- linux-2.6.0-test6/net/ipv4/tcp_ipv4.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/tcp_ipv4.c 2003-10-05 00:33:25.000000000 -0700
+@@ -56,6 +56,7 @@
+
+ #include <linux/types.h>
+ #include <linux/fcntl.h>
++#include <linux/module.h>
+ #include <linux/random.h>
+ #include <linux/cache.h>
+ #include <linux/jhash.h>
+@@ -2644,3 +2645,32 @@ void __init tcp_v4_init(struct net_proto
+ */
+ tcp_socket->sk->sk_prot->unhash(tcp_socket->sk);
+ }
++
++EXPORT_SYMBOL(ipv4_specific);
++EXPORT_SYMBOL(tcp_bind_hash);
++EXPORT_SYMBOL(tcp_bucket_create);
++EXPORT_SYMBOL(tcp_hashinfo);
++EXPORT_SYMBOL(tcp_inherit_port);
++EXPORT_SYMBOL(tcp_listen_wlock);
++EXPORT_SYMBOL(tcp_port_rover);
++EXPORT_SYMBOL(tcp_prot);
++EXPORT_SYMBOL(tcp_put_port);
++EXPORT_SYMBOL(tcp_unhash);
++EXPORT_SYMBOL(tcp_v4_conn_request);
++EXPORT_SYMBOL(tcp_v4_connect);
++EXPORT_SYMBOL(tcp_v4_do_rcv);
++EXPORT_SYMBOL(tcp_v4_lookup_listener);
++EXPORT_SYMBOL(tcp_v4_rebuild_header);
++EXPORT_SYMBOL(tcp_v4_remember_stamp);
++EXPORT_SYMBOL(tcp_v4_send_check);
++EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
++
++#ifdef CONFIG_PROC_FS
++EXPORT_SYMBOL(tcp_proc_register);
++EXPORT_SYMBOL(tcp_proc_unregister);
++#endif
++#ifdef CONFIG_SYSCTL
++EXPORT_SYMBOL(sysctl_local_port_range);
++EXPORT_SYMBOL(sysctl_max_syn_backlog);
++EXPORT_SYMBOL(sysctl_tcp_low_latency);
++#endif
+--- linux-2.6.0-test6/net/ipv4/tcp_minisocks.c 2003-07-02 14:53:18.000000000 -0700
++++ 25/net/ipv4/tcp_minisocks.c 2003-10-05 00:33:25.000000000 -0700
+@@ -22,6 +22,7 @@
+
+ #include <linux/config.h>
+ #include <linux/mm.h>
++#include <linux/module.h>
+ #include <linux/sysctl.h>
+ #include <linux/workqueue.h>
+ #include <net/tcp.h>
+@@ -1053,3 +1054,13 @@ int tcp_child_process(struct sock *paren
+ sock_put(child);
+ return ret;
+ }
++
++EXPORT_SYMBOL(tcp_check_req);
++EXPORT_SYMBOL(tcp_child_process);
++EXPORT_SYMBOL(tcp_create_openreq_child);
++EXPORT_SYMBOL(tcp_timewait_state_process);
++EXPORT_SYMBOL(tcp_tw_deschedule);
++
++#ifdef CONFIG_SYSCTL
++EXPORT_SYMBOL(sysctl_tcp_tw_recycle);
++#endif
+--- linux-2.6.0-test6/net/ipv4/tcp_output.c 2003-07-02 14:53:18.000000000 -0700
++++ 25/net/ipv4/tcp_output.c 2003-10-05 00:33:25.000000000 -0700
+@@ -39,6 +39,7 @@
+ #include <net/tcp.h>
+
+ #include <linux/compiler.h>
++#include <linux/module.h>
+ #include <linux/smp_lock.h>
+
+ /* People can turn this off for buggy TCP's found in printers etc. */
+@@ -1542,3 +1543,14 @@ void tcp_send_probe0(struct sock *sk)
+ min(tp->rto << tp->backoff, TCP_RESOURCE_PROBE_INTERVAL));
+ }
+ }
++
++EXPORT_SYMBOL(tcp_acceptable_seq);
++EXPORT_SYMBOL(tcp_connect);
++EXPORT_SYMBOL(tcp_connect_init);
++EXPORT_SYMBOL(tcp_make_synack);
++EXPORT_SYMBOL(tcp_send_synack);
++EXPORT_SYMBOL(tcp_simple_retransmit);
++EXPORT_SYMBOL(tcp_sync_mss);
++EXPORT_SYMBOL(tcp_transmit_skb);
++EXPORT_SYMBOL(tcp_write_wakeup);
++EXPORT_SYMBOL(tcp_write_xmit);
+--- linux-2.6.0-test6/net/ipv4/tcp_timer.c 2003-06-16 22:32:21.000000000 -0700
++++ 25/net/ipv4/tcp_timer.c 2003-10-05 00:33:25.000000000 -0700
+@@ -20,6 +20,7 @@
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
++#include <linux/module.h>
+ #include <net/tcp.h>
+
+ int sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
+@@ -656,3 +657,8 @@ out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+ }
++
++EXPORT_SYMBOL(tcp_clear_xmit_timers);
++EXPORT_SYMBOL(tcp_delete_keepalive_timer);
++EXPORT_SYMBOL(tcp_init_xmit_timers);
++EXPORT_SYMBOL(tcp_reset_keepalive_timer);
+--- linux-2.6.0-test6/net/ipv4/udp.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/ipv4/udp.c 2003-10-05 00:33:25.000000000 -0700
+@@ -83,6 +83,7 @@
+ #include <asm/ioctls.h>
+ #include <linux/types.h>
+ #include <linux/fcntl.h>
++#include <linux/module.h>
+ #include <linux/socket.h>
+ #include <linux/sockios.h>
+ #include <linux/in.h>
+@@ -1532,3 +1533,17 @@ void udp4_proc_exit(void)
+ udp_proc_unregister(&udp4_seq_afinfo);
+ }
+ #endif /* CONFIG_PROC_FS */
++
++EXPORT_SYMBOL(udp_connect);
++EXPORT_SYMBOL(udp_disconnect);
++EXPORT_SYMBOL(udp_hash);
++EXPORT_SYMBOL(udp_hash_lock);
++EXPORT_SYMBOL(udp_ioctl);
++EXPORT_SYMBOL(udp_port_rover);
++EXPORT_SYMBOL(udp_prot);
++EXPORT_SYMBOL(udp_sendmsg);
++
++#ifdef CONFIG_PROC_FS
++EXPORT_SYMBOL(udp_proc_register);
++EXPORT_SYMBOL(udp_proc_unregister);
++#endif
+--- linux-2.6.0-test6/net/ipv4/utils.c 2003-07-02 14:53:18.000000000 -0700
++++ 25/net/ipv4/utils.c 2003-10-05 00:33:25.000000000 -0700
+@@ -21,6 +21,7 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <asm/byteorder.h>
+
+@@ -55,3 +56,4 @@ __u32 in_aton(const char *str)
+ return(htonl(l));
+ }
+
++EXPORT_SYMBOL(in_aton);
+--- linux-2.6.0-test6/net/ipv4/xfrm4_tunnel.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/ipv4/xfrm4_tunnel.c 2003-10-05 00:33:25.000000000 -0700
+@@ -169,6 +169,7 @@ static struct xfrm_type ipip_type = {
+ static struct inet_protocol ipip_protocol = {
+ .handler = ipip_rcv,
+ .err_handler = ipip_err,
++ .no_policy = 1,
+ };
+
+ static int __init ipip_init(void)
+--- linux-2.6.0-test6/net/ipv6/netfilter/ip6t_ipv6header.c 2003-06-14 12:18:51.000000000 -0700
++++ 25/net/ipv6/netfilter/ip6t_ipv6header.c 2003-10-05 00:33:25.000000000 -0700
+@@ -126,18 +126,11 @@ ipv6header_checkentry(const char *tablen
+ return 1;
+ }
+
+-static void
+-ipv6header_destroy(void *matchinfo,
+- unsigned int matchinfosize)
+-{
+- return;
+-}
+-
+ static struct ip6t_match ip6t_ipv6header_match = {
+ .name = "ipv6header",
+ .match = &ipv6header_match,
+ .checkentry = &ipv6header_checkentry,
+- .destroy = &ipv6header_destroy,
++ .destroy = NULL,
+ .me = THIS_MODULE,
+ };
+
+--- linux-2.6.0-test6/net/ipv6/netfilter/ip6t_owner.c 2003-06-14 12:18:30.000000000 -0700
++++ 25/net/ipv6/netfilter/ip6t_owner.c 2003-10-05 00:36:15.000000000 -0700
+@@ -56,7 +56,7 @@ match_sid(const struct sk_buff *skb, pid
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ struct files_struct *files;
+- if (p->session != sid)
++ if (process_session(p) != sid)
+ continue;
+
+ task_lock(p);
+--- linux-2.6.0-test6/net/irda/irda_device.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/irda/irda_device.c 2003-10-05 00:33:25.000000000 -0700
+@@ -85,7 +85,7 @@ static void irda_task_timer_expired(void
+
+ int __init irda_device_init( void)
+ {
+- dongles = hashbin_new(HB_LOCK);
++ dongles = hashbin_new(HB_NOLOCK);
+ if (dongles == NULL) {
+ printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
+ return -ENOMEM;
+@@ -109,7 +109,9 @@ void __exit irda_device_cleanup(void)
+ IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
+
+ hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
++ spin_lock(&dongles->hb_spinlock);
+ hashbin_delete(dongles, NULL);
++ spin_unlock(&dongles->hb_spinlock);
+ }
+
+ /*
+@@ -378,8 +380,6 @@ void irda_device_setup(struct net_device
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+
+- dev->destructor = free_netdev;
+-
+ dev->type = ARPHRD_IRDA;
+ dev->tx_queue_len = 8; /* Window size + 1 s-frame */
+
+@@ -390,6 +390,17 @@ void irda_device_setup(struct net_device
+ }
+
+ /*
++ * Funciton alloc_irdadev
++ * Allocates and sets up an IRDA device in a manner similar to
++ * alloc_etherdev.
++ */
++struct net_device *alloc_irdadev(int sizeof_priv)
++{
++ return alloc_netdev(sizeof_priv, "irda%d", irda_device_setup);
++}
++
++
++/*
+ * Function irda_device_txqueue_empty (dev)
+ *
+ * Check if there is still some frames in the transmit queue for this
+@@ -415,25 +426,34 @@ int irda_device_txqueue_empty(struct net
+ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
+ {
+ struct dongle_reg *reg;
+- dongle_t *dongle;
++ dongle_t *dongle = NULL;
++
++ might_sleep();
+
+- ASSERT(dev != NULL, return NULL;);
++ spin_lock(&dongles->hb_spinlock);
++ reg = hashbin_find(dongles, type, NULL);
+
+ #ifdef CONFIG_KMOD
+- ASSERT(!in_interrupt(), return NULL;);
+ /* Try to load the module needed */
+- request_module("irda-dongle-%d", type);
++ if (!reg && capable(CAP_SYS_MODULE)) {
++ spin_unlock(&dongles->hb_spinlock);
++
++ request_module("irda-dongle-%d", type);
++
++ spin_lock(&dongles->hb_spinlock);
++ reg = hashbin_find(dongles, type, NULL);
++ }
+ #endif
+
+- if (!(reg = hashbin_lock_find(dongles, type, NULL))) {
+- ERROR("IrDA: Unable to find requested dongle\n");
+- return NULL;
++ if (!reg || !try_module_get(reg->owner) ) {
++ ERROR("IrDA: Unable to find requested dongle type %x\n", type);
++ goto out;
+ }
+
+ /* Allocate dongle info for this instance */
+ dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
+ if (!dongle)
+- return NULL;
++ goto out;
+
+ memset(dongle, 0, sizeof(dongle_t));
+
+@@ -441,6 +461,8 @@ dongle_t *irda_device_dongle_init(struct
+ dongle->issue = reg;
+ dongle->dev = dev;
+
++ out:
++ spin_unlock(&dongles->hb_spinlock);
+ return dongle;
+ }
+
+@@ -452,7 +474,7 @@ int irda_device_dongle_cleanup(dongle_t
+ ASSERT(dongle != NULL, return -1;);
+
+ dongle->issue->close(dongle);
+-
++ module_put(dongle->issue->owner);
+ kfree(dongle);
+
+ return 0;
+@@ -463,14 +485,16 @@ int irda_device_dongle_cleanup(dongle_t
+ */
+ int irda_device_register_dongle(struct dongle_reg *new)
+ {
++ spin_lock(&dongles->hb_spinlock);
+ /* Check if this dongle has been registered before */
+- if (hashbin_lock_find(dongles, new->type, NULL)) {
+- MESSAGE("%s: Dongle already registered\n", __FUNCTION__);
+- return 0;
+- }
+-
+- /* Insert IrDA dongle into hashbin */
+- hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
++ if (hashbin_find(dongles, new->type, NULL)) {
++ MESSAGE("%s: Dongle type %x already registered\n",
++ __FUNCTION__, new->type);
++ } else {
++ /* Insert IrDA dongle into hashbin */
++ hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
++ }
++ spin_unlock(&dongles->hb_spinlock);
+
+ return 0;
+ }
+@@ -485,11 +509,11 @@ void irda_device_unregister_dongle(struc
+ {
+ struct dongle *node;
+
++ spin_lock(&dongles->hb_spinlock);
+ node = hashbin_remove(dongles, dongle->type, NULL);
+- if (!node) {
++ if (!node)
+ ERROR("%s: dongle not found!\n", __FUNCTION__);
+- return;
+- }
++ spin_unlock(&dongles->hb_spinlock);
+ }
+
+ /*
+--- linux-2.6.0-test6/net/irda/irsyms.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/irda/irsyms.c 2003-10-05 00:33:25.000000000 -0700
+@@ -150,6 +150,7 @@ EXPORT_SYMBOL(irlap_close);
+ EXPORT_SYMBOL(irda_init_max_qos_capabilies);
+ EXPORT_SYMBOL(irda_qos_bits_to_value);
+ EXPORT_SYMBOL(irda_device_setup);
++EXPORT_SYMBOL(alloc_irdadev);
+ EXPORT_SYMBOL(irda_device_set_media_busy);
+ EXPORT_SYMBOL(irda_device_txqueue_empty);
+
+--- linux-2.6.0-test6/net/Makefile 2003-06-14 12:18:08.000000000 -0700
++++ 25/net/Makefile 2003-10-05 00:33:25.000000000 -0700
+@@ -40,6 +40,5 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/
+ obj-$(CONFIG_IP_SCTP) += sctp/
+
+ ifeq ($(CONFIG_NET),y)
+-obj-$(CONFIG_MODULES) += netsyms.o
+ obj-$(CONFIG_SYSCTL) += sysctl_net.o
+ endif
+--- linux-2.6.0-test6/net/netlink/af_netlink.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/netlink/af_netlink.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1133,4 +1133,22 @@ core_initcall(netlink_proto_init);
+ module_exit(netlink_proto_exit);
+
+ MODULE_LICENSE("GPL");
++
+ MODULE_ALIAS_NETPROTO(PF_NETLINK);
++
++EXPORT_SYMBOL(netlink_ack);
++EXPORT_SYMBOL(netlink_broadcast);
++EXPORT_SYMBOL(netlink_broadcast_deliver);
++EXPORT_SYMBOL(netlink_dump_start);
++EXPORT_SYMBOL(netlink_kernel_create);
++EXPORT_SYMBOL(netlink_register_notifier);
++EXPORT_SYMBOL(netlink_set_err);
++EXPORT_SYMBOL(netlink_set_nonroot);
++EXPORT_SYMBOL(netlink_unicast);
++EXPORT_SYMBOL(netlink_unregister_notifier);
++
++#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
++EXPORT_SYMBOL(netlink_attach);
++EXPORT_SYMBOL(netlink_detach);
++EXPORT_SYMBOL(netlink_post);
++#endif
+--- linux-2.6.0-test6/net/netsyms.c 2003-09-27 18:57:47.000000000 -0700
++++ /dev/null 2002-08-30 16:31:37.000000000 -0700
+@@ -1,640 +0,0 @@
+-/*
+- * linux/net/netsyms.c
+- *
+- * Symbol table for the linux networking subsystem. Moved here to
+- * make life simpler in ksyms.c.
+- */
+-
+-#include <linux/config.h>
+-#include <linux/module.h>
+-
+-#include <linux/types.h>
+-#include <linux/net.h>
+-#include <linux/in.h>
+-#include <linux/netdevice.h>
+-#include <linux/inetdevice.h>
+-#include <linux/fddidevice.h>
+-#include <linux/trdevice.h>
+-#include <linux/fcdevice.h>
+-#include <linux/ioport.h>
+-#include <linux/tty.h>
+-#include <linux/ethtool.h>
+-#include <net/neighbour.h>
+-#include <net/snmp.h>
+-#include <net/dst.h>
+-#include <net/checksum.h>
+-#include <linux/etherdevice.h>
+-#include <net/route.h>
+-#ifdef CONFIG_HIPPI
+-#include <linux/hippidevice.h>
+-#endif
+-#include <net/pkt_sched.h>
+-#include <net/scm.h>
+-#include <linux/if_bridge.h>
+-#include <linux/if_vlan.h>
+-#include <linux/random.h>
+-#ifdef CONFIG_NET_DIVERT
+-#include <linux/divert.h>
+-#endif /* CONFIG_NET_DIVERT */
+-
+-#ifdef CONFIG_NET
+-extern __u32 sysctl_wmem_max;
+-extern __u32 sysctl_rmem_max;
+-#endif
+-
+-#ifdef CONFIG_INET
+-#include <linux/ip.h>
+-#include <net/protocol.h>
+-#include <net/arp.h>
+-#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+-#include <net/atmclip.h>
+-#endif
+-#include <net/ip.h>
+-#include <net/udp.h>
+-#include <net/tcp.h>
+-#include <net/icmp.h>
+-#include <net/inet_common.h>
+-#include <linux/inet.h>
+-#include <linux/mroute.h>
+-#include <linux/igmp.h>
+-#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE)
+-#include <net/ah.h>
+-#endif
+-#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+-#include <net/esp.h>
+-#endif
+-
+-extern struct net_proto_family inet_family_ops;
+-
+-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) \
+- || defined (CONFIG_IP_SCTP_MODULE)
+-#include <linux/in6.h>
+-#include <linux/icmpv6.h>
+-#include <net/ipv6.h>
+-#include <net/ndisc.h>
+-#include <net/transp_v6.h>
+-#include <net/addrconf.h>
+-
+-extern int sysctl_local_port_range[2];
+-extern int tcp_port_rover;
+-extern int udp_port_rover;
+-#endif
+-
+-#endif
+-
+-#include <linux/rtnetlink.h>
+-
+-#ifdef CONFIG_IPX_MODULE
+-extern struct datalink_proto *make_EII_client(void);
+-extern struct datalink_proto *make_8023_client(void);
+-extern void destroy_EII_client(struct datalink_proto *);
+-extern void destroy_8023_client(struct datalink_proto *);
+-#endif
+-
+-#ifdef CONFIG_ATALK_MODULE
+-#include <net/sock.h>
+-#endif
+-
+-#ifdef CONFIG_SYSCTL
+-extern int sysctl_max_syn_backlog;
+-#endif
+-
+-/* Skbuff symbols. */
+-EXPORT_SYMBOL(skb_over_panic);
+-EXPORT_SYMBOL(skb_under_panic);
+-
+-/* Socket layer registration */
+-EXPORT_SYMBOL(sock_register);
+-EXPORT_SYMBOL(sock_unregister);
+-
+-/* Socket locking */
+-EXPORT_SYMBOL(__lock_sock);
+-EXPORT_SYMBOL(__release_sock);
+-
+-/* Socket layer support routines */
+-EXPORT_SYMBOL(memcpy_fromiovec);
+-EXPORT_SYMBOL(memcpy_tokerneliovec);
+-EXPORT_SYMBOL(sock_create);
+-EXPORT_SYMBOL(sock_alloc);
+-EXPORT_SYMBOL(sock_release);
+-EXPORT_SYMBOL(sock_setsockopt);
+-EXPORT_SYMBOL(sock_getsockopt);
+-EXPORT_SYMBOL(sock_sendmsg);
+-EXPORT_SYMBOL(sock_recvmsg);
+-EXPORT_SYMBOL(sk_alloc);
+-EXPORT_SYMBOL(sk_free);
+-EXPORT_SYMBOL(sk_send_sigurg);
+-EXPORT_SYMBOL(sock_wake_async);
+-EXPORT_SYMBOL(sock_alloc_send_skb);
+-EXPORT_SYMBOL(sock_alloc_send_pskb);
+-EXPORT_SYMBOL(sock_init_data);
+-EXPORT_SYMBOL(sock_no_release);
+-EXPORT_SYMBOL(sock_no_bind);
+-EXPORT_SYMBOL(sock_no_connect);
+-EXPORT_SYMBOL(sock_no_socketpair);
+-EXPORT_SYMBOL(sock_no_accept);
+-EXPORT_SYMBOL(sock_no_getname);
+-EXPORT_SYMBOL(sock_no_poll);
+-EXPORT_SYMBOL(sock_no_ioctl);
+-EXPORT_SYMBOL(sock_no_listen);
+-EXPORT_SYMBOL(sock_no_shutdown);
+-EXPORT_SYMBOL(sock_no_getsockopt);
+-EXPORT_SYMBOL(sock_no_setsockopt);
+-EXPORT_SYMBOL(sock_no_sendmsg);
+-EXPORT_SYMBOL(sock_no_recvmsg);
+-EXPORT_SYMBOL(sock_no_mmap);
+-EXPORT_SYMBOL(sock_no_sendpage);
+-EXPORT_SYMBOL(sock_rfree);
+-EXPORT_SYMBOL(sock_wfree);
+-EXPORT_SYMBOL(sock_wmalloc);
+-EXPORT_SYMBOL(sock_rmalloc);
+-EXPORT_SYMBOL(__skb_linearize);
+-EXPORT_SYMBOL(skb_checksum);
+-EXPORT_SYMBOL(skb_checksum_help);
+-EXPORT_SYMBOL(skb_recv_datagram);
+-EXPORT_SYMBOL(skb_free_datagram);
+-EXPORT_SYMBOL(skb_copy_datagram);
+-EXPORT_SYMBOL(skb_copy_datagram_iovec);
+-EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
+-EXPORT_SYMBOL(skb_copy_bits);
+-EXPORT_SYMBOL(skb_copy_and_csum_bits);
+-EXPORT_SYMBOL(skb_copy_and_csum_dev);
+-EXPORT_SYMBOL(skb_copy_expand);
+-EXPORT_SYMBOL(___pskb_trim);
+-EXPORT_SYMBOL(__pskb_pull_tail);
+-EXPORT_SYMBOL(pskb_expand_head);
+-EXPORT_SYMBOL(pskb_copy);
+-EXPORT_SYMBOL(skb_realloc_headroom);
+-EXPORT_SYMBOL(datagram_poll);
+-EXPORT_SYMBOL(put_cmsg);
+-EXPORT_SYMBOL(sock_kmalloc);
+-EXPORT_SYMBOL(sock_kfree_s);
+-EXPORT_SYMBOL(sock_map_fd);
+-EXPORT_SYMBOL(sockfd_lookup);
+-
+-EXPORT_SYMBOL(sk_run_filter);
+-EXPORT_SYMBOL(sk_chk_filter);
+-
+-EXPORT_SYMBOL(neigh_table_init);
+-EXPORT_SYMBOL(neigh_table_clear);
+-EXPORT_SYMBOL(neigh_resolve_output);
+-EXPORT_SYMBOL(neigh_connected_output);
+-EXPORT_SYMBOL(neigh_update);
+-EXPORT_SYMBOL(neigh_create);
+-EXPORT_SYMBOL(neigh_lookup);
+-EXPORT_SYMBOL(__neigh_event_send);
+-EXPORT_SYMBOL(neigh_event_ns);
+-EXPORT_SYMBOL(neigh_ifdown);
+-#ifdef CONFIG_ARPD
+-EXPORT_SYMBOL(neigh_app_ns);
+-#endif
+-#ifdef CONFIG_SYSCTL
+-EXPORT_SYMBOL(neigh_sysctl_register);
+-EXPORT_SYMBOL(neigh_sysctl_unregister);
+-#endif
+-EXPORT_SYMBOL(pneigh_lookup);
+-EXPORT_SYMBOL(pneigh_enqueue);
+-EXPORT_SYMBOL(neigh_destroy);
+-EXPORT_SYMBOL(neigh_parms_alloc);
+-EXPORT_SYMBOL(neigh_parms_release);
+-EXPORT_SYMBOL(neigh_rand_reach_time);
+-EXPORT_SYMBOL(neigh_compat_output);
+-EXPORT_SYMBOL(neigh_changeaddr);
+-
+-/* dst_entry */
+-EXPORT_SYMBOL(dst_alloc);
+-EXPORT_SYMBOL(__dst_free);
+-EXPORT_SYMBOL(dst_destroy);
+-
+-/* misc. support routines */
+-EXPORT_SYMBOL(net_ratelimit);
+-EXPORT_SYMBOL(net_random);
+-EXPORT_SYMBOL(net_srandom);
+-
+-/* Needed by smbfs.o */
+-EXPORT_SYMBOL(__scm_destroy);
+-EXPORT_SYMBOL(__scm_send);
+-
+-/* Needed by unix.o */
+-EXPORT_SYMBOL(scm_fp_dup);
+-EXPORT_SYMBOL(files_stat);
+-EXPORT_SYMBOL(memcpy_toiovec);
+-
+-#ifdef CONFIG_IPX_MODULE
+-EXPORT_SYMBOL(make_8023_client);
+-EXPORT_SYMBOL(destroy_8023_client);
+-EXPORT_SYMBOL(make_EII_client);
+-EXPORT_SYMBOL(destroy_EII_client);
+-#endif
+-
+-/* for 801q VLAN support */
+-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+-EXPORT_SYMBOL(dev_change_flags);
+-#endif
+-
+-EXPORT_SYMBOL(scm_detach_fds);
+-
+-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+-EXPORT_SYMBOL(br_handle_frame_hook);
+-#endif
+-
+-#ifdef CONFIG_NET_DIVERT
+-EXPORT_SYMBOL(alloc_divert_blk);
+-EXPORT_SYMBOL(free_divert_blk);
+-#endif /* CONFIG_NET_DIVERT */
+-
+-#ifdef CONFIG_INET
+-/* Internet layer registration */
+-EXPORT_SYMBOL(inetdev_lock);
+-EXPORT_SYMBOL(inet_add_protocol);
+-EXPORT_SYMBOL(inet_del_protocol);
+-EXPORT_SYMBOL(inet_register_protosw);
+-EXPORT_SYMBOL(inet_unregister_protosw);
+-EXPORT_SYMBOL(ip_route_output_key);
+-EXPORT_SYMBOL(ip_route_input);
+-EXPORT_SYMBOL(icmp_send);
+-EXPORT_SYMBOL(icmp_statistics);
+-EXPORT_SYMBOL(icmp_err_convert);
+-EXPORT_SYMBOL(ip_options_compile);
+-EXPORT_SYMBOL(ip_options_undo);
+-EXPORT_SYMBOL(arp_send);
+-EXPORT_SYMBOL(arp_broken_ops);
+-EXPORT_SYMBOL(__ip_select_ident);
+-EXPORT_SYMBOL(ip_send_check);
+-EXPORT_SYMBOL(ip_fragment);
+-EXPORT_SYMBOL(inet_family_ops);
+-EXPORT_SYMBOL(in_aton);
+-EXPORT_SYMBOL(ip_mc_inc_group);
+-EXPORT_SYMBOL(ip_mc_dec_group);
+-EXPORT_SYMBOL(ip_mc_join_group);
+-EXPORT_SYMBOL(ip_finish_output);
+-EXPORT_SYMBOL(inet_stream_ops);
+-EXPORT_SYMBOL(inet_dgram_ops);
+-EXPORT_SYMBOL(ip_cmsg_recv);
+-EXPORT_SYMBOL(inet_addr_type);
+-EXPORT_SYMBOL(inet_select_addr);
+-EXPORT_SYMBOL(ip_dev_find);
+-EXPORT_SYMBOL(inetdev_by_index);
+-EXPORT_SYMBOL(in_dev_finish_destroy);
+-EXPORT_SYMBOL(ip_defrag);
+-EXPORT_SYMBOL(inet_peer_idlock);
+-
+-/* Route manipulation */
+-EXPORT_SYMBOL(ip_rt_ioctl);
+-EXPORT_SYMBOL(devinet_ioctl);
+-EXPORT_SYMBOL(register_inetaddr_notifier);
+-EXPORT_SYMBOL(unregister_inetaddr_notifier);
+-
+-/* proc */
+-#ifdef CONFIG_PROC_FS
+-EXPORT_SYMBOL(udp_proc_register);
+-EXPORT_SYMBOL(udp_proc_unregister);
+-EXPORT_SYMBOL(tcp_proc_register);
+-EXPORT_SYMBOL(tcp_proc_unregister);
+-#endif
+-
+-/* needed for ip_gre -cw */
+-EXPORT_SYMBOL(ip_statistics);
+-#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
+-EXPORT_SYMBOL_GPL(skb_cow_data);
+-EXPORT_SYMBOL_GPL(pskb_put);
+-EXPORT_SYMBOL_GPL(skb_to_sgvec);
+-#endif
+-
+-EXPORT_SYMBOL(flow_cache_lookup);
+-EXPORT_SYMBOL(flow_cache_genid);
+-
+-#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE)
+-/* inet functions common to v4 and v6 */
+-EXPORT_SYMBOL(inet_release);
+-EXPORT_SYMBOL(inet_stream_connect);
+-EXPORT_SYMBOL(inet_dgram_connect);
+-EXPORT_SYMBOL(inet_accept);
+-EXPORT_SYMBOL(inet_listen);
+-EXPORT_SYMBOL(inet_shutdown);
+-EXPORT_SYMBOL(inet_setsockopt);
+-EXPORT_SYMBOL(inet_getsockopt);
+-EXPORT_SYMBOL(inet_sendmsg);
+-EXPORT_SYMBOL(inet_recvmsg);
+-#ifdef INET_REFCNT_DEBUG
+-EXPORT_SYMBOL(inet_sock_nr);
+-#endif
+-EXPORT_SYMBOL(inet_sock_destruct);
+-EXPORT_SYMBOL(inet_sock_release);
+-
+-/* Socket demultiplexing. */
+-EXPORT_SYMBOL(tcp_hashinfo);
+-EXPORT_SYMBOL(tcp_listen_wlock);
+-EXPORT_SYMBOL(udp_hash);
+-EXPORT_SYMBOL(udp_hash_lock);
+-
+-EXPORT_SYMBOL(tcp_destroy_sock);
+-EXPORT_SYMBOL(ip_queue_xmit);
+-EXPORT_SYMBOL(memcpy_fromiovecend);
+-EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
+-EXPORT_SYMBOL(tcp_v4_lookup_listener);
+-/* UDP/TCP exported functions for TCPv6 */
+-EXPORT_SYMBOL(udp_ioctl);
+-EXPORT_SYMBOL(udp_connect);
+-EXPORT_SYMBOL(udp_disconnect);
+-EXPORT_SYMBOL(udp_sendmsg);
+-EXPORT_SYMBOL(tcp_bind_hash);
+-EXPORT_SYMBOL(tcp_close);
+-EXPORT_SYMBOL(tcp_disconnect);
+-EXPORT_SYMBOL(tcp_accept);
+-EXPORT_SYMBOL(tcp_write_wakeup);
+-EXPORT_SYMBOL(tcp_write_space);
+-EXPORT_SYMBOL(tcp_poll);
+-EXPORT_SYMBOL(tcp_ioctl);
+-EXPORT_SYMBOL(tcp_shutdown);
+-EXPORT_SYMBOL(tcp_setsockopt);
+-EXPORT_SYMBOL(tcp_getsockopt);
+-EXPORT_SYMBOL(tcp_recvmsg);
+-EXPORT_SYMBOL(tcp_send_synack);
+-EXPORT_SYMBOL(tcp_check_req);
+-EXPORT_SYMBOL(tcp_child_process);
+-EXPORT_SYMBOL(tcp_parse_options);
+-EXPORT_SYMBOL(tcp_rcv_established);
+-EXPORT_SYMBOL(tcp_init_xmit_timers);
+-EXPORT_SYMBOL(tcp_clear_xmit_timers);
+-EXPORT_SYMBOL(tcp_statistics);
+-EXPORT_SYMBOL(tcp_rcv_state_process);
+-EXPORT_SYMBOL(tcp_timewait_state_process);
+-EXPORT_SYMBOL(tcp_timewait_cachep);
+-EXPORT_SYMBOL(tcp_sendmsg);
+-EXPORT_SYMBOL(tcp_v4_rebuild_header);
+-EXPORT_SYMBOL(tcp_v4_send_check);
+-EXPORT_SYMBOL(tcp_v4_conn_request);
+-EXPORT_SYMBOL(tcp_create_openreq_child);
+-EXPORT_SYMBOL(tcp_bucket_create);
+-EXPORT_SYMBOL(tcp_put_port);
+-EXPORT_SYMBOL(tcp_inherit_port);
+-EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
+-EXPORT_SYMBOL(tcp_v4_do_rcv);
+-EXPORT_SYMBOL(tcp_v4_connect);
+-EXPORT_SYMBOL(tcp_unhash);
+-EXPORT_SYMBOL(udp_prot);
+-EXPORT_SYMBOL(tcp_prot);
+-EXPORT_SYMBOL(tcp_openreq_cachep);
+-EXPORT_SYMBOL(ipv4_specific);
+-EXPORT_SYMBOL(tcp_simple_retransmit);
+-EXPORT_SYMBOL(tcp_transmit_skb);
+-EXPORT_SYMBOL(tcp_connect);
+-EXPORT_SYMBOL(tcp_make_synack);
+-EXPORT_SYMBOL(tcp_tw_deschedule);
+-EXPORT_SYMBOL(tcp_delete_keepalive_timer);
+-EXPORT_SYMBOL(tcp_reset_keepalive_timer);
+-EXPORT_SYMBOL(sysctl_local_port_range);
+-EXPORT_SYMBOL(tcp_port_rover);
+-EXPORT_SYMBOL(udp_port_rover);
+-EXPORT_SYMBOL(tcp_sync_mss);
+-EXPORT_SYMBOL(net_statistics);
+-EXPORT_SYMBOL(__tcp_mem_reclaim);
+-EXPORT_SYMBOL(tcp_sockets_allocated);
+-EXPORT_SYMBOL(sysctl_tcp_reordering);
+-EXPORT_SYMBOL(sysctl_tcp_rmem);
+-EXPORT_SYMBOL(sysctl_tcp_wmem);
+-EXPORT_SYMBOL(sysctl_tcp_ecn);
+-EXPORT_SYMBOL(tcp_cwnd_application_limited);
+-EXPORT_SYMBOL(tcp_sendpage);
+-EXPORT_SYMBOL(sysctl_tcp_low_latency);
+-
+-EXPORT_SYMBOL(tcp_write_xmit);
+-
+-EXPORT_SYMBOL(tcp_v4_remember_stamp);
+-
+-extern int sysctl_tcp_tw_recycle;
+-
+-#ifdef CONFIG_SYSCTL
+-EXPORT_SYMBOL(sysctl_tcp_tw_recycle);
+-EXPORT_SYMBOL(sysctl_max_syn_backlog);
+-#endif
+-
+-EXPORT_SYMBOL(ip_generic_getfrag);
+-
+-#endif
+-
+-EXPORT_SYMBOL(tcp_read_sock);
+-
+-#ifdef CONFIG_IP_SCTP_MODULE
+-EXPORT_SYMBOL(ip_setsockopt);
+-EXPORT_SYMBOL(ip_getsockopt);
+-EXPORT_SYMBOL(inet_ioctl);
+-EXPORT_SYMBOL(inet_bind);
+-EXPORT_SYMBOL(inet_getname);
+-#endif /* CONFIG_IP_SCTP_MODULE */
+-
+-EXPORT_SYMBOL(netlink_set_err);
+-EXPORT_SYMBOL(netlink_broadcast);
+-EXPORT_SYMBOL(netlink_unicast);
+-EXPORT_SYMBOL(netlink_kernel_create);
+-EXPORT_SYMBOL(netlink_dump_start);
+-EXPORT_SYMBOL(netlink_ack);
+-EXPORT_SYMBOL(netlink_set_nonroot);
+-EXPORT_SYMBOL(netlink_register_notifier);
+-EXPORT_SYMBOL(netlink_unregister_notifier);
+-#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
+-EXPORT_SYMBOL(netlink_attach);
+-EXPORT_SYMBOL(netlink_detach);
+-EXPORT_SYMBOL(netlink_post);
+-#endif
+-
+-EXPORT_SYMBOL(rtattr_parse);
+-EXPORT_SYMBOL(__rta_fill);
+-EXPORT_SYMBOL(neigh_delete);
+-EXPORT_SYMBOL(neigh_add);
+-EXPORT_SYMBOL(neigh_dump_info);
+-
+-
+-/* ABI emulation layers need this */
+-EXPORT_SYMBOL(move_addr_to_kernel);
+-EXPORT_SYMBOL(move_addr_to_user);
+-
+-/* Used by at least ipip.c. */
+-EXPORT_SYMBOL(ipv4_config);
+-
+-/* Used by other modules */
+-EXPORT_SYMBOL(xrlim_allow);
+-
+-EXPORT_SYMBOL(ip_rcv);
+-EXPORT_SYMBOL(arp_rcv);
+-EXPORT_SYMBOL(arp_tbl);
+-#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+-EXPORT_SYMBOL(clip_tbl_hook);
+-#endif
+-EXPORT_SYMBOL(arp_find);
+-
+-#endif /* CONFIG_INET */
+-
+-#ifdef CONFIG_TR
+-EXPORT_SYMBOL(tr_source_route);
+-EXPORT_SYMBOL(tr_type_trans);
+-#endif
+-
+-/* Device callback registration */
+-EXPORT_SYMBOL(register_netdevice_notifier);
+-EXPORT_SYMBOL(unregister_netdevice_notifier);
+-EXPORT_SYMBOL(call_netdevice_notifiers);
+-
+-/* support for loadable net drivers */
+-#ifdef CONFIG_NET
+-EXPORT_SYMBOL(loopback_dev);
+-EXPORT_SYMBOL(register_netdevice);
+-EXPORT_SYMBOL(unregister_netdevice);
+-EXPORT_SYMBOL(free_netdev);
+-EXPORT_SYMBOL(synchronize_net);
+-EXPORT_SYMBOL(netdev_state_change);
+-EXPORT_SYMBOL(netdev_boot_setup_check);
+-EXPORT_SYMBOL(dev_new_index);
+-EXPORT_SYMBOL(dev_get_by_flags);
+-EXPORT_SYMBOL(__dev_get_by_flags);
+-EXPORT_SYMBOL(dev_get_by_index);
+-EXPORT_SYMBOL(__dev_get_by_index);
+-EXPORT_SYMBOL(dev_get_by_name);
+-EXPORT_SYMBOL(__dev_get_by_name);
+-EXPORT_SYMBOL(dev_getbyhwaddr);
+-EXPORT_SYMBOL(netdev_set_master);
+-EXPORT_SYMBOL(eth_type_trans);
+-#ifdef CONFIG_FDDI
+-EXPORT_SYMBOL(fddi_type_trans);
+-#endif /* CONFIG_FDDI */
+-#if 0
+-EXPORT_SYMBOL(eth_copy_and_sum);
+-#endif
+-EXPORT_SYMBOL(alloc_skb);
+-EXPORT_SYMBOL(__kfree_skb);
+-EXPORT_SYMBOL(skb_clone);
+-EXPORT_SYMBOL(skb_copy);
+-EXPORT_SYMBOL(skb_pad);
+-EXPORT_SYMBOL(netif_rx);
+-EXPORT_SYMBOL(netif_receive_skb);
+-EXPORT_SYMBOL(dev_add_pack);
+-EXPORT_SYMBOL(dev_remove_pack);
+-EXPORT_SYMBOL(__dev_remove_pack);
+-EXPORT_SYMBOL(__dev_get);
+-EXPORT_SYMBOL(dev_alloc);
+-EXPORT_SYMBOL(dev_alloc_name);
+-EXPORT_SYMBOL(__netdev_watchdog_up);
+-#ifdef CONFIG_KMOD
+-EXPORT_SYMBOL(dev_load);
+-#endif
+-EXPORT_SYMBOL(dev_ioctl);
+-EXPORT_SYMBOL(dev_queue_xmit);
+-#ifdef CONFIG_NET_HW_FLOWCONTROL
+-EXPORT_SYMBOL(netdev_dropping);
+-EXPORT_SYMBOL(netdev_register_fc);
+-EXPORT_SYMBOL(netdev_unregister_fc);
+-EXPORT_SYMBOL(netdev_fc_xoff);
+-#endif
+-EXPORT_SYMBOL(dev_base);
+-EXPORT_SYMBOL(dev_base_lock);
+-EXPORT_SYMBOL(dev_open);
+-EXPORT_SYMBOL(dev_close);
+-EXPORT_SYMBOL(dev_mc_add);
+-EXPORT_SYMBOL(dev_mc_delete);
+-EXPORT_SYMBOL(dev_mc_upload);
+-EXPORT_SYMBOL(dev_set_allmulti);
+-EXPORT_SYMBOL(dev_set_promiscuity);
+-EXPORT_SYMBOL(__kill_fasync);
+-
+-EXPORT_SYMBOL(rtnl);
+-EXPORT_SYMBOL(rtnetlink_links);
+-EXPORT_SYMBOL(rtnetlink_dump_ifinfo);
+-EXPORT_SYMBOL(rtnetlink_put_metrics);
+-EXPORT_SYMBOL(rtnl_sem);
+-EXPORT_SYMBOL(rtnl_lock);
+-EXPORT_SYMBOL(rtnl_unlock);
+-
+-#ifdef CONFIG_HIPPI
+-EXPORT_SYMBOL(hippi_type_trans);
+-#endif
+-
+-#ifdef CONFIG_NET_FASTROUTE
+-EXPORT_SYMBOL(netdev_fastroute);
+-#endif
+-
+-#ifdef CONFIG_SYSCTL
+-EXPORT_SYMBOL(sysctl_wmem_max);
+-EXPORT_SYMBOL(sysctl_rmem_max);
+-#ifdef CONFIG_INET
+-EXPORT_SYMBOL(sysctl_ip_default_ttl);
+-#endif
+-#endif
+-
+-/* Packet scheduler modules want these. */
+-EXPORT_SYMBOL(qdisc_destroy);
+-EXPORT_SYMBOL(qdisc_reset);
+-EXPORT_SYMBOL(qdisc_restart);
+-EXPORT_SYMBOL(qdisc_create_dflt);
+-EXPORT_SYMBOL(noop_qdisc);
+-EXPORT_SYMBOL(qdisc_tree_lock);
+-#ifdef CONFIG_NET_SCHED
+-PSCHED_EXPORTLIST;
+-EXPORT_SYMBOL(pfifo_qdisc_ops);
+-EXPORT_SYMBOL(bfifo_qdisc_ops);
+-EXPORT_SYMBOL(register_qdisc);
+-EXPORT_SYMBOL(unregister_qdisc);
+-EXPORT_SYMBOL(qdisc_get_rtab);
+-EXPORT_SYMBOL(qdisc_put_rtab);
+-EXPORT_SYMBOL(qdisc_copy_stats);
+-#ifdef CONFIG_NET_ESTIMATOR
+-EXPORT_SYMBOL(qdisc_new_estimator);
+-EXPORT_SYMBOL(qdisc_kill_estimator);
+-#endif
+-#ifdef CONFIG_NET_CLS_POLICE
+-EXPORT_SYMBOL(tcf_police);
+-EXPORT_SYMBOL(tcf_police_locate);
+-EXPORT_SYMBOL(tcf_police_destroy);
+-EXPORT_SYMBOL(tcf_police_dump);
+-#endif
+-#endif
+-#ifdef CONFIG_NET_CLS
+-EXPORT_SYMBOL(register_tcf_proto_ops);
+-EXPORT_SYMBOL(unregister_tcf_proto_ops);
+-#endif
+-#ifdef CONFIG_NETFILTER
+-#include <linux/netfilter.h>
+-EXPORT_SYMBOL(nf_register_hook);
+-EXPORT_SYMBOL(nf_unregister_hook);
+-EXPORT_SYMBOL(nf_register_sockopt);
+-EXPORT_SYMBOL(nf_unregister_sockopt);
+-EXPORT_SYMBOL(nf_reinject);
+-EXPORT_SYMBOL(nf_register_queue_handler);
+-EXPORT_SYMBOL(nf_unregister_queue_handler);
+-EXPORT_SYMBOL(nf_hook_slow);
+-EXPORT_SYMBOL(nf_hooks);
+-EXPORT_SYMBOL(nf_setsockopt);
+-EXPORT_SYMBOL(nf_getsockopt);
+-EXPORT_SYMBOL(ip_ct_attach);
+-#ifdef CONFIG_INET
+-#include <linux/netfilter_ipv4.h>
+-EXPORT_SYMBOL(ip_route_me_harder);
+-#endif
+-#endif
+-
+-EXPORT_SYMBOL(register_gifconf);
+-
+-EXPORT_PER_CPU_SYMBOL(softnet_data);
+-
+-#ifdef CONFIG_NET_RADIO
+-#include <net/iw_handler.h> /* Wireless Extensions driver API */
+-EXPORT_SYMBOL(wireless_send_event);
+-EXPORT_SYMBOL(iw_handler_set_spy);
+-EXPORT_SYMBOL(iw_handler_get_spy);
+-EXPORT_SYMBOL(iw_handler_set_thrspy);
+-EXPORT_SYMBOL(iw_handler_get_thrspy);
+-EXPORT_SYMBOL(wireless_spy_update);
+-#endif /* CONFIG_NET_RADIO */
+-
+-EXPORT_SYMBOL(linkwatch_fire_event);
+-
+-/* ethtool.c */
+-EXPORT_SYMBOL(ethtool_op_get_link);
+-EXPORT_SYMBOL(ethtool_op_get_tx_csum);
+-EXPORT_SYMBOL(ethtool_op_set_tx_csum);
+-EXPORT_SYMBOL(ethtool_op_get_sg);
+-EXPORT_SYMBOL(ethtool_op_set_sg);
+-EXPORT_SYMBOL(ethtool_op_get_tso);
+-EXPORT_SYMBOL(ethtool_op_set_tso);
+-
+-#endif /* CONFIG_NET */
+--- linux-2.6.0-test6/net/sched/cls_api.c 2003-06-14 12:18:03.000000000 -0700
++++ 25/net/sched/cls_api.c 2003-10-05 00:33:25.000000000 -0700
+@@ -467,3 +467,6 @@ int __init tc_filter_init(void)
+ #endif
+ return 0;
+ }
++
++EXPORT_SYMBOL(register_tcf_proto_ops);
++EXPORT_SYMBOL(unregister_tcf_proto_ops);
+--- linux-2.6.0-test6/net/sched/estimator.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/sched/estimator.c 2003-10-05 00:33:25.000000000 -0700
+@@ -12,6 +12,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/bitops.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/jiffies.h>
+@@ -194,3 +195,5 @@ void qdisc_kill_estimator(struct tc_stat
+ }
+ }
+
++EXPORT_SYMBOL(qdisc_kill_estimator);
++EXPORT_SYMBOL(qdisc_new_estimator);
+--- linux-2.6.0-test6/net/sched/police.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/sched/police.c 2003-10-05 00:33:25.000000000 -0700
+@@ -13,6 +13,7 @@
+ #include <asm/system.h>
+ #include <asm/bitops.h>
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+@@ -248,3 +249,12 @@ rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+ }
++
++EXPORT_SYMBOL(tcf_police);
++EXPORT_SYMBOL(tcf_police_destroy);
++EXPORT_SYMBOL(tcf_police_dump);
++EXPORT_SYMBOL(tcf_police_hash);
++EXPORT_SYMBOL(tcf_police_ht);
++EXPORT_SYMBOL(tcf_police_locate);
++EXPORT_SYMBOL(tcf_police_lookup);
++EXPORT_SYMBOL(tcf_police_new_index);
+--- linux-2.6.0-test6/net/sched/sch_api.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/sched/sch_api.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1255,3 +1255,10 @@ int __init pktsched_init(void)
+
+ return 0;
+ }
++
++EXPORT_SYMBOL(qdisc_copy_stats);
++EXPORT_SYMBOL(qdisc_get_rtab);
++EXPORT_SYMBOL(qdisc_put_rtab);
++EXPORT_SYMBOL(register_qdisc);
++EXPORT_SYMBOL(unregister_qdisc);
++PSCHED_EXPORTLIST;
+--- linux-2.6.0-test6/net/sched/sch_fifo.c 2003-07-10 18:50:32.000000000 -0700
++++ 25/net/sched/sch_fifo.c 2003-10-05 00:33:25.000000000 -0700
+@@ -203,3 +203,6 @@ struct Qdisc_ops bfifo_qdisc_ops = {
+ .dump = fifo_dump,
+ .owner = THIS_MODULE,
+ };
++
++EXPORT_SYMBOL(bfifo_qdisc_ops);
++EXPORT_SYMBOL(pfifo_qdisc_ops);
+--- linux-2.6.0-test6/net/sched/sch_generic.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/net/sched/sch_generic.c 2003-10-05 00:33:25.000000000 -0700
+@@ -531,3 +531,12 @@ void dev_shutdown(struct net_device *dev
+ spin_unlock_bh(&dev->queue_lock);
+ write_unlock(&qdisc_tree_lock);
+ }
++
++EXPORT_SYMBOL(__netdev_watchdog_up);
++EXPORT_SYMBOL(noop_qdisc);
++EXPORT_SYMBOL(noop_qdisc_ops);
++EXPORT_SYMBOL(qdisc_create_dflt);
++EXPORT_SYMBOL(qdisc_destroy);
++EXPORT_SYMBOL(qdisc_reset);
++EXPORT_SYMBOL(qdisc_restart);
++EXPORT_SYMBOL(qdisc_tree_lock);
+--- linux-2.6.0-test6/net/sctp/associola.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/associola.c 2003-10-05 00:33:25.000000000 -0700
+@@ -141,9 +141,9 @@ struct sctp_association *sctp_associatio
+ * socket values.
+ */
+ asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
+- asoc->rto_initial = sp->rtoinfo.srto_initial * HZ / 1000;
+- asoc->rto_max = sp->rtoinfo.srto_max * HZ / 1000;
+- asoc->rto_min = sp->rtoinfo.srto_min * HZ / 1000;
++ asoc->rto_initial = MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
++ asoc->rto_max = MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
++ asoc->rto_min = MSECS_TO_JIFFIES(sp->rtoinfo.srto_min);
+
+ asoc->overall_error_count = 0;
+
+@@ -168,7 +168,8 @@ struct sctp_association *sctp_associatio
+ asoc->c.sinit_num_ostreams = sp->initmsg.sinit_num_ostreams;
+ asoc->max_init_attempts = sp->initmsg.sinit_max_attempts;
+
+- asoc->max_init_timeo = sp->initmsg.sinit_max_init_timeo * HZ / 1000;
++ asoc->max_init_timeo =
++ MSECS_TO_JIFFIES(sp->initmsg.sinit_max_init_timeo);
+
+ /* Allocate storage for the ssnmap after the inbound and outbound
+ * streams have been negotiated during Init.
+@@ -246,6 +247,11 @@ struct sctp_association *sctp_associatio
+ */
+ asoc->peer.sack_needed = 1;
+
++ /* Assume that the peer recongizes ASCONF until reported otherwise
++ * via an ERROR chunk.
++ */
++ asoc->peer.asconf_capable = 1;
++
+ /* Create an input queue. */
+ sctp_inq_init(&asoc->base.inqueue);
+ sctp_inq_set_th_handler(&asoc->base.inqueue,
+@@ -495,7 +501,7 @@ struct sctp_transport *sctp_assoc_add_pe
+ /* Initialize the peer's heartbeat interval based on the
+ * sock configured value.
+ */
+- peer->hb_interval = sp->paddrparam.spp_hbinterval * HZ;
++ peer->hb_interval = MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval);
+
+ /* Set the path max_retrans. */
+ peer->max_retrans = asoc->max_retrans;
+--- linux-2.6.0-test6/net/sctp/bind_addr.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/bind_addr.c 2003-10-05 00:33:25.000000000 -0700
+@@ -324,6 +324,43 @@ int sctp_bind_addr_match(struct sctp_bin
+ return 0;
+ }
+
++/* Find the first address in the bind address list that is not present in
++ * the addrs packed array.
++ */
++union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
++ const union sctp_addr *addrs,
++ int addrcnt,
++ struct sctp_opt *opt)
++{
++ struct sctp_sockaddr_entry *laddr;
++ union sctp_addr *addr;
++ void *addr_buf;
++ struct sctp_af *af;
++ struct list_head *pos;
++ int i;
++
++ list_for_each(pos, &bp->address_list) {
++ laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
++
++ addr_buf = (union sctp_addr *)addrs;
++ for (i = 0; i < addrcnt; i++) {
++ addr = (union sctp_addr *)addr_buf;
++ af = sctp_get_af_specific(addr->v4.sin_family);
++ if (!af)
++ return NULL;
++
++ if (opt->pf->cmp_addr(&laddr->a, addr, opt))
++ break;
++
++ addr_buf += af->sockaddr_len;
++ }
++ if (i == addrcnt)
++ return &laddr->a;
++ }
++
++ return NULL;
++}
++
+ /* Copy out addresses from the global local address list. */
+ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
+ union sctp_addr *addr,
+--- linux-2.6.0-test6/net/sctp/endpointola.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/net/sctp/endpointola.c 2003-10-05 00:33:25.000000000 -0700
+@@ -129,7 +129,7 @@ struct sctp_endpoint *sctp_endpoint_init
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+ SCTP_DEFAULT_TIMEOUT_T1_INIT;
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
+- sp->rtoinfo.srto_initial * HZ / 1000;
++ MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
+
+@@ -138,7 +138,7 @@ struct sctp_endpoint *sctp_endpoint_init
+ * recommended value of 5 times 'RTO.Max'.
+ */
+ ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
+- = 5 * (sp->rtoinfo.srto_max * HZ / 1000);
++ = 5 * MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
+
+ ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
+ SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
+--- linux-2.6.0-test6/net/sctp/sm_make_chunk.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/sm_make_chunk.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,5 +1,5 @@
+ /* SCTP kernel reference Implementation
+- * Copyright (C) IBM Corp. 2001, 2003
++ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001-2002 Intel Corp.
+@@ -1288,7 +1288,7 @@ sctp_cookie_param_t *sctp_pack_cookie(co
+
+ /* Set an expiration time for the cookie. */
+ do_gettimeofday(&cookie->c.expiration);
+- tv_add(&asoc->cookie_life, &cookie->c.expiration);
++ TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);
+
+ /* Copy the peer's init packet. */
+ memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
+@@ -2021,11 +2021,11 @@ struct sctp_chunk *sctp_make_asconf(stru
+ sctp_addiphdr_t asconf;
+ struct sctp_chunk *retval;
+ int length = sizeof(asconf) + vparam_len;
+- union sctp_params addrparam;
++ union sctp_addr_param addrparam;
+ int addrlen;
+ struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
+
+- addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam);
++ addrlen = af->to_addr_param(addr, &addrparam);
+ if (!addrlen)
+ return NULL;
+ length += addrlen;
+@@ -2046,6 +2046,83 @@ struct sctp_chunk *sctp_make_asconf(stru
+ }
+
+ /* ADDIP
++ * 3.2.1 Add IP Address
++ * 0 1 2 3
++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | Type = 0xC001 | Length = Variable |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | ASCONF-Request Correlation ID |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | Address Parameter |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ *
++ * 3.2.2 Delete IP Address
++ * 0 1 2 3
++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | Type = 0xC002 | Length = Variable |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | ASCONF-Request Correlation ID |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ * | Address Parameter |
++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ *
++ */
++struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
++ union sctp_addr *laddr,
++ struct sockaddr *addrs,
++ int addrcnt,
++ int flags)
++{
++ sctp_addip_param_t param;
++ struct sctp_chunk *retval;
++ union sctp_addr_param addr_param;
++ union sctp_addr *addr;
++ void *addr_buf;
++ struct sctp_af *af;
++ int paramlen = sizeof(param);
++ int addr_param_len = 0;
++ int totallen = 0;
++ int i;
++
++ /* Get total length of all the address parameters. */
++ addr_buf = addrs;
++ for (i = 0; i < addrcnt; i++) {
++ addr = (union sctp_addr *)addr_buf;
++ af = sctp_get_af_specific(addr->v4.sin_family);
++ addr_param_len = af->to_addr_param(addr, &addr_param);
++
++ totallen += paramlen;
++ totallen += addr_param_len;
++
++ addr_buf += af->sockaddr_len;
++ }
++
++ /* Create an asconf chunk with the required length. */
++ retval = sctp_make_asconf(asoc, laddr, totallen);
++ if (!retval)
++ return NULL;
++
++ /* Add the address parameters to the asconf chunk. */
++ addr_buf = addrs;
++ for (i = 0; i < addrcnt; i++) {
++ addr = (union sctp_addr *)addr_buf;
++ af = sctp_get_af_specific(addr->v4.sin_family);
++ addr_param_len = af->to_addr_param(addr, &addr_param);
++ param.param_hdr.type = flags;
++ param.param_hdr.length = htons(paramlen + addr_param_len);
++ param.crr_id = htonl(i);
++
++ sctp_addto_chunk(retval, paramlen, ¶m);
++ sctp_addto_chunk(retval, addr_param_len, &addr_param);
++
++ addr_buf += af->sockaddr_len;
++ }
++ return retval;
++}
++
++/* ADDIP
+ * 3.2.4 Set Primary IP Address
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+@@ -2065,11 +2142,11 @@ struct sctp_chunk *sctp_make_asconf_set_
+ sctp_addip_param_t param;
+ struct sctp_chunk *retval;
+ int len = sizeof(param);
+- union sctp_params addrparam;
++ union sctp_addr_param addrparam;
+ int addrlen;
+ struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
+
+- addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam);
++ addrlen = af->to_addr_param(addr, &addrparam);
+ if (!addrlen)
+ return NULL;
+ len += addrlen;
+@@ -2089,11 +2166,7 @@ struct sctp_chunk *sctp_make_asconf_set_
+ return retval;
+ }
+
+-/*
+- * Unpack the parameters in an ASCONF chunk into an association and
+- * generate ASCONF-ACK chunk.
+- *
+- * ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
++/* ADDIP 3.1.2 Address Configuration Acknowledgement Chunk (ASCONF-ACK)
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+@@ -2110,8 +2183,28 @@ struct sctp_chunk *sctp_make_asconf_set_
+ * | ASCONF Parameter Response#N |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+- * All the parameter respoinces will be added in this function.
++ * Create an ASCONF_ACK chunk with enough space for the parameter responses.
+ */
++struct sctp_chunk *sctp_make_asconf_ack(struct sctp_association *asoc,
++ int serial, int vparam_len)
++{
++ sctp_addiphdr_t asconf;
++ struct sctp_chunk *retval;
++ int length = sizeof(asconf) + vparam_len;
++
++ /* Create the chunk. */
++ retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF_ACK, 0, length);
++ if (!retval)
++ return NULL;
++
++ asconf.serial = serial;
++
++ retval->subh.addip_hdr =
++ sctp_addto_chunk(retval, sizeof(asconf), &asconf);
++
++ return retval;
++}
++
+ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
+ struct sctp_chunk *asconf,
+ int vparam_len)
+--- linux-2.6.0-test6/net/sctp/sm_sideeffect.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/net/sctp/sm_sideeffect.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,7 +1,7 @@
+ /* SCTP kernel reference Implementation
++ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (c) 1999 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+- * Copyright (c) 2001-2002 International Business Machines Corp.
+ *
+ * This file is part of the SCTP kernel reference Implementation
+ *
+@@ -690,6 +690,44 @@ static void sctp_cmd_setup_t4(sctp_cmd_s
+ chunk->transport = t;
+ }
+
++/* Process an incoming Operation Error Chunk. */
++static void sctp_cmd_process_operr(sctp_cmd_seq_t *cmds,
++ struct sctp_association *asoc,
++ struct sctp_chunk *chunk)
++{
++ struct sctp_operr_chunk *operr_chunk;
++ struct sctp_errhdr *err_hdr;
++
++ operr_chunk = (struct sctp_operr_chunk *)chunk->chunk_hdr;
++ err_hdr = &operr_chunk->err_hdr;
++
++ switch (err_hdr->cause) {
++ case SCTP_ERROR_UNKNOWN_CHUNK:
++ {
++ struct sctp_chunkhdr *unk_chunk_hdr;
++
++ unk_chunk_hdr = (struct sctp_chunkhdr *)err_hdr->variable;
++ switch (unk_chunk_hdr->type) {
++ /* ADDIP 4.1 A9) If the peer responds to an ASCONF with an
++ * ERROR chunk reporting that it did not recognized the ASCONF
++ * chunk type, the sender of the ASCONF MUST NOT send any
++ * further ASCONF chunks and MUST stop its T-4 timer.
++ */
++ case SCTP_CID_ASCONF:
++ asoc->peer.asconf_capable = 0;
++ sctp_add_cmd_sf(cmds, SCTP_CMD_TIMER_STOP,
++ SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
++ break;
++ default:
++ break;
++ }
++ break;
++ }
++ default:
++ break;
++ }
++}
++
+ /* These three macros allow us to pull the debugging code out of the
+ * main flow of sctp_do_sm() to keep attention focused on the real
+ * functionality there.
+@@ -1205,6 +1243,9 @@ int sctp_cmd_interpreter(sctp_event_t ev
+ sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);
+ break;
+
++ case SCTP_CMD_PROCESS_OPERR:
++ sctp_cmd_process_operr(commands, asoc, chunk);
++ break;
+ default:
+ printk(KERN_WARNING "Impossible command: %u, %p\n",
+ cmd->verb, cmd->obj.ptr);
+--- linux-2.6.0-test6/net/sctp/sm_statefuns.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/sm_statefuns.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,7 +1,7 @@
+ /* SCTP kernel reference Implementation
++ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+- * Copyright (c) 2001-2002 International Business Machines, Corp.
+ * Copyright (c) 2001-2002 Intel Corp.
+ * Copyright (c) 2002 Nokia Corp.
+ *
+@@ -2864,6 +2864,9 @@ sctp_disposition_t sctp_sf_operr_notify(
+ sctp_ulpevent_free(ev);
+ goto nomem;
+ }
++
++ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR,
++ SCTP_CHUNK(chunk));
+ }
+ return SCTP_DISPOSITION_CONSUME;
+
+--- linux-2.6.0-test6/net/sctp/socket.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/socket.c 2003-10-05 00:33:25.000000000 -0700
+@@ -97,6 +97,8 @@ static void sctp_wait_for_close(struct s
+ static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int);
+ static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
+ static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
++static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
++static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
+ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
+ static int sctp_autobind(struct sock *sk);
+ static void sctp_sock_migrate(struct sock *, struct sock *,
+@@ -349,6 +351,106 @@ err_bindx_add:
+ return retval;
+ }
+
++/* Send an ASCONF chunk with Add IP address parameters to all the peers of the
++ * associations that are part of the endpoint indicating that a list of local
++ * addresses are added to the endpoint.
++ *
++ * If any of the addresses is already in the bind address list of the
++ * association, we do not send the chunk for that association. But it will not
++ * affect other associations.
++ *
++ * Only sctp_setsockopt_bindx() is supposed to call this function.
++ */
++static int sctp_send_asconf_add_ip(struct sock *sk,
++ struct sockaddr *addrs,
++ int addrcnt)
++{
++ struct sctp_opt *sp;
++ struct sctp_endpoint *ep;
++ struct sctp_association *asoc;
++ struct sctp_bind_addr *bp;
++ struct sctp_chunk *chunk;
++ struct sctp_sockaddr_entry *laddr;
++ union sctp_addr *addr;
++ void *addr_buf;
++ struct sctp_af *af;
++ struct list_head *pos;
++ struct list_head *p;
++ int i;
++ int retval = 0;
++
++ sp = sctp_sk(sk);
++ ep = sp->ep;
++
++ SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
++ __FUNCTION__, sk, addrs, addrcnt);
++
++ list_for_each(pos, &ep->asocs) {
++ asoc = list_entry(pos, struct sctp_association, asocs);
++
++ if (!sctp_state(asoc, ESTABLISHED))
++ continue;
++
++ if (!asoc->peer.asconf_capable)
++ continue;
++
++ /* Check if any address in the packed array of addresses is
++ * in the bind address list of the association. If so,
++ * do not send the asconf chunk to its peer, but continue with
++ * other associations.
++ */
++ addr_buf = addrs;
++ for (i = 0; i < addrcnt; i++) {
++ addr = (union sctp_addr *)addr_buf;
++ af = sctp_get_af_specific(addr->v4.sin_family);
++ if (!af) {
++ retval = -EINVAL;
++ goto out;
++ }
++
++ if (sctp_assoc_lookup_laddr(asoc, addr))
++ break;
++
++ addr_buf += af->sockaddr_len;
++ }
++ if (i < addrcnt)
++ continue;
++
++ /* Use the first address in bind addr list of association as
++ * Address Parameter of ASCONF CHUNK.
++ */
++ sctp_read_lock(&asoc->base.addr_lock);
++ bp = &asoc->base.bind_addr;
++ p = bp->address_list.next;
++ laddr = list_entry(p, struct sctp_sockaddr_entry, list);
++ sctp_read_unlock(&asoc->base.addr_lock);
++
++ chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
++ addrcnt, SCTP_PARAM_ADD_IP);
++ if (!chunk) {
++ retval = -ENOMEM;
++ goto out;
++ }
++
++ retval = sctp_primitive_ASCONF(asoc, chunk);
++ if (retval) {
++ sctp_chunk_free(chunk);
++ goto out;
++ }
++
++ /* FIXME: After sending the add address ASCONF chunk, we
++ * cannot append the address to the association's binding
++ * address list, because the new address may be used as the
++ * source of a message sent to the peer before the ASCONF
++ * chunk is received by the peer. So we should wait until
++ * ASCONF_ACK is received.
++ */
++ }
++
++out:
++ return retval;
++}
++
+ /* Remove a list of addresses from bind addresses list. Do not remove the
+ * last address.
+ *
+@@ -436,6 +538,106 @@ err_bindx_rem:
+ return retval;
+ }
+
++/* Send an ASCONF chunk with Delete IP address parameters to all the peers of
++ * the associations that are part of the endpoint indicating that a list of
++ * local addresses are removed from the endpoint.
++ *
++ * If any of the addresses is already in the bind address list of the
++ * association, we do not send the chunk for that association. But it will not
++ * affect other associations.
++ *
++ * Only sctp_setsockopt_bindx() is supposed to call this function.
++ */
++static int sctp_send_asconf_del_ip(struct sock *sk,
++ struct sockaddr *addrs,
++ int addrcnt)
++{
++ struct sctp_opt *sp;
++ struct sctp_endpoint *ep;
++ struct sctp_association *asoc;
++ struct sctp_bind_addr *bp;
++ struct sctp_chunk *chunk;
++ union sctp_addr *laddr;
++ void *addr_buf;
++ struct sctp_af *af;
++ struct list_head *pos;
++ int i;
++ int retval = 0;
++
++ sp = sctp_sk(sk);
++ ep = sp->ep;
++
++ SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
++ __FUNCTION__, sk, addrs, addrcnt);
++
++ list_for_each(pos, &ep->asocs) {
++ asoc = list_entry(pos, struct sctp_association, asocs);
++
++ if (!sctp_state(asoc, ESTABLISHED))
++ continue;
++
++ if (!asoc->peer.asconf_capable)
++ continue;
++
++ /* Check if any address in the packed array of addresses is
++ * not present in the bind address list of the association.
++ * If so, do not send the asconf chunk to its peer, but
++ * continue with other associations.
++ */
++ addr_buf = addrs;
++ for (i = 0; i < addrcnt; i++) {
++ laddr = (union sctp_addr *)addr_buf;
++ af = sctp_get_af_specific(laddr->v4.sin_family);
++ if (!af) {
++ retval = -EINVAL;
++ goto out;
++ }
++
++ if (!sctp_assoc_lookup_laddr(asoc, laddr))
++ break;
++
++ addr_buf += af->sockaddr_len;
++ }
++ if (i < addrcnt)
++ continue;
++
++ /* Find one address in the association's bind address list
++ * that is not in the packed array of addresses. This is to
++ * make sure that we do not delete all the addresses in the
++ * association.
++ */
++ sctp_read_lock(&asoc->base.addr_lock);
++ bp = &asoc->base.bind_addr;
++ laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
++ addrcnt, sp);
++ sctp_read_unlock(&asoc->base.addr_lock);
++ if (!laddr)
++ continue;
++
++ chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt,
++ SCTP_PARAM_DEL_IP);
++ if (!chunk) {
++ retval = -ENOMEM;
++ goto out;
++ }
++
++ retval = sctp_primitive_ASCONF(asoc, chunk);
++ if (retval) {
++ sctp_chunk_free(chunk);
++ goto out;
++ }
++
++ /* FIXME: After sending the delete address ASCONF chunk, we
++ * cannot remove the addresses from the association's bind
++ * address list, because there maybe some packet send to
++ * the delete addresses, so we should wait until ASCONF_ACK
++ * packet is received.
++ */
++ }
++out:
++ return retval;
++}
++
+ /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
+ *
+ * API 8.1
+@@ -564,10 +766,16 @@ SCTP_STATIC int sctp_setsockopt_bindx(st
+ switch (op) {
+ case SCTP_BINDX_ADD_ADDR:
+ err = sctp_bindx_add(sk, kaddrs, addrcnt);
++ if (err)
++ goto out;
++ err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt);
+ break;
+
+ case SCTP_BINDX_REM_ADDR:
+ err = sctp_bindx_rem(sk, kaddrs, addrcnt);
++ if (err)
++ goto out;
++ err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt);
+ break;
+
+ default:
+@@ -575,6 +783,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(st
+ break;
+ };
+
++out:
+ kfree(kaddrs);
+
+ return err;
+@@ -962,8 +1171,8 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+ = sinit->sinit_max_attempts;
+ }
+ if (sinit->sinit_max_init_timeo) {
+- asoc->max_init_timeo
+- = sinit->sinit_max_init_timeo * HZ;
++ asoc->max_init_timeo =
++ MSECS_TO_JIFFIES(sinit->sinit_max_init_timeo);
+ }
+ }
+
+@@ -1401,7 +1610,8 @@ static int sctp_setsockopt_peer_addr_par
+ */
+ if (params.spp_hbinterval) {
+ trans->hb_allowed = 1;
+- trans->hb_interval = params.spp_hbinterval * HZ / 1000;
++ trans->hb_interval =
++ MSECS_TO_JIFFIES(params.spp_hbinterval);
+ } else
+ trans->hb_allowed = 0;
+ }
+@@ -1560,11 +1770,12 @@ static int sctp_setsockopt_rtoinfo(struc
+
+ if (asoc) {
+ if (rtoinfo.srto_initial != 0)
+- asoc->rto_initial = rtoinfo.srto_initial * HZ / 1000;
++ asoc->rto_initial =
++ MSECS_TO_JIFFIES(rtoinfo.srto_initial);
+ if (rtoinfo.srto_max != 0)
+- asoc->rto_max = rtoinfo.srto_max * HZ / 1000;
++ asoc->rto_max = MSECS_TO_JIFFIES(rtoinfo.srto_max);
+ if (rtoinfo.srto_min != 0)
+- asoc->rto_min = rtoinfo.srto_min * HZ / 1000;
++ asoc->rto_min = MSECS_TO_JIFFIES(rtoinfo.srto_min);
+ } else {
+ /* If there is no association or the association-id = 0
+ * set the values to the endpoint.
+@@ -2088,14 +2299,14 @@ SCTP_STATIC int sctp_init_sock(struct so
+ sp->initmsg.sinit_num_ostreams = sctp_max_outstreams;
+ sp->initmsg.sinit_max_instreams = sctp_max_instreams;
+ sp->initmsg.sinit_max_attempts = sctp_max_retrans_init;
+- sp->initmsg.sinit_max_init_timeo = (sctp_rto_max / HZ) * 1000;
++ sp->initmsg.sinit_max_init_timeo = JIFFIES_TO_MSECS(sctp_rto_max);
+
+ /* Initialize default RTO related parameters. These parameters can
+ * be modified for with the SCTP_RTOINFO socket option.
+ */
+- sp->rtoinfo.srto_initial = (sctp_rto_initial / HZ) * 1000;
+- sp->rtoinfo.srto_max = (sctp_rto_max / HZ) * 1000;
+- sp->rtoinfo.srto_min = (sctp_rto_min / HZ) * 1000;
++ sp->rtoinfo.srto_initial = JIFFIES_TO_MSECS(sctp_rto_initial);
++ sp->rtoinfo.srto_max = JIFFIES_TO_MSECS(sctp_rto_max);
++ sp->rtoinfo.srto_min = JIFFIES_TO_MSECS(sctp_rto_min);
+
+ /* Initialize default association related parameters. These parameters
+ * can be modified with the SCTP_ASSOCINFO socket option.
+@@ -2104,8 +2315,8 @@ SCTP_STATIC int sctp_init_sock(struct so
+ sp->assocparams.sasoc_number_peer_destinations = 0;
+ sp->assocparams.sasoc_peer_rwnd = 0;
+ sp->assocparams.sasoc_local_rwnd = 0;
+- sp->assocparams.sasoc_cookie_life = (sctp_valid_cookie_life / HZ)
+- * 1000;
++ sp->assocparams.sasoc_cookie_life =
++ JIFFIES_TO_MSECS(sctp_valid_cookie_life);
+
+ /* Initialize default event subscriptions. By default, all the
+ * options are off.
+@@ -2115,7 +2326,7 @@ SCTP_STATIC int sctp_init_sock(struct so
+ /* Default Peer Address Parameters. These defaults can
+ * be modified via SCTP_PEER_ADDR_PARAMS
+ */
+- sp->paddrparam.spp_hbinterval = (sctp_hb_interval / HZ) * 1000;
++ sp->paddrparam.spp_hbinterval = JIFFIES_TO_MSECS(sctp_hb_interval);
+ sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
+
+ /* If enabled no SCTP message fragmentation will be performed.
+@@ -2265,7 +2476,7 @@ static int sctp_getsockopt_sctp_status(s
+ status.sstat_primary.spinfo_state = transport->active;
+ status.sstat_primary.spinfo_cwnd = transport->cwnd;
+ status.sstat_primary.spinfo_srtt = transport->srtt;
+- status.sstat_primary.spinfo_rto = (transport->rto / HZ) * 1000;
++ status.sstat_primary.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
+ status.sstat_primary.spinfo_mtu = transport->pmtu;
+
+ if (put_user(len, optlen)) {
+@@ -2320,7 +2531,7 @@ static int sctp_getsockopt_peer_addr_inf
+ pinfo.spinfo_state = transport->active;
+ pinfo.spinfo_cwnd = transport->cwnd;
+ pinfo.spinfo_srtt = transport->srtt;
+- pinfo.spinfo_rto = (transport->rto / HZ) * 1000;
++ pinfo.spinfo_rto = JIFFIES_TO_MSECS(transport->rto);
+ pinfo.spinfo_mtu = transport->pmtu;
+
+ if (put_user(len, optlen)) {
+@@ -2524,7 +2735,7 @@ static int sctp_getsockopt_peer_addr_par
+ if (!trans->hb_allowed)
+ params.spp_hbinterval = 0;
+ else
+- params.spp_hbinterval = trans->hb_interval * 1000 / HZ;
++ params.spp_hbinterval = JIFFIES_TO_MSECS(trans->hb_interval);
+
+ /* spp_pathmaxrxt contains the maximum number of retransmissions
+ * before this address shall be considered unreachable.
+@@ -2582,10 +2793,8 @@ static int sctp_getsockopt_peer_addrs_nu
+ list_for_each(pos, &asoc->peer.transport_addr_list) {
+ cnt ++;
+ }
+- if (copy_to_user(optval, &cnt, sizeof(int)))
+- return -EFAULT;
+
+- return 0;
++ return cnt;
+ }
+
+ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
+@@ -2666,10 +2875,8 @@ static int sctp_getsockopt_local_addrs_n
+ list_for_each(pos, &bp->address_list) {
+ cnt ++;
+ }
+- if (copy_to_user(optval, &cnt, sizeof(int)))
+- return -EFAULT;
+
+- return 0;
++ return cnt;
+ }
+
+ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
+@@ -2879,9 +3086,9 @@ static int sctp_getsockopt_rtoinfo(struc
+
+ /* Values corresponding to the specific association. */
+ if (asoc) {
+- rtoinfo.srto_initial = (asoc->rto_initial / HZ) * 1000;
+- rtoinfo.srto_max = (asoc->rto_max / HZ) * 1000;
+- rtoinfo.srto_min = (asoc->rto_min / HZ) * 1000;
++ rtoinfo.srto_initial = JIFFIES_TO_MSECS(asoc->rto_initial);
++ rtoinfo.srto_max = JIFFIES_TO_MSECS(asoc->rto_max);
++ rtoinfo.srto_min = JIFFIES_TO_MSECS(asoc->rto_min);
+ } else {
+ /* Values corresponding to the endpoint. */
+ struct sctp_opt *sp = sctp_sk(sk);
+--- linux-2.6.0-test6/net/sctp/sysctl.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/sctp/sysctl.c 2003-10-05 00:33:25.000000000 -0700
+@@ -44,7 +44,7 @@
+ #include <linux/sysctl.h>
+
+ static ctl_handler sctp_sysctl_jiffies_ms;
+-static long rto_timer_min = 0;
++static long rto_timer_min = 1;
+ static long rto_timer_max = 86400000; /* One day */
+
+ static ctl_table sctp_table[] = {
+--- linux-2.6.0-test6/net/socket.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/socket.c 2003-10-05 00:34:03.000000000 -0700
+@@ -394,6 +394,7 @@ int sock_map_fd(struct socket *sock)
+ file->f_dentry->d_op = &sockfs_dentry_operations;
+ d_add(file->f_dentry, SOCK_INODE(sock));
+ file->f_vfsmnt = mntget(sock_mnt);
++ file->f_mapping = file->f_dentry->d_inode->i_mapping;
+
+ sock->file = file;
+ file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
+@@ -1989,3 +1990,18 @@ void socket_seq_show(struct seq_file *se
+ seq_printf(seq, "sockets: used %d\n", counter);
+ }
+ #endif /* CONFIG_PROC_FS */
++
++/* ABI emulation layers need these two */
++EXPORT_SYMBOL(move_addr_to_kernel);
++EXPORT_SYMBOL(move_addr_to_user);
++EXPORT_SYMBOL(sock_alloc);
++EXPORT_SYMBOL(sock_alloc_inode);
++EXPORT_SYMBOL(sock_create);
++EXPORT_SYMBOL(sock_map_fd);
++EXPORT_SYMBOL(sock_recvmsg);
++EXPORT_SYMBOL(sock_register);
++EXPORT_SYMBOL(sock_release);
++EXPORT_SYMBOL(sock_sendmsg);
++EXPORT_SYMBOL(sock_unregister);
++EXPORT_SYMBOL(sock_wake_async);
++EXPORT_SYMBOL(sockfd_lookup);
+--- linux-2.6.0-test6/net/unix/af_unix.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/unix/af_unix.c 2003-10-05 00:33:25.000000000 -0700
+@@ -448,7 +448,7 @@ static int unix_listen(struct socket *so
+ sk->sk_max_ack_backlog = backlog;
+ sk->sk_state = TCP_LISTEN;
+ /* set credentials so connect can copy them */
+- sk->sk_peercred.pid = current->pid;
++ sk->sk_peercred.pid = current->tgid;
+ sk->sk_peercred.uid = current->euid;
+ sk->sk_peercred.gid = current->egid;
+ err = 0;
+@@ -983,7 +983,7 @@ restart:
+ unix_peer(newsk) = sk;
+ newsk->sk_state = TCP_ESTABLISHED;
+ newsk->sk_type = SOCK_STREAM;
+- newsk->sk_peercred.pid = current->pid;
++ newsk->sk_peercred.pid = current->tgid;
+ newsk->sk_peercred.uid = current->euid;
+ newsk->sk_peercred.gid = current->egid;
+ newu = unix_sk(newsk);
+@@ -1045,7 +1045,7 @@ static int unix_socketpair(struct socket
+ sock_hold(skb);
+ unix_peer(ska)=skb;
+ unix_peer(skb)=ska;
+- ska->sk_peercred.pid = skb->sk_peercred.pid = current->pid;
++ ska->sk_peercred.pid = skb->sk_peercred.pid = current->tgid;
+ ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
+ ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
+
+--- linux-2.6.0-test6/net/x25/af_x25.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/net/x25/af_x25.c 2003-10-05 00:34:48.000000000 -0700
+@@ -345,10 +345,8 @@ void x25_destroy_socket(struct sock *sk)
+ if (atomic_read(&sk->sk_wmem_alloc) ||
+ atomic_read(&sk->sk_rmem_alloc)) {
+ /* Defer: outstanding buffers */
+- init_timer(&sk->sk_timer);
+ sk->sk_timer.expires = jiffies + 10 * HZ;
+ sk->sk_timer.function = x25_destroy_timer;
+- sk->sk_timer.data = (unsigned long)sk;
+ add_timer(&sk->sk_timer);
+ } else {
+ /* drop last reference so sock_put will free */
+@@ -463,6 +461,8 @@ frees:
+ goto out;
+ }
+
++void x25_init_timers(struct sock *sk);
++
+ static int x25_create(struct socket *sock, int protocol)
+ {
+ struct sock *sk;
+@@ -481,7 +481,7 @@ static int x25_create(struct socket *soc
+ sock_init_data(sock, sk);
+ sk_set_owner(sk, THIS_MODULE);
+
+- init_timer(&x25->timer);
++ x25_init_timers(sk);
+
+ sock->ops = &x25_proto_ops;
+ sk->sk_protocol = protocol;
+@@ -537,7 +537,7 @@ static struct sock *x25_make_new(struct
+ x25->facilities = ox25->facilities;
+ x25->qbitincl = ox25->qbitincl;
+
+- init_timer(&x25->timer);
++ x25_init_timers(sk);
+ out:
+ return sk;
+ }
+--- linux-2.6.0-test6/net/x25/x25_link.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/net/x25/x25_link.c 2003-10-05 00:34:48.000000000 -0700
+@@ -51,15 +51,9 @@ static void x25_t20timer_expiry(unsigned
+ /*
+ * Linux set/reset timer routines
+ */
+-static void x25_start_t20timer(struct x25_neigh *nb)
++static inline void x25_start_t20timer(struct x25_neigh *nb)
+ {
+- del_timer(&nb->t20timer);
+-
+- nb->t20timer.data = (unsigned long)nb;
+- nb->t20timer.function = &x25_t20timer_expiry;
+- nb->t20timer.expires = jiffies + nb->t20;
+-
+- add_timer(&nb->t20timer);
++ mod_timer(&nb->t20timer, jiffies + nb->t20);
+ }
+
+ static void x25_t20timer_expiry(unsigned long param)
+@@ -71,12 +65,12 @@ static void x25_t20timer_expiry(unsigned
+ x25_start_t20timer(nb);
+ }
+
+-static void x25_stop_t20timer(struct x25_neigh *nb)
++static inline void x25_stop_t20timer(struct x25_neigh *nb)
+ {
+ del_timer(&nb->t20timer);
+ }
+
+-static int x25_t20timer_pending(struct x25_neigh *nb)
++static inline int x25_t20timer_pending(struct x25_neigh *nb)
+ {
+ return timer_pending(&nb->t20timer);
+ }
+@@ -291,6 +285,8 @@ void x25_link_device_up(struct net_devic
+ skb_queue_head_init(&nb->queue);
+
+ init_timer(&nb->t20timer);
++ nb->t20timer.data = (unsigned long)nb;
++ nb->t20timer.function = &x25_t20timer_expiry;
+
+ dev_hold(dev);
+ nb->dev = dev;
+--- linux-2.6.0-test6/net/x25/x25_timer.c 2003-06-14 12:17:57.000000000 -0700
++++ 25/net/x25/x25_timer.c 2003-10-05 00:34:48.000000000 -0700
+@@ -43,15 +43,22 @@
+ static void x25_heartbeat_expiry(unsigned long);
+ static void x25_timer_expiry(unsigned long);
+
+-void x25_start_heartbeat(struct sock *sk)
++void x25_init_timers(struct sock *sk)
+ {
+- del_timer(&sk->sk_timer);
++ struct x25_opt *x25 = x25_sk(sk);
+
++ init_timer(&x25->timer);
++ x25->timer.data = (unsigned long)sk;
++ x25->timer.function = &x25_timer_expiry;
++
++ /* initialized by sock_init_data */
+ sk->sk_timer.data = (unsigned long)sk;
+ sk->sk_timer.function = &x25_heartbeat_expiry;
+- sk->sk_timer.expires = jiffies + 5 * HZ;
++}
+
+- add_timer(&sk->sk_timer);
++void x25_start_heartbeat(struct sock *sk)
++{
++ mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
+ }
+
+ void x25_stop_heartbeat(struct sock *sk)
+@@ -63,52 +70,28 @@ void x25_start_t2timer(struct sock *sk)
+ {
+ struct x25_opt *x25 = x25_sk(sk);
+
+- del_timer(&x25->timer);
+-
+- x25->timer.data = (unsigned long)sk;
+- x25->timer.function = &x25_timer_expiry;
+- x25->timer.expires = jiffies + x25->t2;
+-
+- add_timer(&x25->timer);
++ mod_timer(&x25->timer, jiffies + x25->t2);
+ }
+
+ void x25_start_t21timer(struct sock *sk)
+ {
+ struct x25_opt *x25 = x25_sk(sk);
+
+- del_timer(&x25->timer);
+-
+- x25->timer.data = (unsigned long)sk;
+- x25->timer.function = &x25_timer_expiry;
+- x25->timer.expires = jiffies + x25->t21;
+-
+- add_timer(&x25->timer);
++ mod_timer(&x25->timer, jiffies + x25->t21);
+ }
+
+ void x25_start_t22timer(struct sock *sk)
+ {
+ struct x25_opt *x25 = x25_sk(sk);
+
+- del_timer(&x25->timer);
+-
+- x25->timer.data = (unsigned long)sk;
+- x25->timer.function = &x25_timer_expiry;
+- x25->timer.expires = jiffies + x25->t22;
+-
+- add_timer(&x25->timer);
++ mod_timer(&x25->timer, jiffies + x25->t22);
+ }
+
+ void x25_start_t23timer(struct sock *sk)
+ {
+ struct x25_opt *x25 = x25_sk(sk);
+
+- del_timer(&x25->timer);
+-
+- x25->timer.data = (unsigned long)sk;
+- x25->timer.function = &x25_timer_expiry;
+- x25->timer.expires = jiffies + x25->t23;
+-
+- add_timer(&x25->timer);
++ mod_timer(&x25->timer, jiffies + x25->t23);
+ }
+
+ void x25_stop_timer(struct sock *sk)
+--- linux-2.6.0-test6/net/xfrm/xfrm_algo.c 2003-08-22 19:23:42.000000000 -0700
++++ 25/net/xfrm/xfrm_algo.c 2003-10-05 00:33:25.000000000 -0700
+@@ -8,7 +8,9 @@
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
++
+ #include <linux/config.h>
++#include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/pfkeyv2.h>
+ #include <net/xfrm.h>
+@@ -617,6 +619,7 @@ skb_to_sgvec(struct sk_buff *skb, struct
+ BUG();
+ return elt;
+ }
++EXPORT_SYMBOL_GPL(skb_to_sgvec);
+
+ /* Check that skb data bits are writable. If they are not, copy data
+ * to newly created private area. If "tailbits" is given, make sure that
+@@ -717,6 +720,7 @@ int skb_cow_data(struct sk_buff *skb, in
+
+ return elt;
+ }
++EXPORT_SYMBOL_GPL(skb_cow_data);
+
+ void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
+ {
+@@ -726,4 +730,5 @@ void *pskb_put(struct sk_buff *skb, stru
+ }
+ return skb_put(tail, len);
+ }
++EXPORT_SYMBOL_GPL(pskb_put);
+ #endif
+--- linux-2.6.0-test6/scripts/bin2c.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/scripts/bin2c.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,3 +1,12 @@
++/*
++ * Unloved program to convert a binary on stdin to a C include on stdout
++ *
++ * Jan 1999 Matt Mackall <mpm@selenic.com>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ */
++
+ #include <stdio.h>
+
+ int main(int argc, char *argv[])
+--- linux-2.6.0-test6/scripts/pnmtologo.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/scripts/pnmtologo.c 2003-10-05 00:33:25.000000000 -0700
+@@ -119,7 +119,8 @@ static unsigned int get_number255(FILE *
+ static void read_image(void)
+ {
+ FILE *fp;
+- int i, j, magic;
++ unsigned int i, j;
++ int magic;
+ unsigned int maxval;
+
+ /* open image file */
+@@ -274,7 +275,7 @@ static void write_hex(unsigned char byte
+
+ static void write_logo_mono(void)
+ {
+- int i, j;
++ unsigned int i, j;
+ unsigned char val, bit;
+
+ /* validate image */
+@@ -302,7 +303,7 @@ static void write_logo_mono(void)
+
+ static void write_logo_vga16(void)
+ {
+- int i, j, k;
++ unsigned int i, j, k;
+ unsigned char val;
+
+ /* validate image */
+@@ -342,7 +343,7 @@ static void write_logo_vga16(void)
+
+ static void write_logo_clut224(void)
+ {
+- int i, j, k;
++ unsigned int i, j, k;
+
+ /* validate image */
+ for (i = 0; i < logo_height; i++)
+@@ -388,7 +389,7 @@ static void write_logo_clut224(void)
+
+ static void write_logo_gray256(void)
+ {
+- int i, j;
++ unsigned int i, j;
+
+ /* validate image */
+ for (i = 0; i < logo_height; i++)
+--- linux-2.6.0-test6/security/dummy.c 2003-07-10 18:50:32.000000000 -0700
++++ 25/security/dummy.c 2003-10-05 00:33:25.000000000 -0700
+@@ -364,7 +364,7 @@ static int dummy_inode_follow_link (stru
+ return 0;
+ }
+
+-static int dummy_inode_permission (struct inode *inode, int mask)
++static int dummy_inode_permission (struct inode *inode, int mask, struct nameidata *nd)
+ {
+ return 0;
+ }
+--- linux-2.6.0-test6/security/selinux/hooks.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/security/selinux/hooks.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1730,13 +1730,18 @@ static int selinux_inode_follow_link(str
+ return dentry_has_perm(current, NULL, dentry, FILE__READ);
+ }
+
+-static int selinux_inode_permission(struct inode *inode, int mask)
++static int selinux_inode_permission(struct inode *inode, int mask,
++ struct nameidata *nd)
+ {
+ if (!mask) {
+ /* No permission to check. Existence test. */
+ return 0;
+ }
+
++ if (nd && nd->dentry)
++ return dentry_has_perm(current, nd->mnt, nd->dentry,
++ file_mask_to_av(inode->i_mode, mask));
++
+ return inode_has_perm(current, inode,
+ file_mask_to_av(inode->i_mode, mask), NULL, NULL);
+ }
+--- linux-2.6.0-test6/security/selinux/ss/services.c 2003-08-08 22:55:14.000000000 -0700
++++ 25/security/selinux/ss/services.c 2003-10-05 00:33:25.000000000 -0700
+@@ -896,7 +896,7 @@ static int convert_context(u32 key,
+ struct user_datum *usrdatum;
+ char *s;
+ u32 len;
+- int rc = -EINVAL;
++ int rc;
+
+ args = p;
+
+@@ -904,6 +904,8 @@ static int convert_context(u32 key,
+ if (rc)
+ goto out;
+
++ rc = -EINVAL;
++
+ /* Convert the user. */
+ usrdatum = hashtab_search(args->newp->p_users.table,
+ args->oldp->p_user_val_to_name[c->user - 1]);
+--- linux-2.6.0-test6/sound/oss/ac97_codec.c 2003-09-27 18:57:47.000000000 -0700
++++ 25/sound/oss/ac97_codec.c 2003-10-05 00:33:25.000000000 -0700
+@@ -46,7 +46,6 @@
+ * Isolated from trident.c to support multiple ac97 codec
+ */
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+--- linux-2.6.0-test6/sound/oss/ali5455.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/ali5455.c 2003-10-05 00:33:25.000000000 -0700
+@@ -47,7 +47,6 @@
+ */
+
+ #include <linux/module.h>
+-#include <linux/version.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+ #include <linux/ioport.h>
+--- linux-2.6.0-test6/sound/oss/au1000.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/au1000.c 2003-10-05 00:33:25.000000000 -0700
+@@ -50,7 +50,6 @@
+ * channels [stevel].
+ *
+ */
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+@@ -2223,8 +2222,9 @@ static int __init au1000_setup(char *opt
+ if (!options || !*options)
+ return 0;
+
+- for(this_opt=strtok(options, ",");
+- this_opt; this_opt=strtok(NULL, ",")) {
++ while (this_opt = strsep(&options, ",")) {
++ if (!*this_opt)
++ continue;
+ if (!strncmp(this_opt, "vra", 3)) {
+ vra = 1;
+ }
+--- linux-2.6.0-test6/sound/oss/btaudio.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/btaudio.c 2003-10-05 00:33:25.000000000 -0700
+@@ -177,8 +177,11 @@ static int alloc_buffer(struct btaudio *
+ bta->risc_size = PAGE_SIZE;
+ bta->risc_cpu = pci_alloc_consistent
+ (bta->pci, bta->risc_size, &bta->risc_dma);
+- if (NULL == bta->risc_cpu)
++ if (NULL == bta->risc_cpu) {
++ pci_free_consistent(bta->pci, bta->buf_size, bta->buf_cpu, bta->buf_dma);
++ bta->buf_cpu = NULL;
+ return -ENOMEM;
++ }
+ }
+ return 0;
+ }
+--- linux-2.6.0-test6/sound/oss/dmasound/dac3550a.c 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/oss/dmasound/dac3550a.c 2003-10-05 00:33:25.000000000 -0700
+@@ -7,7 +7,6 @@
+ * for more details.
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/sound/oss/dmasound/Kconfig 2003-09-27 18:57:47.000000000 -0700
++++ 25/sound/oss/dmasound/Kconfig 2003-10-05 00:33:25.000000000 -0700
+@@ -1,7 +1,7 @@
+-# drivers/sound/dmasound/Config.in
+ config DMASOUND_ATARI
+ tristate "Atari DMA sound support"
+ depends on ATARI && SOUND
++ select DMASOUND
+ help
+ If you want to use the internal audio of your Atari in Linux, answer
+ Y to this question. This will provide a Sun-like /dev/audio,
+@@ -15,6 +15,7 @@ config DMASOUND_ATARI
+ config DMASOUND_PMAC
+ tristate "PowerMac DMA sound support"
+ depends on PPC_PMAC && SOUND && I2C
++ select DMASOUND
+ help
+ If you want to use the internal audio of your PowerMac in Linux,
+ answer Y to this question. This will provide a Sun-like /dev/audio,
+@@ -28,6 +29,7 @@ config DMASOUND_PMAC
+ config DMASOUND_PAULA
+ tristate "Amiga DMA sound support"
+ depends on (AMIGA || APUS) && SOUND
++ select DMASOUND
+ help
+ If you want to use the internal audio of your Amiga in Linux, answer
+ Y to this question. This will provide a Sun-like /dev/audio,
+@@ -41,6 +43,7 @@ config DMASOUND_PAULA
+ config DMASOUND_Q40
+ tristate "Q40 sound support"
+ depends on Q40 && SOUND
++ select DMASOUND
+ help
+ If you want to use the internal audio of your Q40 in Linux, answer
+ Y to this question. This will provide a Sun-like /dev/audio,
+@@ -53,13 +56,3 @@ config DMASOUND_Q40
+
+ config DMASOUND
+ tristate
+- depends on SOUND!=n
+- default m if DMASOUND_ATARI!=y && DMASOUND_AWACS!=y && DMASOUND_PAULA!=y && DMASOUND_Q40!=y && (DMASOUND_ATARI=m || DMASOUND_AWACS=m || DMASOUND_PAULA=m || DMASOUND_Q40=m)
+- default y if DMASOUND_ATARI=y || DMASOUND_AWACS=y || DMASOUND_PAULA=y || DMASOUND_Q40=y
+- help
+- Support built-in audio chips accessible by DMA on various machines
+- that have them. Note that this symbol does not affect the kernel
+- directly; rather, it controls whether configuration questions
+- enabling DMA sound drivers for various specific machine
+- architectures will be used.
+-
+--- linux-2.6.0-test6/sound/oss/dmasound/tas3001c.c 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/oss/dmasound/tas3001c.c 2003-10-05 00:33:25.000000000 -0700
+@@ -15,7 +15,6 @@
+ *
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/sound/oss/dmasound/tas3004.c 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/oss/dmasound/tas3004.c 2003-10-05 00:33:25.000000000 -0700
+@@ -13,7 +13,6 @@
+ *
+ */
+
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/sound/oss/dmasound/tas_common.c 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/oss/dmasound/tas_common.c 2003-10-05 00:33:25.000000000 -0700
+@@ -1,4 +1,3 @@
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/proc_fs.h>
+--- linux-2.6.0-test6/sound/oss/harmony.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/harmony.c 2003-10-05 00:33:25.000000000 -0700
+@@ -28,14 +28,14 @@ TODO:
+ #include <linux/delay.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/types.h>
+ #include <linux/mm.h>
+ #include <linux/pci.h>
+
+-#include <asm/gsc.h>
++#include <asm/parisc-device.h>
+ #include <asm/io.h>
+-#include <asm/pgalloc.h>
+
+ #include "sound_config.h"
+
+--- linux-2.6.0-test6/sound/oss/ite8172.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/ite8172.c 2003-10-05 00:33:25.000000000 -0700
+@@ -54,7 +54,6 @@
+ * 07.30.2003 Removed initialisation to zero for static variables
+ * (spdif[NR_DEVICE], i2s_fmt[NR_DEVICE], and devindex)
+ */
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+@@ -2238,8 +2237,9 @@ static int __init it8172_setup(char *opt
+ if (!options || !*options)
+ return 0;
+
+- for(this_opt=strtok(options, ",");
+- this_opt; this_opt=strtok(NULL, ",")) {
++ while (this_opt = strsep(&options, ",")) {
++ if (!*this_opt)
++ continue;
+ if (!strncmp(this_opt, "spdif", 5)) {
+ spdif[nr_dev] = 1;
+ } else if (!strncmp(this_opt, "i2s:", 4)) {
+--- linux-2.6.0-test6/sound/oss/opl3sa2.c 2003-08-22 19:23:43.000000000 -0700
++++ 25/sound/oss/opl3sa2.c 2003-10-05 00:33:25.000000000 -0700
+@@ -324,15 +324,6 @@ static void opl3sa3_set_treble(opl3sa2_s
+ }
+
+
+-static void opl3sa3_set_wide(opl3sa2_state_t* devc, int left, int right)
+-{
+- unsigned char wide;
+-
+- wide = left ? ((unsigned char) (8 * left / 101)) : 0;
+- wide |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
+-
+- opl3sa2_write(devc->cfg_port, OPL3SA3_WIDE, wide);
+-}
+
+
+ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
+@@ -401,7 +392,7 @@ static inline int ret_vol_stereo(int lef
+
+ static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+ {
+- int cmdf = cmd & 0xff;
++ int retval, value, cmdf = cmd & 0xff;
+
+ opl3sa2_state_t* devc = &opl3sa2_state[dev];
+
+@@ -422,23 +413,31 @@ static int opl3sa2_mixer_ioctl(int dev,
+ if (((cmd >> 8) & 0xff) != 'M')
+ return -EINVAL;
+
++ retval = 0;
+ if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
+ switch (cmdf) {
+ case SOUND_MIXER_VOLUME:
+- arg_to_vol_stereo(*(unsigned int*)arg,
+- &devc->volume_l, &devc->volume_r);
++ retval = get_user(value, (unsigned int *) arg);
++ if (retval)
++ break;
++ arg_to_vol_stereo(value, &devc->volume_l, &devc->volume_r);
+ opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
+- *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r);
+- return 0;
++ value = ret_vol_stereo(devc->volume_l, devc->volume_r);
++ retval = put_user(value, (int *) arg);
++ break;
+
+ case SOUND_MIXER_MIC:
+- arg_to_vol_mono(*(unsigned int*)arg, &devc->mic);
++ retval = get_user(value, (unsigned int *) arg);
++ if (retval)
++ break;
++ arg_to_vol_mono(value, &devc->mic);
+ opl3sa2_set_mic(devc, devc->mic);
+- *(int*)arg = ret_vol_mono(devc->mic);
+- return 0;
++ value = ret_vol_mono(devc->mic);
++ retval = put_user(value, (int *) arg);
++ break;
+
+ default:
+- return -EINVAL;
++ retval = -EINVAL;
+ }
+ }
+ else {
+@@ -447,122 +446,72 @@ static int opl3sa2_mixer_ioctl(int dev,
+ */
+ switch (cmdf) {
+ case SOUND_MIXER_DEVMASK:
+- *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC);
+- return 0;
++ retval = put_user(SOUND_MASK_VOLUME | SOUND_MASK_MIC, (int *) arg);
++ break;
+
+ case SOUND_MIXER_STEREODEVS:
+- *(int*)arg = SOUND_MASK_VOLUME;
+- return 0;
++ retval = put_user(SOUND_MASK_VOLUME, (int *) arg);
++ break;
+
+ case SOUND_MIXER_RECMASK:
+ /* No recording devices */
+- return (*(int*)arg = 0);
++ retval = put_user(0, (int *) arg);
++ break;
+
+ case SOUND_MIXER_CAPS:
+- *(int*)arg = SOUND_CAP_EXCL_INPUT;
+- return 0;
++ retval = put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
++ break;
+
+ case SOUND_MIXER_RECSRC:
+ /* No recording source */
+- return (*(int*)arg = 0);
++ retval = put_user(0, (int *) arg);
++ break;
+
+ case SOUND_MIXER_VOLUME:
+- *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r);
+- return 0;
++ value = ret_vol_stereo(devc->volume_l, devc->volume_r);
++ retval = put_user(value, (int *) arg);
++ break;
+
+ case SOUND_MIXER_MIC:
+- *(int*)arg = ret_vol_mono(devc->mic);
+- return 0;
++ value = ret_vol_mono(devc->mic);
++ put_user(value, (int *) arg);
++ break;
+
+ default:
+- return -EINVAL;
++ retval = -EINVAL;
+ }
+ }
++ return retval;
+ }
+ /* opl3sa2_mixer_ioctl end */
+
+
+ static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+ {
+- int cmdf = cmd & 0xff;
++ int value, retval, cmdf = cmd & 0xff;
+
+ opl3sa2_state_t* devc = &opl3sa2_state[dev];
+
+ switch (cmdf) {
+- case SOUND_MIXER_BASS:
+- case SOUND_MIXER_TREBLE:
+- case SOUND_MIXER_DIGITAL1:
+- case SOUND_MIXER_DEVMASK:
+- case SOUND_MIXER_STEREODEVS:
+- break;
+-
+- default:
+- return opl3sa2_mixer_ioctl(dev, cmd, arg);
+- }
+-
+- if (((cmd >> 8) & 0xff) != 'M')
+- return -EINVAL;
++ case SOUND_MIXER_BASS:
++ value = ret_vol_stereo(devc->bass_l, devc->bass_r);
++ retval = put_user(value, (int *) arg);
++ break;
+
+- if (_SIOC_DIR (cmd) & _SIOC_WRITE) {
+- switch (cmdf) {
+- case SOUND_MIXER_BASS:
+- arg_to_vol_stereo(*(unsigned int*)arg,
+- &devc->bass_l, &devc->bass_r);
+- opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
+- *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r);
+- return 0;
+-
+- case SOUND_MIXER_TREBLE:
+- arg_to_vol_stereo(*(unsigned int*)arg,
+- &devc->treble_l, &devc->treble_r);
+- opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
+- *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r);
+- return 0;
+-
+- case SOUND_MIXER_DIGITAL1:
+- arg_to_vol_stereo(*(unsigned int*)arg,
+- &devc->wide_l, &devc->wide_r);
+- opl3sa3_set_wide(devc, devc->wide_l, devc->wide_r);
+- *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r);
+- return 0;
++ case SOUND_MIXER_TREBLE:
++ value = ret_vol_stereo(devc->treble_l, devc->treble_r);
++ retval = put_user(value, (int *) arg);
++ break;
+
+- default:
+- return -EINVAL;
+- }
+- }
+- else
+- {
+- /*
+- * Return parameters
+- */
+- switch (cmdf) {
+- case SOUND_MIXER_DEVMASK:
+- *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC |
+- SOUND_MASK_BASS | SOUND_MASK_TREBLE |
+- SOUND_MASK_DIGITAL1);
+- return 0;
+-
+- case SOUND_MIXER_STEREODEVS:
+- *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_BASS |
+- SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1);
+- return 0;
+-
+- case SOUND_MIXER_BASS:
+- *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r);
+- return 0;
+-
+- case SOUND_MIXER_TREBLE:
+- *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r);
+- return 0;
+-
+- case SOUND_MIXER_DIGITAL1:
+- *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r);
+- return 0;
++ case SOUND_MIXER_DIGITAL1:
++ value = ret_vol_stereo(devc->wide_l, devc->wide_r);
++ retval = put_user(value, (int *) arg);
++ break;
+
+- default:
+- return -EINVAL;
+- }
++ default:
++ retval = -EINVAL;
+ }
++ return retval;
+ }
+ /* opl3sa3_mixer_ioctl end */
+
+--- linux-2.6.0-test6/sound/oss/swarm_cs4297a.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/swarm_cs4297a.c 2003-10-05 00:33:25.000000000 -0700
+@@ -59,7 +59,6 @@
+ *******************************************************************************/
+
+ #include <linux/list.h>
+-#include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/ioport.h>
+--- linux-2.6.0-test6/sound/oss/via82cxxx_audio.c 2003-09-08 13:58:59.000000000 -0700
++++ 25/sound/oss/via82cxxx_audio.c 2003-10-05 00:36:10.000000000 -0700
+@@ -1844,6 +1844,7 @@ static void via_ac97_cleanup (struct via
+
+ /**
+ * via_intr_channel - handle an interrupt for a single channel
++ * @card: unused
+ * @chan: handle interrupt for this channel
+ *
+ * This is the "meat" of the interrupt handler,
+--- linux-2.6.0-test6/sound/parisc/harmony.c 2003-08-22 19:23:43.000000000 -0700
++++ 25/sound/parisc/harmony.c 2003-10-05 00:33:25.000000000 -0700
+@@ -66,6 +66,7 @@
+ #include <linux/delay.h>
+ #include <sound/driver.h>
+ #include <linux/init.h>
++#include <linux/interrupt.h>
+ #include <linux/slab.h>
+ #include <linux/time.h>
+ #include <linux/wait.h>
+@@ -77,8 +78,8 @@
+ #include <sound/initval.h>
+ #include <sound/info.h>
+ #include <asm/hardware.h>
+-#include <asm/gsc.h>
+ #include <asm/io.h>
++#include <asm/parisc-device.h>
+
+ MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
+ MODULE_DESCRIPTION("ALSA Harmony sound driver");
+@@ -709,8 +710,8 @@ static int snd_card_harmony_playback_ope
+ * harmony is not "real" pci, but we need a pci_dev
+ * to alloc PCI DMA pages
+ */
+- substream->dma_private = harmony->fake_pci_dev;
+- substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI;
++ substream->runtime->dma_private = harmony->fake_pci_dev;
++// substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI;
+
+ harmony->playback_substream = substream;
+ runtime->hw = snd_card_harmony_playback;
+@@ -733,8 +734,8 @@ static int snd_card_harmony_capture_open
+ * harmony is not "real" pci, but we need a pci_dev
+ * to alloc PCI DMA pages
+ */
+- substream->dma_private = harmony->fake_pci_dev;
+- substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI;
++ substream->runtime->dma_private = harmony->fake_pci_dev;
++// substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI;
+
+ harmony->capture_substream = substream;
+ runtime->hw = snd_card_harmony_capture;
+--- linux-2.6.0-test6/sound/pci/cmipci.c 2003-08-08 22:55:15.000000000 -0700
++++ 25/sound/pci/cmipci.c 2003-10-05 00:33:25.000000000 -0700
+@@ -2791,6 +2791,7 @@ static int __devinit snd_cmipci_mixer_ne
+ * proc interface
+ */
+
++#ifdef CONFIG_PROC_FS
+ static void snd_cmipci_proc_read(snd_info_entry_t *entry,
+ snd_info_buffer_t *buffer)
+ {
+@@ -2817,6 +2818,9 @@ static void __devinit snd_cmipci_proc_in
+ if (! snd_card_proc_new(cm->card, "cmipci", &entry))
+ snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read);
+ }
++#else /* !CONFIG_PROC_FS */
++static inline void snd_cmipci_proc_init(cmipci_t *cm) {}
++#endif
+
+
+ static struct pci_device_id snd_cmipci_ids[] = {
+--- linux-2.6.0-test6/sound/pci/intel8x0.c 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/pci/intel8x0.c 2003-10-05 00:34:31.000000000 -0700
+@@ -2271,10 +2271,8 @@ static void __devinit intel8x0_measure_a
+
+ t = stop_time.tv_sec - start_time.tv_sec;
+ t *= 1000000;
+- if (stop_time.tv_usec < start_time.tv_usec)
+- t -= start_time.tv_usec - stop_time.tv_usec;
+- else
+- t += stop_time.tv_usec - start_time.tv_usec;
++ t += stop_time.tv_usec - start_time.tv_usec;
++ printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t);
+ if (t == 0) {
+ snd_printk(KERN_ERR "?? calculation error..\n");
+ return;
+--- linux-2.6.0-test6/sound/pci/Kconfig 2003-09-27 18:57:48.000000000 -0700
++++ 25/sound/pci/Kconfig 2003-10-05 00:34:45.000000000 -0700
+@@ -17,7 +17,8 @@ config SND_AZT3328
+
+ config SND_CS46XX
+ tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 /
+ CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips.
+@@ -30,7 +31,8 @@ config SND_CS46XX_NEW_DSP
+
+ config SND_CS4281
+ tristate "Cirrus Logic (Sound Fusion) CS4281"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for Cirrus Logic CS4281.
+
+@@ -83,7 +85,8 @@ config SND_HDSP
+
+ config SND_TRIDENT
+ tristate "Trident 4D-Wave DX/NX; SiS 7018"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for Trident 4D-Wave DX/NX and
+ SiS 7018 soundcards.
+@@ -110,20 +113,23 @@ config SND_CMIPCI
+
+ config SND_ENS1370
+ tristate "(Creative) Ensoniq AudioPCI 1370"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1370.
+
+ config SND_ENS1371
+ tristate "(Creative) Ensoniq AudioPCI 1371/1373"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1371 and
+ Sound Blaster PCI 64 or 128 soundcards.
+
+ config SND_ES1938
+ tristate "ESS ES1938/1946/1969 (Solo-1)"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for ESS Solo-1 (ES1938, ES1946, ES1969)
+ soundcard.
+@@ -173,7 +179,8 @@ config SND_INTEL8X0
+
+ config SND_SONICVIBES
+ tristate "S3 SonicVibes"
+- depends on SND && GAMEPORT
++ depends on SND
++ select GAMEPORT
+ help
+ Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
+