## Automatically generated incremental diff
## From:   linux-2.4.27-pre5
## To:     linux-2.4.27-pre6
## Robot:  $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $

diff -urN linux-2.4.27-pre5/Documentation/Configure.help linux-2.4.27-pre6/Documentation/Configure.help
--- linux-2.4.27-pre5/Documentation/Configure.help	2004-06-16 11:33:25.760988411 -0700
+++ linux-2.4.27-pre6/Documentation/Configure.help	2004-06-16 11:33:27.707069401 -0700
@@ -1309,11 +1309,13 @@
 
   If unsure, say N.
 
-PROMISE PDC20246/PDC20262/PDC20265/PDC20267/PDC20268 support
+Promise PDC202{46|62|65|67} support
 CONFIG_BLK_DEV_PDC202XX_OLD
-  Promise Ultra33 or PDC20246
-  Promise Ultra66 or PDC20262
-  Promise Ultra100 or PDC20265/PDC20267/PDC20268
+  Promise Ultra 33 [PDC20246]
+  Promise Ultra 66 [PDC20262]
+  Promise FastTrak 66 [PDC20263]
+  Promise MB Ultra 100 [PDC20265]
+  Promise Ultra 100 [PDC20267]
 
   This driver adds up to 4 more EIDE devices sharing a single
   interrupt. This add-on card is a bootable PCI UDMA controller. Since
@@ -1322,7 +1324,7 @@
   not match, the driver attempts to do dynamic tuning of the chipset
   at boot-time for max-speed.  Ultra33 BIOS 1.25 or newer is required
   for more than one card. This card may require that you say Y to
-  "Special UDMA Feature".
+  "Force (U)DMA burst transfers" (old name: "Special UDMA Feature").
 
   If you say Y here, you need to say Y to "Use DMA by default when
   available" as well.
@@ -1332,7 +1334,7 @@
 
   If unsure, say N.
 
-PROMISE PDC202{68|69|70|71|75|76|77} support
+Promise PDC202{68|69|70|71|75|76|77} support
 CONFIG_BLK_DEV_PDC202XX_NEW
   Promise Ultra 100 TX2 [PDC20268]
   Promise Ultra 133 PTX2 [PDC20269]
@@ -1347,17 +1349,16 @@
   multiple cards can be installed and there are BIOS ROM problems that
   happen if the BIOS revisions of all installed cards (max of five) do
   not match, the driver attempts to do dynamic tuning of the chipset
-  at boot-time for max speed.  Ultra33 BIOS 1.25 or newer is required
-  for more than one card.
+  at boot-time for max speed.
 
   If you say Y here, you need to say Y to "Use DMA by default when
   available" as well.
 
   If unsure, say N.
 
-Special UDMA Feature
+Force (U)DMA burst transfers
 CONFIG_PDC202XX_BURST
-  This option causes the pdc202xx driver to enable UDMA modes on the
+  This option causes the pdc202xx_old driver to enable UDMA modes on the
   PDC202xx even when the PDC202xx BIOS has not done so.
 
   It was originally designed for the PDC20246/Ultra33, whose BIOS will
@@ -1370,9 +1371,17 @@
 
   If unsure, say N.
 
-Special FastTrak Feature
+Ignore BIOS port disabled setting on FastTrak
 CONFIG_PDC202XX_FORCE
-  For FastTrak enable overriding BIOS.
+  Chipsets affected:
+
+  PDC202{46|62|63|65|67}
+  (pdc202xx_old driver)
+
+  PDC202{70|76}
+  (pdc202xx_new driver)
+
+  Say Y unless you want to use Promise proprietary driver.
 
 SiS5513 chipset support
 CONFIG_BLK_DEV_SIS5513
@@ -5596,14 +5605,15 @@
 SIS 300 series support
 CONFIG_FB_SIS_300
   This enables support for SiS 300 series chipsets (300/305, 540, 630,
-  730).  Documentation available at the maintainer's website at
-   <http://www.winischhofer.net/linuxsisvga.shtml>.
+  630S, 730S). Documentation available at the maintainer's website at
+  <http://www.winischhofer.net/linuxsisvga.shtml>.
 
 SIS 315/330 series support
 CONFIG_FB_SIS_315
-  This enables support for SiS 315/330 series chipsets (315, 550, 650,
-  M650, 651, 661FX, M661FX, 740, 741, 330). Documentation available at
-  the maintainer's site <http://www.winischhofer.net/linuxsisvga.shtml>.
+  This enables support for SiS 315/330 series chipsets (315, 315PRO, 
+  55x, (M)650, 651, (M)661FX, 661MX, 740, (M)741(GX), (M)760, 330).
+  Documentation available at the maintainer's website at
+  <http://www.winischhofer.net/linuxsisvga.shtml>.
 
 IMS Twin Turbo display support
 CONFIG_FB_IMSTT
@@ -17332,7 +17342,7 @@
   automounter (amd), which is a pure user space daemon.
 
   To use the automounter you need the user-space tools from
-  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
+  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/v4/>; you also
   want to answer Y to "NFS file system support", below.
 
   If you want to compile this as a module ( = code which can be
diff -urN linux-2.4.27-pre5/Documentation/ioctl-number.txt linux-2.4.27-pre6/Documentation/ioctl-number.txt
--- linux-2.4.27-pre5/Documentation/ioctl-number.txt	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.27-pre6/Documentation/ioctl-number.txt	2004-06-16 11:33:27.710069526 -0700
@@ -183,5 +183,6 @@
 0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:michael.klein@puffin.lb.shuttle.de>
-
+0xF3    00-3F   linux/sisfb.h 		SiS framebuffer device driver
+					<mailto:thomas@winischhofer.net>
 0xFE	00-9F	Logical Volume Manager	<mailto:linux-lvm@sistina.com>
diff -urN linux-2.4.27-pre5/Documentation/networking/packet_mmap.txt linux-2.4.27-pre6/Documentation/networking/packet_mmap.txt
--- linux-2.4.27-pre5/Documentation/networking/packet_mmap.txt	2004-04-14 06:05:25.000000000 -0700
+++ linux-2.4.27-pre6/Documentation/networking/packet_mmap.txt	2004-06-16 11:33:27.711069568 -0700
@@ -1,11 +1,3 @@
-
-DaveM:
-
-If you agree with it I will send two small patches to modify
-kernel's configure help. 
-
-	Ulisses
-
 --------------------------------------------------------------------------------
 + ABSTRACT
 --------------------------------------------------------------------------------
@@ -405,8 +397,3 @@
    
    Jesse Brandeburg, for fixing my grammathical/spelling errors
 
->>> EOF
--
-To unsubscribe from this list: send the line "unsubscribe linux-net" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at  http://vger.kernel.org/majordomo-info.html
\ No newline at end of file
diff -urN linux-2.4.27-pre5/Makefile linux-2.4.27-pre6/Makefile
--- linux-2.4.27-pre5/Makefile	2004-06-16 11:33:25.854992323 -0700
+++ linux-2.4.27-pre6/Makefile	2004-06-16 11:33:27.713069651 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 27
-EXTRAVERSION = -pre5
+EXTRAVERSION = -pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -175,6 +175,7 @@
 DRIVERS-$(CONFIG_PPC32) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o
+DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
 DRIVERS-$(CONFIG_VT) += drivers/video/video.o
 DRIVERS-$(CONFIG_PARIDE) += drivers/block/paride/paride.a
 DRIVERS-$(CONFIG_HAMRADIO) += drivers/net/hamradio/hamradio.o
@@ -186,7 +187,6 @@
 DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o
 DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
-DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
 DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
 DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o
diff -urN linux-2.4.27-pre5/arch/alpha/kernel/sys_eiger.c linux-2.4.27-pre6/arch/alpha/kernel/sys_eiger.c
--- linux-2.4.27-pre5/arch/alpha/kernel/sys_eiger.c	2001-10-12 15:35:53.000000000 -0700
+++ linux-2.4.27-pre6/arch/alpha/kernel/sys_eiger.c	2004-06-16 11:33:27.714069693 -0700
@@ -193,27 +193,20 @@
 	   case 0x0f: bridge_count = 4; break; /* 4 */
 	};
 
-	/*  Check first for the built-in bridges on hose 0. */
-	if (hose->index == 0
-	    && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {
-		slot = PCI_SLOT(dev->devfn);
-	} else {
-		/* Must be a card-based bridge.  */
-		do {
-			/* Check for built-in bridges on hose 0. */
-			if (hose->index == 0
-			    && (PCI_SLOT(dev->bus->self->devfn)
-				> 20 - bridge_count)) {
-                  		slot = PCI_SLOT(dev->devfn);
-				break;
-			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-
-			/* Move up the chain of bridges.  */
-			dev = dev->bus->self;
-			/* Slot of the next bridge.  */
+	slot = PCI_SLOT(dev->devfn);
+	while (dev->bus->self) {
+		/* Check for built-in bridges on hose 0. */
+		if (hose->index == 0
+		    && (PCI_SLOT(dev->bus->self->devfn)
+			> 20 - bridge_count)) {
 			slot = PCI_SLOT(dev->devfn);
-		} while (dev->bus->self);
+			break;
+		}
+		/* Must be a card-based bridge.  */
+		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+		/* Move up the chain of bridges.  */
+		dev = dev->bus->self;
 	}
 	*pinp = pin;
 	return slot;
diff -urN linux-2.4.27-pre5/arch/alpha/kernel/sys_takara.c linux-2.4.27-pre6/arch/alpha/kernel/sys_takara.c
--- linux-2.4.27-pre5/arch/alpha/kernel/sys_takara.c	2000-10-27 10:55:01.000000000 -0700
+++ linux-2.4.27-pre6/arch/alpha/kernel/sys_takara.c	2004-06-16 11:33:27.714069693 -0700
@@ -230,8 +230,12 @@
 	int slot = PCI_SLOT(dev->devfn);
 	int pin = *pinp;
 	unsigned int ctlreg = inl(0x500);
-	unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
+	unsigned int busslot;
 
+	if (!dev->bus->self)
+		return slot;
+
+	busslot = PCI_SLOT(dev->bus->self->devfn);
 	/* Check for built-in bridges.  */
 	if (dev->bus->number != 0
 	    && busslot > 16
diff -urN linux-2.4.27-pre5/arch/ppc/boot/simple/m8260_tty.c linux-2.4.27-pre6/arch/ppc/boot/simple/m8260_tty.c
--- linux-2.4.27-pre5/arch/ppc/boot/simple/m8260_tty.c	2004-04-14 06:05:27.000000000 -0700
+++ linux-2.4.27-pre6/arch/ppc/boot/simple/m8260_tty.c	2004-06-16 11:33:27.736070608 -0700
@@ -156,7 +156,7 @@
 	sccp->scc_sccm = 0;
 	sccp->scc_scce = 0xffff;
 	sccp->scc_dsr = 0x7e7e;
-	sccp->scc_pmsr = 0x3000;
+	sccp->scc_psmr = 0x3000;
 
 	/* Wire BRG1 to SCC1.  The console driver will take care of
 	 * others.
diff -urN linux-2.4.27-pre5/arch/ppc/kernel/m8260_setup.c linux-2.4.27-pre6/arch/ppc/kernel/m8260_setup.c
--- linux-2.4.27-pre5/arch/ppc/kernel/m8260_setup.c	2004-04-14 06:05:27.000000000 -0700
+++ linux-2.4.27-pre6/arch/ppc/kernel/m8260_setup.c	2004-06-16 11:33:27.737070650 -0700
@@ -93,7 +93,7 @@
  */
 static uint rtc_time;
 
-static static int
+static int
 m8260_set_rtc_time(unsigned long time)
 {
 	rtc_time = time;
diff -urN linux-2.4.27-pre5/arch/sparc/kernel/unaligned.c linux-2.4.27-pre6/arch/sparc/kernel/unaligned.c
--- linux-2.4.27-pre5/arch/sparc/kernel/unaligned.c	2002-02-25 11:37:56.000000000 -0800
+++ linux-2.4.27-pre6/arch/sparc/kernel/unaligned.c	2004-06-16 11:33:27.744070941 -0700
@@ -136,8 +136,8 @@
 	return &win->locals[reg - 16];
 }
 
-static inline unsigned long compute_effective_address(struct pt_regs *regs,
-						      unsigned int insn)
+static unsigned long compute_effective_address(struct pt_regs *regs,
+					       unsigned int insn)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
@@ -152,8 +152,8 @@
 	}
 }
 
-static inline unsigned long safe_compute_effective_address(struct pt_regs *regs,
-							   unsigned int insn)
+unsigned long safe_compute_effective_address(struct pt_regs *regs,
+					     unsigned int insn)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
diff -urN linux-2.4.27-pre5/arch/sparc/mm/fault.c linux-2.4.27-pre6/arch/sparc/mm/fault.c
--- linux-2.4.27-pre5/arch/sparc/mm/fault.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.27-pre6/arch/sparc/mm/fault.c	2004-06-16 11:33:27.745070983 -0700
@@ -200,6 +200,25 @@
 	return 0;
 }
 
+extern unsigned long safe_compute_effective_address(struct pt_regs *,
+						    unsigned int);
+
+static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
+{
+	unsigned int insn;
+
+	if (text_fault)
+		return regs->pc;
+
+	if (regs->psr & PSR_PS) {
+		insn = *(unsigned int *) regs->pc;
+	} else {
+		__get_user(insn, (unsigned int *) regs->pc);
+	}
+
+	return safe_compute_effective_address(regs, insn);
+}
+
 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 			       unsigned long address)
 {
@@ -306,7 +325,7 @@
 		info.si_errno = 0;
 		/* info.si_code set above to make clear whether
 		   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
-		info.si_addr = (void *)address;
+		info.si_addr = (void *) compute_si_addr(regs, text_fault);
 		info.si_trapno = 0;
 		force_sig_info (SIGSEGV, &info, tsk);
 		return;
@@ -360,7 +379,7 @@
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) compute_si_addr(regs, text_fault);
 	info.si_trapno = 0;
 	force_sig_info (SIGBUS, &info, tsk);
 	if (!from_user)
@@ -523,7 +542,7 @@
 	info.si_errno = 0;
 	/* info.si_code set above to make clear whether
 	   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) address;
 	info.si_trapno = 0;
 	force_sig_info (SIGSEGV, &info, tsk);
 	return;
@@ -533,7 +552,7 @@
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) address;
 	info.si_trapno = 0;
 	force_sig_info (SIGBUS, &info, tsk);
 }
diff -urN linux-2.4.27-pre5/arch/sparc64/kernel/unaligned.c linux-2.4.27-pre6/arch/sparc64/kernel/unaligned.c
--- linux-2.4.27-pre5/arch/sparc64/kernel/unaligned.c	2004-06-16 11:33:26.076001521 -0700
+++ linux-2.4.27-pre6/arch/sparc64/kernel/unaligned.c	2004-06-16 11:33:27.757071482 -0700
@@ -149,8 +149,8 @@
 	}
 }
 
-static inline unsigned long compute_effective_address(struct pt_regs *regs,
-						      unsigned int insn, unsigned int rd)
+unsigned long compute_effective_address(struct pt_regs *regs,
+					unsigned int insn, unsigned int rd)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
diff -urN linux-2.4.27-pre5/arch/sparc64/mm/fault.c linux-2.4.27-pre6/arch/sparc64/mm/fault.c
--- linux-2.4.27-pre5/arch/sparc64/mm/fault.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.27-pre6/arch/sparc64/mm/fault.c	2004-06-16 11:33:27.757071482 -0700
@@ -203,14 +203,21 @@
 	return insn;
 }
 
-static void do_fault_siginfo(int code, int sig, unsigned long address)
+extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
+
+static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
+			     unsigned int insn, int fault_code)
 {
 	siginfo_t info;
 
 	info.si_code = code;
 	info.si_signo = sig;
 	info.si_errno = 0;
-	info.si_addr = (void *) address;
+	if (fault_code & FAULT_CODE_ITLB)
+		info.si_addr = (void *) regs->tpc;
+	else
+		info.si_addr = (void *)
+			compute_effective_address(regs, insn, 0);
 	info.si_trapno = 0;
 	force_sig_info(sig, &info, current);
 }
@@ -291,7 +298,7 @@
 		/* The si_code was set to make clear whether
 		 * this was a SEGV_MAPERR or SEGV_ACCERR fault.
 		 */
-		do_fault_siginfo(si_code, SIGSEGV, address);
+		do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code);
 		return;
 	}
 
@@ -467,7 +474,7 @@
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
 	 */
-	do_fault_siginfo(BUS_ADRERR, SIGBUS, address);
+	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code);
 
 	/* Kernel mode? Handle exceptions or die */
 	if (regs->tstate & TSTATE_PRIV)
diff -urN linux-2.4.27-pre5/arch/x86_64/boot/bootsect.S linux-2.4.27-pre6/arch/x86_64/boot/bootsect.S
--- linux-2.4.27-pre5/arch/x86_64/boot/bootsect.S	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.27-pre6/arch/x86_64/boot/bootsect.S	2004-06-16 11:33:27.759071565 -0700
@@ -234,9 +234,10 @@
 die:	jne	die			# %es must be at 64kB boundary
 	xorw	%bx, %bx		# %bx is starting address within segment
 rp_read:
-#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
+#ifdef __BIG_KERNEL__				
+					# look in setup.S for bootsect_kludge
 	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
-	lcall	bootsect_kludge		# bootsector + bootsect_kludge offset
+	lcall	*bootsect_kludge		# bootsector + bootsect_kludge offset
 #else
 	movw	%es, %ax
 	subw	$SYSSEG, %ax
diff -urN linux-2.4.27-pre5/arch/x86_64/kernel/Makefile linux-2.4.27-pre6/arch/x86_64/kernel/Makefile
--- linux-2.4.27-pre5/arch/x86_64/kernel/Makefile	2004-04-14 06:05:28.000000000 -0700
+++ linux-2.4.27-pre6/arch/x86_64/kernel/Makefile	2004-06-16 11:33:27.760071607 -0700
@@ -14,7 +14,8 @@
 
 O_TARGET := kernel.o
 
-export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o swiotlb.o
+export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o \
+		swiotlb.o  bluesmoke.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
diff -urN linux-2.4.27-pre5/arch/x86_64/kernel/bluesmoke.c linux-2.4.27-pre6/arch/x86_64/kernel/bluesmoke.c
--- linux-2.4.27-pre5/arch/x86_64/kernel/bluesmoke.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.27-pre6/arch/x86_64/kernel/bluesmoke.c	2004-06-16 11:33:27.762071690 -0700
@@ -1,19 +1,24 @@
 /* 
  * Machine check handler.
  * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
- * Rest from unknown author(s). 
+ * Additional K8 decoding and simplification Copyright 2003 Eric Morton, Newisys Inc
+ * Rest from unknown author(s).
  */
+#include <linux/config.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/notifier.h>
+#include <asm/bluesmoke.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/kdebug.h>
-#include <linux/pci.h>
-#include <linux/timer.h>
 
 static int mce_disabled __initdata;
 static unsigned long mce_cpus; 
@@ -25,18 +30,34 @@
 static int banks;
 static unsigned long ignored_banks, disabled_banks;
 
+/* Machine Check on everything dubious. This is a good setting
+   for device driver testing. */
+#define K8_DRIVER_DEBUG ((1<<13)-1)
+/* Report RAM errors and Hyper Transport Problems, but ignore Device
+   aborts and GART errors. */
+#define K8_NORMAL_OP    0xff
+static u32 k8_nb_flags __initdata = K8_NORMAL_OP;
+struct notifier_block *mc_notifier_list = NULL;
+EXPORT_SYMBOL(mc_notifier_list);
+
 static void generic_machine_check(struct pt_regs * regs, long error_code)
 {
 	int recover=1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
 	int i;
-	
+	struct notifier_mc_err mc_err;
+
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
 
-	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
+	/* Make sure unrecoverable MCEs reach the console */
+	if(recover & 3)
+		oops_in_progress++;
+
+	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", 
+				smp_processor_id(), mcgsth, mcgstl);
 	
 	if (regs && (mcgstl & 2))
 		printk(KERN_EMERG "RIP <%02lx>:%016lx RSP %016lx\n", 
@@ -50,6 +71,10 @@
 		rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
 		if(high&(1<<31))
 		{
+			memset(&mc_err, 0x00, sizeof(mc_err));
+			mc_err.cpunum = safe_smp_processor_id();
+			mc_err.banknum = i;
+			mc_err.mci_status = ((u64)high << 32) | low;
 			if(high&(1<<29))
 				recover|=1;
 			if(high&(1<<25))
@@ -59,19 +84,26 @@
 			if(high&(1<<27))
 			{
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
+				mc_err.mci_misc = ((u64)ahigh << 32) | alow;
 				printk("[%08x%08x]", alow, ahigh);
 			}
 			if(high&(1<<26))
 			{
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
-				printk(" at %08x%08x", 
+				mc_err.mci_addr = ((u64)ahigh << 32) | alow;
+				printk(" at %08x%08x",
 					ahigh, alow);
 			}
+			rdmsr(MSR_IA32_MC0_CTL+i*4, alow, ahigh);
+			mc_err.mci_ctl = ((u64)ahigh << 32) | alow;
+
 			printk("\n");
+
 			/* Clear it */
 			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
 			/* Serialize */
 			wmb();
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_INTEL, &mc_err);
 		}
 	}
 
@@ -105,56 +137,51 @@
  *	K8 machine check.
  */
 
-static struct pci_dev *find_k8_nb(void)
-{ 
-	struct pci_dev *dev;
-	int cpu = smp_processor_id(); 
-	pci_for_each_dev(dev) {
-		if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 &&
-		    PCI_SLOT(dev->devfn) == (24+cpu))
-			return dev;
-	}
-	return NULL;
-}
-
+static char *k8bank[] = {
+	"data cache",
+	"instruction cache",
+	"bus unit",
+	"load/store unit",
+	"northbridge"
+};
 static char *transaction[] = { 
 	"instruction", "data", "generic", "reserved"
 }; 
 static char *cachelevel[] = { 
-	"level 0", "level 1", "level 2", "level generic"
+	"0", "1", "2", "generic"
 };
 static char *memtrans[] = { 
 	"generic error", "generic read", "generic write", "data read",
-	"data write", "instruction fetch", "prefetch", "snoop",
+	"data write", "instruction fetch", "prefetch", "evict", "snoop",
 	"?", "?", "?", "?", "?", "?", "?"
 };
 static char *partproc[] = { 
 	"local node origin", "local node response", 
-	"local node observed", "generic" 
+	"local node observed", "generic participation"
 };
 static char *timeout[] = { 
 	"request didn't time out",
 	"request timed out"
 };
 static char *memoryio[] = { 
-	"memory access", "res.", "i/o access", "generic"
-}; 
-static char *extendederr[] = { 
-	"ecc error", 
-	"crc error",
-	"sync error",
-	"mst abort",
-	"tgt abort",
-	"gart error",
-	"rmw error",
-	"wdog error",
-	"chipkill ecc error", 
+	"memory", "res.", "i/o", "generic"
+};
+static char *nbextendederr[] = { 
+	"ECC error", 
+	"CRC error",
+	"Sync error",
+	"Master abort",
+	"Target abort",
+	"GART error",
+	"RMW error",
+	"Watchdog error",
+	"Chipkill ECC error", 
 	"<9>","<10>","<11>","<12>",
 	"<13>","<14>","<15>"
-}; 
+};
 static char *highbits[32] = { 
-	[31] = "previous error lost", 
-	[30] = "error overflow",
+	[31] = "valid",
+	[30] = "error overflow (multiple errors)",
 	[29] = "error uncorrected",
 	[28] = "error enable",
 	[27] = "misc error valid",
@@ -169,128 +196,290 @@
 	[11] = "res11",
 	[10] = "res10",
 	[9] = "res9",
-	[8] = "dram scrub error", 
+	[8] = "error found by scrub", 
 	[7] = "res7",
 	/* 6-4 ht link number of error */ 
 	[3] = "res3",
 	[2] = "res2",
-	[1] = "err cpu0",
-	[0] = "err cpu1",
+	[1] = "err cpu1",
+	[0] = "err cpu0",
 };
 
-static void check_k8_nb(int header)
-{
-	struct pci_dev *nb;
-	nb = find_k8_nb(); 
-	if (nb == NULL)
-		return;
-
-	u32 statuslow, statushigh;
-	pci_read_config_dword(nb, 0x48, &statuslow);
-	pci_read_config_dword(nb, 0x4c, &statushigh);
-	if (!(statushigh & (1<<31)))
-		return;
-	if (header) 
-		printk(KERN_ERR "CPU %d: Silent Northbridge MCE\n", smp_processor_id());
 
-	printk(KERN_ERR "Northbridge status %08x:%08x\n",
-	       statushigh,statuslow); 
+static void decode_k8_generic_errcode(unsigned int cpunum, u64 status)
+{
+	unsigned short errcode = status & 0xffff;
+	int i;
 
-	printk(KERN_ERR "    Error %s\n", extendederr[(statuslow >> 16) & 0xf]); 
+	for (i=0; i<32; i++) {
+		if (i==31 || i==28 || i==26)
+			continue;
+		if (highbits[i] && (status & (1UL<<(i+32)))) {
+			printk(KERN_ERR "CPU%d:   bit%d = %s\n", cpunum, i+32, highbits[i]);
+		}
+	}
 
-	unsigned short errcode = statuslow & 0xffff;	
-	switch ((statuslow >> 16) & 0xF) { 
-	case 5: 					
-		printk(KERN_ERR "    GART TLB error %s %s\n", 
-		       transaction[(errcode >> 2) & 3], 
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB error '%s transaction, level %s'\n",
+		       cpunum,
+		       transaction[(errcode >> 2) & 3],
 		       cachelevel[errcode & 3]);
-		break;
-	case 8:
-		printk(KERN_ERR "    ECC error syndrome %x\n", 
-		       (((statuslow >> 24) & 0xff)  << 8) | ((statushigh >> 15) & 0x7f));		
-		/*FALL THROUGH*/
-	default:
-		printk(KERN_ERR "    bus error %s, %s\n    %s\n    %s, %s\n",
+	}
+	else if ((errcode & 0xFF00) == 0x0100) {
+		printk(KERN_ERR "CPU%d: memory/cache error '%s mem transaction, %s transaction, level %s'\n",
+		       cpunum,
+		       memtrans[(errcode >> 4) & 0xf],
+		       transaction[(errcode >> 2) & 3],
+		       cachelevel[errcode & 3]);
+	}
+	else if ((errcode & 0xF800) == 0x0800) {
+		printk(KERN_ERR "CPU%d: bus error '%s, %s\n      %s mem transaction\n      %s access, level %s'\n",
+		       cpunum,
 		       partproc[(errcode >> 9) & 0x3],
 		       timeout[(errcode >> 8) & 1],
-			       memtrans[(errcode >> 4) & 0xf],
-			       memoryio[(errcode >> 2) & 0x3], 
-			       cachelevel[(errcode & 0x3)]); 
-		/* should only print when it was a HyperTransport related error. */
-		printk(KERN_ERR "    link number %x\n", (statushigh >> 4) & 3);
+		       memtrans[(errcode >> 4) & 0xf],
+		       memoryio[(errcode >> 2) & 0x3],
+		       cachelevel[(errcode & 0x3)]);
+	}
+}
+
+static void decode_k8_dc_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+	unsigned short errcode = status & 0xffff;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: Data cache ECC error (syndrome %x)",
+		       cpunum,
+		       (u32) (status >> 47) & 0xff);
+		if(status&(1UL<<40)) {
+			printk(" found by scrubber");
+		}
+		printk("\n");
+	}
+
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",
+		       cpunum,
+		       (exterrcode == 0) ? "physical" : "virtual");
+	}
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_ic_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+	unsigned short errcode = status & 0xffff;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: Instruction cache ECC error\n",
+		       cpunum);
+	}
+
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",
+		       cpunum,
+		       (exterrcode == 0) ? "physical" : "virtual");
+	}
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_bu_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: L2 cache ECC error\n",
+		       cpunum);
+	}
+
+	printk(KERN_ERR "CPU%d: %s array error\n",
+	       cpunum,
+	       (exterrcode == 0) ? "Bus or cache" : "Cache tag");
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_ls_mc(unsigned int cpunum, u64 status)
+{
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_nb_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+
+	printk(KERN_ERR "CPU%d: Northbridge %s\n", cpunum, nbextendederr[exterrcode]);
+
+	switch (exterrcode) { 
+	case 0:
+		printk(KERN_ERR "CPU%d: ECC syndrome = %x\n",
+		       cpunum,
+		       (u32) (status >> 47) & 0xff);
 		break;
-	} 
-	
+	case 8:	
+		printk(KERN_ERR "CPU%d: Chipkill ECC syndrome = %x\n",
+		       cpunum,
+	    	   (u32) ((((status >> 24) & 0xff) << 8) | ((status >> 47) & 0xff)));
+		break;
+	case 1: 
+	case 2:
+	case 3:
+	case 4:
+	case 6:
+		printk(KERN_ERR "CPU%d: link number = %x\n",
+		       cpunum,
+		       (u32) (status >> 36) & 0x7);
+		break;		   
+	}
 
-	int i;
-	for (i = 0; i < 32; i++) { 
-		if (i == 26 || i == 28) 
-			continue;
-		if (highbits[i] && (statushigh & (1<<i)))
-			printk(KERN_ERR "    %s\n", highbits[i]); 
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_mc(unsigned int banknum, unsigned int cpunum, u64 status)
+{
+	switch(banknum) {
+		case 0:
+			decode_k8_dc_mc(cpunum, status);
+			break;
+		case 1:
+			decode_k8_ic_mc(cpunum, status);
+			break;
+		case 2:
+			decode_k8_bu_mc(cpunum, status);
+			break;
+		case 3:
+			decode_k8_ls_mc(cpunum, status);
+			break;
+		case 4:
+			decode_k8_nb_mc(cpunum, status);
+			break;
 	}
+}
 
-	if (statushigh & (1<<26)) { 
-		u32 addrhigh, addrlow; 
-		pci_read_config_dword(nb, 0x54, &addrhigh); 
-		pci_read_config_dword(nb, 0x50, &addrlow); 
-		printk(KERN_ERR "    NB error address %08x%08x\n", addrhigh,addrlow); 
+static void k8_poll_machine_check(void)
+{
+	int cpunum = safe_smp_processor_id();
+	int banknum;
+	u64 address, status, ctl;
+	struct notifier_mc_err mc_err;
+
+	for(banknum=0; banknum<banks; banknum++) {
+		if ((1UL<<banknum) & ignored_banks)
+			continue;
+
+		rdmsrl(MSR_IA32_MC0_STATUS+banknum*4, status);
+		if(status&(1UL<<63)) {
+			mc_err.cpunum = cpunum;
+			mc_err.banknum = banknum;
+			mc_err.mci_status = status;
+	        	rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, address);
+			mc_err.mci_addr = address;
+
+			/* Can't write anything but zeros to status, or K8 will GPF */
+			wrmsrl(MSR_IA32_MC0_STATUS+banknum*4, 0UL);
+			printk(KERN_ERR "CPU%d %s polled machine check error status: %016Lx",
+			       cpunum,
+			       k8bank[banknum],
+			       status);
+			if(status&(1UL<<58)) {
+				printk(" at address %016Lx", address);
+			}
+			printk("\n");
+			rdmsrl(MSR_IA32_MC0_CTL+banknum*4, ctl);
+			mc_err.mci_ctl = ctl;
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_AMD, &mc_err);
+			decode_k8_mc(banknum, cpunum, status);
+		}
 	}
-	statushigh &= ~(1<<31); 
-	pci_write_config_dword(nb, 0x4c, statushigh); 		
 }
 
 static void k8_machine_check(struct pt_regs * regs, long error_code)
-{ 
-	u64 status, nbstatus;
-
-	rdmsrl(MSR_IA32_MCG_STATUS, status); 
-	if ((status & (1<<2)) == 0) { 
-		if (!regs) 
-			check_k8_nb(1);
-		return; 
+{
+	int norecover=1;
+	u64 addr, status, ctl, mcgst;
+	int banknum;
+	unsigned int cpunum = safe_smp_processor_id();
+	struct notifier_mc_err mc_err;
+
+	rdmsrl(MSR_IA32_MCG_STATUS, mcgst); 
+	if(mcgst&(1UL<<0)) {	/* Recoverable ? */
+		norecover=0;
 	}
-	printk(KERN_EMERG "CPU %d: Machine Check Exception: %016Lx\n", smp_processor_id(), status);
 
-	if (status & 1)
-		printk(KERN_EMERG "MCG_STATUS: unrecoverable\n"); 
+	/* Make sure unrecoverable MCEs reach the console */
+	if(norecover)
+		oops_in_progress++;
+
+	printk(KERN_EMERG "CPU %d: Machine Check Exception: %016Lx\n", cpunum, mcgst);
+
+	if (regs && (mcgst & (1UL<<1))) {
+		printk(KERN_EMERG "CPU%d: RIP <%02lx>:%016lx RSP %016lx %s\n",
+		       cpunum, regs->cs, regs->rip, regs->rsp,
+			   (mcgst & 1) ? "" : "!INEXACT!");
+	}
 
-	rdmsrl(MSR_IA32_MC0_STATUS+4*4, nbstatus); 
-	if ((nbstatus & (1UL<<63)) == 0)
-		goto others; 
-	
-	printk(KERN_EMERG "Northbridge Machine Check %s %016lx %lx\n", 
-	       regs ? "exception" : "timer",
-	       (unsigned long)nbstatus, error_code); 
-	if (nbstatus & (1UL<<62))
-		printk(KERN_EMERG "Lost at least one NB error condition\n"); 	
-	if (nbstatus & (1UL<<61))
-		printk(KERN_EMERG "Uncorrectable condition\n"); 
-	if (nbstatus & (1UL<57))
-		printk(KERN_EMERG "Unrecoverable condition\n"); 
-		
-	check_k8_nb(0);
+	for(banknum=0; banknum<banks; banknum++) {
+		if ((1UL<<banknum) & ignored_banks)
+			continue;
+		rdmsrl(MSR_IA32_MC0_STATUS+banknum*4, status);
+		if(status&(1UL<<63)) {
+			memset(&mc_err, 0x00, sizeof(mc_err));
+			mc_err.cpunum = cpunum;
+			mc_err.banknum = banknum;
+			mc_err.mci_status = status;
+			if(status&(1UL<<61)) {
+				norecover|=1; /* uncorrectable */
+			}
+			if(status &(1UL<<57)) {
+				norecover|=2; /* processor context corrupt */
+			}
+			printk(KERN_EMERG "CPU%d %s error status: %016Lx",
+			       cpunum,
+			       k8bank[banknum],
+			       status);
+			if(status&(1UL<<58)) {
+				rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, addr);
+				mc_err.mci_addr = addr;
+				printk(" at address %016Lx", addr);
+			} else if ((banknum==4) && (((status>>16)&0x0f)==7)) {
+				/* NB watchdog, address reg has details but validity bit is not set */
+				rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, addr);
+				mc_err.mci_addr = addr;
+				printk(" error details %016Lx", addr);
+			}
+			printk("\n");
+			rdmsrl(MSR_IA32_MC0_CTL+banknum*4, ctl);
+			mc_err.mci_ctl = ctl;
+			/* Clear it */
+            /* Can't write anything but zeros to status, or K8 will GPF */
+			wrmsrl(MSR_IA32_MC0_STATUS+banknum*4, 0UL);
+			/* Serialize */
+			wmb();
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_AMD, &mc_err);
+		}
+	}
 
-	if (nbstatus & (1UL<<58)) { 
-		u64 adr;
-		rdmsrl(MSR_IA32_MC0_ADDR+4*4, adr);
-		printk(KERN_EMERG "Address: %016lx\n", (unsigned long)adr);
+	if(norecover&2) {
+		panic("CPU context corrupt");
 	}
-	
-	wrmsrl(MSR_IA32_MC0_STATUS+4*4, 0); 
-	wrmsrl(MSR_IA32_MCG_STATUS, 0);
-       
- others:
-	generic_machine_check(regs, error_code); 
-} 
+	if(norecover&1) {
+		panic("Unable to continue");
+	}
+	printk(KERN_EMERG "Attempting to continue.\n");
+	mcgst&=~(1UL<<2);
+	wrmsrl(MSR_IA32_MCG_STATUS,mcgst);
+}
 
 static struct timer_list mcheck_timer;
-int mcheck_interval = 30*HZ; 
+int mcheck_interval = 60*HZ;
 
 #ifndef CONFIG_SMP 
 static void mcheck_timer_handler(unsigned long data)
 {
-	k8_machine_check(NULL,0);
+	k8_poll_machine_check();
 	mcheck_timer.expires = jiffies + mcheck_interval;
 	add_timer(&mcheck_timer);
 }
@@ -301,13 +490,13 @@
 
 static void mcheck_timer_other(void *data)
 { 
-	k8_machine_check(NULL, 0); 
+	k8_poll_machine_check();
 } 
 
 static void mcheck_timer_dist(void *data)
 { 
 	smp_call_function(mcheck_timer_other,0,0,0);
-	k8_machine_check(NULL, 0); 
+	k8_poll_machine_check();
 	mcheck_timer.expires = jiffies + mcheck_interval;
 	add_timer(&mcheck_timer);
 } 
@@ -334,17 +523,22 @@
 
 	rdmsrl(MSR_IA32_MCG_CAP, cap); 
 	banks = cap&0xff; 
-	machine_check_vector = k8_machine_check; 
 	for (i = 0; i < banks; i++) { 
 		u64 val = ((1UL<<i) & disabled_banks) ? 0 : ~0UL; 
+		if (val && i == 4)
+			val = k8_nb_flags;
+		wrmsrl(MSR_IA32_MC0_STATUS+4*i,0UL);
+		wrmsrl(MSR_IA32_MC0_ADDR+4*i,0UL);
 		wrmsrl(MSR_IA32_MC0_CTL+4*i, val);
-		wrmsrl(MSR_IA32_MC0_STATUS+4*i,0); 
 	}
 
-	if (cap & (1<<8))
-		wrmsrl(MSR_IA32_MCG_CTL, 0xffffffffffffffffULL);
+	/* set up the vector first, before enabling MCG_CTL */
+	machine_check_vector = k8_machine_check;
+	set_in_cr4(X86_CR4_MCE);
 
-	set_in_cr4(X86_CR4_MCE);	   	
+	if (cap & (1<<8)) {
+		wrmsrl(MSR_IA32_MCG_CTL, 0xffffffffffffffffULL);
+	}
 
 	if (mcheck_interval && (smp_processor_id() == 0)) { 
 		init_timer(&mcheck_timer); 
@@ -399,7 +593,8 @@
 		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
 	}
 	set_in_cr4(X86_CR4_MCE);
-	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", 
+					 smp_processor_id());
 	done=1;
 }
 
@@ -419,8 +614,10 @@
 	case X86_VENDOR_AMD:
 		if (c->x86 == 15 && !nok8) {
 			k8_mcheck_init(c); 
-			break;
+		} else {
+			generic_mcheck_init(c);
 		}
+		break;
 		/* FALL THROUGH */
 	default:
 	case X86_VENDOR_INTEL:
@@ -440,6 +637,7 @@
    mce=nok8 disable k8 specific features
    mce=disable<NUMBER> disable bank NUMBER
    mce=enable<NUMBER> enable bank number
+   mce=device	Enable device driver test reporting in NB
    mce=NUMBER mcheck timer interval number seconds. 
    Can be also comma separated in a single mce= */
 static int __init mcheck_enable(char *str)
@@ -447,18 +645,20 @@
 	char *p;
 	while ((p = strsep(&str,",")) != NULL) { 
 		if (isdigit(*p))
-			mcheck_interval = simple_strtol(p,NULL,0) * HZ; 
+			mcheck_interval = simple_strtol(p,NULL,0) * HZ;
 		else if (!strcmp(p,"off"))
 			mce_disabled = 1; 
 		else if (!strncmp(p,"enable",6))
-			disabled_banks &= ~(1<<simple_strtol(p+6,NULL,0));
+			disabled_banks &= ~(1UL << simple_strtol(p+6,NULL,0));
 		else if (!strncmp(p,"disable",7))
-			disabled_banks |= ~(1<<simple_strtol(p+7,NULL,0));
+			disabled_banks |= 1UL << simple_strtol(p+7,NULL,0);
 		else if (!strcmp(p,"nok8"))
 			nok8 = 1;
+		else if (!strcmp(p,"device"))
+			k8_nb_flags = K8_DRIVER_DEBUG;
 	}
 	return 0;
 }
 
 __setup("nomce", mcheck_disable);
-__setup("mce", mcheck_enable);
+__setup("mce=", mcheck_enable);
diff -urN linux-2.4.27-pre5/arch/x86_64/kernel/pci-gart.c linux-2.4.27-pre6/arch/x86_64/kernel/pci-gart.c
--- linux-2.4.27-pre5/arch/x86_64/kernel/pci-gart.c	2004-04-14 06:05:28.000000000 -0700
+++ linux-2.4.27-pre6/arch/x86_64/kernel/pci-gart.c	2004-06-16 11:33:27.765071815 -0700
@@ -503,12 +503,13 @@
 	no_agp = no_agp || (agp_init() < 0) || (agp_copy_info(&info) < 0); 
 #endif	
 
+#ifdef CONFIG_SWIOTLB
 	if (swiotlb) { 
 		no_iommu = 1;
 		printk(KERN_INFO "PCI-DMA: Using SWIOTLB\n"); 
 		return; 
-	} 
-
+	}
+#endif
 
 	if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT) || !iommu_aperture) { 
 		printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); 
diff -urN linux-2.4.27-pre5/crypto/digest.c linux-2.4.27-pre6/crypto/digest.c
--- linux-2.4.27-pre5/crypto/digest.c	2004-06-16 11:33:26.109002894 -0700
+++ linux-2.4.27-pre6/crypto/digest.c	2004-06-16 11:33:27.768071940 -0700
@@ -27,13 +27,28 @@
                    struct scatterlist *sg, unsigned int nsg)
 {
 	unsigned int i;
-	
+
 	for (i = 0; i < nsg; i++) {
-		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
-		                                      p, sg[i].length);
-		crypto_kunmap(p, 0);
-		crypto_yield(tfm);
+
+		struct page *pg = sg[i].page;
+		unsigned int offset = sg[i].offset;
+		unsigned int l = sg[i].length;
+
+		do {
+			unsigned int bytes_from_page = min(l, ((unsigned int)
+							   (PAGE_SIZE)) - 
+							   offset);
+			char *p = crypto_kmap(pg, 0) + offset;
+
+			tfm->__crt_alg->cra_digest.dia_update
+					(crypto_tfm_ctx(tfm), p,
+					 bytes_from_page);
+			crypto_kunmap(p, 0);
+			crypto_yield(tfm);
+			offset = 0;
+			pg++;
+			l -= bytes_from_page;
+		} while (l > 0);
 	}
 }
 
diff -urN linux-2.4.27-pre5/drivers/block/cciss.c linux-2.4.27-pre6/drivers/block/cciss.c
--- linux-2.4.27-pre5/drivers/block/cciss.c	2004-06-16 11:33:26.137004060 -0700
+++ linux-2.4.27-pre6/drivers/block/cciss.c	2004-06-16 11:33:27.920078266 -0700
@@ -493,6 +493,142 @@
 	return 0;
 }
 
+#ifdef __x86_64__
+/* for AMD 64 bit kernel compatibility with 32-bit userland ioctls */
+extern int sys_ioctl(unsigned int fd, unsigned cmd, unsigned long arg);
+
+extern int 
+register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
+      unsigned int, unsigned long, struct file *));
+extern int unregister_ioctl32_conversion(unsigned int cmd);
+
+static int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, struct file *file);
+static int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg, 
+	struct file *file);
+
+typedef long (*handler type) (unsigned int, unsigned int, unsigned long,
+				struct file *);
+
+static struct ioctl32_map {
+	unsigned int cmd; 
+	handler_type handler;
+	int registered;
+} cciss_ioctl32_map[] = {
+	{ CCISS_GETPCIINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETHEARTBEAT,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETBUSTYPES,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETFIRMVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETDRIVVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REVALIDVOLS,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_PASSTHRU32,	cciss_ioctl32_passthru, 0 },
+	{ CCISS_DEREGDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWD,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_RESCANDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETLUNINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_BIG_PASSTHRU32,	cciss_ioctl32_big_passthru, 0 },
+};
+#define NCCISS_IOCTL32_ENTRIES (sizeof(cciss_ioctl32_map) / sizeof(cciss_ioctl32_map[0]))
+static void register_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		rc = register_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd,
+			cciss_ioctl32_map[i].handler);
+		if (rc != 0) {
+			printk(KERN_WARNING "cciss: failed to register "
+				"32 bit compatible ioctl 0x%08x\n", 
+				cciss_ioctl32_map[i].cmd);
+			cciss_ioctl32_map[i].registered = 0;
+		} else
+			cciss_ioctl32_map[i].registered = 1;
+	}
+}
+static void unregister_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		if (!cciss_ioctl32_map[i].registered)
+			continue;
+		rc = unregister_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd);
+		if (rc == 0) {
+			cciss_ioctl32_map[i].registered = 0;
+			continue;
+		}
+		printk(KERN_WARNING "cciss: failed to unregister "
+			"32 bit compatible ioctl 0x%08x\n",
+			cciss_ioctl32_map[i].cmd);
+	}
+}
+int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, 
+				struct file *file)
+{
+	IOCTL32_Command_struct *arg32 = 
+		(IOCTL32_Command_struct *) arg;
+	IOCTL_Command_struct arg64;
+	mm_segment_t old_fs; 
+	int err;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.buf, &arg32->buf);
+	if (err) 
+		return -EFAULT; 
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err) 
+		return -EFAULT; 
+	return err;
+}
+int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
+					struct file *file)
+{
+	BIG_IOCTL32_Command_struct *arg32 = 
+		(BIG_IOCTL32_Command_struct *) arg;
+	BIG_IOCTL_Command_struct arg64;
+	mm_segment_t old_fs; 
+	int err;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.malloc_size, &arg32->malloc_size);
+	err |= get_user(arg64.buf, &arg32->buf);
+	if (err) return -EFAULT; 
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err) 
+		return -EFAULT; 
+	return err;
+}
+#else 
+static inline void register_cciss_ioctl32(void) {}
+static inline void unregister_cciss_ioctl32(void) {}
+#endif
 /*
  * ioctl 
  */
@@ -3323,7 +3459,7 @@
 EXPORT_NO_SYMBOLS;
 static int __init init_cciss_module(void)
 {
-
+	register_cciss_ioctl32();
 	return cciss_init();
 }
 
@@ -3331,6 +3467,7 @@
 {
 	int i;
 
+	unregister_cciss_ioctl32();
 	pci_unregister_driver(&cciss_pci_driver);
 	/* double check that all controller entrys have been removed */
 	for (i=0; i< MAX_CTLR; i++) {
diff -urN linux-2.4.27-pre5/drivers/cdrom/cdrom.c linux-2.4.27-pre6/drivers/cdrom/cdrom.c
--- linux-2.4.27-pre5/drivers/cdrom/cdrom.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/cdrom/cdrom.c	2004-06-16 11:33:27.949079473 -0700
@@ -1,7 +1,8 @@
 /* linux/drivers/cdrom/cdrom.c. 
    Copyright (c) 1996, 1997 David A. van Leeuwen.
    Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
-   Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk>
+   Copyright (c) 1998-2004 Jens Axboe <axboe@image.dk>
+   Copyright (c) 2004, Iomega Corp.
 
    May be copied or modified under the terms of the GNU General Public
    License.  See linux/COPYING for more information.
@@ -447,6 +448,100 @@
 	return cdi;
 }
 
+int cdrom_get_random_writable(struct cdrom_device_info *cdi,
+			      struct rwrt_feature_desc *rfd)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[24];
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_RWRT;			/* often 0x0020 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x18 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
+	return 0;
+}
+
+int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[16];
+	__u16 *feature_code;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+	cgc.cmd[3] = CDF_HWDM;
+	cgc.cmd[8] = sizeof(buffer);
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	feature_code = (__u16 *) &buffer[sizeof(struct feature_header)];
+	if (be16_to_cpu(*feature_code) == CDF_HWDM)
+		return 0;
+
+	return 1;
+}
+
+
+int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	*write = 0;
+
+	if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+		return ret;
+
+	if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+		*write = 1;
+
+	return 0;
+}
+
+static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	if ((ret = cdrom_has_defect_mgt(cdi)))
+		return ret;
+	else
+		if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+			return ret;
+		else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+			ret = !rfd.curr;
+
+	cdinfo(CD_OPEN, "can open for random write\n");
+	return ret;
+}
+
+/*
+ * returns 0 for ok to open write, non-0 to disallow
+ */
+static int cdrom_open_write(struct cdrom_device_info *cdi)
+{
+	int ret;
+	if (CDROM_CAN(CDC_RAM) &&
+	    !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R)) 
+		ret = cdrom_ram_open_write(cdi);
+	else
+		ret = 1;
+
+	return ret;
+}
+
 /* We use the open-option O_NONBLOCK to indicate that the
  * purpose of opening is only for subsequent ioctl() calls; no device
  * integrity checks are performed.
@@ -465,8 +560,15 @@
 	if ((cdi = cdrom_find_device(dev)) == NULL)
 		return -ENODEV;
 
-	if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM))
-		return -EROFS;
+	cdi->use_count++;
+	ret = -EROFS;
+	if (fp->f_mode & FMODE_WRITE) {
+		/* printk("cdrom: %s opening for WRITE\n", current->comm); */
+		if (!CDROM_CAN(CDC_RAM))
+			goto out;
+		if (cdrom_open_write(cdi))
+			goto out;
+	}
 
 	/* if this was a O_NONBLOCK open and we should honor the flags,
 	 * do a quick open without drive/disc integrity checks. */
@@ -475,12 +577,13 @@
 	else
 		ret = open_for_data(cdi);
 
-	if (!ret) cdi->use_count++;
-
 	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(dev);
+out:
+	if (ret)
+		cdi->use_count--;
 	return ret;
 }
 
@@ -657,15 +760,14 @@
 
 	cdinfo(CD_CLOSE, "entering cdrom_release\n"); 
 
-	if (cdi->use_count > 0)
-		cdi->use_count--;
-	if (cdi->use_count == 0)
+	if (!--cdi->use_count) {
 		cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
-	if (cdi->use_count == 0 &&
-	    cdo->capability & CDC_LOCK && !keeplocked) {
-		cdinfo(CD_CLOSE, "Unlocking door!\n");
-		cdo->lock_door(cdi, 0);
+		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);
@@ -1909,10 +2011,24 @@
 		}
 	}
 
+	/*
+	 * queue command and wait for it to complete
+	 */
 	ret = cdi->ops->generic_packet(cdi, cgc);
-	__copy_to_user(usense, cgc->sense, sizeof(*usense));
+
+	/*
+	 * always copy back sense, command need not have failed for it to
+	 * contain useful info
+	 */
+	if (usense)
+		__copy_to_user(usense, cgc->sense, sizeof(*usense));
+
+	/*
+	 * this really needs to be modified to copy back good bytes
+	 */
 	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);
@@ -2392,6 +2508,7 @@
 EXPORT_SYMBOL(cdrom_mode_sense);
 EXPORT_SYMBOL(init_cdrom_command);
 EXPORT_SYMBOL(cdrom_find_device);
+EXPORT_SYMBOL(cdrom_is_random_writable);
 
 #ifdef CONFIG_SYSCTL
 
@@ -2488,6 +2605,10 @@
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
 	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
 
+	pos += sprintf(info+pos, "\nCan write RAM:\t");
+	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
+
 	strcpy(info+pos,"\n\n");
 		
         return proc_dostring(ctl, write, filp, buffer, lenp);
diff -urN linux-2.4.27-pre5/drivers/char/ChangeLog linux-2.4.27-pre6/drivers/char/ChangeLog
--- linux-2.4.27-pre5/drivers/char/ChangeLog	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.27-pre6/drivers/char/ChangeLog	2004-06-16 11:33:27.965080139 -0700
@@ -1,3 +1,8 @@
+2002-09-21  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+	* parport_serial.c: Move from ../parport/ here, must be initialised
+	after serial.c for register_serial to work.
+
 2001-08-11  Tim Waugh  <twaugh@redhat.com>
 
 	* serial.c (get_pci_port): Deal with awkward Titan cards.
diff -urN linux-2.4.27-pre5/drivers/char/Makefile linux-2.4.27-pre6/drivers/char/Makefile
--- linux-2.4.27-pre5/drivers/char/Makefile	2004-06-16 11:33:26.142004268 -0700
+++ linux-2.4.27-pre6/drivers/char/Makefile	2004-06-16 11:33:28.002081679 -0700
@@ -171,6 +171,7 @@
 
 obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
 obj-$(CONFIG_SERIAL) += $(SERIAL)
+obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o
 obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
 obj-$(CONFIG_SERIAL_21285) += serial_21285.o
 obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
diff -urN linux-2.4.27-pre5/drivers/char/drm/sis_mm.c linux-2.4.27-pre6/drivers/char/drm/sis_mm.c
--- linux-2.4.27-pre5/drivers/char/drm/sis_mm.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.27-pre6/drivers/char/drm/sis_mm.c	2004-06-16 11:33:28.083085050 -0700
@@ -120,7 +120,7 @@
     return -1;
   }
 
-  sis_free(fb.free);
+  sis_free((u32)fb.free);
   if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
     retval = -1;
 
diff -urN linux-2.4.27-pre5/drivers/char/parport_serial.c linux-2.4.27-pre6/drivers/char/parport_serial.c
--- linux-2.4.27-pre5/drivers/char/parport_serial.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.27-pre6/drivers/char/parport_serial.c	2004-06-16 11:33:28.084085092 -0700
@@ -0,0 +1,436 @@
+/*
+ * Support for common PCI multi-I/O cards (which is most of them)
+ *
+ * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
+ *
+ * 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.
+ *
+ *
+ * Multi-function PCI cards are supposed to present separate logical
+ * devices on the bus.  A common thing to do seems to be to just use
+ * one logical device with lots of base address registers for both
+ * parallel ports and serial ports.  This driver is for dealing with
+ * that.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/parport.h>
+#include <linux/parport_pc.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/list.h>
+
+#include <asm/serial.h>
+
+enum parport_pc_pci_cards {
+	titan_110l = 0,
+	titan_210l,
+	netmos_9735,
+	netmos_9835,
+	avlab_1s1p,
+	avlab_1s1p_650,
+	avlab_1s1p_850,
+	avlab_1s2p,
+	avlab_1s2p_650,
+	avlab_1s2p_850,
+	avlab_2s1p,
+	avlab_2s1p_650,
+	avlab_2s1p_850,
+	siig_1s1p_10x,
+	siig_2s1p_10x,
+	siig_2p1s_20x,
+	siig_1s1p_20x,
+	siig_2s1p_20x,
+};
+
+
+/* each element directly indexed from enum list, above */
+static struct parport_pc_pci {
+	int numports;
+	struct { /* BAR (base address registers) numbers in the config
+                    space header */
+		int lo;
+		int hi; /* -1 if not there, >6 for offset-method (max
+                           BAR is 6) */
+	} addr[4];
+
+	/* If set, this is called immediately after pci_enable_device.
+	 * If it returns non-zero, no probing will take place and the
+	 * ports will not be used. */
+	int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
+
+	/* If set, this is called after probing for ports.  If 'failed'
+	 * is non-zero we couldn't use any of the ports. */
+	void (*postinit_hook) (struct pci_dev *pdev, int failed);
+} cards[] __devinitdata = {
+	/* titan_110l */		{ 1, { { 3, -1 }, } },
+	/* titan_210l */		{ 1, { { 3, -1 }, } },
+	/* netmos_9735 (not tested) */	{ 1, { { 2, -1 }, } },
+	/* netmos_9835 */		{ 1, { { 2, -1 }, } },
+	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
+	/* avlab_1s1p_650 */		{ 1, { { 1, 2}, } },
+	/* avlab_1s1p_850 */		{ 1, { { 1, 2}, } },
+	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_1s2p_650 */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_1s2p_850 */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
+	/* avlab_2s1p_650 */		{ 1, { { 2, 3}, } },
+	/* avlab_2s1p_850 */		{ 1, { { 2, 3}, } },
+	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
+	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
+	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
+	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
+};
+
+static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
+	/* PCI cards */
+	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
+	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
+	{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
+	{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
+	{ 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850},
+	{ 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p},
+	{ 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650},
+	{ 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850},
+	{ 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
+	{ 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
+	{ 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+
+	{ 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
+
+struct pci_board_no_ids {
+	int flags;
+	int num_ports;
+	int base_baud;
+	int uart_offset;
+	int reg_shift;
+	int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
+			int enable);
+	int first_uart_offset;
+};
+
+static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig10x_fn(dev, NULL, enable);
+}
+
+static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig20x_fn(dev, NULL, enable);
+}
+
+static struct pci_board_no_ids pci_boards[] __devinitdata = {
+	/*
+	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
+	 * Offset to get to next UART's registers,
+	 * Register shift to use for memory-mapped I/O,
+	 * Initialization function, first UART offset
+	 */
+
+// Cards not tested are marked n/t
+// If you have one of these cards and it works for you, please tell me..
+
+/* titan_110l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
+/* titan_210l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+/* netmos_9735 (n/t)*/	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* netmos_9835 */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_1s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_2s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* siig_1s1p_10x */	{ SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
+/* siig_2s1p_10x */	{ SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
+/* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+};
+
+struct parport_serial_private {
+	int num_ser;
+	int line[20];
+	struct pci_board_no_ids ser;
+	int num_par;
+	struct parport *port[PARPORT_MAX];
+};
+
+static int __devinit get_pci_port (struct pci_dev *dev,
+				   struct pci_board_no_ids *board,
+				   struct serial_struct *req,
+				   int idx)
+{
+	unsigned long port;
+	int base_idx;
+	int max_port;
+	int offset;
+
+	base_idx = SPCI_FL_GET_BASE(board->flags);
+	if (board->flags & SPCI_FL_BASE_TABLE)
+		base_idx += idx;
+
+	if (board->flags & SPCI_FL_REGION_SZ_CAP) {
+		max_port = pci_resource_len(dev, base_idx) / 8;
+		if (idx >= max_port)
+			return 1;
+	}
+
+	offset = board->first_uart_offset;
+
+	/* Timedia/SUNIX uses a mixture of BARs and offsets */
+	/* Ugh, this is ugly as all hell --- TYT */
+	if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
+		switch(idx) {
+			case 0: base_idx=0;
+				break;
+			case 1: base_idx=0; offset=8;
+				break;
+			case 2: base_idx=1;
+				break;
+			case 3: base_idx=1; offset=8;
+				break;
+			case 4: /* BAR 2*/
+			case 5: /* BAR 3 */
+			case 6: /* BAR 4*/
+			case 7: base_idx=idx-2; /* BAR 5*/
+		}
+
+	port =  pci_resource_start(dev, base_idx) + offset;
+
+	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
+		port += idx * (board->uart_offset ? board->uart_offset : 8);
+
+	if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
+		int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
+		req->port = port;
+		if (high_bits_offset)
+			req->port_high = port >> high_bits_offset;
+		else
+			req->port_high = 0;
+		return 0;
+	}
+	req->io_type = SERIAL_IO_MEM;
+	req->iomem_base = ioremap(port, board->uart_offset);
+	req->iomem_reg_shift = board->reg_shift;
+	req->port = 0;
+	return req->iomem_base ? 0 : 1;
+}
+
+/* Register the serial port(s) of a PCI card. */
+static int __devinit serial_register (struct pci_dev *dev,
+				      const struct pci_device_id *id)
+{
+	struct pci_board_no_ids *board = &pci_boards[id->driver_data];
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	struct serial_struct serial_req;
+	int base_baud;
+	int k;
+	int success = 0;
+
+	priv->ser = *board;
+	if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
+		return 1;
+
+	base_baud = board->base_baud;
+	if (!base_baud)
+		base_baud = BASE_BAUD;
+	memset (&serial_req, 0, sizeof (serial_req));
+
+	for (k = 0; k < board->num_ports; k++) {
+		int line;
+		serial_req.irq = dev->irq;
+		if (get_pci_port (dev, board, &serial_req, k))
+			break;
+		serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+		serial_req.baud_base = base_baud;
+		line = register_serial (&serial_req);
+		if (line < 0) {
+			printk (KERN_DEBUG
+				"parport_serial: register_serial failed\n");
+			continue;
+		}
+		priv->line[priv->num_ser++] = line;
+		success = 1;
+	}
+
+	return success ? 0 : 1;
+}
+
+/* Register the parallel port(s) of a PCI card. */
+static int __devinit parport_register (struct pci_dev *dev,
+				       const struct pci_device_id *id)
+{
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	int i = id->driver_data, n;
+	int success = 0;
+
+	if (cards[i].preinit_hook &&
+	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
+		return -ENODEV;
+
+	for (n = 0; n < cards[i].numports; n++) {
+		struct parport *port;
+		int lo = cards[i].addr[n].lo;
+		int hi = cards[i].addr[n].hi;
+		unsigned long io_lo, io_hi;
+		io_lo = pci_resource_start (dev, lo);
+		io_hi = 0;
+		if ((hi >= 0) && (hi <= 6))
+			io_hi = pci_resource_start (dev, hi);
+		else if (hi > 6)
+			io_lo += hi; /* Reinterpret the meaning of
+                                        "hi" as an offset (see SYBA
+                                        def.) */
+		/* TODO: test if sharing interrupts works */
+		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
+			"I/O at %#lx(%#lx)\n",
+			parport_serial_pci_tbl[i].vendor,
+			parport_serial_pci_tbl[i].device, io_lo, io_hi);
+		port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+					      PARPORT_DMA_NONE, dev);
+		if (port) {
+			priv->port[priv->num_par++] = port;
+			success = 1;
+		}
+	}
+
+	if (cards[i].postinit_hook)
+		cards[i].postinit_hook (dev, !success);
+
+	return success ? 0 : 1;
+}
+
+static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
+					       const struct pci_device_id *id)
+{
+	struct parport_serial_private *priv;
+	int err;
+
+	priv = kmalloc (sizeof *priv, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->num_ser = priv->num_par = 0;
+	pci_set_drvdata (dev, priv);
+
+	err = pci_enable_device (dev);
+	if (err) {
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return err;
+	}
+
+	if (parport_register (dev, id)) {
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return -ENODEV;
+	}
+
+	if (serial_register (dev, id)) {
+		int i;
+		for (i = 0; i < priv->num_par; i++)
+			parport_pc_unregister_port (priv->port[i]);
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
+{
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	int i;
+
+	// Serial ports
+	for (i = 0; i < priv->num_ser; i++) {
+		unregister_serial (priv->line[i]);
+
+		if (priv->ser.init_fn)
+			(priv->ser.init_fn) (dev, &priv->ser, 0);
+	}
+	pci_set_drvdata (dev, NULL);
+
+	// Parallel ports
+	for (i = 0; i < priv->num_par; i++)
+		parport_pc_unregister_port (priv->port[i]);
+
+	kfree (priv);
+	return;
+}
+
+static struct pci_driver parport_serial_pci_driver = {
+	name:		"parport_serial",
+	id_table:	parport_serial_pci_tbl,
+	probe:		parport_serial_pci_probe,
+	remove:		__devexit_p(parport_serial_pci_remove),
+};
+
+
+static int __init parport_serial_init (void)
+{
+	return pci_module_init (&parport_serial_pci_driver);
+}
+
+static void __exit parport_serial_exit (void)
+{
+	pci_unregister_driver (&parport_serial_pci_driver);
+	return;
+}
+
+MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
+MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
+MODULE_LICENSE("GPL");
+
+module_init(parport_serial_init);
+module_exit(parport_serial_exit);
diff -urN linux-2.4.27-pre5/drivers/ide/Config.in linux-2.4.27-pre6/drivers/ide/Config.in
--- linux-2.4.27-pre5/drivers/ide/Config.in	2004-04-14 06:05:29.000000000 -0700
+++ linux-2.4.27-pre6/drivers/ide/Config.in	2004-06-16 11:33:28.138087339 -0700
@@ -63,11 +63,11 @@
 	    fi
 	    dep_tristate '    NS87415 chipset support' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL
-	    dep_tristate '    PROMISE PDC202{46|62|65|67} support' CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
-	    dep_mbool     '      Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
-	    dep_tristate '    PROMISE PDC202{68|69|70|71|75|76|77} support' CONFIG_BLK_DEV_PDC202XX_NEW $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_tristate '    Promise PDC202{46|62|65|67} support' CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_mbool     '      Force (U)DMA burst transfers' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX_OLD
+	    dep_tristate '    Promise PDC202{68|69|70|71|75|76|77} support' CONFIG_BLK_DEV_PDC202XX_NEW $CONFIG_BLK_DEV_IDEDMA_PCI
 	    if [ "$CONFIG_BLK_DEV_PDC202XX_OLD" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_OLD" = "m" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "m" ]; then
-	        bool     '    Special FastTrak Feature' CONFIG_PDC202XX_FORCE
+	        bool     '    Ignore BIOS port disabled setting on FastTrak' CONFIG_PDC202XX_FORCE
 	    fi
 	    dep_tristate '    RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86
 	    dep_tristate '    SCx200 chipset support' CONFIG_BLK_DEV_SC1200 $CONFIG_BLK_DEV_IDEDMA_PCI
diff -urN linux-2.4.27-pre5/drivers/ide/ide-cd.c linux-2.4.27-pre6/drivers/ide/ide-cd.c
--- linux-2.4.27-pre5/drivers/ide/ide-cd.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/ide/ide-cd.c	2004-06-16 11:33:28.140087422 -0700
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
+ * Copyright (C) 1998-2004  Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2004 Iomega Corp
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
@@ -2683,7 +2684,7 @@
 				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
 				CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
 				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
-				CDC_GENERIC_PACKET,
+				CDC_GENERIC_PACKET | CDC_RAM,
 	generic_packet:		ide_cdrom_packet,
 };
 
@@ -2718,6 +2719,8 @@
 		devinfo->mask |= CDC_PLAY_AUDIO;
 	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
 		devinfo->mask |= CDC_CLOSE_TRAY;
+	if (!CDROM_CONFIG_FLAGS(drive)->ram)
+		devinfo->mask |= CDC_RAM;
 
 	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
 				     HWIF(drive)->major, minor,
@@ -2766,7 +2769,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct atapi_capabilities_page cap;
-	int nslots = 1;
+	int nslots = 1, ram_write = 0;
 
 	if (CDROM_CONFIG_FLAGS(drive)->nec260) {
 		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;                       
@@ -2776,7 +2779,9 @@
 
 	if (ide_cdrom_get_capabilities(drive, &cap))
 		return 0;
-
+	cdrom_is_random_writable(cdi, &ram_write);
+	if (ram_write) 
+		CDROM_CONFIG_FLAGS(drive)->ram = 1;
 	if (cap.lock == 0)
 		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
 	if (cap.eject)
@@ -2789,8 +2794,10 @@
 		CDROM_CONFIG_FLAGS(drive)->test_write = 1;
 	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
 		CDROM_CONFIG_FLAGS(drive)->dvd = 1;
-	if (cap.dvd_ram_write)
+	if (cap.dvd_ram_write) {
 		CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
+		CDROM_CONFIG_FLAGS(drive)->ram = 1;
+	}
 	if (cap.dvd_r_write)
 		CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
 	if (cap.audio_play)
@@ -3000,7 +3007,8 @@
 
 	nslots = ide_cdrom_probe_capabilities (drive);
 
-	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
+	if ((CDROM_CONFIG_FLAGS(drive)->dvd_ram) ||
+	    (CDROM_CONFIG_FLAGS(drive)->ram))
 		set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
 
 #if 0
diff -urN linux-2.4.27-pre5/drivers/ide/ide-cd.h linux-2.4.27-pre6/drivers/ide/ide-cd.h
--- linux-2.4.27-pre5/drivers/ide/ide-cd.h	2003-06-13 07:51:33.000000000 -0700
+++ linux-2.4.27-pre6/drivers/ide/ide-cd.h	2004-06-16 11:33:28.141087464 -0700
@@ -2,7 +2,8 @@
  *  linux/drivers/ide/ide_cd.h
  *
  *  Copyright (C) 1996-98  Erik Andersen
- *  Copyright (C) 1998-2000 Jens Axboe
+ *  Copyright (C) 1998-2004 Jens Axboe
+ *  Copyright (C) 2004 Iomega Corp
  */
 #ifndef _IDE_CD_H
 #define _IDE_CD_H
@@ -75,6 +76,7 @@
 	__u8 dvd		: 1; /* Drive is a DVD-ROM */
 	__u8 dvd_r		: 1; /* Drive can write DVD-R */
 	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
+	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
 	__u8 test_write		: 1; /* Drive can fake writes */
 	__u8 supp_disc_present	: 1; /* Changer can report exact contents
 					of slots. */
diff -urN linux-2.4.27-pre5/drivers/ide/ide.c linux-2.4.27-pre6/drivers/ide/ide.c
--- linux-2.4.27-pre5/drivers/ide/ide.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.27-pre6/drivers/ide/ide.c	2004-06-16 11:33:28.144087589 -0700
@@ -2993,7 +2993,24 @@
 
 			/* set the drive to standby */
 			printk("%s ", drive->name);
+#ifdef	CONFIG_ALPHA
+			/* On Alpha, halt(8) doesn't actually turn the machine
+			   off, it puts you into the sort of firmware monitor.
+			   Typically, it's used to boot another kernel image,
+			   so it's not much different from reboot(8).
+			   Therefore, we don't need to spin down the disk in
+			   this case, especially since Alpha firmware doesn't
+			   handle disks in standby mode properly.
+			   On the other hand, it's reasonably safe to turn
+			   the power off when the shutdown process reaches
+			   the firmware prompt, as the firmware initialization
+			   takes rather long time - at least 10 seconds,
+			   which should be sufficient for the disk to expire
+			   its write cache. */
+			if (event == SYS_POWER_OFF)
+#else
 			if (event != SYS_RESTART)
+#endif
 				if (DRIVER(drive)->standby(drive))
 					continue;
 
diff -urN linux-2.4.27-pre5/drivers/ide/pci/amd74xx.c linux-2.4.27-pre6/drivers/ide/pci/amd74xx.c
--- linux-2.4.27-pre5/drivers/ide/pci/amd74xx.c	2004-04-14 06:05:29.000000000 -0700
+++ linux-2.4.27-pre6/drivers/ide/pci/amd74xx.c	2004-06-16 11:33:28.145087630 -0700
@@ -1,7 +1,8 @@
 /*
  * Version 2.13
  *
- * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s IDE driver for Linux.
+ * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
+ * IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -68,6 +69,12 @@
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,	0x50, AMD_UDMA_133 },
 	{ 0 }
 };
 
@@ -464,6 +471,12 @@
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
 	{ 0, },
 };
 
diff -urN linux-2.4.27-pre5/drivers/ide/pci/amd74xx.h linux-2.4.27-pre6/drivers/ide/pci/amd74xx.h
--- linux-2.4.27-pre5/drivers/ide/pci/amd74xx.h	2004-04-14 06:05:29.000000000 -0700
+++ linux-2.4.27-pre6/drivers/ide/pci/amd74xx.h	2004-06-16 11:33:28.145087630 -0700
@@ -112,7 +112,7 @@
 	{	/* 7 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,
-		.name		= "NFORCE2S",
+		.name		= "NFORCE2-U400R",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -123,7 +123,7 @@
 	{	/* 8 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
-		.name		= "NFORCE2S-SATA",
+		.name		= "NFORCE2-U400R-SATA",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -134,7 +134,7 @@
 	{	/* 9 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,
-		.name		= "NFORCE3",
+		.name		= "NFORCE3-150",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -145,7 +145,7 @@
 	{	/* 10 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,
-		.name		= "NFORCE3S",
+		.name		= "NFORCE3-250",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -156,7 +156,7 @@
 	{	/* 11 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
-		.name		= "NFORCE3S-SATA",
+		.name		= "NFORCE3-250-SATA",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -167,7 +167,73 @@
 	{	/* 12 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
-		.name		= "NFORCE3S-SATA2",
+		.name		= "NFORCE3-250-SATA2",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 13 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,
+		.name		= "NFORCE-CK804",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 14 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+		.name		= "NFORCE-CK804-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 15 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+		.name		= "NFORCE-CK804-SATA2",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 16 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,
+		.name		= "NFORCE-MCP04",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 17 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+		.name		= "NFORCE-MCP04-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 18 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+		.name		= "NFORCE-MCP04-SATA2",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
diff -urN linux-2.4.27-pre5/drivers/ide/pci/hpt366.c linux-2.4.27-pre6/drivers/ide/pci/hpt366.c
--- linux-2.4.27-pre5/drivers/ide/pci/hpt366.c	2004-06-16 11:33:26.194006432 -0700
+++ linux-2.4.27-pre6/drivers/ide/pci/hpt366.c	2004-06-16 11:33:28.148087755 -0700
@@ -123,7 +123,7 @@
 				"                             %s\n",
 			(c0 & 0x80) ? "no" : "yes",
 			(c1 & 0x80) ? "no" : "yes");
-
+#if 0
 		if (hpt_minimum_revision(dev, 3)) {
 			u8 cbl;
 			cbl = inb(iobase + 0x7b);
@@ -136,7 +136,7 @@
 				(cbl & 0x01) ? 33 : 66);
 			p += sprintf(p, "\n");
 		}
-
+#endif
 		p += sprintf(p, "--------------- drive0 --------- drive1 "
 				"------- drive0 ---------- drive1 -------\n");
 		p += sprintf(p, "DMA capable:    %s              %s" 
diff -urN linux-2.4.27-pre5/drivers/ieee1394/pcilynx.c linux-2.4.27-pre6/drivers/ieee1394/pcilynx.c
--- linux-2.4.27-pre5/drivers/ieee1394/pcilynx.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/ieee1394/pcilynx.c	2004-06-16 11:33:28.154088005 -0700
@@ -1464,7 +1464,7 @@
                 reg_write(lynx, PCI_INT_ENABLE, 0);
                 free_irq(lynx->dev->irq, lynx);
 
-		/* Disable IRM Contender */
+		/* Disable IRM Contender and LCtrl */
 		if (lynx->phyic.reg_1394a)
 			set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4));
 
@@ -1792,12 +1792,12 @@
                 reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
                 reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); 
         } else {
-                /* set the contender bit in the extended PHY register
+                /* set the contender and LCtrl bit in the extended PHY register
                  * set. (Should check that bis 0,1,2 (=0xE0) is set
                  * in register 2?)
                  */
                 i = get_phy_reg(lynx, 4);
-                if (i != -1) set_phy_reg(lynx, 4, i | 0x40);
+                if (i != -1) set_phy_reg(lynx, 4, i | 0xc0);
         }
 
 
diff -urN linux-2.4.27-pre5/drivers/ieee1394/sbp2.c linux-2.4.27-pre6/drivers/ieee1394/sbp2.c
--- linux-2.4.27-pre5/drivers/ieee1394/sbp2.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/ieee1394/sbp2.c	2004-06-16 11:33:28.155088047 -0700
@@ -113,8 +113,8 @@
  * badly behaved sbp2 devices.
  */
 MODULE_PARM(sbp2_serialize_io,"i");
-MODULE_PARM_DESC(sbp2_serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)");
-static int sbp2_serialize_io = 0;	/* serialize I/O - available for debugging purposes */
+MODULE_PARM_DESC(sbp2_serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 1)");
+static int sbp2_serialize_io = 1;	/* serialize I/O - available for debugging purposes */
 
 /*
  * Bump up sbp2_max_sectors if you'd like to support very large sized
diff -urN linux-2.4.27-pre5/drivers/ieee1394/video1394.c linux-2.4.27-pre6/drivers/ieee1394/video1394.c
--- linux-2.4.27-pre5/drivers/ieee1394/video1394.c	2004-04-14 06:05:30.000000000 -0700
+++ linux-2.4.27-pre6/drivers/ieee1394/video1394.c	2004-06-16 11:33:28.157088130 -0700
@@ -21,6 +21,9 @@
 /* jds -- add private data to file to keep track of iso contexts associated
    with each open -- so release won't kill all iso transfers */
 
+/* Damien Douxchamps: Fix failure when the number of DMA pages per frame is
+   one */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -405,33 +408,43 @@
 				(unsigned long)d->dma.kvirt));
 	ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
 					1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-	/* the second descriptor will read PAGE_SIZE-4 bytes */
-	ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-		DMA_CTL_BRANCH | (PAGE_SIZE-4));
-	ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
-					(unsigned long)d->dma.kvirt));
-	ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-					2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+	/* if there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
+ 	if (d->nb_cmd>2) {
+  	        /* the second descriptor will read PAGE_SIZE-4 bytes */
+	        ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+					        DMA_CTL_BRANCH | (PAGE_SIZE-4));
+		ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
+						(unsigned long)d->dma.kvirt));
+		ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					   2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	
-	for (i=2;i<d->nb_cmd-1;i++) {
+		for (i=2;i<d->nb_cmd-1;i++) {
+		        ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+							DMA_CTL_BRANCH | PAGE_SIZE);
+			ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+							(buf+(i-1)*PAGE_SIZE) -
+							(unsigned long)d->dma.kvirt));
+
+			ir_prg[i].branchAddress =
+			             cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+				     (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+		}
+
+		/* the last descriptor will generate an interrupt */
 		ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-			DMA_CTL_BRANCH | PAGE_SIZE);
+					        DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
 		ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
 					        (buf+(i-1)*PAGE_SIZE) -
-						(unsigned long)d->dma.kvirt));
-
-		ir_prg[i].branchAddress =
-			cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-				(i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+					        (unsigned long)d->dma.kvirt));
+	}
+	else { 
+	       /* only one DMA page is used. Read d->left_size immediately and */
+	       /* generate an interrupt as this is also the last page */
+	       ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+		                           DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
+	       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+		  			       (buf + 4) - (unsigned long)d->dma.kvirt));
 	}
-
-	/* the last descriptor will generate an interrupt */
-	ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-		DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-	ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-					(buf+(i-1)*PAGE_SIZE) -
-					(unsigned long)d->dma.kvirt));
 }
 	
 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
diff -urN linux-2.4.27-pre5/drivers/md/raid5.c linux-2.4.27-pre6/drivers/md/raid5.c
--- linux-2.4.27-pre5/drivers/md/raid5.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.27-pre6/drivers/md/raid5.c	2004-06-16 11:33:28.178089004 -0700
@@ -950,7 +950,7 @@
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 */
-	if (to_read || (syncing && (uptodate+failed < disks))) {
+	if (to_read || (syncing && (uptodate < disks))) {
 		for (i=disks; i--;) {
 			bh = sh->bh_cache[i];
 			if (!buffer_locked(bh) && !buffer_uptodate(bh) &&
diff -urN linux-2.4.27-pre5/drivers/net/tg3.c linux-2.4.27-pre6/drivers/net/tg3.c
--- linux-2.4.27-pre5/drivers/net/tg3.c	2004-06-16 11:33:26.307011135 -0700
+++ linux-2.4.27-pre6/drivers/net/tg3.c	2004-06-16 11:33:28.302094165 -0700
@@ -55,8 +55,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.5"
-#define DRV_MODULE_RELDATE	"May 25, 2004"
+#define DRV_MODULE_VERSION	"3.6"
+#define DRV_MODULE_RELDATE	"June 12, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -176,6 +176,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2,
@@ -194,6 +196,10 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
@@ -7534,6 +7540,14 @@
 	udelay(50);
 	tg3_nvram_init(tp);
 
+	/* Always use host TXDs, it performs better in particular
+	 * with multi-frag packets.  The tests below are kept here
+	 * as documentation should we change this decision again
+	 * in the future.
+	 */
+	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+
+#if 0
 	/* Determine if TX descriptors will reside in
 	 * main memory or in the chip SRAM.
 	 */
@@ -7541,6 +7555,7 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
 		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+#endif
 
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
@@ -7563,7 +7578,9 @@
 	     tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
 	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
 	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)))
+	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
+	    (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+	     tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F))
 		tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
 	err = tg3_phy_probe(tp);
@@ -8438,6 +8455,8 @@
 	if (!netif_running(dev))
 		return 0;
 
+	pci_restore_state(tp->pdev, tp->pci_cfg_state);
+
 	err = tg3_set_power_state(tp, 0);
 	if (err)
 		return err;
diff -urN linux-2.4.27-pre5/drivers/net/tun.c linux-2.4.27-pre6/drivers/net/tun.c
--- linux-2.4.27-pre5/drivers/net/tun.c	2002-08-02 17:39:44.000000000 -0700
+++ linux-2.4.27-pre6/drivers/net/tun.c	2004-06-16 11:33:28.356096412 -0700
@@ -138,8 +138,8 @@
 		dev->addr_len = 0;
 		dev->mtu = 1500;
 
-		/* Type PPP seems most suitable */
-		dev->type = ARPHRD_PPP; 
+		/* Zero header length */
+		dev->type = ARPHRD_NONE; 
 		dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
 		dev->tx_queue_len = 10;
 		break;
diff -urN linux-2.4.27-pre5/drivers/parport/ChangeLog linux-2.4.27-pre6/drivers/parport/ChangeLog
--- linux-2.4.27-pre5/drivers/parport/ChangeLog	2003-06-13 07:51:35.000000000 -0700
+++ linux-2.4.27-pre6/drivers/parport/ChangeLog	2004-06-16 11:33:28.386097661 -0700
@@ -1,7 +1,16 @@
+2004-06-13  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+       * parport_serial.c: Move from here to ../char/, must be initialised
+       after serial.c for register_serial to work.
+
 2002-11-29  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_pc.c: Fix ECP hang on Aladdin card.
 
+	2001-10-11  Tim Waugh  <twaugh@redhat.com>
+	* parport_pc.c, parport_serial.c: Support for NetMos cards.
+	Patch originally from Michael Reinelt <reinelt@eunet.at>.
+
 2002-04-25  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_serial.c, parport_pc.c: Move some SIIG cards around.
diff -urN linux-2.4.27-pre5/drivers/parport/Makefile linux-2.4.27-pre6/drivers/parport/Makefile
--- linux-2.4.27-pre5/drivers/parport/Makefile	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.27-pre6/drivers/parport/Makefile	2004-06-16 11:33:28.387097702 -0700
@@ -22,7 +22,6 @@
 
 obj-$(CONFIG_PARPORT)		+= parport.o
 obj-$(CONFIG_PARPORT_PC)	+= parport_pc.o
-obj-$(CONFIG_PARPORT_SERIAL)	+= parport_serial.o
 obj-$(CONFIG_PARPORT_PC_PCMCIA)	+= parport_cs.o
 obj-$(CONFIG_PARPORT_AMIGA)	+= parport_amiga.o
 obj-$(CONFIG_PARPORT_MFC3)	+= parport_mfc3.o
diff -urN linux-2.4.27-pre5/drivers/parport/parport_pc.c linux-2.4.27-pre6/drivers/parport/parport_pc.c
--- linux-2.4.27-pre5/drivers/parport/parport_pc.c	2003-06-13 07:51:35.000000000 -0700
+++ linux-2.4.27-pre6/drivers/parport/parport_pc.c	2004-06-16 11:33:28.388097744 -0700
@@ -2699,6 +2699,10 @@
 	oxsemi_840,
 	aks_0100,
 	mobility_pp,
+	netmos_9705,
+	netmos_9805,
+	netmos_9815,
+	netmos_9855,
 };
 
 
@@ -2768,6 +2772,10 @@
 	/* oxsemi_840 */		{ 1, { { 0, -1 }, } },
 	/* aks_0100 */			{ 1, { { 0, -1 }, } },
 	/* mobility_pp */		{ 1, { { 0, 1 }, } },
+	/* netmos_9705 */               { 1, { { 0, -1 }, } }, /* untested */
+	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
+	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
+	/* netmos_9855 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2836,6 +2844,15 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_840 },
 	{ PCI_VENDOR_ID_AKS, PCI_DEVICE_ID_AKS_ALADDINCARD,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, aks_0100 },
+	/* NetMos communication controllers */
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9705,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9705 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9805,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff -urN linux-2.4.27-pre5/drivers/parport/parport_serial.c linux-2.4.27-pre6/drivers/parport/parport_serial.c
--- linux-2.4.27-pre5/drivers/parport/parport_serial.c	2002-08-02 17:39:44.000000000 -0700
+++ linux-2.4.27-pre6/drivers/parport/parport_serial.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,426 +0,0 @@
-/*
- * Support for common PCI multi-I/O cards (which is most of them)
- *
- * Copyright (C) 2001  Tim Waugh <twaugh@redhat.com>
- *
- * 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.
- *
- *
- * Multi-function PCI cards are supposed to present separate logical
- * devices on the bus.  A common thing to do seems to be to just use
- * one logical device with lots of base address registers for both
- * parallel ports and serial ports.  This driver is for dealing with
- * that.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/parport.h>
-#include <linux/parport_pc.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/list.h>
-
-#include <asm/serial.h>
-
-enum parport_pc_pci_cards {
-	titan_110l = 0,
-	titan_210l,
-	avlab_1s1p,
-	avlab_1s1p_650,
-	avlab_1s1p_850,
-	avlab_1s2p,
-	avlab_1s2p_650,
-	avlab_1s2p_850,
-	avlab_2s1p,
-	avlab_2s1p_650,
-	avlab_2s1p_850,
-	siig_1s1p_10x,
-	siig_2s1p_10x,
-	siig_2p1s_20x,
-	siig_1s1p_20x,
-	siig_2s1p_20x,
-};
-
-
-/* each element directly indexed from enum list, above */
-static struct parport_pc_pci {
-	int numports;
-	struct { /* BAR (base address registers) numbers in the config
-                    space header */
-		int lo;
-		int hi; /* -1 if not there, >6 for offset-method (max
-                           BAR is 6) */
-	} addr[4];
-
-	/* If set, this is called immediately after pci_enable_device.
-	 * If it returns non-zero, no probing will take place and the
-	 * ports will not be used. */
-	int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
-
-	/* If set, this is called after probing for ports.  If 'failed'
-	 * is non-zero we couldn't use any of the ports. */
-	void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
-	/* titan_110l */		{ 1, { { 3, -1 }, } },
-	/* titan_210l */		{ 1, { { 3, -1 }, } },
-	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
-	/* avlab_1s1p_650 */		{ 1, { { 1, 2}, } },
-	/* avlab_1s1p_850 */		{ 1, { { 1, 2}, } },
-	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_1s2p_650 */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_1s2p_850 */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
-	/* avlab_2s1p_650 */		{ 1, { { 2, 3}, } },
-	/* avlab_2s1p_850 */		{ 1, { { 2, 3}, } },
-	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
-	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
-	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
-	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
-	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
-};
-
-static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
-	/* PCI cards */
-	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
-	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
-	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
-	{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
-	{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
-	{ 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850},
-	{ 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p},
-	{ 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650},
-	{ 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850},
-	{ 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
-	{ 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
-	{ 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-
-	{ 0, } /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
-
-struct pci_board_no_ids {
-	int flags;
-	int num_ports;
-	int base_baud;
-	int uart_offset;
-	int reg_shift;
-	int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
-			int enable);
-	int first_uart_offset;
-};
-
-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-	return pci_siig10x_fn(dev, NULL, enable);
-}
-
-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-	return pci_siig20x_fn(dev, NULL, enable);
-}
-
-static struct pci_board_no_ids pci_boards[] __devinitdata = {
-	/*
-	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-	 * Offset to get to next UART's registers,
-	 * Register shift to use for memory-mapped I/O,
-	 * Initialization function, first UART offset
-	 */
-
-// Cards not tested are marked n/t
-// If you have one of these cards and it works for you, please tell me..
-
-/* titan_110l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
-/* titan_210l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* avlab_1s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_2s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* siig_1s1p_10x */	{ SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
-/* siig_2s1p_10x */	{ SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
-/* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-};
-
-struct parport_serial_private {
-	int num_ser;
-	int line[20];
-	struct pci_board_no_ids ser;
-	int num_par;
-	struct parport *port[PARPORT_MAX];
-};
-
-static int __devinit get_pci_port (struct pci_dev *dev,
-				   struct pci_board_no_ids *board,
-				   struct serial_struct *req,
-				   int idx)
-{
-	unsigned long port;
-	int base_idx;
-	int max_port;
-	int offset;
-
-	base_idx = SPCI_FL_GET_BASE(board->flags);
-	if (board->flags & SPCI_FL_BASE_TABLE)
-		base_idx += idx;
-
-	if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-		max_port = pci_resource_len(dev, base_idx) / 8;
-		if (idx >= max_port)
-			return 1;
-	}
-			
-	offset = board->first_uart_offset;
-
-	/* Timedia/SUNIX uses a mixture of BARs and offsets */
-	/* Ugh, this is ugly as all hell --- TYT */
-	if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
-		switch(idx) {
-			case 0: base_idx=0;
-				break;
-			case 1: base_idx=0; offset=8;
-				break;
-			case 2: base_idx=1; 
-				break;
-			case 3: base_idx=1; offset=8;
-				break;
-			case 4: /* BAR 2*/
-			case 5: /* BAR 3 */
-			case 6: /* BAR 4*/
-			case 7: base_idx=idx-2; /* BAR 5*/
-		}
-  
-	port =  pci_resource_start(dev, base_idx) + offset;
-
-	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-		port += idx * (board->uart_offset ? board->uart_offset : 8);
-
-	if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
-		int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
-		req->port = port;
-		if (high_bits_offset)
-			req->port_high = port >> high_bits_offset;
-		else
-			req->port_high = 0;
-		return 0;
-	}
-	req->io_type = SERIAL_IO_MEM;
-	req->iomem_base = ioremap(port, board->uart_offset);
-	req->iomem_reg_shift = board->reg_shift;
-	req->port = 0;
-	return req->iomem_base ? 0 : 1;
-}
-
-/* Register the serial port(s) of a PCI card. */
-static int __devinit serial_register (struct pci_dev *dev,
-				      const struct pci_device_id *id)
-{
-	struct pci_board_no_ids *board = &pci_boards[id->driver_data];
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	struct serial_struct serial_req;
-	int base_baud;
-	int k;
-	int success = 0;
-
-	priv->ser = *board;
-	if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
-		return 1;
-
-	base_baud = board->base_baud;
-	if (!base_baud)
-		base_baud = BASE_BAUD;
-	memset (&serial_req, 0, sizeof (serial_req));
-
-	for (k = 0; k < board->num_ports; k++) {
-		int line;
-		serial_req.irq = dev->irq;
-		if (get_pci_port (dev, board, &serial_req, k))
-			break;
-		serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-		serial_req.baud_base = base_baud;
-		line = register_serial (&serial_req);
-		if (line < 0) {
-			printk (KERN_DEBUG
-				"parport_serial: register_serial failed\n");
-			continue;
-		}
-		priv->line[priv->num_ser++] = line;
-		success = 1;
-	}
-
-	return success ? 0 : 1;
-}
-
-/* Register the parallel port(s) of a PCI card. */
-static int __devinit parport_register (struct pci_dev *dev,
-				       const struct pci_device_id *id)
-{
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	int i = id->driver_data, n;
-	int success = 0;
-
-	if (cards[i].preinit_hook &&
-	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
-		return -ENODEV;
-
-	for (n = 0; n < cards[i].numports; n++) {
-		struct parport *port;
-		int lo = cards[i].addr[n].lo;
-		int hi = cards[i].addr[n].hi;
-		unsigned long io_lo, io_hi;
-		io_lo = pci_resource_start (dev, lo);
-		io_hi = 0;
-		if ((hi >= 0) && (hi <= 6))
-			io_hi = pci_resource_start (dev, hi);
-		else if (hi > 6)
-			io_lo += hi; /* Reinterpret the meaning of
-                                        "hi" as an offset (see SYBA
-                                        def.) */
-		/* TODO: test if sharing interrupts works */
-		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
-			"I/O at %#lx(%#lx)\n",
-			parport_serial_pci_tbl[i].vendor,
-			parport_serial_pci_tbl[i].device, io_lo, io_hi);
-		port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-					      PARPORT_DMA_NONE, dev);
-		if (port) {
-			priv->port[priv->num_par++] = port;
-			success = 1;
-		}
-	}
-
-	if (cards[i].postinit_hook)
-		cards[i].postinit_hook (dev, !success);
-
-	return success ? 0 : 1;
-}
-
-static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
-					       const struct pci_device_id *id)
-{
-	struct parport_serial_private *priv;
-	int err;
-
-	priv = kmalloc (sizeof *priv, GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	priv->num_ser = priv->num_par = 0;
-	pci_set_drvdata (dev, priv);
-
-	err = pci_enable_device (dev);
-	if (err) {
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return err;
-	}
-
-	if (parport_register (dev, id)) {
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return -ENODEV;
-	}
-
-	if (serial_register (dev, id)) {
-		int i;
-		for (i = 0; i < priv->num_par; i++)
-			parport_pc_unregister_port (priv->port[i]);
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
-{
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	int i;
-
-	// Serial ports
-	for (i = 0; i < priv->num_ser; i++) {
-		unregister_serial (priv->line[i]);
-
-		if (priv->ser.init_fn)
-			(priv->ser.init_fn) (dev, &priv->ser, 0);
-	}
-	pci_set_drvdata (dev, NULL);
-	
-	// Parallel ports
-	for (i = 0; i < priv->num_par; i++)
-		parport_pc_unregister_port (priv->port[i]);
-
-	kfree (priv);
-	return;
-}
-
-static struct pci_driver parport_serial_pci_driver = {
-	name:		"parport_serial",
-	id_table:	parport_serial_pci_tbl,
-	probe:		parport_serial_pci_probe,
-	remove:		__devexit_p(parport_serial_pci_remove),
-};
-
-
-static int __init parport_serial_init (void)
-{
-	return pci_module_init (&parport_serial_pci_driver);
-}
-
-static void __exit parport_serial_exit (void)
-{
-	pci_unregister_driver (&parport_serial_pci_driver);
-	return;
-}
-
-MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
-MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
-MODULE_LICENSE("GPL");
-
-module_init(parport_serial_init);
-module_exit(parport_serial_exit);
diff -urN linux-2.4.27-pre5/drivers/pci/pci.ids linux-2.4.27-pre6/drivers/pci/pci.ids
--- linux-2.4.27-pre5/drivers/pci/pci.ids	2004-06-16 11:33:26.331012134 -0700
+++ linux-2.4.27-pre6/drivers/pci/pci.ids	2004-06-16 11:33:28.433099617 -0700
@@ -5552,9 +5552,12 @@
 	1676  NetXtreme BCM5750 Gigabit Ethernet
 	1677  NetXtreme BCM5751 Gigabit Ethernet
 	167c  NetXtreme BCM5750M Gigabit Ethernet
+	167d  NetXtreme BCM5751M Gigabit Ethernet
+	167e  NetXtreme BCM5751F Gigabit Ethernet
 	1696  NetXtreme BCM5782 Gigabit Ethernet
 		14e4 000d  NetXtreme BCM5782 1000Base-T
 	169c  NetXtreme BCM5788 Gigabit Ethernet
+	169d  NetXtreme BCM5789 Gigabit Ethernet
 	16a6  NetXtreme BCM5702 Gigabit Ethernet
 		0e11 00bb  NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
 		1028 0126  BCM5702 1000Base-T
diff -urN linux-2.4.27-pre5/drivers/scsi/sr.c linux-2.4.27-pre6/drivers/scsi/sr.c
--- linux-2.4.27-pre5/drivers/scsi/sr.c	2003-06-13 07:51:36.000000000 -0700
+++ linux-2.4.27-pre6/drivers/scsi/sr.c	2004-06-16 11:33:28.609106942 -0700
@@ -1,6 +1,7 @@
 /*
  *  sr.c Copyright (C) 1992 David Giller
  *           Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
+ *       Copyright (C) 2004 Iomega Corp
  *
  *  adapted from:
  *      sd.c Copyright (C) 1992 Drew Eckhardt
@@ -128,7 +129,7 @@
 				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
 				CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS |
 				CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
-				CDC_DVD_RAM | CDC_GENERIC_PACKET,
+				CDC_DVD_RAM | CDC_GENERIC_PACKET | CDC_RAM,
 	generic_packet:		sr_packet,
 };
 
@@ -693,7 +694,7 @@
 {
 	unsigned char cmd[6];
 	unsigned char *buffer;
-	int rc, n;
+	int rc, n, ram_write=0;
 
 	static char *loadmech[] =
 	{
@@ -731,6 +732,11 @@
 		printk("sr%i: scsi-1 drive\n", i);
 		return;
 	}
+	if (cdrom_is_random_writable(&scsi_CDs[i].cdi, &ram_write))
+		scsi_CDs[i].cdi.mask |= CDC_RAM;
+	if (!ram_write)
+		scsi_CDs[i].cdi.mask |= CDC_RAM;
+
 	n = buffer[3] + 4;
 	scsi_CDs[i].cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
 	scsi_CDs[i].readcd_known = 1;
@@ -754,8 +760,6 @@
 	if ((buffer[n + 3] & 0x20) == 0) {
 		/* can't write DVD-RAM media */
 		scsi_CDs[i].cdi.mask |= CDC_DVD_RAM;
-	} else {
-		scsi_CDs[i].device->writeable = 1;
 	}
 	if ((buffer[n + 3] & 0x10) == 0)
 		/* can't write DVD-R media */
@@ -780,6 +784,13 @@
 	/*else    I don't think it can close its tray
 	   scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */
 
+	/*
+	 * if DVD-RAM of MRW-W, we are randomly writeable
+	 */
+	if ((scsi_CDs[i].cdi.mask & (CDC_DVD_RAM | CDC_RAM)) !=
+	    (CDC_DVD_RAM | CDC_RAM))
+		scsi_CDs[i].device->writeable = 1;
+
 	scsi_free(buffer, 512);
 }
 
diff -urN linux-2.4.27-pre5/drivers/usb/gadget/config.c linux-2.4.27-pre6/drivers/usb/gadget/config.c
--- linux-2.4.27-pre5/drivers/usb/gadget/config.c	2004-04-14 06:05:32.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/gadget/config.c	2004-06-16 11:33:28.697110604 -0700
@@ -51,7 +51,7 @@
 	for (; 0 != *src; src++) {
 		unsigned		len = (*src)->bLength;
 
-		if (len > buflen);
+		if (len > buflen)
 			return -EINVAL;
 		memcpy(dest, *src, len);
 		buflen -= len;
diff -urN linux-2.4.27-pre5/drivers/usb/host/ehci-hcd.c linux-2.4.27-pre6/drivers/usb/host/ehci-hcd.c
--- linux-2.4.27-pre5/drivers/usb/host/ehci-hcd.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.27-pre6/drivers/usb/host/ehci-hcd.c	2004-06-16 11:33:28.699110687 -0700
@@ -291,7 +291,7 @@
 		int msec = 500;
 
 		/* request handoff to OS */
-		cap &= 1 << 24;
+		cap |= 1 << 24;
 		pci_write_config_dword (ehci->hcd.pdev, where, cap);
 
 		/* and wait a while for it to happen */
diff -urN linux-2.4.27-pre5/drivers/usb/host/ehci-sched.c linux-2.4.27-pre6/drivers/usb/host/ehci-sched.c
--- linux-2.4.27-pre5/drivers/usb/host/ehci-sched.c	2004-04-14 06:05:33.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/host/ehci-sched.c	2004-06-16 11:33:28.699110687 -0700
@@ -402,7 +402,7 @@
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= ~0xffff;
+		qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
 		qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
 	} else
 		dbg ("reused previous qh %p schedule", qh);
diff -urN linux-2.4.27-pre5/drivers/usb/serial/ftdi_sio.c linux-2.4.27-pre6/drivers/usb/serial/ftdi_sio.c
--- linux-2.4.27-pre5/drivers/usb/serial/ftdi_sio.c	2004-04-14 06:05:34.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/serial/ftdi_sio.c	2004-06-16 11:33:28.702110812 -0700
@@ -17,6 +17,9 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (10/Mar/2004) Jan Capek
+ *      Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc.
+ *
  * (09/Feb/2004) Ian Abbott
  *      Changed full name of USB-UIRT device to avoid "/" character.
  *      Added FTDI's alternate PID (0x6006) for FT232/245 devices.
@@ -428,6 +431,8 @@
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -526,6 +531,8 @@
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ }						/* Terminating entry */
 };
 
diff -urN linux-2.4.27-pre5/drivers/usb/serial/ftdi_sio.h linux-2.4.27-pre6/drivers/usb/serial/ftdi_sio.h
--- linux-2.4.27-pre5/drivers/usb/serial/ftdi_sio.h	2004-04-14 06:05:34.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/serial/ftdi_sio.h	2004-06-16 11:33:28.703110854 -0700
@@ -165,6 +165,11 @@
 #define PROTEGO_SPECIAL_3	0xFC72	/* special/unknown device */
 #define PROTEGO_SPECIAL_4	0xFC73	/* special/unknown device */ 
 
+/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
+/* unit for PIC16's/PIC18's */
+#define FTDI_CCSICDU20_0_PID  0xF9D0     
+#define FTDI_CCSICDU40_1_PID  0xF9D1     
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff -urN linux-2.4.27-pre5/drivers/usb/serial/mct_u232.c linux-2.4.27-pre6/drivers/usb/serial/mct_u232.c
--- linux-2.4.27-pre5/drivers/usb/serial/mct_u232.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.27-pre6/drivers/usb/serial/mct_u232.c	2004-06-16 11:33:28.704110895 -0700
@@ -169,7 +169,8 @@
 
 
 struct mct_u232_private {
-	unsigned long	     control_state; /* Modem Line Setting (TIOCM) */
+	spinlock_t lock;
+	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
 	unsigned char        last_lcr;      /* Line Control Register */
 	unsigned char	     last_lsr;      /* Line Status Register */
 	unsigned char	     last_msr;      /* Modem Status Register */
@@ -181,25 +182,49 @@
 
 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
 
+/*
+ * Later day 2.6.0-test kernels have new baud rates like B230400 which
+ * we do not know how to support. We ignore them for the moment.
+ * XXX Rate-limit the error message, it's user triggerable.
+ */
 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
 	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
 	  || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
 		switch (value) {
-			case    300: return 0x01;
-			case    600: return 0x02; /* this one not tested */
-			case   1200: return 0x03;
-			case   2400: return 0x04;
-			case   4800: return 0x06;
-			case   9600: return 0x08;
-			case  19200: return 0x09;
-			case  38400: return 0x0a;
-			case  57600: return 0x0b;
-			case 115200: return 0x0c;
-			default:     return -1; /* normally not reached */
+		case    B300: return 0x01;
+		case    B600: return 0x02; /* this one not tested */
+		case   B1200: return 0x03;
+		case   B2400: return 0x04;
+		case   B4800: return 0x06;
+		case   B9600: return 0x08;
+		case  B19200: return 0x09;
+		case  B38400: return 0x0a;
+		case  B57600: return 0x0b;
+		case B115200: return 0x0c;
+		default:
+			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
+			    " using default of B9600", value);
+			return 0x08;
+		}
+	} else {
+		switch (value) {
+		case    B300: value =     300;
+		case    B600: value =     600;
+		case   B1200: value =    1200;
+		case   B2400: value =    2400;
+		case   B4800: value =    4800;
+		case   B9600: value =    9600;
+		case  B19200: value =   19200;
+		case  B38400: value =   38400;
+		case  B57600: value =   57600;
+		case B115200: value =  115200;
+		default:
+			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
+			    " using default of B9600", value);
+			value = 9600;
 		}
+		return 115200/value;
 	}
-	else
-		return MCT_U232_BAUD_RATE(value);
 }
 
 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
@@ -207,7 +232,9 @@
 	unsigned int divisor;
         int rc;
         unsigned char zero_byte = 0;
+
 	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
+
         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                              MCT_U232_SET_BAUD_RATE_REQUEST,
 			     MCT_U232_SET_REQUEST_TYPE,
@@ -215,7 +242,7 @@
 			     WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
-	dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
+	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
 
 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
 	   always sends two extra USB 'device request' messages after the
@@ -263,7 +290,7 @@
 } /* mct_u232_set_line_ctrl */
 
 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
-				   unsigned long control_state)
+				   unsigned int control_state)
 {
         int rc;
 	unsigned char mcr = MCT_U232_MCR_NONE;
@@ -280,7 +307,7 @@
 			     WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
-	dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
+	dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
 
         return rc;
 } /* mct_u232_set_modem_ctrl */
@@ -301,7 +328,7 @@
         return rc;
 } /* mct_u232_get_modem_stat */
 
-static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
+static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
 {
  	/* Translate Control Line states */
 	if (msr & MCT_U232_MSR_DSR)
@@ -320,7 +347,7 @@
 		*control_state |=  TIOCM_CD;
 	else
 		*control_state &= ~TIOCM_CD;
- 	dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
+ 	dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
 } /* mct_u232_msr_to_state */
 
 /*
@@ -330,20 +357,32 @@
 static int mct_u232_startup (struct usb_serial *serial)
 {
 	struct mct_u232_private *priv;
+	struct usb_serial_port *port, *rport;
 
 	/* allocate the private data structure */
-	serial->port->private = kmalloc(sizeof(struct mct_u232_private),
-					GFP_KERNEL);
-	if (!serial->port->private)
-		return (-1); /* error */
-	priv = (struct mct_u232_private *)serial->port->private;
+	priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 	/* set initial values for control structures */
+	spin_lock_init(&priv->lock);
 	priv->control_state = 0;
 	priv->last_lsr = 0;
 	priv->last_msr = 0;
-
+	serial->port->private = priv;
+ 
 	init_waitqueue_head(&serial->port->write_wait);
-	
+
+	/* Puh, that's dirty */
+	port = &serial->port[0];
+	rport = &serial->port[1];
+	if (port->read_urb) {
+		/* No unlinking, it wasn't submitted yet. */
+		usb_free_urb(port->read_urb);
+	}
+	port->read_urb = rport->interrupt_in_urb;
+	rport->interrupt_in_urb = NULL;
+	port->read_urb->context = port;
+
 	return (0);
 } /* mct_u232_startup */
 
@@ -354,7 +393,6 @@
 	
 	dbg("%s", __FUNCTION__);
 
-	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
 		/* My special items, the standard routines free my urbs */
 		if (serial->port[i].private)
@@ -367,6 +405,10 @@
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	int retval = 0;
+	unsigned int control_state;
+	unsigned long flags;
+	unsigned char last_lcr;
+	unsigned char last_msr;
 
 	dbg("%s port %d", __FUNCTION__, port->number);
 
@@ -383,29 +425,27 @@
 	 * sure if this is really necessary. But it should not harm
 	 * either.
 	 */
+	spin_lock_irqsave(&priv->lock, flags);
 	if (port->tty->termios->c_cflag & CBAUD)
 		priv->control_state = TIOCM_DTR | TIOCM_RTS;
 	else
 		priv->control_state = 0;
-	mct_u232_set_modem_ctrl(serial, priv->control_state);
 	
 	priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
 			  MCT_U232_PARITY_NONE |
 			  MCT_U232_STOP_BITS_1);
-	mct_u232_set_line_ctrl(serial, priv->last_lcr);
+	control_state = priv->control_state;
+	last_lcr = priv->last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	mct_u232_set_modem_ctrl(serial, control_state);
+	mct_u232_set_line_ctrl(serial, last_lcr);
 
 	/* Read modem status and update control state */
-	mct_u232_get_modem_stat(serial, &priv->last_msr);
+	mct_u232_get_modem_stat(serial, &last_msr);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->last_msr = last_msr;
 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
-
-	{
-		/* Puh, that's dirty */
-		struct usb_serial_port *rport;	
-		rport = &serial->port[1];
-		rport->tty = port->tty;
-		rport->private = port->private;
-		port->read_urb = rport->interrupt_in_urb;
-	}
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	port->read_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(port->read_urb);
@@ -551,6 +591,7 @@
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
 
         dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -587,6 +628,7 @@
 	 * The interrupt-in pipe signals exceptional conditions (modem line
 	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
 	 */
+	spin_lock_irqsave(&priv->lock, flags);
 	priv->last_msr = data[MCT_U232_MSR_INDEX];
 	
 	/* Record Control Line states */
@@ -617,6 +659,7 @@
 		}
 	}
 #endif
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* INT urbs are automatically re-submitted */
 } /* mct_u232_read_int_callback */
@@ -628,125 +671,113 @@
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	unsigned int iflag = port->tty->termios->c_iflag;
-	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int cflag = port->tty->termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
-	
+	unsigned long flags;
+	unsigned int control_state, new_state;
+	unsigned char last_lcr;
+
+	/* get a local copy of the current port settings */
+	spin_lock_irqsave(&priv->lock, flags);
+	control_state = priv->control_state;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	last_lcr = 0;
+
 	/*
-	 * Update baud rate
+	 * Update baud rate.
+	 * Do not attempt to cache old rates and skip settings,
+	 * disconnects screw such tricks up completely.
+	 * Premature optimization is the root of all evil.
 	 */
-	if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
-	        /* reassert DTR and (maybe) RTS on transition from B0 */
-		if( (old_cflag & CBAUD) == B0 ) {
-			dbg("%s: baud was B0", __FUNCTION__);
-			priv->control_state |= TIOCM_DTR;
-			/* don't set RTS if using hardware flow control */
-			if (!(old_cflag & CRTSCTS)) {
-				priv->control_state |= TIOCM_RTS;
-			}
-			mct_u232_set_modem_ctrl(serial, priv->control_state);
-		}
-		
-		switch(cflag & CBAUD) {
-		case B0: /* handled below */
-			break;
-		case B300: mct_u232_set_baud_rate(serial, 300);
-			break;
-		case B600: mct_u232_set_baud_rate(serial, 600);
-			break;
-		case B1200: mct_u232_set_baud_rate(serial, 1200);
-			break;
-		case B2400: mct_u232_set_baud_rate(serial, 2400);
-			break;
-		case B4800: mct_u232_set_baud_rate(serial, 4800);
-			break;
-		case B9600: mct_u232_set_baud_rate(serial, 9600);
-			break;
-		case B19200: mct_u232_set_baud_rate(serial, 19200);
-			break;
-		case B38400: mct_u232_set_baud_rate(serial, 38400);
-			break;
-		case B57600: mct_u232_set_baud_rate(serial, 57600);
-			break;
-		case B115200: mct_u232_set_baud_rate(serial, 115200);
-			break;
-		default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
-			mct_u232_set_baud_rate(serial, 9600); break;
-		}
-		if ((cflag & CBAUD) == B0 ) {
-			dbg("%s: baud is B0", __FUNCTION__);
-			/* Drop RTS and DTR */
-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-        		mct_u232_set_modem_ctrl(serial, priv->control_state);
-		}
+
+        /* reassert DTR and (maybe) RTS on transition from B0 */
+	if ((old_cflag & CBAUD) == B0) {
+		dbg("%s: baud was B0", __FUNCTION__);
+		control_state |= TIOCM_DTR;
+		/* don't set RTS if using hardware flow control */
+		if (!(old_cflag & CRTSCTS)) {
+			control_state |= TIOCM_RTS;
+		}
+		mct_u232_set_modem_ctrl(serial, control_state);
+	}
+
+	mct_u232_set_baud_rate(serial, cflag & CBAUD);
+
+	if ((cflag & CBAUD) == B0 ) {
+		dbg("%s: baud is B0", __FUNCTION__);
+		/* Drop RTS and DTR */
+		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+       		mct_u232_set_modem_ctrl(serial, control_state);
 	}
 
 	/*
 	 * Update line control register (LCR)
 	 */
-	if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
-	    || (cflag & CSIZE) != (old_cflag & CSIZE)
-	    || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
-		
 
-		priv->last_lcr = 0;
+	/* set the parity */
+	if (cflag & PARENB)
+		last_lcr |= (cflag & PARODD) ?
+			MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
+	else
+		last_lcr |= MCT_U232_PARITY_NONE;
 
-		/* set the parity */
-		if (cflag & PARENB)
-			priv->last_lcr |= (cflag & PARODD) ?
-				MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
-		else
-			priv->last_lcr |= MCT_U232_PARITY_NONE;
+	/* set the number of data bits */
+	switch (cflag & CSIZE) {
+	case CS5:
+		last_lcr |= MCT_U232_DATA_BITS_5; break;
+	case CS6:
+		last_lcr |= MCT_U232_DATA_BITS_6; break;
+	case CS7:
+		last_lcr |= MCT_U232_DATA_BITS_7; break;
+	case CS8:
+		last_lcr |= MCT_U232_DATA_BITS_8; break;
+	default:
+		err("CSIZE was not CS5-CS8, using default of 8");
+		last_lcr |= MCT_U232_DATA_BITS_8;
+		break;
+	}
 
-		/* set the number of data bits */
-		switch (cflag & CSIZE) {
-		case CS5:
-			priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
-		case CS6:
-			priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
-		case CS7:
-			priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
-		case CS8:
-			priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
-		default:
-			err("CSIZE was not CS5-CS8, using default of 8");
-			priv->last_lcr |= MCT_U232_DATA_BITS_8;
-			break;
-		}
+	/* set the number of stop bits */
+	last_lcr |= (cflag & CSTOPB) ?
+		MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
 
-		/* set the number of stop bits */
-		priv->last_lcr |= (cflag & CSTOPB) ?
-			MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
+	mct_u232_set_line_ctrl(serial, last_lcr);
 
-		mct_u232_set_line_ctrl(serial, priv->last_lcr);
-	}
-	
 	/*
 	 * Set flow control: well, I do not really now how to handle DTR/RTS.
 	 * Just do what we have seen with SniffUSB on Win98.
 	 */
-	if( (iflag & IXOFF) != (old_iflag & IXOFF)
-	    || (iflag & IXON) != (old_iflag & IXON)
-	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
-		
-		/* Drop DTR/RTS if no flow control otherwise assert */
-		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
-			priv->control_state |= TIOCM_DTR | TIOCM_RTS;
-		else
-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-		mct_u232_set_modem_ctrl(serial, priv->control_state);
+	/* Drop DTR/RTS if no flow control otherwise assert */
+	new_state = control_state;
+	if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
+		new_state |= TIOCM_DTR | TIOCM_RTS;
+	else
+		new_state &= ~(TIOCM_DTR | TIOCM_RTS);
+	if (new_state != control_state) {
+		mct_u232_set_modem_ctrl(serial, control_state);
+		control_state = new_state;
 	}
-} /* mct_u232_set_termios */
 
+	/* save off the modified port settings */
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->control_state = control_state;
+	priv->last_lcr = last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+} /* mct_u232_set_termios */
 
 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
-	unsigned char lcr = priv->last_lcr;
+	unsigned char lcr;
+	unsigned long flags;
 
 	dbg("%sstate=%d", __FUNCTION__, break_state);
 
+	spin_lock_irqsave(&priv->lock, flags);
+	lcr = priv->last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	if (break_state)
 		lcr |= MCT_U232_SET_BREAK;
 
@@ -760,7 +791,8 @@
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	int mask;
-	
+	unsigned long flags;
+
 	dbg("%scmd=0x%x", __FUNCTION__, cmd);
 
 	/* Based on code from acm.c and others */
@@ -775,6 +807,7 @@
 		if (get_user(mask, (unsigned long *) arg))
 			return -EFAULT;
 
+		spin_lock_irqsave(&priv->lock, flags);
 		if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
 			/* RTS needs set */
 			if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
@@ -792,6 +825,7 @@
 			else
 				priv->control_state &= ~TIOCM_DTR;
 		}
+		spin_unlock_irqrestore(&priv->lock, flags);
 		mct_u232_set_modem_ctrl(serial, priv->control_state);
 		break;
 					
diff -urN linux-2.4.27-pre5/drivers/usb/serial/pl2303.c linux-2.4.27-pre6/drivers/usb/serial/pl2303.c
--- linux-2.4.27-pre5/drivers/usb/serial/pl2303.c	2004-04-14 06:05:35.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/serial/pl2303.c	2004-06-16 11:33:28.705110937 -0700
@@ -107,6 +107,7 @@
 #define VENDOR_READ_REQUEST		0x01
 
 #define UART_STATE			0x08
+#define UART_STATE_TRANSIENT_MASK	0x74
 #define UART_DCD			0x01
 #define UART_DSR			0x02
 #define UART_BREAK_ERROR		0x04
@@ -198,6 +199,9 @@
 
 	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
 
+	if (!count)
+		return count;
+
 	if (port->write_urb->status == -EINPROGRESS) {
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
@@ -678,6 +682,7 @@
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
 	unsigned long flags;
+	u8 uart_state;
 
 	dbg("%s (%d)", __FUNCTION__, port->number);
 
@@ -708,8 +713,10 @@
 		return;
 
 	/* Save off the uart status for others to look at */
+	uart_state = data[UART_STATE];
 	spin_lock_irqsave(&priv->lock, flags);
-	priv->line_status = data[UART_STATE];
+	uart_state |= (priv->line_status & UART_STATE_TRANSIENT_MASK);
+	priv->line_status = uart_state;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	wake_up_interruptible (&priv->delta_msr_wait);
 
@@ -767,7 +774,9 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 	status = priv->line_status;
+	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
+	wake_up_interruptible (&priv->delta_msr_wait); //AF from 2.6
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
diff -urN linux-2.4.27-pre5/drivers/usb/serial/usb-serial.h linux-2.4.27-pre6/drivers/usb/serial/usb-serial.h
--- linux-2.4.27-pre5/drivers/usb/serial/usb-serial.h	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/usb/serial/usb-serial.h	2004-06-16 11:33:28.705110937 -0700
@@ -111,6 +111,8 @@
 	int			bulk_out_size;
 	struct urb *		write_urb;
 	__u8			bulk_out_endpointAddress;
+	char			write_busy;	/* URB is active */
+	int			write_backlog;	/* Fifo used */
 
 	wait_queue_head_t	write_wait;
 	struct tq_struct	tqueue;
@@ -161,6 +163,7 @@
 	__u16				product;
 	struct usb_serial_port		port[MAX_NUM_PORTS];
 	void *				private;
+	int				ref;
 };
 
 
diff -urN linux-2.4.27-pre5/drivers/usb/serial/usbserial.c linux-2.4.27-pre6/drivers/usb/serial/usbserial.c
--- linux-2.4.27-pre5/drivers/usb/serial/usbserial.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.27-pre6/drivers/usb/serial/usbserial.c	2004-06-16 11:33:28.707111020 -0700
@@ -297,6 +297,7 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/usb.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
@@ -347,11 +348,29 @@
 };
 #endif
 
+/*
+ * The post kludge structures and variables.
+ */
+#define POST_BSIZE	100	/* little below 128 in total */
+struct usb_serial_post_job {
+	struct list_head link;
+	struct usb_serial_port *port;
+	int len;
+	char buff[POST_BSIZE];
+};
+static spinlock_t post_lock = SPIN_LOCK_UNLOCKED;	/* Also covers ->ref */
+static struct list_head post_list = LIST_HEAD_INIT(post_list);
+static struct tq_struct post_task;
 
 /* local function prototypes */
 static int  serial_open (struct tty_struct *tty, struct file * filp);
 static void serial_close (struct tty_struct *tty, struct file * filp);
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
 static int  serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static int  serial_post_job(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count);
+static int  serial_post_one(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count);
 static int  serial_write_room (struct tty_struct *tty);
 static int  serial_chars_in_buffer (struct tty_struct *tty);
 static void serial_throttle (struct tty_struct * tty);
@@ -448,6 +467,63 @@
 	return;
 }
 
+/*
+ * The post kludge.
+ *
+ * Our component drivers are hideously buggy and written by people
+ * who have difficulty understanding the concept of spinlocks.
+ * There were so many races and lockups that Greg K-H made a watershed
+ * decision to provide what is essentially a single-threaded sandbox
+ * for component drivers, protected by a semaphore. It helped a lot, but
+ * for one little problem: when tty->low_latency is set, line disciplines
+ * can call ->write from an interrupt, where the semaphore oopses.
+ *
+ * Rather than open the whole can of worms again, we just post writes
+ * into a helper which can sleep.
+ *
+ * Kernel 2.6 has a proper fix. It replaces semaphores with proper locking.
+ */
+static void post_helper(void *arg)
+{
+	struct list_head *pos;
+	struct usb_serial_post_job *job;
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+	unsigned int flags;
+
+	spin_lock_irqsave(&post_lock, flags);
+	pos = post_list.next;
+	while (pos != &post_list) {
+		job = list_entry(pos, struct usb_serial_post_job, link);
+		port = job->port;
+		/* get_usb_serial checks port->tty, so cannot be used */
+		serial = port->serial;
+		if (port->write_busy) {
+			dbg("%s - port %d busy", __FUNCTION__, port->number);
+			pos = pos->next;
+			continue;
+		}
+		list_del(&job->link);
+		spin_unlock_irqrestore(&post_lock, flags);
+
+		down(&port->sem);
+		dbg("%s - port %d len %d backlog %d", __FUNCTION__,
+		    port->number, job->len, port->write_backlog);
+		if (port->tty != NULL)
+			__serial_write(port, 0, job->buff, job->len);
+		up(&port->sem);
+
+		spin_lock_irqsave(&post_lock, flags);
+		port->write_backlog -= job->len;
+		kfree(job);
+		if (--serial->ref == 0)
+			kfree(serial);
+		/* Have to reset because we dropped spinlock */
+		pos = post_list.next;
+	}
+	spin_unlock_irqrestore(&post_lock, flags);
+}
+
 #ifdef USES_EZUSB_FUNCTIONS
 /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
 #define CPUCS_REG    0x7F92
@@ -580,23 +656,34 @@
 
 	/* if disconnect beat us to the punch here, there's nothing to do */
 	if (tty->driver_data) {
+		/*
+		 * XXX The right thing would be to wait for the output to drain.
+		 * But we are not sufficiently daring to experiment in 2.4.
+		 * N.B. If we do wait, no need to run post_helper here.
+		 * Normall callback mechanism wakes it up just fine.
+		 */
+#if I_AM_A_DARING_HACKER
+		tty->closing = 1;
+		up (&port->sem);
+		if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+			tty_wait_until_sent(tty, info->closing_wait);
+		down (&port->sem);
+		if (!tty->driver_data) /* woopsie, disconnect, now what */ ;
+#endif
 		__serial_close(port, filp);
 	}
 
 	up (&port->sem);
 }
 
-static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
-	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	int retval = -EINVAL;
 
 	if (!serial)
 		return -ENODEV;
 
-	down (&port->sem);
-
 	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
 
 	if (!port->open_count) {
@@ -611,10 +698,132 @@
 		retval = generic_write(port, from_user, buf, count);
 
 exit:
-	up (&port->sem);
 	return retval;
 }
 
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+	int rc;
+
+	if (!in_interrupt()) {
+		/*
+		 * Run post_list to reduce a possiblity of reordered writes.
+		 * Tasks can make keventd to sleep, sometimes for a long time.
+		 */
+		post_helper(NULL);
+
+		down(&port->sem);
+		/*
+		 * This happens when a line discipline asks how much room
+		 * we have, gets 64, then tries to perform two writes
+		 * for a byte each. First write takes whole URB, second
+		 * write hits this check.
+		 */
+		if (port->write_busy) {
+			up(&port->sem);
+			return serial_post_job(port, from_user, GFP_KERNEL,
+			    buf, count);
+		}
+
+		rc = __serial_write(port, from_user, buf, count);
+		up(&port->sem);
+		return rc;
+	}
+
+	if (from_user) {
+		/*
+		 * This is a BUG-able offense because we cannot
+		 * pagefault while in_interrupt, but we want to see
+		 * something in dmesg rather than just blinking LEDs.
+		 */
+		err("user data in interrupt write");
+		return -EINVAL;
+	}
+
+	return serial_post_job(port, 0, GFP_ATOMIC, buf, count);
+}
+
+static int serial_post_job(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count)
+{
+	int done = 0, length;
+	int rc;
+
+	if (port == NULL)
+		return -EPIPE;
+
+	if (count >= 512) {
+		static int rate = 0;
+		/*
+		 * Data loss due to extreme circumstances.
+		 * It's a ususal thing on serial to lose characters, isn't it?
+		 * Neener, neener! Actually, it's probably an echo loop anyway.
+		 * Only happens when getty starts talking to Visor.
+		 */
+		if (++rate % 1000 < 3) {
+			err("too much data (%d) from %s", count,
+			    from_user? "user": "kernel");
+		}
+		count = 512;
+	}
+
+	while (done < count) {
+		length = count - done;
+		if (length > POST_BSIZE)
+			length = POST_BSIZE;
+		if (length > port->bulk_out_size)
+			length = port->bulk_out_size;
+
+		rc = serial_post_one(port, from_user, gfp, buf + done, length);
+		if (rc <= 0) {
+			if (done != 0)
+				return done;
+			return rc;
+		}
+		done += rc;
+	}
+
+	return done;
+}
+
+static int serial_post_one(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct usb_serial_post_job *job;
+	unsigned long flags;
+
+	dbg("%s - port %d user %d count %d", __FUNCTION__, port->number, from_user, count);
+
+	job = kmalloc(sizeof(struct usb_serial_post_job), gfp);
+	if (job == NULL)
+		return -ENOMEM;
+
+	job->port = port;
+	if (count >= POST_BSIZE)
+		count = POST_BSIZE;
+	job->len = count;
+
+	if (from_user) {
+		if (copy_from_user(job->buff, buf, count)) {
+			kfree(job);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(job->buff, buf, count);
+	}
+
+	spin_lock_irqsave(&post_lock, flags);
+	port->write_backlog += count;
+	list_add_tail(&job->link, &post_list);
+	serial->ref++;		/* Protect the port->sem from kfree() */
+	schedule_task(&post_task);
+	spin_unlock_irqrestore(&post_lock, flags);
+
+	return count;
+}
+
 static int serial_write_room (struct tty_struct *tty) 
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
@@ -624,6 +833,14 @@
 	if (!serial)
 		return -ENODEV;
 
+	if (in_interrupt()) {
+		retval = 0;
+		if (!port->write_busy && port->write_backlog == 0)
+			retval = port->bulk_out_size;
+		dbg("%s - returns %d", __FUNCTION__, retval);
+		return retval;
+	}
+
 	down (&port->sem);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -655,10 +872,8 @@
 
 	down (&port->sem);
 
-	dbg("%s = port %d", __FUNCTION__, port->number);
-
 	if (!port->open_count) {
-		dbg("%s - port not open", __FUNCTION__);
+		dbg("%s - port %d: not open", __FUNCTION__, port->number);
 		goto exit;
 	}
 
@@ -917,18 +1132,23 @@
 {
 	struct usb_serial *serial = port->serial;
 	int result;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
+	unsigned long flags;
 
 	if (count == 0) {
 		dbg("%s - write request of 0 bytes", __FUNCTION__);
 		return (0);
 	}
+	if (count < 0) {
+		err("%s - port %d: write request of %d bytes", __FUNCTION__,
+		    port->number, count);
+		return (0);
+	}
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS) {
-			dbg("%s - already writing", __FUNCTION__);
+		if (port->write_busy) {
+			/* Happens when two threads run port_helper. Watch. */
+			info("%s - already writing", __FUNCTION__);
 			return (0);
 		}
 
@@ -937,12 +1157,10 @@
 		if (from_user) {
 			if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
 				return -EFAULT;
-		}
-		else {
+		} else {
 			memcpy (port->write_urb->transfer_buffer, buf, count);
 		}
-
-		usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+		dbg("%s - port %d [%d]", __FUNCTION__, port->number, count);
 
 		/* set up our urb */
 		usb_fill_bulk_urb (port->write_urb, serial->dev,
@@ -954,10 +1172,18 @@
 				     generic_write_bulk_callback), port);
 
 		/* send the data out the bulk port */
+		port->write_busy = 1;
 		result = usb_submit_urb(port->write_urb);
-		if (result)
-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
-		else
+		if (result) {
+			err("%s - port %d: failed submitting write urb (%d)",
+			     __FUNCTION__, port->number, result);
+			port->write_busy = 0;
+			spin_lock_irqsave(&post_lock, flags);
+			if (port->write_backlog != 0)
+				schedule_task(&post_task);
+			spin_unlock_irqrestore(&post_lock, flags);
+
+		} else
 			result = count;
 
 		return result;
@@ -972,14 +1198,12 @@
 	struct usb_serial *serial = port->serial;
 	int room = 0;
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
-	
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status != -EINPROGRESS)
+		if (!port->write_busy && port->write_backlog == 0)
 			room = port->bulk_out_size;
 	}
 
-	dbg("%s - returns %d", __FUNCTION__, room);
+	dbg("%s - port %d, returns %d", __FUNCTION__, port->number, room);
 	return (room);
 }
 
@@ -991,8 +1215,9 @@
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS)
-			chars = port->write_urb->transfer_buffer_length;
+		if (port->write_busy)
+			chars += port->write_urb->transfer_buffer_length;
+		chars += port->write_backlog;	/* spin_lock... Baah */
 	}
 
 	dbg("%s - returns %d", __FUNCTION__, chars);
@@ -1056,14 +1281,16 @@
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	port->write_busy = 0;
+	wmb();
+
 	if (!serial) {
-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		err("%s - null serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-		return;
 	}
 
 	queue_task(&port->tqueue, &tq_immediate);
@@ -1089,12 +1316,18 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)private;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	struct tty_struct *tty;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (!serial)
 		return;
 
+	spin_lock_irqsave(&post_lock, flags);
+	if (port->write_backlog != 0)
+		schedule_task(&post_task);
+	spin_unlock_irqrestore(&post_lock, flags);
+
 	tty = port->tty;
 	if (!tty)
 		return;
@@ -1108,7 +1341,6 @@
 }
 
 
-
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
 			       const struct usb_device_id *id)
 {
@@ -1132,6 +1364,7 @@
 	int num_ports;
 	int max_endpoints;
 	const struct usb_device_id *id_pattern = NULL;
+	unsigned long flags;
 
 	/* loop through our list of known serial converters, and see if this
 	   device matches. */
@@ -1342,11 +1575,15 @@
 		init_MUTEX (&port->sem);
 	}
 
+	spin_lock_irqsave(&post_lock, flags);
+	serial->ref = 1;
+	spin_unlock_irqrestore(&post_lock, flags);
+
 	/* if this device type has a startup function, call it */
 	if (type->startup) {
 		i = type->startup (serial);
 		if (i < 0)
-			goto probe_error;
+			goto startup_error;
 		if (i > 0)
 			return serial;
 	}
@@ -1361,6 +1598,12 @@
 	return serial; /* success */
 
 
+startup_error:
+	spin_lock_irqsave(&post_lock, flags);
+	if (serial->ref != 1) {
+		err("bug in component startup: ref %d\n", serial->ref);
+	}
+	spin_unlock_irqrestore(&post_lock, flags);
 probe_error:
 	for (i = 0; i < num_bulk_in; ++i) {
 		port = &serial->port[i];
@@ -1396,6 +1639,7 @@
 {
 	struct usb_serial *serial = (struct usb_serial *) ptr;
 	struct usb_serial_port *port;
+	unsigned long flags;
 	int i;
 
 	dbg ("%s", __FUNCTION__);
@@ -1453,7 +1697,10 @@
 		return_serial (serial);
 
 		/* free up any memory that we allocated */
-		kfree (serial);
+		spin_lock_irqsave(&post_lock, flags);
+		if (--serial->ref == 0)
+			kfree(serial);
+		spin_unlock_irqrestore(&post_lock, flags);
 
 	} else {
 		info("device disconnected");
@@ -1505,6 +1752,7 @@
 	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
 		serial_table[i] = NULL;
 	}
+	post_task.routine = post_helper;
 
 	/* register the tty driver */
 	serial_tty_driver.init_termios          = tty_std_termios;
diff -urN linux-2.4.27-pre5/drivers/usb/serial/visor.c linux-2.4.27-pre6/drivers/usb/serial/visor.c
--- linux-2.4.27-pre5/drivers/usb/serial/visor.c	2004-04-14 06:05:35.000000000 -0700
+++ linux-2.4.27-pre6/drivers/usb/serial/visor.c	2004-06-16 11:33:28.708111062 -0700
@@ -184,6 +184,7 @@
 static void visor_read_bulk_callback	(struct urb *urb);
 static void visor_read_int_callback	(struct urb *urb);
 static int  clie_3_5_startup	(struct usb_serial *serial);
+static int  clie_5_startup	(struct usb_serial *serial);
 static void treo_attach		(struct usb_serial *serial);
 
 /* Parameters that may be passed into the module. */
@@ -211,7 +212,6 @@
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) },
-	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
@@ -224,6 +224,12 @@
 	{ }					/* Terminating entry */
 };
 
+
+static struct usb_device_id clie_id_5_table [] = {
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
+	{ }					/* Terminating entry */
+};
+
 static __devinitdata struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
@@ -310,6 +316,32 @@
 	.read_bulk_callback =	visor_read_bulk_callback,
 };
 
+
+/* device info for the Sony Clie OS version 5.0 */
+static struct usb_serial_device_type clie_5_device = {
+	.owner =		THIS_MODULE,
+	.name =			"Sony Clié 5.0",
+	.id_table =		clie_id_5_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		2,
+	.num_bulk_out =		2,
+	.num_ports =		2,
+	.open =			visor_open,
+	.close =		visor_close,
+	.throttle =		visor_throttle,
+	.unthrottle =		visor_unthrottle,
+	.startup =		clie_5_startup,
+	.shutdown =		visor_shutdown,
+	.ioctl =		visor_ioctl,
+	.set_termios =		visor_set_termios,
+	.write =		visor_write,
+	.write_room =		visor_write_room,
+	.chars_in_buffer =	visor_chars_in_buffer,
+	.write_bulk_callback =	visor_write_bulk_callback,
+	.read_bulk_callback =	visor_read_bulk_callback,
+	.read_int_callback =	visor_read_int_callback,
+};
+
 /* This structure is for Handspring Visor, and Palm 4.0 devices that are not
  * compiled into the kernel, but can be passed in when the module is loaded.
  * This will allow the visor driver to work with new Vendor and Device IDs
@@ -853,6 +885,68 @@
 	return 0;
 }
 
+
+static int clie_5_startup (struct usb_serial *serial)
+{
+	int response;
+	unsigned char *transfer_buffer;
+
+	dbg("%s", __FUNCTION__);
+
+	dbg("%s - Set config to 1", __FUNCTION__);
+	usb_set_configuration(serial->dev, 1);
+
+	struct palm_ext_connection_info *connection_info;
+
+	transfer_buffer = kmalloc(sizeof (*connection_info),
+					GFP_KERNEL);
+	if (!transfer_buffer) {
+		err("%s - kmalloc(%d) failed.", __FUNCTION__,
+			sizeof (*connection_info));
+		return -ENOMEM;
+	}
+
+	response = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 
+					PALM_GET_EXT_CONNECTION_INFORMATION,
+					0xc2, 0x0000, 0x0000, transfer_buffer, 
+					sizeof(*connection_info), 300);
+	if (response < 0) {
+		err("%s - error %d getting connection info",
+			 __FUNCTION__, response);
+	} else {
+		usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
+	}
+
+	/* ask for the number of bytes available, but ignore the response as it is broken */
+	response = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
+					0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
+	if (response < 0) {
+		err("%s - error getting bytes available request", __FUNCTION__);
+	}
+
+	kfree (transfer_buffer);
+
+	/* UX50/TH55 registers 2 ports. 
+	   Communication in from the TH55 uses bulk_in_endpointAddress from port 0 
+	   Communication out to the TH55 uses bulk_out_endpointAddress from port 1 
+
+	   Lets do a quick and dirty mapping
+	*/
+
+	/* some sanity check */
+	if (serial->num_ports < 2)
+		return -ENODEV;
+
+	/* port 0 now uses the modified endpoint Address */
+	serial->port[0].bulk_out_endpointAddress = serial->port[1].bulk_out_endpointAddress;
+
+	/* continue on with initialization */
+	return 0;
+}
+
+
+
+
 static void treo_attach (struct usb_serial *serial)
 {
 	struct usb_serial_port *port;
@@ -993,6 +1087,7 @@
 	}
 	usb_serial_register (&handspring_device);
 	usb_serial_register (&clie_3_5_device);
+	usb_serial_register (&clie_5_device);
 	
 	/* create our write urb pool and transfer buffers */ 
 	spin_lock_init (&write_urb_pool_lock);
@@ -1029,6 +1124,7 @@
 	}
 	usb_serial_deregister (&handspring_device);
 	usb_serial_deregister (&clie_3_5_device);
+	usb_serial_deregister (&clie_5_device);
 
 	spin_lock_irqsave (&write_urb_pool_lock, flags);
 
diff -urN linux-2.4.27-pre5/drivers/usb/storage/unusual_devs.h linux-2.4.27-pre6/drivers/usb/storage/unusual_devs.h
--- linux-2.4.27-pre5/drivers/usb/storage/unusual_devs.h	2004-06-16 11:33:26.386014423 -0700
+++ linux-2.4.27-pre6/drivers/usb/storage/unusual_devs.h	2004-06-16 11:33:28.711111187 -0700
@@ -273,6 +273,13 @@
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
 
+/* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500, 
+		"Sony",
+		"Handycam HC-85",
+		US_SC_UFI, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
+
 UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U01N",
diff -urN linux-2.4.27-pre5/drivers/video/sis/300vtbl.h linux-2.4.27-pre6/drivers/video/sis/300vtbl.h
--- linux-2.4.27-pre5/drivers/video/sis/300vtbl.h	2004-04-14 06:05:39.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/300vtbl.h	2004-06-16 11:33:28.716111395 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 300 series
  *
@@ -75,93 +76,93 @@
 
 static const SiS_ExtStruct  SiS300_EModeIDTable[] =
 {
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
-	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
-	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
-	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
-	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
-	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
-	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
-	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
-	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
-	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
-	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
-	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
-	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
-	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
-	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
-	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
- 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
-	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
-	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
-	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
-	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
-	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
-	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
-	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
-	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
-	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
-	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
-	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
-	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
-	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
-	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
-	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
-	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
-	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
-	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
-	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
-	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
-	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},
+	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x8 */
+	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x8 */
+	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x16 */
+	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x16 */
+	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x32 */
+	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},  /* 1280x1024x8 */
+	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x15 */
+	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x15 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x8  */
+	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x8  */
+	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x8  */
+	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x16 */
+	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x16 */
+	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x16 */
+	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
+	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
+	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
+ 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 - not in BIOS! */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 - not in BIOS! */
+	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
+	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
+	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
+	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x16 */
+	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x32 */
+	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x32 */
+	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x32 */
+	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x8 */
+	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x16 */
+	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x8 */
+	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x16 */
+	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x32 */
+	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},  /* 1024x600 */
+	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},  /* 1152x768 */
+	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},  /* 1152x864 */
+	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},  /* 848x480 */
+	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},  /* 856x480 */
+	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},  /* 1360x768 */
+	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x32 */
+	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x32 */
+	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x32 */
+	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},  /* 1280x768   */
+	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x8 */
+	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x16 */
+	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x32 */
+	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x8 (BARCO) */
+	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x16 (BARCO) */
+	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x32 (BARCO) */
 	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
 };
 
diff -urN linux-2.4.27-pre5/drivers/video/sis/310vtbl.h linux-2.4.27-pre6/drivers/video/sis/310vtbl.h
--- linux-2.4.27-pre5/drivers/video/sis/310vtbl.h	2004-04-14 06:05:39.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/310vtbl.h	2004-06-16 11:33:28.719111520 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 315/330 series
  *
@@ -75,97 +76,97 @@
 
 static const SiS_ExtStruct  SiS310_EModeIDTable[]=
 {
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
-        {0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
-	{0x32,0x0a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
-	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
-	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
-	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
-	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
-	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
-	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
-  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
-	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
-	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
- 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
-	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
-	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
-	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
-	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
-	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
-	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
-	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
-	{0x77,0x0a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
-	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
-	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
-	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
-	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
-	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
-	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x48,0x2a1b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
-	{0x4b,0x2a3d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4e,0x2a7f,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
-	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
-	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
-	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576 */
-	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
-	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
-	{0x14,0x0e1b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b}, /* 1280x800 */
-	{0x15,0x0e3d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
-	{0x16,0x0e7f,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
-	{0x17,0x0e1b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c}, /* 1680x1050 */
-	{0x18,0x0e3d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
-	{0x19,0x0e7f,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
-	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+        {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */
+	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */
+	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */
+	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3},
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
+  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
+ 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
+	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
+	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0},
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */
+	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */
+	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */
+	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */
+	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */
+	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */
+	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */
+	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
+	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
+	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
+	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1}, /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1}, /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x48,0x6a1b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1}, /* 1360x768 */
+	{0x4b,0x6a3d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4e,0x6a7f,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1}, /* 768x576 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x61,0x6a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x14,0x0e1b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7}, /* 1280x800 */
+	{0x15,0x0e3d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x16,0x0e7f,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x17,0x0e1b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9}, /* 1680x1050 */
+	{0x18,0x0e3d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0x19,0x0e7f,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
 };
 
 static const SiS_Ext2Struct SiS310_RefIndex[]=
@@ -187,8 +188,8 @@
 	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
 	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
 	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-	{0xc04f,0x3c,0x01,0x06,0x00,0x31, 720, 480, 0x30}, /* 0x11 */
-	{0x004f,0x3d,0x03,0x06,0x00,0x32, 720, 576, 0x30}, /* 0x12 */
+	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
+	{0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
 	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
 	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
 	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
@@ -222,12 +223,12 @@
 	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
 	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
 	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-	{0x0057,0x32,0x40,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x34 */
-	{0x0047,0x33,0x07,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x35 */
-	{0x0047,0x34,0x0a,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x36 */
-	{0x0057,0x35,0x0b,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x37 */
-	{0x0047,0x36,0x11,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x38 */
-	{0x0047,0x37,0x16,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x39 */
+	{0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
+	{0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
+	{0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
+	{0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
+	{0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
+	{0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
 	{0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
 	{0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
 	{0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
@@ -237,14 +238,14 @@
         {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */    /* 0x5b was 0x12 */
 	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
 	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
-	{0x0107,0x44,0x19,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
-	{0x0107,0x4a,0x1e,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
-	{0x0087,0x45,0x57,0x00,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
-	{0xc067,0x46,0x55,0x0b,0x00,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
-	{0x0087,0x47,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
-	{0xc047,0x48,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
-	{0x0067,0x49,0x58,0x0c,0x00,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
-	{0x004f,0x4d,0x03,0x06,0x00,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
+	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
+	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
+	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
+	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
+	{0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
+	{0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
 	{0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4b 1280x800-60Hz  */
 	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4c 1680x1050-60Hz */
 	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0}
@@ -685,7 +686,12 @@
 	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
 	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
 	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
 };
 
 static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
@@ -788,14 +794,19 @@
 	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
 	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
    	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
-	{ 0x9c,0x62, 69}, /* 0x5c 1280x800 LCD - wrong? */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800 LCD - (was 0x9c,0x62, 69 - wrong?) */
 	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
 	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
 	{ 0x52,0x27, 75}, /* 0x5f 1280x720 LCD TMDS + HDTV (correct) */
 	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
 	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
 	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
 };
 
 static const DRAM4Type SiS310_SR15[8] = {
diff -urN linux-2.4.27-pre5/drivers/video/sis/init.c linux-2.4.27-pre6/drivers/video/sis/init.c
--- linux-2.4.27-pre5/drivers/video/sis/init.c	2004-04-14 06:05:39.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/init.c	2004-06-16 11:33:28.724111728 -0700
@@ -1,8 +1,9 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT1 section) for
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661FX/740/741/M741/330/660/M660/760/M760
+ *     SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
  * (Universal module for Linux kernel framebuffer and XFree86 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
@@ -635,47 +636,33 @@
 	  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
           break;
      case 720:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-             else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-          }
+          if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+          else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
           break;
      case 768:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-          }
+          if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 	  break;
      case 800:
-	  if(VDisplay == 600)    ModeIndex = ModeIndex_800x600[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-	  }
+	  if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
+	  else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
           break;
      case 848:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-	  }
+	  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 	  break;
      case 856:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-	  }
+	  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 	  break;
      case 1024:
-          if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 576)    ModeIndex = ModeIndex_1024x576[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
-             }
+          if(VDisplay == 768)      ModeIndex = ModeIndex_1024x768[Depth];
+	  else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	  else if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
 	  }
           break;
      case 1152:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 864)    ModeIndex = ModeIndex_1152x864[Depth];
-             else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-             }
+          if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+          if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
 	  }
 	  break;
      case 1280:
@@ -695,7 +682,7 @@
 	        ModeIndex = ModeIndex_1280x720[Depth];
 	     }
 	  } else if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 960)      ModeIndex = ModeIndex_1280x960[Depth];
+             if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth];
 	     else if(VDisplay == 768) {
 	        if(VGAEngine == SIS_300_VGA) {
 	           ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -706,9 +693,9 @@
 	  }
           break;
      case 1360:
+          if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
           if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 768)     ModeIndex = ModeIndex_1360x768[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
+	     if(VGAEngine == SIS_300_VGA) {
 	        if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
              }
 	  }
@@ -874,17 +861,49 @@
 	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 	     break;
+	case 720:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+	     }
+	     break;
+	case 768:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+	     }
+	     break;
 	case 800:
 	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+	     }
+	     break;
+	case 848:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+	     }
+	     break;
+	case 856:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	     }
 	     break;
 	case 1024:
 	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	     }
+	     break;
+	case 1152:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+	     }
 	     break;
 	case 1280:
 	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 	     else if(VDisplay == 768) {
-		if((LCDheight == 768) || (LCDwidth == 1680) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		if((LCDheight == 768) ||  (LCDwidth == 1680) ||
+		   (VBFlags & VB_SISTMDS)) {
 		   if(VGAEngine == SIS_300_VGA) {
 		      ModeIndex = ModeIndex_300_1280x768[Depth];
 		   } else {
@@ -892,24 +911,28 @@
 		   }
 		}
 	     } else if(VDisplay == 960) {
-	        if((LCDheight == 960) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+	        if((LCDheight == 960) || (VBFlags & VB_SISTMDS)) {
 		   ModeIndex = ModeIndex_1280x960[Depth];
 		}
 	     } else if(VGAEngine == SIS_315_VGA) {
 	        if(VDisplay == 800) {
 		   if((LCDheight == 800) || (LCDwidth == 1680) ||
-		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		      (VBFlags & VB_SISTMDS)) {
 		      ModeIndex = ModeIndex_1280x800[Depth];
 		   }
 		} else if(VDisplay == 720) {
-		   if((LCDheight == 720) || (LCDwidth == 1680) ||
-		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		   if((LCDheight == 720) || (LCDwidth == 1680) || (LCDwidth == 1400) ||
+		      (VBFlags & VB_SISTMDS)) {
 		      ModeIndex = ModeIndex_1280x720[Depth];
 		   }
 		}
 	     }
 	     break;
+	case 1360:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+	     }
+	     break;
 	case 1400:
 	     if(VGAEngine == SIS_315_VGA) {
 	        if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
@@ -992,7 +1015,7 @@
 	case 720:
 	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
                 if(VDisplay == 480) {
-		   if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM)))
+		   /* if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM))) */
                       ModeIndex = ModeIndex_720x480[Depth];
                 } else if(VDisplay == 576) {
 		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
@@ -1280,10 +1303,12 @@
    /* (SR11 is used for DDC and in enable/disablebridge) */
    SiS_Pr->SiS_SensibleSR11 = FALSE;
    SiS_Pr->SiS_MyCR63 = 0x63;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_SensibleSR11 = TRUE;
+   if(HwInfo->jChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
-   }
+      if(HwInfo->jChipType >= SIS_661) {
+         SiS_Pr->SiS_SensibleSR11 = TRUE;
+      }           
+   }   
 
    /* You should use the macros, not these flags directly */
 
@@ -1324,7 +1349,7 @@
    }
    if(HwInfo->jChipType == SIS_760) {
       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
-      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760UMA;
+      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
    }
 }
 
@@ -1387,7 +1412,7 @@
 void
 SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   ULONG   temp;
+   USHORT temp;
 
    SiS_Pr->SiS_IF_DEF_LVDS = 0;
    SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
@@ -1471,6 +1496,12 @@
    USHORT romversoffs, romvmaj = 1, romvmin = 0;
 
    if(HwInfo->jChipType >= SIS_661) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
       romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
       if(romversoffs) {
 	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
@@ -1515,7 +1546,7 @@
 	  */
 	 SiS_Pr->SiS_UseROM = TRUE;
       } else {
-         /* 315/330 series stick to the standard */
+         /* 315/330 series stick to the standard(s) */
 	 SiS_Pr->SiS_UseROM = TRUE;
 	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
 	    /* Find out about LCD data table entry size */
@@ -1525,7 +1556,7 @@
 	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
 	          SiS_Pr->SiS661LCD2TableSize = 34;
 	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)
-	          SiS_Pr->SiS661LCD2TableSize = 36;
+	          SiS_Pr->SiS661LCD2TableSize = 36;  /* 0.94 final */
 	    }
 	 }
       }
@@ -1641,7 +1672,7 @@
      if(rev >= 0xE0) {
 	flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
 	if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
-	else 	 	 SiS_Pr->SiS_VBType = VB_SIS302ELV;
+	else 	 	 SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
      } else if(rev >= 0xD0) {
 	SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
@@ -1649,95 +1680,6 @@
 }
 
 /*********************************************/
-/*            HELPER: GetDRAMSize            */
-/*********************************************/
-
-#ifndef LINUX_XF86
-static ULONG
-GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  ULONG   AdapterMemorySize = 0;
-#ifdef SIS315H
-  USHORT  counter;
-#endif
-
-  switch(HwInfo->jChipType) {
-#ifdef SIS315H
-  case SIS_315H:
-  case SIS_315:
-  case SIS_315PRO:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter >>= 2;
-	counter &= 0x03;
-	if(counter == 0x02) {
-		AdapterMemorySize += (AdapterMemorySize / 2);      /* DDR asymetric */
-	} else if(counter != 0) {
-		AdapterMemorySize <<= 1;                           /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */
-	}
-	AdapterMemorySize *= (1024*1024);
-        break;
-
-  case SIS_330:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter &= 0x0c;
-	if(counter != 0) {
-		AdapterMemorySize <<= 1;
-	}
-	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_550:
-  case SIS_650:
-  case SIS_740:
-  	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	counter++;
-      	AdapterMemorySize = counter * 4;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_661:
-  case SIS_741:
-        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
-	AdapterMemorySize = 1 << counter;
-      	AdapterMemorySize *= (1024*1024);
-        break;
-
-  case SIS_660:
-  case SIS_760:
-        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
-	if(counter) {
-	   AdapterMemorySize = 1 << counter;
-      	   AdapterMemorySize *= (1024*1024);
-	}
-	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x78) & 0x30;
-	if(counter) {
-	   if(counter == 0x10) AdapterMemorySize += (32 * 1024 * 1024);
-	   else		       AdapterMemorySize += (64 * 1024 * 1024);
-	}
-	break;
-#endif
-
-#ifdef SIS300
-  case SIS_300:
-  case SIS_540:
-  case SIS_630:
-  case SIS_730:
-      	AdapterMemorySize = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	AdapterMemorySize++;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-#endif
-  default:
-        break;
-  }
-
-  return AdapterMemorySize;
-}
-#endif
-
-/*********************************************/
 /*           HELPER: Check RAM size          */
 /*********************************************/
 
@@ -1746,8 +1688,8 @@
 SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo, USHORT ModeIdIndex)
 {
+  USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
   USHORT memorysize,modeflag;
-  ULONG  temp;
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -1763,11 +1705,8 @@
   memorysize >>= MemorySizeShift;		/* Get required memory size */
   memorysize++;
 
-  temp = GetDRAMSize(SiS_Pr, HwInfo);       	/* Get adapter memory size (in MB) */
-  temp /= (1024*1024);
-
-  if(temp < memorysize) return(FALSE);
-  else return(TRUE);
+  if(AdapterMemSize < memorysize) return FALSE;
+  return TRUE;
 }
 #endif
 
@@ -1781,14 +1720,14 @@
 {
    UCHAR data, temp;
 
-   if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
-     data = *SiS_Pr->pSiS_SoftSetting & 0x03;
+   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
+     data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
    } else {
-     if(HwInfo->jChipType >= SIS_660) {
-        /* data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; */
-	data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
-     } else if(HwInfo->jChipType >= SIS_661) {
-        data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+     if(HwInfo->jChipType >= SIS_661) {
+        data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; 
+	if(SiS_Pr->SiS_ROMNew) {
+	   data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+	}
      } else if(IS_SIS550650740) {
         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
      } else {	/* 315, 330 */
@@ -1815,10 +1754,14 @@
 USHORT
 SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
   USHORT index;
 
   index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
   if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_ROMNew) {
+        return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
+     }
      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
   } else if(index >= 4) {
      index -= 4;
@@ -1844,20 +1787,17 @@
 
   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
      if(ModeNo > 0x13) {
-        AdapterMemorySize = GetDRAMSize(SiS_Pr, HwInfo);
-        SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0);
+        SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
      } else {
         pBuffer = (USHORT *)VideoMemoryAddress;
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0000;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0000;
      }
   } else {
-     pBuffer = (USHORT *)VideoMemoryAddress;
      if(SiS_Pr->SiS_ModeType < ModeCGA) {
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0720;
+        pBuffer = (USHORT *)VideoMemoryAddress;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0720;
      } else {
-        SiS_SetMemory(VideoMemoryAddress,0x8000,0);
+        SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
      }
   }
 }
@@ -1913,10 +1853,10 @@
    UCHAR index;
 
    if(ModeNo <= 0x13) {
-     	index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
+      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
    } else {
-     	if(SiS_Pr->SiS_ModeType <= 0x02) index = 0x1B;    /* 02 -> ModeEGA  */
-     	else index = 0x0F;
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;   
+      else index = 0x0F;
    }
    return index;
 }
@@ -1931,7 +1871,7 @@
     USHORT temp,temp1,temp2;
 
     if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-       return(1);
+       return(TRUE);
     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
     SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
     temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
@@ -1941,13 +1881,13 @@
     SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
     if((HwInfo->jChipType >= SIS_315H) ||
        (HwInfo->jChipType == SIS_300)) {
-       if(temp2 == 0x55) return(0);
-       else return(1);
+       if(temp2 == 0x55) return(FALSE);
+       else return(TRUE);
     } else {
-       if(temp2 != 0x55) return(1);
+       if(temp2 != 0x55) return(TRUE);
        else {
           SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-          return(0);
+          return(FALSE);
        }
     }
 }
@@ -3002,7 +2942,7 @@
 
   data = 0;
   if(ModeNo > 0x13) {
-     if(SiS_Pr->SiS_ModeType > 0x02) {
+     if(SiS_Pr->SiS_ModeType > ModeEGA) {
         data |= 0x02;
         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
      }
@@ -3065,7 +3005,7 @@
      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
 
   } else if( (HwInfo->jChipType == SIS_330) ||
-             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760UMA))) {
+             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
 
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
      if(HwInfo->jChipType == SIS_330) {
@@ -3109,7 +3049,7 @@
 	      if(data2 >= 0x127)      data = 0xba;
 	      else                    data = 0x7a;
 	   }
-	} else {
+	} else {  /* 760+LFB */
 	   if     (data2 >= 0x190) data = 0xba;
 	   else if(data2 >= 0xff)  data = 0x7a;
 	   else if(data2 >= 0xd3)  data = 0x3a;
@@ -3379,8 +3319,6 @@
   }
 }
 
-
-
 /*********************************************/
 /*         HELPER: RESET VIDEO BRIDGE        */
 /*********************************************/
@@ -5105,10 +5043,7 @@
 int
 sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin, 
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode)
+			 struct fb_var_screeninfo *var)
 {
     USHORT ModeNo = modeno;
     USHORT ModeIdIndex = 0, index = 0;
@@ -5196,15 +5131,15 @@
 	 /* 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);
+       var->left_margin = (400 - 376);
+       var->right_margin = (328 - 320);
+       var->hsync_len = (376 - 328);
 
     } else {
 
-       *left_margin = D * 8;
-       *right_margin = F * 8;
-       *hsync_len = C * 8;
+       var->left_margin = D * 8;
+       var->right_margin = F * 8;
+       var->hsync_len = C * 8;
 
     }
 
@@ -5266,47 +5201,47 @@
 
     D = B - F - C;
       
-    *upper_margin = D;
-    *lower_margin = F;
-    *vsync_len = C;
+    var->upper_margin = D;
+    var->lower_margin = F;
+    var->vsync_len = C;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
-       *sync &= ~FB_SYNC_VERT_HIGH_ACT;
+       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
     else
-       *sync |= FB_SYNC_VERT_HIGH_ACT;
+       var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)       
-       *sync &= ~FB_SYNC_HOR_HIGH_ACT;
+       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
     else
-       *sync |= FB_SYNC_HOR_HIGH_ACT;
+       var->sync |= FB_SYNC_HOR_HIGH_ACT;
 		
-    *vmode = FB_VMODE_NONINTERLACED;
+    var->vmode = FB_VMODE_NONINTERLACED;
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
-       *vmode = FB_VMODE_INTERLACED;
+       var->vmode = FB_VMODE_INTERLACED;
     else {
-      j = 0;
-      while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+       j = 0;
+       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
           if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
 	                  SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
               if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-	      	  *vmode = FB_VMODE_DOUBLE;
+	      	  var->vmode = FB_VMODE_DOUBLE;
               }
 	      break;
           }
 	  j++;
-      }
+       }
     }       
 
-    if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+    if((var->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;
+       var->upper_margin <<= 1;
+       var->lower_margin <<= 1;
+       var->vsync_len <<= 1;
+#endif
+    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       var->upper_margin >>= 1;
+       var->lower_margin >>= 1;
+       var->vsync_len >>= 1;
     }
 
     return 1;       
diff -urN linux-2.4.27-pre5/drivers/video/sis/init.h linux-2.4.27-pre6/drivers/video/sis/init.h
--- linux-2.4.27-pre5/drivers/video/sis/init.h	2004-04-14 06:05:39.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/init.h	2004-06-16 11:33:28.726111811 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init.c
  *
@@ -253,8 +254,8 @@
 	{ 1152, 768, 8,16},   /* 0x1a */
 	{  768, 576, 8,16},   /* 0x1b */
 	{ 1360,1024, 8,16},   /* 0x1c */
-	{ 1280, 800, 8,16},   /* 0x1d */
-	{ 1680,1050, 8,16}    /* 0x1e */
+	{ 1680,1050, 8,16},   /* 0x1d */
+	{ 1280, 800, 8,16}    /* 0x1e */ 
 };
 
 static SiS_StandTableStruct SiS_StandTable[]=
@@ -840,7 +841,8 @@
  {   36,  25,1060, 648,1270, 530, 438,   0, 438,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 - better */
  {    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 */
- {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20}   /* 1024x768 (for NTSC equ) */
+ {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
+ {    9,   4, 848, 528,1270, 530,   0,   0,  50,0xf5,0xfb,0x1b,0x2a}   /* 720x480 test */
 };
 
 static const SiS_TVDataStruct  SiS_StNTSCData[] =
@@ -929,7 +931,10 @@
  {  143,  70, 0x39c,0x189,0x4f6,0x1b8,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
  {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480  */
  {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600  */
+#if 0 
  {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480  */
+#endif
+ {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480 test */ 
  {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768 */
  {    5,   2, 0x3a7,0x226,0x500,0x2a8,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x576  */
  {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720 */
@@ -1057,17 +1062,30 @@
 	{   1,    1, 1688, 1066, 1688, 1066 }
 };
 
+#undef SISUSE6330MODES
+
 static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
 {
-	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 */
+#ifdef SISUSE6330MODES
+	{ 211,   60, 1260,  410, 1688, 1066 }, /* 640x400 (6330) */
+#else	
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
+#endif	
 	{ 211,   64, 1536,  358, 1688, 1066 },
 	{ 211,  100, 2100,  408, 1688, 1066 },
 	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 */
-	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 */
-	{ 211,  128, 1400,  776, 1688, 1066 },
-	{ 211,  205, 1680, 1041, 1688, 1066 },
-	{   1,    1, 1688, 1066, 1688, 1066 }
+#ifdef SISUSE6330MODES
+	{ 211,   80, 1400,  490, 1688, 1066 }, /* 640x480 (6330) */
+	{ 211,  117, 1638,  613, 1688, 1066 }, /* 800x600 (6330) */
+#else
+	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 (6325) WORKS */
+	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 (6325) WORKS */
+#endif	
+	{ 211,  128, 1400,  776, 1688, 1066 }, /* 1024x768 */
+	{ 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
+	{   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
+	{   0,    0,    0,    0,    0,    0 }, /* kludge */
+	{ 211,  120, 1400,  730, 1688, 1066 }  /* 1280x720 */
 };
 
 static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
@@ -1097,21 +1115,29 @@
 	{ 4,  1,1080, 625, 2160, 1250 },
 	{ 5,  2,1350, 800, 2160, 1250 },
 	{135,88,1600,1100, 2160, 1250 },
-	{135,88,1600,1100, 2160, 1250 },
+	{72, 49,1680,1092, 2160, 1250 }, 
 	{ 1,  1,2160,1250, 2160, 1250 }
 };
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1600x1200Data[] =
 {
-	{27, 4, 800, 500, 2160, 1250 },
+#ifndef SISUSE6330MODES
+	{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) */
+#else	
+	{27, 4, 800, 500, 2160, 1250 }, /* 640x400 (6235) */
+#endif	
 	{27, 4, 800, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
-	{27, 1, 800, 500, 2160, 1250 },
+#ifndef SISUSE6330MODES
+	{45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) */
+#else
+	{27, 1, 800, 500, 2160, 1250 }, /* 640x480 (6325) */
+#endif	
 	{ 4, 1,1080, 625, 2160, 1250 },
 	{ 5, 2,1350, 800, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
+	{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
+	{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
 	{ 1, 1,2160,1250, 2160, 1250 }
 };
 
@@ -1129,13 +1155,22 @@
         { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
 	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
 	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
-	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS)  */
-	{ 1, 1,1408, 816,1408, 816 },  /* 0x0d: 1280x800  */
+	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS, projector)  */
+	{ 1, 1,1656, 841,1656, 841 },  /* 0x0d: 1280x800 (was: 1408, 816) */
 	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
 	{ 1, 1,1408, 806,1408, 806 },  /* 0x0f: 1280x768_2 */
 	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 */
 	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768: Std, TMDS only */
-	{ 1, 1,1344, 806,1344, 806 }   /* 0x12: 1280x720 (LVDS)  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x12: 1280x720 (LVDS)  */
+	{ 1, 1, 896, 497, 896, 497 },  /* 0x13: 720x480 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x14: 720x576 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x15: 768x576 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x16: 848x480 */
+	{ 1, 1,1064, 497,1064, 497 },  /* 0x17: 856x480 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x18: 800x480 */
+	{ 1, 1,1328, 739,1328, 739 },  /* 0x19: 1024x576 */
+	{ 1, 1,1680, 892,1680, 892 },  /* 0x1a: 1152x864 */
+	{ 1, 1,1808, 808,1808, 808 }   /* 0x1b: 1360x768 */
 };
 
 
@@ -2387,10 +2422,7 @@
 			      unsigned char modeno, unsigned char rateindex);
 int    sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin,
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode);
+			 struct fb_var_screeninfo *var);
 BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
 #endif
diff -urN linux-2.4.27-pre5/drivers/video/sis/init301.c linux-2.4.27-pre6/drivers/video/sis/init301.c
--- linux-2.4.27-pre5/drivers/video/sis/init301.c	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/init301.c	2004-06-16 11:33:28.741112435 -0700
@@ -1,9 +1,10 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT2 section)
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661xX/740/741/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ *     SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
+ * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
@@ -115,7 +116,10 @@
 static void
 SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
 {
-   if(HwInfo->jChipType >= SIS_661) DataAND &= 0x0f;
+   if(HwInfo->jChipType >= SIS_661) {
+      DataAND &= 0x0f;
+      DataOR  &= 0x0f;
+   }
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 }
 
@@ -137,7 +141,7 @@
 
    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
       myptr = (UCHAR *)SiS_LCDStruct661;
-      romindex = SISGETROMW(0x100);  /* 10c, 0.93: 10e */
+      romindex = SISGETROMW(0x100);  
       if(romindex) {
          romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26);
          myptr = &ROMAddr[romindex];
@@ -157,7 +161,7 @@
     */
 
    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-      romptr = SISGETROMW(0x102);  /* 2ad */
+      romptr = SISGETROMW(0x102);  
       romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
 
@@ -275,10 +279,11 @@
   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
   if(ModeNo == 0xfe) return 0;
 
-  if(ModeNo <= 0x13)
+  if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  else
+  } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  }
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -474,7 +479,6 @@
          Delay = 3;
       } else {
          if(DelayTime >= 2) DelayTime -= 2;
-
          if(!(DelayTime & 0x01)) {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
          } else {
@@ -482,15 +486,12 @@
          }
 	 if(SiS_Pr->SiS_UseROM) {
             if(ROMAddr[0x220] & 0x40) {
-               if(!(DelayTime & 0x01)) {
-	          Delay = (USHORT)ROMAddr[0x225];
-               } else {
-	    	  Delay = (USHORT)ROMAddr[0x226];
-               }
+               if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
+               else 	    	       Delay = (USHORT)ROMAddr[0x226];
             }
          }
       }
-      SiS_ShortDelay(SiS_Pr,Delay);
+      SiS_ShortDelay(SiS_Pr, Delay);
 
 #endif  /* SIS300 */
 
@@ -498,7 +499,9 @@
 
 #ifdef SIS315H
 
-      if(HwInfo->jChipType >= SIS_661) {
+      if((HwInfo->jChipType >= SIS_661)    ||
+         (HwInfo->jChipType <= SIS_315PRO) ||
+	 (HwInfo->jChipType == SIS_330)) {
 
          if(!(DelayTime & 0x01)) {
 	    SiS_DDC2Delay(SiS_Pr, 0x1000);
@@ -506,11 +509,9 @@
 	    SiS_DDC2Delay(SiS_Pr, 0x4000);
          }
 
-      } else if(HwInfo->jChipType >= SIS_330) return;
-
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {			/* 315 series, LVDS; Special */
+	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {			/* 315 series, LVDS; Special */
 
          if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
             PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
@@ -541,7 +542,7 @@
                   }
                }
             }
-	    SiS_ShortDelay(SiS_Pr,Delay);
+	    SiS_ShortDelay(SiS_Pr, Delay);
 	 }
 
       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {			/* 315 series, all bridges */
@@ -584,7 +585,6 @@
   USHORT watchdog;
 
   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
-
   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 
   watchdog = 65535;
@@ -640,10 +640,10 @@
        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
        if(temp & 0x01) {
           if((tempal & 0x08))  continue;
-          if(!(tempal & 0x08)) break;
+          else break;
        } else {
           if(!(tempal & 0x08)) continue;
-          if((tempal & 0x08))  break;
+          else break;
        }
     }
     temp ^= 0x01;
@@ -664,12 +664,14 @@
 /*               HELPER: MISC                */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_Is301B(SiS_Private *SiS_Pr)
 {
   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
   return FALSE;
 }
+#endif
 
 static BOOLEAN
 SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
@@ -715,6 +717,16 @@
   return FALSE;
 }
 
+#ifdef SIS315H
+static BOOLEAN
+SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
+  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
+  return FALSE;  
+}
+#endif
+
 static BOOLEAN
 SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
@@ -754,11 +766,8 @@
 static BOOLEAN
 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT flag;
-
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
-     if(flag & 0x10) return TRUE;
+     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
   }
   return FALSE;
 }
@@ -854,12 +863,12 @@
   USHORT flag;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     return FALSE;
+     return TRUE;
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-     if((flag == 1) || (flag == 2)) return FALSE;
+     if((flag == 1) || (flag == 2)) return TRUE;
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
@@ -867,21 +876,21 @@
 {
   USHORT flag;
 
-  if(!(SiS_BridgeIsOn(SiS_Pr))) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
      if(HwInfo->jChipType < SIS_315H) {
        flag &= 0xa0;
-       if((flag == 0x80) || (flag == 0x20)) return FALSE;
+       if((flag == 0x80) || (flag == 0x20)) return TRUE;
      } else {
        flag &= 0x50;
-       if((flag == 0x40) || (flag == 0x10)) return FALSE;
+       if((flag == 0x40) || (flag == 0x10)) return TRUE;
      }
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
-SiS_BridgeInSlave(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
 {
   USHORT flag1;
 
@@ -942,7 +951,7 @@
   SiS_Pr->SiS_ModeType = modeflag & ModeInfoFlag;
 
   tempbx = 0;
-  if(SiS_BridgeIsOn(SiS_Pr) == 0) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
     	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 #if 0
    	if(HwInfo->jChipType < SIS_661) {
@@ -970,7 +979,7 @@
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
 	      }
 	      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
-	         /* Reset LCDA setting */
+	         /* Reset LCDA setting if not driver mode */
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	      }
 	      if(IS_SIS650) {
@@ -1125,9 +1134,9 @@
 	         }
               }
       	   } else {
-              if(!(SiS_BridgeIsEnabled(SiS_Pr,HwInfo))) {
+              if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
           	 if(!(tempbx & DriverMode)) {
-            	    if(SiS_BridgeInSlave(SiS_Pr)) {
+            	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
 		       tempbx |= SetSimuScanMode;
             	    }
                  }
@@ -1437,21 +1446,49 @@
 {
 #ifdef SIS315H
    UCHAR  *ROMAddr;
+   USHORT temp;   
+   
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT, 
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif   
 
    if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
-      SiS_Pr->PanelHT  = SISGETROMW(6);
-      SiS_Pr->PanelVT  = SISGETROMW(8);
+      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->PanelHT  = temp;
+      }
+      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+         SiS_Pr->PanelVT  = temp;
+      }
       SiS_Pr->PanelHRS = SISGETROMW(10);
       SiS_Pr->PanelHRE = SISGETROMW(12);
       SiS_Pr->PanelVRS = SISGETROMW(14);
       SiS_Pr->PanelVRE = SISGETROMW(16);
       SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
-	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)ROMAddr[18];
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
 	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
-      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
 	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+	 
+#ifdef TWDEBUG
+      xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT, 
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif	 
+
    }
 #endif
 }
@@ -1478,6 +1515,7 @@
   SiS_Pr->PanelHRE        = 999; /* HSync end */
   SiS_Pr->PanelVRS        = 999; /* VSync start */
   SiS_Pr->PanelVRE        = 999; /* VSync end */
+  SiS_Pr->SiS_NeedRomModeData = FALSE;
 
   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
 
@@ -1491,6 +1529,7 @@
   }
 
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+  if(!temp) return;
 
   if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
      SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
@@ -1628,10 +1667,10 @@
 			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
 			    break;
      case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
-			    SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
-			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK69_315;
+     			    SiS_Pr->PanelHT   = 1656; SiS_Pr->PanelVT   =  841;  /* 1408, 816 */
+			    SiS_Pr->PanelHRS   =  32; SiS_Pr->PanelHRE  =  312;  /*   16,  64 */
+			    SiS_Pr->PanelVRS   =  16; SiS_Pr->PanelVRE  =    8;  /*    4,   3 */
+			    SiS_Pr->PanelVCLKIdx315 = VCLK83_315;
 			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
 			    break;
      case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
@@ -1757,6 +1796,10 @@
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(modeflag & NoSupportLCDScale) {
+	   /* No scaling for this mode on any panel */
+	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	}
         switch(SiS_Pr->SiS_LCDResInfo) {
         case Panel_Custom:
 		/* For non-standard LCD resolution, we let the panel scale */
@@ -1774,7 +1817,7 @@
 	 	SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
 		break;
 	case Panel_1280x1024:
-	        if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	        if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
 		   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
 		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
 		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16) {
@@ -1791,13 +1834,30 @@
 		}
 		break;
 	case Panel_1400x1050:
+	 	if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
+	  	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16 ||
+		      ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25) {
+	      	      /* Do not scale to 1280x720/768/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		   if(ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78) {
+		      if(SiS_Pr->UsePanelScaler == -1) {
+		         /* Do not scale to 1280x720 by default (LVDS bridges) */
+	      	         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		      }
+		   }
+		}
 		if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
-	      	   /* We do not scale to 1280x1024 (all bridges) */
+	      	   /* Do not scale to 1280x1024 (all bridges) */
 	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	   	}
 		break;
 	case Panel_1600x1200:
-		if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+		if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
 	      	   /* No idea about the timing and zoom factors (C bridge only) */
 	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	   	}
@@ -1832,6 +1892,10 @@
   if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
      SiS_Pr->SiS_LCDInfo |= LCDPass11;
   }
+  
+  if(SiS_Pr->UseCustomMode) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
 
   /* (In)validate LCDPass11 flag */
   if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
@@ -1975,10 +2039,25 @@
 	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
 	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	         VCLKIndex = VCLKIndexGEN;
-		 if(resinfo == SIS_RI_1280x720) VCLKIndex = VCLK_1280x720;
-		 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
-		    if(SiS_Pr->PanelHT == 1344) VCLKIndex = VCLK_1280x720_2;
+		 switch(resinfo) {
+		 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; 
+		 		       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		                          if(SiS_Pr->PanelHT == 1344) {
+					     VCLKIndex = VCLK_1280x720_2;
+					  }
+				       }
+		 		       break;
+		 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
+		 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
+		 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
+		 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
+		 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
+		 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
+		 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
+		 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+		 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
 		 }
+		 
 		 if(ModeNo <= 0x13) {
 		    if(HwInfo->jChipType <= SIS_315PRO) {
 		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
@@ -2150,12 +2229,10 @@
                     PSIS_HW_INFO HwInfo)
 {
   USHORT i,j,modeflag;
-  USHORT tempcl,tempah=0;
-#ifdef SIS300
-  USHORT temp;
-#endif
+  USHORT tempbl,tempcl,tempah=0;
 #ifdef SIS315H
-  USHORT tempbl, tempah2, tempbl2;
+  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+  USHORT tempah2, tempbl2;
 #endif
 
   if(ModeNo <= 0x13) {
@@ -2178,6 +2255,9 @@
   } else {
 
      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
+     if(HwInfo->jChipType >= SIS_315H) {
+        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
+     }
 
      tempcl = SiS_Pr->SiS_ModeType;
 
@@ -2187,14 +2267,14 @@
 
         /* For 301BDH: (with LCD via LVDS) */
         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	   temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
-	   temp &= 0xef;
-	   temp |= 0x02;
+	   tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
+	   tempbl &= 0xef;
+	   tempbl |= 0x02;
 	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	      temp |= 0x10;
-	      temp &= 0xfd;
+	      tempbl |= 0x10;
+	      tempbl &= 0xfd;
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
         }
 
         if(ModeNo > 0x13) {
@@ -2368,7 +2448,7 @@
 
 #ifdef SIS315H
 
-        unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);;
+        unsigned char bridgerev = SiS_GetReg(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
@@ -2399,10 +2479,11 @@
 	 * in a 650 box (Jake). What is the criteria?
 	 */
 
-	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661)) {
+	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
 	   tempah = 0x30;
 	   tempbl = 0xc0;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+	   if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+	      ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
 	      tempah = 0x00;
 	      tempbl = 0x00;
 	   }
@@ -2433,23 +2514,23 @@
 
 	if(IS_SIS740) {
 	   tempah = 0x80;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-	      tempah = 0x00;
-	   }
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
 	} else {
 	   tempah = 0x00;
            tempbl = 0x7f;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempbl = 0xff;
-	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
-	         tempah = 0x80;
-	      }
+	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
            }
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
 	}
-
-	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here (old BIOS) */
+	
+#if 0	
+	if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0xc0);
+	}
+#endif	
 
 #endif /* SIS315H */
 
@@ -2478,9 +2559,7 @@
 	   tempbl = 0xfb;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempah = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	         tempbl = 0xff;
-	      }
+	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
            }
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
 
@@ -2560,9 +2639,11 @@
 
   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
 
+#if 0  
         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
            if(xres == 720) xres = 640;
 	}
+#endif
 
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	   switch(SiS_Pr->SiS_LCDResInfo) {
@@ -2726,7 +2807,12 @@
 
         tempbx = SiS_Pr->SiS_LCDResInfo;
 	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
-
+	
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
+	   if     (resinfo == SIS_RI_1280x800)  tempal =  9;
+	   else if(resinfo == SIS_RI_1400x1050) tempal = 11;
+	}
+	
   	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {  /* Pass 1:1 only (center-screen handled outside) */
 	   tempbx = 100;
 	   if(ModeNo >= 0x13) {
@@ -2783,6 +2869,9 @@
 	      (resinfo == SIS_RI_720x576) ||
 	      (resinfo == SIS_RI_768x576)) {
 	      tempal = 6;
+	      if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
+	         if(resinfo == SIS_RI_720x480) tempal = 9;
+	      }
 	   }
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
@@ -3080,11 +3169,14 @@
                    USHORT RefreshRateTableIndex,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,modeflag;
-  USHORT resinfo;
-  USHORT CRT2Index,ResIndex;
+  UCHAR  *ROMAddr = NULL;
+  USHORT tempax,tempbx,modeflag,romptr=0;
+  USHORT resinfo,CRT2Index,ResIndex;
   const SiS_LCDDataStruct *LCDPtr = NULL;
   const SiS_TVDataStruct  *TVPtr  = NULL;
+#ifdef SIS315H    
+  SHORT  resinfo661;
+#endif    
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -3095,6 +3187,20 @@
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS315H     
+     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
+         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+         (resinfo661 >= 0)                     && 
+	 (SiS_Pr->SiS_NeedRomModeData) ) {
+        if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((romptr = (SISGETROMW(21)))) {
+              romptr += (resinfo661 * 10);
+	      ROMAddr = HwInfo->pjVirtualRomBase;
+	   }
+	}
+     }
+#endif     
   }
   
   SiS_Pr->SiS_NewFlickerMode = 0;
@@ -3238,6 +3344,8 @@
         SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
 
      } else {
+     
+        BOOLEAN gotit = FALSE;
 
         if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
 
@@ -3245,8 +3353,23 @@
            SiS_Pr->SiS_VGAVT     = SiS_Pr->PanelVT;
            SiS_Pr->SiS_HT        = SiS_Pr->PanelHT;
            SiS_Pr->SiS_VT        = SiS_Pr->PanelVT;
+	   gotit = TRUE;
 
-	} else {
+	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
+	
+#ifdef SIS315H	
+	   SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
+           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+           SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
+           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+           SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+	   if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
+#endif	   
+	
+	} 
+	
+	if(!gotit) {
 
            SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
                           &CRT2Index,&ResIndex,HwInfo);
@@ -3445,8 +3568,10 @@
 #ifdef SIS315H
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
         /* non-pass 1:1 only, see above */
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
            SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	}
+	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
 	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
 	}
      }
@@ -3562,207 +3687,142 @@
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
 
         if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300	   /* 300 series */
 
-           if(HwInfo->jChipType == SIS_300) {  /* For 300+301LV (A907) */
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		 }
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      }
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	   }
+	   if(SiS_Is301B(SiS_Pr)) {
 	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
 	      SiS_ShortDelay(SiS_Pr,1);
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	         if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	             (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-		 }
-	      }
-
-	   } else {
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-	      }
-	      if(SiS_Is301B(SiS_Pr)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
-	         SiS_ShortDelay(SiS_Pr,1);
-	      }
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      SiS_UnLockCRT2(SiS_Pr,HwInfo);
+           }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
+	   SiS_DisplayOff(SiS_Pr);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	   SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	   if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-	      if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	          (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
-	      }
 	   }
-
+	   if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
+	       (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+	      }
+	   }	        
+	      
 #endif  /* SIS300 */
 
         } else {
 
 #ifdef SIS315H	   /* 315 series */
+	   
+	   BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                      (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
 
-           if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
-
-	      modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
+	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
 
-              if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {			/* LV */
+           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	
+	   		
 #ifdef SET_EMI
-	         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-		    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-	               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		    }
+	      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		 }
+	      }
 #endif
-		 if( (modenum <= 0x13) ||
-		     (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-		     (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
-	     	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		       SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		    }
-	         }
-
-		 if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		    (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		    SiS_DDC2Delay(SiS_Pr,0xff00);
-		    SiS_DDC2Delay(SiS_Pr,0xe000);
-
-	            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-
-                    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-
-		    if(IS_SIS740) {
-		       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-		    }
-
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      if( (modenum <= 0x13)                  ||
+		  (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
+		  (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
+	     	 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+		 if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-		    if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
-	               tempah = 0xef;
-	               if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	                  tempah = 0xf7;
-                       }
-	               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	            }
+	      if(!custom1) {
+		 SiS_DDC2Delay(SiS_Pr,0xff00);
+		 SiS_DDC2Delay(SiS_Pr,0xe000);
+	         SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+		 if(IS_SIS740) {
+		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
 		 }
+	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-              } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* B-DH */
-
-	         if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,0xef);
-	         }
+           } 
+	      
+	   if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	      tempah = 0xef;
+	      if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	   }
+	      
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
+	   }
+              
+	   tempah = 0x3f;
+	   if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+	      tempah = 0x7f;
+	      if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+	   }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-	      }
+           if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
 
-	      if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0xef);
+	      SiS_DisplayOff(SiS_Pr);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	      }
-
-              if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	         (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
+		 
+	   } 
+	      
+	   if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+
+	      if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+		 SiS_DisplayOff(SiS_Pr);
 	      }
-
-              if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	         ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    SiS_DisplayOff(SiS_Pr);
-		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-		 } else {
-	            SiS_DisplayOff(SiS_Pr);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13)) {
-		       SiS_DisplayOff(SiS_Pr);
-	               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	               temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-		    }
-		 }
-
-	      } else {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
-		       SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
-		       SiS_DisplayOff(SiS_Pr);
-		    }
-		    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-		 } else {
-                    SiS_DisplayOff(SiS_Pr);
-	            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		 }
-
-		 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+		 
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	      }
 
-	      if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-	         (SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		 (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-
-		 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,~0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	   }
+	      
+	   if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	   }
 
-		 if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		 }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      
+	      if(!custom1) {
 
 	         if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
 	            if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
 	               if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
 		          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
@@ -3773,89 +3833,31 @@
 	         SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
 
 		 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	            if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
+	            if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
 		       SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
 		    }
 	         }
-
-  	      } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-
-	         /* NIL */
-
-	      } else if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	                (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-			(SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-
-		 if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            tempah = 0xef;
-	            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-		       if(modenum > 0x13) {
-	                  tempah = 0xf7;
-		       }
-                    }
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-		 }
-		 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-		       (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
-		       if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
-		          (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	     	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 4);
-	               }
+	      
+	      } else {
+	      
+		 if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
+		    if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
+		       (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	     	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 4);
 		    }
 		 }
 
 	      }
-
-	  } else {			/* 315, 330 - all bridge types */
-
-	     if(SiS_Is301B(SiS_Pr)) {
-	        tempah = 0x3f;
-	        if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	           tempah = 0x7f;
-	           if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		      tempah = 0xbf;
-                   }
-	        }
-	        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-	        if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	           SiS_DisplayOff(SiS_Pr);
-		   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	        }
-	     }
-	     if( (!(SiS_Is301B(SiS_Pr))) ||
-	         (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
-
- 	 	if( (!(SiS_Is301B(SiS_Pr))) ||
-		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
-
-	           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);
-
-	        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
-	     }
-
-	  }    /* 315/330 */
+           }
 
 #endif /* SIS315H */
 
 	}
 
-      } else {     /* ============ For 301 ================ */
+     } else {     /* ============ For 301 ================ */
 
         if(HwInfo->jChipType < SIS_315H) {
 #ifdef SIS300
@@ -3947,6 +3949,10 @@
 
 #ifdef SIS315H	/* 315 series */
 
+        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+        }
+
 	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 
 	   if(HwInfo->jChipType == SIS_740) {
@@ -4077,7 +4083,6 @@
   BOOLEAN delaylong = FALSE;
 #endif
 
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
@@ -4086,28 +4091,55 @@
 
 #ifdef SIS300     /* 300 series */
 
-         if(HwInfo->jChipType == SIS_300) {
-
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-	          if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
-	             SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	          }
+	 if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+	    }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
+	       if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
+	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	       }
 	    }
+	 }
+	    
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+	    (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+	       
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   		/* Enable CRT2 */
+            SiS_DisplayOn(SiS_Pr);
+	    SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+      	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+      	    } else {
+      	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+            }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		  if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+                  }
+		  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+               }
+	    }
+	       
+	 } else {
+	    
 	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-            if(SiS_BridgeInSlave(SiS_Pr)) {
+            if(SiS_BridgeInSlavemode(SiS_Pr)) {
                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-               if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
             }
             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
 	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
 	    SiS_DisplayOn(SiS_Pr);
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
 		     if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
 		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
@@ -4116,441 +4148,279 @@
 	 	  }
 	       }
 	    }
+	       
+	 }
 
-	 } else {
-
-	    if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-	       (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
-	       /* This is only for LCD output on 301B-DH via LVDS */
-	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-	       if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	       }
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   /* Enable CRT2 */
-               SiS_DisplayOn(SiS_Pr);
-	       SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-      		  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-      	       } else {
-      		  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-               }
-	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-	           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		       if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-		           SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                       }
-		       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
-                   }
-	       }
-            } else {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-               if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
-	       SiS_DisplayOn(SiS_Pr);
-	    }
-
-         }
+	 
 #endif /* SIS300 */
 
       } else {
 
 #ifdef SIS315H    /* 315 series */
 
-	 if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
-
-	    UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0;
-
-	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	 UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
+	 /* USHORT  emidelay=0; */
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
-		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	    }
 #endif
-	       }
-
-               if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	       }
-
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-	          SiS_DisplayOff(SiS_Pr);
-	          pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-	          if(IS_SIS740) {
-	             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-	          }
-	       }
-
-	       if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	           (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-                  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-		     if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		        (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-			   SiS_GenericDelay(SiS_Pr, 0x4500);
-			}
-	                SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-		     } else {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-		     }
-	          }
-	       }
-
-               if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
-                     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		     delaylong = TRUE;
-		  }
-	       }
-
-	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x10);
-	       }
-
-  	    } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	 }
 
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	       }
-	       
+         if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	    tempah = 0x10;
+	    if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+	       if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+	       else 			         tempah = 0x08;
 	    }
+	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	 }
 
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-               temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC)) {
-		     if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
-		  }
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+	    SiS_DisplayOff(SiS_Pr);
+	    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+	    if(IS_SIS740) {
+	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+	    }
 
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-	       
-	       if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		  temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-		  if(!(temp & 0x80)) {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	    if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+               if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		     SiS_GenericDelay(SiS_Pr, 0x4500);
 		  }
-	       } else {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	       }
-	    } else {
-	       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
 	    }
 
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
-
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-	       if(!(temp & 0x80)) {
-		  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	       }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
+               SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+	       delaylong = TRUE;
 	    }
 
-	    tempah = 0xc0;
-	    if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	       tempah = 0x80;
-	       if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) {
-	          tempah = 0x40;
-               }
-	    }
-            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	 } 
 
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400))     &&
-	        (!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))))) {
-               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	    }
+	 if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
+	 
+            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+               if(!(tempah & SetCRT2ToRAMDAC)) {
+		  if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
+	       }
+            }
+            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
+	    
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	    
 	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	    }
+	    
+	 } else {
+	 
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	    
+	 }
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#ifdef COMPAQ_HACK
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#endif
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	 
+	 tempah = 0xc0;
+	 if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+	    tempah = 0x80;
+	    if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+	 }
+         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-	       if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	    SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+
+	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	       }
 #endif
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
 #ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 
-		     cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-
-		     /*                                              (P4_30|0x40)  */
-		     /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
-		     /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
-		     /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
-		     /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
-		     /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
-		     /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
-
-		     if(SiS_Pr->HaveEMI) {
-		        r30 = SiS_Pr->EMI_30;
-			r31 = SiS_Pr->EMI_31;
-			r32 = SiS_Pr->EMI_32;
-			r33 = SiS_Pr->EMI_33;
-		     } else {
-		        r30 = 0;
+		  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); 
+		     
+		  if(SiS_Pr->SiS_ROMNew) {
+		     UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+		     USHORT romptr   = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+		     if(romptr) {
+		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
+			SiS_Pr->EMI_30 = 0;
+			SiS_Pr->EMI_31 = ROMAddr[romptr + 14];
+			SiS_Pr->EMI_32 = ROMAddr[romptr + 15];
+			SiS_Pr->EMI_33 = ROMAddr[romptr + 16];
+			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
+			/* emidelay = SISGETROMW((romptr + 0x22)); */
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
 		     }
+		  }
 
-		     /* EMI_30 is read at driver start; however, the BIOS sets this
-		      * (if it is used) only if the LCD is in use. In case we caught
-		      * the machine while on TV output, this bit is not set and we
-		      * don't know if it should be set - hence our detection is wrong.
-		      * Work-around this here:
-		      */
-
-		     if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
-		        if((cr36 & 0x0f) == 0x02) {			/* 1024x768 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x03) {		/* 1280x1024 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x09) {		/* 1400x1050 */
-		           r30 |= 0x40;
-		        } else if((cr36 & 0x0f) == 0x0b) {		/* 1600x1200 - unknown */
-		           r30 |= 0x40;
-		        }
-                     }
+		  /*                                              (P4_30|0x40)  */
+		  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
+		  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
+		  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
+		  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
+		  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
+		  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
+
+		  if(SiS_Pr->HaveEMI) {
+		     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
+		     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
+		  } else {
+		     r30 = 0;
+		  }
 
-		     if(!SiS_Pr->HaveEMI) {
-		        if((cr36 & 0x0f) == 0x02) {
+		  /* EMI_30 is read at driver start; however, the BIOS sets this
+		   * (if it is used) only if the LCD is in use. In case we caught
+		   * the machine while on TV output, this bit is not set and we
+		   * don't know if it should be set - hence our detection is wrong.
+		   * Work-around this here:
+		   */
+
+		  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
+		     switch((cr36 & 0x0f)) {
+		     case 2:  
+			r30 |= 0x40;
+			if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x33;
 			   if((cr36 & 0xf0) == 0x30) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x33;
-			   }
-		        } else if((cr36 & 0x0f) == 0x03) {
+			   } 
+			}
+			break;
+		     case 3:  /* 1280x1024 */
+			if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
-			   } else {
-			      r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   }
-			} else if((cr36 & 0x0f) == 0x09) {
+			}
+			break;
+		     case 9:  /* 1400x1050 */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   }
-			} else {
+			}
+			break;
+		     case 11: /* 1600x1200 - unknown */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
 			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			}
 		     }
+                  }
 
-		     /* BIOS values don't work so well sometimes */
-		     if(!SiS_Pr->OverruleEMI) {
+		  /* BIOS values don't work so well sometimes */
+		  if(!SiS_Pr->OverruleEMI) {
 #ifdef COMPAL_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-		           if((cr36 & 0x0f) == 0x09) {
-			      r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			   }
- 		        }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
+		        if((cr36 & 0x0f) == 0x09) {
+			   r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			}
+ 		     }
 #endif
 #ifdef COMPAQ_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-		           if((cr36 & 0x0f) == 0x03) {
-			      r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;     /* rev 1 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+		        if((cr36 & 0x0f) == 0x03) {
+			   r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;    
 			}
+		     }
 #endif
 #ifdef ASUS_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-		           if((cr36 & 0x0f) == 0x02) {
-			      /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
-			      /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
-			      /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
-			      /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+		        if((cr36 & 0x0f) == 0x02) {
+			   /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
+			   /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
+			   /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
+			   /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
 			}
-#endif
- 		     }
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
-		     }
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-		     } else {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x00);
-		     }
-		     if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-	                if(r30 & 0x40) {
-		           SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			   if(delaylong) {
-			      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			      delaylong = FALSE;
-			   }
-			   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			   if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-			      SiS_GenericDelay(SiS_Pr, 0x500);
-			   }
-	                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
-	                }
 		     }
-		  }
 #endif
-	       }
-
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-
-	          if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		     SiS_DisplayOn(SiS_Pr);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		     SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		     if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-	  	     }
+ 		  }
+		     
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
 		  }
-
-	       } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		        SiS_DisplayOn(SiS_Pr);
-		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-		     }
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+		  } else {
+		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x00);
 		  }
-
-	       } else {
-
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 ((SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        if(delaylong) {
-			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        }
-                        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		     
+		  if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) || 
+	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {  
+	             if(r30 & 0x40) {
+		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			if(delaylong) {
+			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			   delaylong = FALSE;
+			}
+			SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+			if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
 			   SiS_GenericDelay(SiS_Pr, 0x500);
 			}
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+	                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   
 	             }
-	          }
-
-	          SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
-	          SiS_DisplayOn(SiS_Pr);
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	          }
-
+		  }
 	       }
-
+#endif
 	    }
 
-	 } else {			/* 315, 330 */
-
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-
-	       temp = SiS_GetReg(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);
-
-	    if(SiS_Is301B(SiS_Pr)) {
-
-	       temp=SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-               if(!(temp & 0x80))
-                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-
-	       tempah = 0xc0;
-	       if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	          tempah = 0x80;
-	          if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	             tempah = 0x40;
-                  }
+	    if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	       if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  if(delaylong) {
+		     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  }
+                  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	 	     SiS_GenericDelay(SiS_Pr, 0x500);
+		  }
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
 	       }
-               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-
-	       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);
-
 	    }
 
-	 }   /* 315, 330 */
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+	    SiS_DisplayOn(SiS_Pr);
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
+
+	 }
+	 
+	 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+	 }
 
 #endif /* SIS315H */
 
@@ -4566,9 +4436,9 @@
        }
 
        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
           tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-          if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
        }
        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
@@ -4621,7 +4491,7 @@
        SiS_DisplayOn(SiS_Pr);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
       	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
        } else {
       	  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
@@ -4653,6 +4523,10 @@
 
 #ifdef SIS315H    /* 315 series */
 
+       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+       }
+
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 	  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
@@ -5234,14 +5108,22 @@
 static void
 SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT temp;
-
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  temp = 0x04;
-  if(HwInfo->jChipType >= SIS_661) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8) == 0x80) temp = 0x44;
+  if( (HwInfo->jChipType == SIS_760)      &&
+      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
+      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
+      (SiS_Pr->SiS_VGAHDE >= 1280)	  &&
+      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
+  } else {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);  
   }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,temp);
+  
 }
 #endif
 
@@ -5250,10 +5132,10 @@
 {
   ULONG tempax,tempbx;
 
-  tempbx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX) & 0xFFFF;
+  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
-  return((USHORT) tempax);
+  return((USHORT)tempax);
 }
 
 /* Set Part 1 / SiS bridge slave mode */
@@ -6143,7 +6025,7 @@
               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
   UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0;
+  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
   USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
   USHORT  tempbl=0;
@@ -6200,40 +6082,8 @@
     	tempbx = pushbx + tempcx;
     	tempcx <<= 1;
     	tempcx += tempbx;
-
-    	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-	   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_TVMode & TVSetNTSC1024) {
-      	      tempbx = 1040;
-      	      tempcx = 1044;
-    	   }
-
-	}
-
-    	temp = tempbx & 0x00FF;
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
+	
+	bridgeadd = 12;
 
 #endif /* SIS300 */
 
@@ -6254,11 +6104,8 @@
 	   }
 	}
 	tempcx--;
-
-	temp = tempcx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
-
-	temp = ((tempcx & 0xff00) >> 8) << 4;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
+	temp = (tempcx >> 4) & 0xF0;
 	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
 	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
@@ -6270,85 +6117,83 @@
 	   tempcx >>= 1;
 	}
 	tempbx += 16;
-
-	temp = tempbx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
+	
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
 
 	pushbx = tempbx;
 	tempcx >>= 1;
 	tempbx += tempcx;
 	tempcx += tempbx;
+	
+	bridgeadd = 16;
 
 	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
 	   if(HwInfo->jChipType >= SIS_661) {
 	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
 		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
 		 if(resinfo == SIS_RI_1280x1024) {
-		    tempcx = 0x30;
+		    tempcx = (tempcx & 0xff00) | 0x30;
 		 } else if(resinfo == SIS_RI_1600x1200) {
-		    tempcx = 0xff;
+		    tempcx = (tempcx & 0xff00) | 0xff;
 		 }
 	      }
 	   }
-
-	   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) {
-	      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_TVMode & TVSetNTSC1024) {
-      	      tempbx = 1040;
-      	      tempcx = 1044;   /* HWCursor bug! */
-      	   }
-
         }
 
-	temp = tempbx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
 #endif  /* SIS315H */
 
      }  /* 315/330 series */
-
-     tempax = tempbx & 0xFF00;
-     tempbx = pushbx;
-     tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-     tempax |= (tempbx & 0xFF00);
-     temp = (tempax & 0xFF00) >> 8;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);
-
-     temp = tempcx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                 /* CRT2 Horizontal Retrace End */
-
+     
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     
+        if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CHSyncStart + bridgeadd;
+	   tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+	}
+	
+	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)) - 3) << 3; 		    /* (VGAHRS-3)*8 */
+           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
+	   tempcx &= 0x00FF;
+	   tempcx |= (tempbx & 0xFF00);
+           tempbx += bridgeadd;
+           tempcx += bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+        }
+     
+        if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	   tempbx = 1040;
+      	   tempcx = 1044;   /* HWCursor bug! */
+        }
+	
+     }
+     
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);            	  /* CRT2 Horizontal Retrace Start */
+     
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
+     
+     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);		  /* Overflow */
+     
      /* 2. Vertical setup */
 
      tempcx = SiS_Pr->SiS_VGAVT - 1;
@@ -6372,12 +6217,10 @@
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
 
      tempbx = SiS_Pr->SiS_VGAVDE - 1;
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                 /* CRT2 Vertical Display Enable End */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
 
-     temp = ((tempbx & 0xFF00) << 3) >> 8;
-     temp |= ((tempcx & 0xFF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow (and HWCursor Test Mode) */
+     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
 
      if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
         tempbx++;
@@ -6396,37 +6239,33 @@
      }
 
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
 	if(SiS_Pr->UseCustomMode) {
 	   tempbx = SiS_Pr->CVSyncStart;
-	   tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
+	   tempcx = SiS_Pr->CVSyncEnd;
 	}
-
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	   unsigned char cr8, cr7, cr13, cr9;
+	   unsigned char cr8, cr7, cr13;
 	   if(SiS_Pr->UseCustomMode) {
-	      cr8  = SiS_Pr->CCRT1CRTC[8];
-	      cr7  = SiS_Pr->CCRT1CRTC[7];
-	      cr13 = SiS_Pr->CCRT1CRTC[13];
-	      cr9  = SiS_Pr->CCRT1CRTC[9];
+	      cr8    = SiS_Pr->CCRT1CRTC[8];
+	      cr7    = SiS_Pr->CCRT1CRTC[7];
+	      cr13   = SiS_Pr->CCRT1CRTC[13];
+	      tempcx = 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];
+	      cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
 	   }
       	   tempbx = cr8;
-      	   if(cr7 & 0x04)  tempbx |= 0x0100;
-      	   if(cr7 & 0x80)  tempbx |= 0x0200;
+      	   if(cr7  & 0x04) tempbx |= 0x0100;
+      	   if(cr7  & 0x80) tempbx |= 0x0200;
       	   if(cr13 & 0x08) tempbx |= 0x0400;
-      	   tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
-    	}
+       	}
      }
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
-     temp = ((tempbx & 0xFF00) >> 8) << 4;
-     temp |= (tempcx & 0x000F);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
+     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
 
      /* 3. Panel delay compensation */
 
@@ -6436,7 +6275,6 @@
 
 	if(SiS_Pr->SiS_VBType & VB_SISVB) {
 	   temp = 0x20;
-
 	   if(HwInfo->jChipType == SIS_300) {
 	      temp = 0x10;
 	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
@@ -6447,10 +6285,10 @@
 	   }
 	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
 	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 	    temp = 0x08;
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
-      	      else 					temp = 0x20;
+      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	    temp = 0x2c;
+      	      else 					    temp = 0x20;
     	   }
 	   if(SiS_Pr->SiS_UseROM) {
 	      if(ROMAddr[0x220] & 0x80) {
@@ -6521,8 +6359,8 @@
 	} /* < 661 */
 
     	tempax = 0;
-    	if (modeflag & DoubleScanMode) tempax |= 0x80;
-    	if (modeflag & HalfDCLK)       tempax |= 0x40;
+    	if(modeflag & DoubleScanMode) tempax |= 0x80;
+    	if(modeflag & HalfDCLK)       tempax |= 0x40;
     	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
@@ -6585,7 +6423,6 @@
 	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
 	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
 	 else 				         	tableptr = SiS_Part2CLVX_5;
-
       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 	 tableptr = SiS_Part2CLVX_6;
       }
@@ -6865,9 +6702,9 @@
 SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
 	      PSIS_HW_INFO HwInfo)
 {
-  USHORT      i, j, tempax, tempbx, tempcx, temp;
-  USHORT      push1, push2, modeflag, crt2crtc, bridgeoffset;
-  ULONG       longtemp, tempeax;
+  USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+  USHORT      push2, modeflag, crt2crtc, bridgeoffset;
+  ULONG       longtemp;
   const       UCHAR *PhasePoint;
   const       UCHAR *TimingPoint;
 #ifdef SIS315H
@@ -7034,47 +6871,38 @@
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx--;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,(tempcx & 0xff));
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
-
-  tempcx++;
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx++;
-  tempcx >>= 1;
-
-  push1 = tempcx;
-
+  
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx += 7;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
 
   tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
   tempbx += tempcx;
-
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
-  temp = ((tempbx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
 
   tempbx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      tempbx -= 4;
      tempcx = tempbx;
   }
-  temp = (tempbx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
 
   j += 2;
   tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,temp);
-  temp = ((tempcx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
 
   tempcx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
-  tempcx = push1;
-
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
@@ -7086,54 +6914,47 @@
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
 
   tempbx = SiS_Pr->SiS_VDE;
-  if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
-  if(HwInfo->jChipType < SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1;
-  } else {
-     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
-         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
-	tempbx >>= 1;
-	if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	   if(ModeNo <= 0x13) {
-	      if(crt2crtc == 1) tempbx++;
-	   }
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
+  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
+     tempbx >>= 1;
+     if(HwInfo->jChipType >= SIS_315H) {
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	   if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
 	} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	   if(crt2crtc == 4) {
-              if(SiS_Pr->SiS_ModeType <= 3) tempbx++;
+	   if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	      if(crt2crtc == 4) tempbx++;
 	   }
 	}
      }
-  }
-  tempbx -= 2;
-  temp = tempbx & 0x00FF;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) temp++;
-     }
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     /* From 1.10.7w - doesn't make sense */
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-           if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	      if(ModeNo == 0x03) temp++;
-	   }
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	   if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
+	} 
+	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	   if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
         }
      }
   }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,temp);
+  tempbx -= 2;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
 
   temp = (tempcx >> 8) & 0x0F;
-  temp |= (((tempbx >> 8) << 6) & 0xC0);
+  temp |= ((tempbx >> 2) & 0xC0);
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
      temp |= 0x10;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
+  
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
+  }
 
+#if 0  
   /* TEST qqqq */
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
      for(i=0x01, j=0; i<=0x2D; i++, j++) {
@@ -7143,86 +6964,64 @@
         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
      }
   }
+#endif
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
      tempbx = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
-           tempbx >>= 1;
-	}
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
+        tempbx >>= 1;
      }
      tempbx -= 3;
-     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
-        if(HwInfo->jChipType >= SIS_661) {
-           temp = 0;
-	   if(tempcx & 0x0400) temp |= 0x20;
-	   if(tempbx & 0x0400) temp |= 0x40;
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x10,temp);
-	} else {
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-              if((SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-                 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
-	         (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
-                 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
-	      }
-           }
-	}
-     }
-     tempbx &= 0x03ff;
-     temp = ((tempbx & 0xFF00) >> 8) << 5;
-     temp |= 0x18;
+     temp = ((tempbx >> 3) & 0x60) | 0x18;
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
+     
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
+     }
   }
 
   tempbx = 0;
   if(!(modeflag & HalfDCLK)) {
      if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
         tempax = 0;
-        tempbx |= 0x2000;
+        tempbx |= 0x20;
      }
   }
 
-  tempcx = 0x0101;
+  tempch = tempcl = 0x01;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
      if(SiS_Pr->SiS_VGAHDE >= 1024) {
         if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
-           tempcx = 0x1920;
+           tempch = 0x19; 
+	   tempcl = 0x20;
            if(SiS_Pr->SiS_VGAHDE >= 1280) {
-              tempcx = 0x1420;
-              tempbx &= ~0x2000;
+              tempch = 0x14; 
+              tempbx &= ~0x20;
            }
         }
      }
   }
 
-  if(!(tempbx & 0x2000)) {
-     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;
-     }
-     tempeax = longtemp / SiS_Pr->SiS_HDE;
-     if(longtemp % SiS_Pr->SiS_HDE) tempeax++;
-     tempax = (USHORT)tempeax;
-     tempbx |= (tempax & 0x1F00);
-     tempcx = (tempax & 0xFF00) >> (8 + 5);
+  if(!(tempbx & 0x20)) {
+     if(modeflag & HalfDCLK) tempcl <<= 1;
+     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+     tempax = longtemp / SiS_Pr->SiS_HDE;
+     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
+     tempbx |= ((tempax >> 8) & 0x1F);
+     tempcx = tempax >> 13;
   }
 
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,(tempbx >> 8));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
-     temp = tempcx & 0x0007;
-     if(tempbx & 0x2000) temp = 0;
-     if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
-        temp |= 0x18;
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp);
+     tempcx &= 0x07;
+     if(tempbx & 0x20) tempcx = 0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
 
      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
         tempbx = 0x0382;
@@ -7233,7 +7032,7 @@
      }
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
-     temp = (tempcx & 0x0300) >> (8 - 2);
+     temp = (tempcx & 0x0300) >> 6;
      temp |= ((tempbx >> 8) & 0x03);
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
         temp |= 0x10;
@@ -7243,7 +7042,7 @@
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
 
      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3));
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
 
      SiS_SetTVSpecial(SiS_Pr, ModeNo);
 
@@ -7258,7 +7057,7 @@
   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp - 1);
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
      }
      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
   }
@@ -7277,8 +7076,7 @@
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   tempbx--;			         	/* RHACTE = HDE - 1 */
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
-  temp = (tempbx & 0xFF00) >> 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
 
   temp = 0x01;
   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
@@ -7297,21 +7095,17 @@
 
   tempbx = SiS_Pr->SiS_VDE - 1;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
-  temp = ((tempbx & 0xFF00) >> 8) & 0x07;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
 
   tempcx = SiS_Pr->SiS_VT - 1;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
-
-  temp = ((tempcx & 0xFF00) >> 8) << 5;
-
-  /* Enable dithering; only do this for 32bpp mode */
+  temp = (tempcx >> 3) & 0xE0;    
   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+     /* Enable dithering; only do this for 32bpp mode */
      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
         temp |= 0x10;
      }
   }
-
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
 
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
@@ -7380,7 +7174,7 @@
        tempbx -= tempax; /* lcdvdee */
     }
 
-    /* Non-expanding: lcdvdees = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
@@ -7389,8 +7183,8 @@
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 3;
-    temp |= ((tempcx & 0xFF00) >> 8);
+    temp = (tempbx >> 5) & 0x38;
+    temp |= ((tempcx >> 8) & 0x07);
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
     tempax = SiS_Pr->SiS_VDE;
@@ -7412,7 +7206,10 @@
 	     if(tempax % 4) { tempax >>= 2; tempax++; }
 	     else           { tempax >>= 2;           }
              tempbx -= (tempax - 1);
-	  } else tempbx -= 10;
+	  } else {
+	     tempbx -= 10;
+	     if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
+	  }
        }
     }
     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
@@ -7437,9 +7234,9 @@
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 4;
+    temp = (tempbx >> 4) & 0xF0;
     tempbx += (tempcx + 1);
-    temp |= (tempbx & 0x000F);
+    temp |= (tempbx & 0x0F);
 
     if(SiS_Pr->UseCustomMode) {
        temp &= 0xf0;
@@ -7469,9 +7266,8 @@
        }
     }
     temp += bridgeoffset;
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	    /* lcdhdes[7:0] */
-    temp = (temp >> 4) & 0xf0;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,temp);  /* lcdhdes [11:8] */
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	     /* lcdhdes */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
 
     tempcx = SiS_Pr->SiS_HT;
     tempax = tempbx = SiS_Pr->SiS_HDE;
@@ -7494,8 +7290,7 @@
     tempbx += bridgeoffset;
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
-    temp = (tempbx >> 8) & 0x0f;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
 
     tempcx = (tempcx - tempax) >> 2;
 
@@ -7521,8 +7316,7 @@
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
-    temp = (tempbx & 0x0F00) >> 4;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
 
     tempbx = push2;
 
@@ -7646,7 +7440,8 @@
 {
    USHORT temp, temp1, resinfo = 0;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
 
    if(ModeNo > 0x13) {
       resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
@@ -7737,7 +7532,7 @@
 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   	      USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempcx,tempbx,modeflag,temp,temp2,resinfo;
+  USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
   ULONG tempebx,tempeax,templong;
 
   if(ModeNo <= 0x13) {
@@ -7783,167 +7578,138 @@
      }
   }
 
-  temp = SiS_Pr->SiS_RVBHCFACT;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
 
   tempbx = SiS_Pr->SiS_RVBHCMAX;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
 
-  temp2 = (tempbx >> 1) & 0x0080;
+  temp = (tempbx >> 1) & 0x80;
 
   tempcx = SiS_Pr->SiS_VGAHT - 1;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
 
-  temp2 |= (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
+  temp |= ((tempcx >> 5) & 0x78);
 
   tempcx = SiS_Pr->SiS_VGAVT - 1;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
 
-  temp = temp2 | (tempcx >> 8);
+  temp |= ((tempcx >> 8) & 0x07);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK) tempbx >>= 1;
-  if(HwInfo->jChipType >= SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-  }
-
-  temp = 0xA0;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+  if(modeflag & HalfDCLK)            tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+    
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
      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(tempbx > 800)        temp = 0x60;
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     temp = 0;
+     if(tempbx == 1024)      temp = 0xA0;
+     else if(tempbx > 1024)  temp = 0xC0;
+  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+     temp = 0;
+     if(tempbx >= 1280)      temp = 0x40;
+     else if(tempbx >= 1024) temp = 0x20;
   } else {
      temp = 0x80;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        temp = 0;
-        if(tempbx > 800) temp = 0x60;
-     }
-  }
-
-  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-     temp = 0;
-     if(SiS_Pr->SiS_VGAHDE == 1024) temp = 0x20;
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp = 0;
+     if(tempbx >= 1024)      temp = 0xA0;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
-        temp |= 0x0A;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
   }
 
   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
-
+  
+  tempeax = SiS_Pr->SiS_VGAVDE;  
   tempebx = SiS_Pr->SiS_VDE;
-
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(!(temp & 0xE0)) tempebx >>=1;
-  }
-
+  }  
+  
   tempcx = SiS_Pr->SiS_RVBHRS;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,temp);
-
-  tempeax = SiS_Pr->SiS_VGAVDE;
-  tempcx |= 0x4000;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
+  tempcx >>= 8;
+  tempcx |= 0x40;
+  
   if(tempeax <= tempebx) {
-     tempcx ^= 0x4000;
+     tempcx ^= 0x40;
   } else {
      tempeax -= tempebx;
   }
 
-  templong = (tempeax * 256 * 1024) % tempebx;
-  tempeax = (tempeax * 256 * 1024) / tempebx;
-  tempebx = tempeax;
-  if(templong != 0) tempebx++;
+  tempeax *= (256 * 1024);
+  templong = tempeax % tempebx;
+  tempeax /= tempebx;
+  if(templong) tempeax++;
 
-  temp = (USHORT)(tempebx & 0x000000FF);
+  temp = (USHORT)(tempeax & 0x000000FF);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
-  temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+  temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
-
-  tempbx = (USHORT)(tempebx >> 16);
-  temp = tempbx & 0x00FF;
-  temp <<= 4;
-  temp |= ((tempcx & 0xFF00) >> 8);
+  temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+  temp |= (tempcx & 0x4F);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
 
+     /* Calc Linebuffer max address and set/clear decimode */
      tempbx = 0;
+     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
      tempax = SiS_Pr->SiS_VGAHDE;
-     if(modeflag & HalfDCLK) 		tempax >>= 1;
+     if(modeflag & HalfDCLK)            tempax >>= 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	if(tempax > 800) tempax -= 800;
-     } else /* if(SiS_Pr->SiS_VBInfo & TvNoHiviNoYPbPr) */ {    /* 651+301C */
-        if(tempax > 800) {
-	   tempbx = 8;
+     if(tempax > 800) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   tempax -= 800;
+	} else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
+	   tempbx = 0x08;
            if(tempax == 1024) tempax *= 25;
            else	              tempax *= 20;
 	   temp = tempax % 32;
 	   tempax /= 32;
-	   tempax--;
-	   if (temp!=0) tempax++;
-        }
-     }
+	   if(temp) tempax++;
+	   tempax++;
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) || 
+	      (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
+	      if(resinfo == SIS_RI_1024x768) {
+	         /* Otherwise white line at right edge */
+	         tempax = (tempax & 0xff00) | 0x20;
+	      }
+	   }
+	}
+     }    
      tempax--;
-     temp = ((tempax & 0xFF00) >> 8) & 0x03;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) {	/* From 1.10.7w */
-	if(ModeNo > 0x13) {					/* From 1.10.7w */
-	   if(resinfo == SIS_RI_1024x768) tempax = 0x1f;	/* From 1.10.7w */
-	   /* ax normally 0x1e */				/* From 1.10.7w */
-	}							/* From 1.10.7w */
-     }								/* From 1.10.7w */
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF);
-     temp <<= 4;
-     temp |= tempbx;
+     temp = ((tempax >> 4) & 0x30) | tempbx;    
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	if(IS_SIS550650740660) {
-	   temp = 0x0026;  /* 1.10.7w; 1.10.8r; needs corresponding code in Dis/EnableBridge! */
-	} else {
-	   temp = 0x0036;
-	}
-     } else {
-	temp = 0x0036;
+     temp = 0x0036; tempbx = 0xD0;
+     if((IS_SIS550650740660) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+	temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
      }
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
 	   temp |= 0x01;
 	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-  	         temp &= 0xFE;
+  	         temp &= ~0x01;
 	      }
 	   }
 	}
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
 
-     tempbx = SiS_Pr->SiS_HT;
+     tempbx = SiS_Pr->SiS_HT >> 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-     tempbx >>= 1;
      tempbx -= 2;
-     temp = ((tempbx & 0x0700) >> 8) << 3;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
+     temp = (tempbx >> 5) & 0x38;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,temp);
 
      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
@@ -9881,7 +9647,7 @@
 	        }
 	        break;
 	    case 1280:
-	        if(yres == 1024) {
+	        if(yres == 1024) {	
 	     	   paneltype = Panel_1280x1024;
 		   checkexpand = TRUE;
 	        } else if(yres == 960) {
@@ -10328,14 +10094,17 @@
        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;
        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
        cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf3,cr37);
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
        SiS_Pr->PanelSelfDetected = TRUE;
 #ifdef TWDEBUG
        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
-       	"CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
+       	   "CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
 #endif	
+   } else {
+       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
    }
    return 0;
 }
@@ -10944,6 +10713,7 @@
            delay = SiS310_LCDDelayCompensation_301[myindex];
 	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	      if(IS_SIS740) delay = 0x01;
+	      else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
 	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
 	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
 	      if(IS_SIS740) delay = 0x01;  /* ? */
@@ -11329,7 +11099,9 @@
          }
 	 if(index < 25) index = 25;
          index = ((index / 25) - 1) << 1;
-         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) index++;
+         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
+	    index++;
+	 }
 	 romptr = SISGETROMW(0x104);  /* 0x4ae */
          delay = ROMAddr[romptr + index];
          if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
@@ -11386,16 +11158,18 @@
             } else
 	       delay = 0x0000;
          }
+	 
+	 /* Override by detected or user-set values */
+	 /* (but only if, for some reason, we can't read value from BIOS) */
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
+            delay = SiS_Pr->PDC & 0x1f;
+         }
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
+            delay = (SiS_Pr->PDCA & 0x1f) << 8;
+         }
 
       }
-
-      /* Override by detected or user-set values */
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
-         delay = SiS_Pr->PDC & 0x1f;
-      }
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
-         delay = (SiS_Pr->PDCA & 0x1f) << 8;
-      }
+     
    }
 
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -11477,8 +11251,10 @@
 	    }
 	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
          }
-         temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
+	 }
       }
 
    }
diff -urN linux-2.4.27-pre5/drivers/video/sis/init301.h linux-2.4.27-pre6/drivers/video/sis/init301.h
--- linux-2.4.27-pre5/drivers/video/sis/init301.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/init301.h	2004-06-16 11:33:28.743112519 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init301.c
  *
@@ -88,8 +89,8 @@
     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,0x8d /*0x9d*/,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50 /*0x53*/,
+    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
@@ -217,49 +218,44 @@
     0x00,0x04,
     0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
     0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D /* 0x7D? */ ,0x7C,0x0D,0x18,0x7F,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D /* 0x1D(6330)? */ ,0x7C,0x0D,0x18,0x7F,
     0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
     0xFF,0xFF,
 };
 
-
 #ifdef SIS315H
-/* 661 et al LCD data structure */
+/* 661 et al LCD data structure (0.94.0) */
 static const UCHAR SiS_LCDStruct661[] = {
     /* 1024x768 */
 /*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
     0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
-    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x37,0x6E,0x05,0x6E,0x04,
+    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
     /*  | vss      |   vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
     /*					      VESA    non-VESA  noscale */
     /* 1280x1024 */
-    0x03,0xE0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x5F,0x6F,0xDB,0x6F,0x08,
+    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
     /* 1400x1050 */
     0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x35,0x70,0x00,0x00,0x09,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
     /* 1600x1200 */
-    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
-    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x07,0x71,0x00,0x00,0x0B,
+    0x0B,0xC0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0B,
     /* 1280x768 */
     0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x05,0x26,0x03,0x10,0x00,0x40,
-    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0xEB,0x6E,0xA5,0x6E,0x06,
+    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0x00,0x00,0x00,0x00,0x06,
     /* 1280x720 */
-    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x40,0x05,0x26,0x03,0x10,0x00,0x02,
-    0x00,0x01,0x00,0x06,0x00,0x41,0x5A,0x64,0x69,0x6E,0x00,0x00,0x05,
-#if 0 /* 0.92: */
-    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x72,0x06,0xEE,0x02,0x2A,0x00,0x3F,
-    0x00,0x01,0x00,0x06,0x00,0x41,0x00,0x00,0xA7,0x6A,0x00,0x00,0x05,
-#endif
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x02,
+    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
     /* 1280x800 */
-    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x15,0x00,0x18,
-    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x31,0x6F,0x00,0x00,0x07,
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x10,0x00,0x40,
+    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x07,
     /* 1680x1050 */
     0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
-    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x99,0x70,0x00,0x00,0x0A, /* 0.93: 0x0A=0x06 - WRONG? */
+    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06, 
     /* 1280x768 (not in 0.93) */
     0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x06,0x1E,0x03,0x40,0x00,0x80,
-    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x6F,0x6B,0x00,0x00,0x06
+    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x00,0x00,0x00,0x00,0x06
 };
 #endif
 
@@ -347,46 +343,45 @@
 static  BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
 #endif
 
-
-USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-void     SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStart(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStop(SiS_Private *SiS_Pr);
-void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT   SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-USHORT   SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-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_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, USHORT DDCdatatype, unsigned char *buffer);
-USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-		       USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
+USHORT  SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
+void    SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStart(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStop(SiS_Private *SiS_Pr);
+void    SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
+USHORT  SiS_SetSCLKLow(SiS_Private *SiS_Pr);
+USHORT  SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
+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_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, 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);
+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_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex);
-void     SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-void     SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+void    SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex);
+void    SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
+void    SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
 #endif
 #ifdef SIS300
-void     SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-void     SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-			USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+void    SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
+void    SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+		       USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
 #endif
 
 extern void     SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
diff -urN linux-2.4.27-pre5/drivers/video/sis/initdef.h linux-2.4.27-pre6/drivers/video/sis/initdef.h
--- linux-2.4.27-pre5/drivers/video/sis/initdef.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/initdef.h	2004-06-16 11:33:28.743112519 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Global definitions for init.c and init301.c
  *
@@ -84,6 +85,8 @@
 #define VB_SIS301B302B          (VB_SIS301B|VB_SIS301C|VB_SIS302B)
 #define VB_SIS301LV302LV        (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
 #define VB_SISVB		(VB_SIS301 | VB_SIS301BLV302BLV)
+#define VB_SISTMDS		(VB_SIS301 | VB_SIS301B302B)
+#define VB_SISLVDS		VB_SIS301LV302LV
 
 /* VBInfo */
 #define SetSimuScanMode         0x0001   /* CR 30 */
@@ -136,6 +139,7 @@
 #define CRT2Mode                0x0800
 #define HalfDCLK                0x1000
 #define NoSupportSimuTV         0x2000
+#define NoSupportLCDScale	0x4000 /* TMDS: No scaling possible (no matter what panel) */
 #define DoubleScanMode          0x8000
 
 /* Infoflag */
@@ -200,7 +204,7 @@
 #define SF_IsM661		0x0020
 #define SF_IsM741		0x0040
 #define SF_IsM760		0x0080
-#define SF_760UMA		0x8000
+#define SF_760LFB		0x8000  /* 760: We have LFB */
 
 /* CR32 (Newer 630, and 315 series)
 
@@ -478,13 +482,23 @@
 #define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
 #define VCLK34_315              0x55
 #define VCLK68_315		0x0d
-#define VCLK69_315		0x5c   /* Index in VBVCLKData table (315) */
+#define VCLK69_315		0x5c   /* deprecated ! Index in VBVCLKData table (315) */
+#define VCLK83_315		0x5c   /* Index in VBVCLKData table (315) */
 #define VCLK121_315		0x5d   /* Index in VBVCLKData table (315) */
 #define VCLK_1280x720		0x5f
 #define VCLK_1280x768_2		0x60
 #define VCLK_1280x768_3		0x61
 #define VCLK_CUSTOM_315		0x62
 #define VCLK_1280x720_2		0x63
+#define VCLK_720x480		0x67 
+#define VCLK_720x576		0x68
+#define VCLK_768x576		0x68
+#define VCLK_848x480		0x65
+#define VCLK_856x480		0x66
+#define VCLK_800x480		0x65
+#define VCLK_1024x576		0x51
+#define VCLK_1152x864		0x64
+#define VCLK_1360x768		0x58
 
 #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) */
@@ -595,7 +609,7 @@
 
 /*
   =============================================================
-   			  for 315 series
+   		  for 315 series (old data layout)
   =============================================================
 */
 #define SoftDRAMType        0x80
diff -urN linux-2.4.27-pre5/drivers/video/sis/oem300.h linux-2.4.27-pre6/drivers/video/sis/oem300.h
--- linux-2.4.27-pre5/drivers/video/sis/oem300.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/oem300.h	2004-06-16 11:33:28.744112560 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 300 series
  *
diff -urN linux-2.4.27-pre5/drivers/video/sis/oem310.h linux-2.4.27-pre6/drivers/video/sis/oem310.h
--- linux-2.4.27-pre5/drivers/video/sis/oem310.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/oem310.h	2004-06-16 11:33:28.744112560 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 315/330 series
  *
@@ -126,7 +127,7 @@
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
+static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB */
 {
 		 0x01,0x01,0x01,    /*   800x600 */
 		 0x0C,0x0C,0x0C,    /*  1024x768 */
@@ -145,6 +146,25 @@
 		 0x02,0x02,0x02
 };
 
+static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] =	   	/* 315+30xLV */
+{
+		 0x01,0x01,0x01,    /*   800x600 */
+		 0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+		 0x0C,0x0C,0x0C,    /* 1280x1024 */
+                 0x08,0x08,0x08,    /*   640x480 */
+		 0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02
+};
+
 static const UCHAR SiS310_TVDelayCompensation_301[] = 		/* 301 */
 {
 		 0x02,0x02,    /* NTSC Enhanced, Standard */
diff -urN linux-2.4.27-pre5/drivers/video/sis/osdef.h linux-2.4.27-pre6/drivers/video/sis/osdef.h
--- linux-2.4.27-pre5/drivers/video/sis/osdef.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/osdef.h	2004-06-16 11:33:28.745112602 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OS depending defines
  *
@@ -84,7 +85,6 @@
 
 #ifdef LINUX_KERNEL
 #include <linux/config.h>
-#include <linux/version.h>
 
 #ifdef CONFIG_FB_SIS_300
 #define SIS300
@@ -94,10 +94,6 @@
 #define SIS315H
 #endif
 
-#if 1
-#define SISFBACCEL	/* Include 2D acceleration */
-#endif
-
 #define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
 #define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
 #define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
@@ -108,7 +104,7 @@
 #endif
 
 /**********************************************************************/
-/*  XFree86                                                           */
+/*  XFree86, X.org                                                    */
 /**********************************************************************/
 
 #ifdef LINUX_XF86
diff -urN linux-2.4.27-pre5/drivers/video/sis/sis.h linux-2.4.27-pre6/drivers/video/sis/sis.h
--- linux-2.4.27-pre5/drivers/video/sis/sis.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.27-pre6/drivers/video/sis/sis.h	2004-06-16 11:33:28.746112643 -0700
@@ -1,10 +1,512 @@
+/*
+ * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ *
+ * 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 named License,
+ * or 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
+ */
+
 #ifndef _SIS_H
 #define _SIS_H
 
-#if 1
-#define TWDEBUG(x)
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include "osdef.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/sisfb.h>
 #else
+#include <linux/sisfb.h>
+#endif
+
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#define VER_MAJOR                 1
+#define VER_MINOR                 7
+#define VER_LEVEL                 10
+
+#undef SIS_CONFIG_COMPAT
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/spinlock.h>
+#ifdef CONFIG_COMPAT
+#include <linux/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__
+/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#include <asm/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#endif
+
+#undef SISFBDEBUG
+
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #define TWDEBUG(x) printk(KERN_INFO x "\n");
+#else
+#define DPRINTK(fmt, args...)
+#define TWDEBUG(x)
+#endif
+
+#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+/* To be included in pci_ids.h */
+#ifndef PCI_DEVICE_ID_SI_650_VGA
+#define PCI_DEVICE_ID_SI_650_VGA  0x6325
+#endif
+#ifndef PCI_DEVICE_ID_SI_650
+#define PCI_DEVICE_ID_SI_650      0x0650
+#endif
+#ifndef PCI_DEVICE_ID_SI_651
+#define PCI_DEVICE_ID_SI_651      0x0651
 #endif
+#ifndef PCI_DEVICE_ID_SI_740
+#define PCI_DEVICE_ID_SI_740      0x0740
+#endif
+#ifndef PCI_DEVICE_ID_SI_330
+#define PCI_DEVICE_ID_SI_330      0x0330
+#endif
+#ifndef PCI_DEVICE_ID_SI_660_VGA
+#define PCI_DEVICE_ID_SI_660_VGA  0x6330
+#endif
+#ifndef PCI_DEVICE_ID_SI_661
+#define PCI_DEVICE_ID_SI_661      0x0661
+#endif
+#ifndef PCI_DEVICE_ID_SI_741
+#define PCI_DEVICE_ID_SI_741      0x0741
+#endif
+#ifndef PCI_DEVICE_ID_SI_660
+#define PCI_DEVICE_ID_SI_660      0x0660
+#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, 65x, 740, 661, 741  */
+#endif
+#ifndef FB_ACCEL_SIS_XABRE
+#define FB_ACCEL_SIS_XABRE        41	/* SiS 330 ("Xabre"), 760 	*/
+#endif
+
+#define MAX_ROM_SCAN              0x10000
+
+/* ivideo->caps */
+#define HW_CURSOR_CAP             0x80
+#define TURBO_QUEUE_CAP           0x40
+#define AGP_CMD_QUEUE_CAP         0x20
+#define VM_CMD_QUEUE_CAP          0x10
+#define MMIO_CMD_QUEUE_CAP        0x08
+
+/* For 300 series */
+#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
+#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
+
+/* For 315/Xabre series */
+#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
+#define COMMAND_QUEUE_THRESHOLD   0x1F
+#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
+
+#define SIS_OH_ALLOC_SIZE         4000
+#define SENTINEL                  0x7fffffff
+
+#define SEQ_ADR                   0x14
+#define SEQ_DATA                  0x15
+#define DAC_ADR                   0x18
+#define DAC_DATA                  0x19
+#define CRTC_ADR                  0x24
+#define CRTC_DATA                 0x25
+#define DAC2_ADR                  (0x16-0x30)
+#define DAC2_DATA                 (0x17-0x30)
+#define VB_PART1_ADR              (0x04-0x30)
+#define VB_PART1_DATA             (0x05-0x30)
+#define VB_PART2_ADR              (0x10-0x30)
+#define VB_PART2_DATA             (0x11-0x30)
+#define VB_PART3_ADR              (0x12-0x30)
+#define VB_PART3_DATA             (0x13-0x30)
+#define VB_PART4_ADR              (0x14-0x30)
+#define VB_PART4_DATA             (0x15-0x30)
+
+#define SISSR			  ivideo->SiS_Pr.SiS_P3c4
+#define SISCR                     ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA                   ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD                   ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1                  ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2                  ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3                  ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4                  ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5                  ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A                  SISPART5
+#define SISDAC2D                  (SISPART5 + 1)
+#define SISMISCR                  (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW                  ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT		  (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL			  ivideo->SiS_Pr.SiS_P3c6
+
+#define IND_SIS_PASSWORD          0x05  /* SRs */
+#define IND_SIS_COLOR_MODE        0x06
+#define IND_SIS_RAMDAC_CONTROL    0x07
+#define IND_SIS_DRAM_SIZE         0x14
+#define IND_SIS_MODULE_ENABLE     0x1E
+#define IND_SIS_PCI_ADDRESS_SET   0x20
+#define IND_SIS_TURBOQUEUE_ADR    0x26
+#define IND_SIS_TURBOQUEUE_SET    0x27
+#define IND_SIS_POWER_ON_TRAP     0x38
+#define IND_SIS_POWER_ON_TRAP2    0x39
+#define IND_SIS_CMDQUEUE_SET      0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
+
+#define IND_SIS_AGP_IO_PAD        0x48
+
+#define SIS_CRT2_WENABLE_300 	  0x24  /* Part1 */
+#define SIS_CRT2_WENABLE_315 	  0x2F
+
+#define SIS_PASSWORD              0x86  /* SR05 */
+#define SIS_INTERLACED_MODE       0x20  /* SR06 */
+#define SIS_8BPP_COLOR_MODE       0x0
+#define SIS_15BPP_COLOR_MODE      0x1 
+#define SIS_16BPP_COLOR_MODE      0x2 
+#define SIS_32BPP_COLOR_MODE      0x4 
+
+#define SIS_ENABLE_2D             0x40  /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
+#define SIS_PCI_ADDR_ENABLE       0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/330 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
+#define SIS_MMIO_CMD_ENABLE       0x20
+#define SIS_CMD_QUEUE_SIZE_512k   0x00
+#define SIS_CMD_QUEUE_SIZE_1M     0x04
+#define SIS_CMD_QUEUE_SIZE_2M     0x08
+#define SIS_CMD_QUEUE_SIZE_4M     0x0C
+#define SIS_CMD_QUEUE_RESET       0x01
+#define SIS_CMD_AUTO_CORR	  0x02
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
+#define SIS_MODE_SELECT_CRT2      0x02
+#define SIS_VB_OUTPUT_COMPOSITE   0x04
+#define SIS_VB_OUTPUT_SVIDEO      0x08
+#define SIS_VB_OUTPUT_SCART       0x10
+#define SIS_VB_OUTPUT_LCD         0x20
+#define SIS_VB_OUTPUT_CRT2        0x40
+#define SIS_VB_OUTPUT_HIVISION    0x80
+
+#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
+#define SIS_DRIVER_MODE           0x40
+
+#define SIS_VB_COMPOSITE          0x01  /* CR32 */
+#define SIS_VB_SVIDEO             0x02
+#define SIS_VB_SCART              0x04
+#define SIS_VB_LCD                0x08
+#define SIS_VB_CRT2               0x10
+#define SIS_CRT1                  0x20
+#define SIS_VB_HIVISION           0x40
+#define SIS_VB_YPBPR              0x80
+#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+                                   SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS             0x02  
+#define SIS_EXTERNAL_CHIP_TRUMPION         0x03  
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  
+#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05  
+#define SIS310_EXTERNAL_CHIP_LVDS          0x02  
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  
+
+#define SIS_AGP_2X                0x20  /* CR48 */
+
+#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
+#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
+
+/* Useful macros */
+#define inSISREG(base)          inb(base)
+#define outSISREG(base,val)     outb(val,base)
+#define orSISREG(base,val)      do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp | (val)); \
+                                } while (0)
+#define andSISREG(base,val)     do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp & (val)); \
+                                } while (0)
+#define inSISIDXREG(base,idx,var)   do { \
+                                      outb(idx,base); var=inb((base)+1); \
+                                    } while (0)
+#define outSISIDXREG(base,idx,val)  do { \
+                                      outb(idx,base); outb((val),(base)+1); \
+                                    } while (0)
+#define orSISIDXREG(base,idx,val)   do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)|(val); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define andSISIDXREG(base,idx,and)  do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)&(and); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define setSISIDXREG(base,idx,and,or)   do { \
+                                          u8 __Temp; \
+                                          outb(idx,base);   \
+                                          __Temp = (inb((base)+1)&(and))|(or); \
+                                          outSISIDXREG(base,idx,__Temp); \
+                                        } while (0)
+
+/* MMIO access macros */
+#define MMIO_IN8(base, offset)  readb((base+offset))
+#define MMIO_IN16(base, offset) readw((base+offset))
+#define MMIO_IN32(base, offset) readl((base+offset))
+
+#define MMIO_OUT8(base, offset, val)  writeb(((u8)(val)), (base+offset))
+#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset))
+#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset))
+
+/* Queue control MMIO registers */
+#define Q_BASE_ADDR		0x85C0  /* Base address of software queue */
+#define Q_WRITE_PTR		0x85C4  /* Current write pointer */
+#define Q_READ_PTR		0x85C8  /* Current read pointer */
+#define Q_STATUS		0x85CC  /* queue status */
+
+#define MMIO_QUEUE_PHYBASE      Q_BASE_ADDR
+#define MMIO_QUEUE_WRITEPORT    Q_WRITE_PTR
+#define MMIO_QUEUE_READPORT     Q_READ_PTR
+
+#if !defined(__i386__) && !defined(__x86_64__)
+#ifndef ioremap_nocache
+#define ioremap_nocache(X, Y) ioremap(X, Y)
+#endif
+#endif
+					
+enum _SIS_CMDTYPE {
+	MMIO_CMD = 0,
+	AGP_CMD_QUEUE,
+	VM_CMD_QUEUE,
+};
+typedef unsigned int SIS_CMDTYPE;
+
+/* Our "par" */
+struct sis_video_info {
+	int		cardnumber;
+	struct fb_info  *memyselfandi;
+	
+	SIS_HW_INFO 	sishw_ext;	
+	SiS_Private  	SiS_Pr;	
+	
+	sisfb_info 	sisfbinfo;	/* For ioctl SISFB_GET_INFO */
+	
+	struct fb_var_screeninfo default_var;
+	
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct fb_fix_screeninfo sisfb_fix;
+	u32 		pseudo_palette[17];
+#endif	
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	struct display 		 sis_disp;
+	struct display_switch 	 sisfb_sw;	
+	struct { 
+		u16 red, green, blue, pad; 
+	} 		sis_palette[256];
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cfb32[16];
+#endif
+	} 		sis_fbcon_cmap;
+#endif	
+
+        struct sisfb_monitor {
+		u16 hmin;
+		u16 hmax;
+		u16 vmin;
+		u16 vmax;
+		u32 dclockmax;
+		u8  feature;
+		BOOLEAN datavalid;
+	} 		sisfb_thismonitor;
+	
+	int           	chip_id;
+	char		myid[40];
+	
+	struct pci_dev  *nbridge;
+	
+	int		mni;	/* Mode number index */
+	
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	int  		currcon;
+#endif	
+
+	unsigned long	video_size;
+	unsigned long 	video_base;
+	unsigned long	mmio_size;
+	unsigned long 	mmio_base;
+	unsigned long 	vga_base;
+	
+	unsigned long  	video_vbase;
+	unsigned long 	mmio_vbase;
+	char  *	      	bios_vbase;
+	char  *	      	bios_abase;
+	
+	int 		mtrr;
+	
+	u32		sisfb_mem;
+	
+	u32 		sisfb_parm_mem;
+	int 	   	sisfb_accel;
+	int 		sisfb_ypan;
+	int 		sisfb_max;
+	int 		sisfb_userom;
+	int 		sisfb_useoem;
+	int		sisfb_mode_idx;
+	int		sisfb_parm_rate;
+	int		sisfb_crt1off;
+	int		sisfb_forcecrt1;
+	int		sisfb_crt2type;
+	int		sisfb_crt2flags;
+	int 		sisfb_dstn;
+	int 		sisfb_fstn;
+	int		sisfb_tvplug;
+	int		sisfb_tvstd;
+	int		sisfb_filter;
+	int		sisfb_nocrt2rate;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	int		sisfb_inverse;
+#endif	
+	
+	u32 		heapstart;        /* offset  */
+	unsigned long  	sisfb_heap_start; /* address */
+	unsigned long  	sisfb_heap_end;   /* address */
+	u32 	      	sisfb_heap_size;
+	int		havenoheap;
+#if 0	
+	SIS_HEAP       	sisfb_heap;
+#endif	
+	
+
+	int    		video_bpp;
+	int    		video_cmap_len;
+	int    		video_width;
+	int    		video_height;
+	int    		video_vwidth;		/* DEPRECATED - use var instead */
+	int    		video_vheight;		/* DEPRECATED - use var instead */
+	int    		org_x;			/* DEPRECATED - use var instead */
+	int    		org_y;			/* DEPRECATED - use var instead */
+	int    		video_linelength;
+	unsigned int 	refresh_rate;
+
+	unsigned int 	chip;
+	u8   		revision_id;
+
+        u16 		DstColor;		/* For 2d acceleration */
+	u32  		SiS310_AccelDepth;
+	u32  		CommandReg;
+	int		cmdqueuelength;
+
+	spinlock_t     	lockaccel;		/* Do not use outside of kernel! */
+
+        unsigned int   	pcibus;
+	unsigned int   	pcislot;
+	unsigned int   	pcifunc;
+
+	int 	       	accel;
+
+	u16 		subsysvendor;
+	u16 		subsysdevice;
+
+	u32  		vbflags;		/* Replacing deprecated stuff from above */
+	u32  		currentvbflags;
+	
+	int		lcdxres, lcdyres;
+	int		lcddefmodeidx, tvdefmodeidx, defmodeidx;
+
+	int    		current_bpp;
+	int    		current_width;
+	int    		current_height;
+	int    		current_htotal;
+	int    		current_vtotal;
+	__u32  		current_pixclock;
+	int    		current_refresh_rate;
+	
+	u8  		mode_no;
+	u8  		rate_idx;
+	int    		modechanged;
+	unsigned char 	modeprechange;
+	
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	u8 		sisfb_lastrates[128];
+#endif
+	
+	int  		newrom;
+	int  		registered;
+#ifdef SIS_CONFIG_COMPAT
+	int		ioctl32registered;
+	int		ioctl32vblankregistered;
+#endif	
+	
+	int 		sisvga_engine;
+	int 		hwcursor_size;
+	int 		CRT2_write_enable;
+	u8            	caps;
+	
+	u8 		detectedpdc;
+	u8 		detectedpdca;
+	u8 		detectedlcda;
+	
+	unsigned long 	hwcursor_vbase;
+	
+	int 		chronteltype;
+	int    		tvxpos, tvypos;
+	u8              p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+	int		tvx, tvy;
+	
+	u8 		sisfblocked;
+	
+	struct sis_video_info *next;
+};
+
+typedef struct _SIS_OH {
+	struct _SIS_OH *poh_next;
+	struct _SIS_OH *poh_prev;
+	u32            offset;
+	u32            size;
+} SIS_OH;
+
+typedef struct _SIS_OHALLOC {
+	struct _SIS_OHALLOC *poha_next;
+	SIS_OH aoh[1];
+} SIS_OHALLOC;
+
+typedef struct _SIS_HEAP {
+	SIS_OH      oh_free;
+	SIS_OH      oh_used;
+	SIS_OH      *poh_freelist;
+	SIS_OHALLOC *poha_chain;
+	u32         max_freesize;
+	struct sis_video_info *vinfo;
+} SIS_HEAP;
 
 #endif
diff -urN linux-2.4.27-pre5/drivers/video/sis/sis_accel.c linux-2.4.27-pre6/drivers/video/sis/sis_accel.c
--- linux-2.4.27-pre5/drivers/video/sis/sis_accel.c	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/sis_accel.c	2004-06-16 11:33:28.748112727 -0700
@@ -18,9 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
- * Based on the XFree86 driver's sis300_accel.c which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
- * and sis310_accel.c which is
+ * Based on the XFree86/X.org driver which is
  *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
  * Author: Thomas Winischhofer <thomas@winischhofer.net>
@@ -33,36 +31,16 @@
 #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/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
 #include <linux/selection.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
-
 #include <linux/types.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include <linux/sisfb.h>
-#else
-#include <video/sisfb.h>
-#endif
-
 #include <asm/io.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -71,16 +49,10 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "osdef.h"
-#include "vgatypes.h"
-#include "vstruct.h"
-#include "sis_accel.h"
 #include "sis.h"
+#include "sis_accel.h"
 
-extern struct   video_info ivideo;
-extern int 	sisfb_accel;
-
-static const int sisALUConv[] =
+static const u8 sisALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
@@ -100,7 +72,7 @@
     0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
 };
 /* same ROP but with Pattern as Source */
-static const int sisPatALUConv[] =
+static const u8 sisPatALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
@@ -121,26 +93,26 @@
 };
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-static const unsigned char myrops[] = {
+static const int myrops[] = {
    	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
-   };
+};
 #endif
 
 /* 300 series ----------------------------------------------------- */
 #ifdef CONFIG_FB_SIS_300
 static void
-SiS300Sync(void)
+SiS300Sync(struct sis_video_info *ivideo)
 {
 	SiS300Idle
 }
 
 static void
-SiS300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, 
+                                 int rop, int trans_color)
 {
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
-	SiS300SetupSRCPitch(ivideo.video_linelength)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
+	SiS300SetupSRCPitch(ivideo->video_linelength)
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
 
 	if(trans_color != -1) {
 		SiS300SetupROP(0x0A)
@@ -158,29 +130,28 @@
 }
 
 static void
-SiS300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, 
+				   int src_y, int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
+	u32 srcbase = 0, dstbase = 0;
 
-	srcbase = dstbase = 0;
-	if (src_y >= 2048) {
-		srcbase = ivideo.video_linelength * src_y;
+	if(src_y >= 2048) {
+		srcbase = ivideo->video_linelength * src_y;
 		src_y = 0;
 	}
-	if (dst_y >= 2048) {
-		dstbase = ivideo.video_linelength * dst_y;
+	if(dst_y >= 2048) {
+		dstbase = ivideo->video_linelength * dst_y;
 		dst_y = 0;
 	}
 
 	SiS300SetupSRCBase(srcbase);
 	SiS300SetupDSTBase(dstbase);
 
-	if(!(ivideo.CommandReg & X_INC))  {
+	if(!(ivideo->CommandReg & X_INC))  {
 		src_x += width-1;
 		dst_x += width-1;
 	}
-	if(!(ivideo.CommandReg & Y_INC))  {
+	if(!(ivideo->CommandReg & Y_INC))  {
 		src_y += height-1;
 		dst_y += height-1;
 	}
@@ -191,23 +162,22 @@
 }
 
 static void
-SiS300SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS300SetupPATFG(color)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
 	SiS300SetupROP(sisPatALUConv[rop])
 	SiS300SetupCMDFlag(PATFG)
 }
 
 static void
-SiS300SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS300SetupDSTBase(dstbase)
@@ -222,19 +192,18 @@
 
 #ifdef CONFIG_FB_SIS_315
 static void
-SiS310Sync(void)
+SiS310Sync(struct sis_video_info *ivideo)
 {
 	SiS310Idle
 }
 
 static void
-SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color)
 {
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
-	SiS310SetupSRCPitch(ivideo.video_linelength)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	if (trans_color != -1) {
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
+	SiS310SetupSRCPitch(ivideo->video_linelength)
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	if(trans_color != -1) {
 		SiS310SetupROP(0x0A)
 		SiS310SetupSRCTrans(trans_color)
 		SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
@@ -243,20 +212,17 @@
 		/* Set command - not needed, both 0 */
 		/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
 	}
-	SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
 	/* The 315 series is smart enough to know the direction */
 }
 
 static void
-SiS310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y,
+			 int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
-	int mymin, mymax;
-
-	srcbase = dstbase = 0;
-	mymin = min(src_y, dst_y);
-	mymax = max(src_y, dst_y);
+	u32 srcbase = 0, dstbase = 0;
+	int mymin = min(src_y, dst_y);
+	int mymax = max(src_y, dst_y);
 	
 	/* Although the chip knows the direction to use
 	 * if the source and destination areas overlap, 
@@ -270,18 +236,18 @@
 	 */
 	if((mymax - mymin) < height) { 
 	   if((src_y >= 2048) || (dst_y >= 2048)) {	      
-	      srcbase = ivideo.video_linelength * mymin;
-	      dstbase = ivideo.video_linelength * mymin;
+	      srcbase = ivideo->video_linelength * mymin;
+	      dstbase = ivideo->video_linelength * mymin;
 	      src_y -= mymin;
 	      dst_y -= mymin;
 	   }
 	} else {
 	   if(src_y >= 2048) {
-	      srcbase = ivideo.video_linelength * src_y;
+	      srcbase = ivideo->video_linelength * src_y;
 	      src_y = 0;
 	   }
 	   if(dst_y >= 2048) {
-	      dstbase = ivideo.video_linelength * dst_y;
+	      dstbase = ivideo->video_linelength * dst_y;
 	      dst_y = 0;
 	   }
 	}
@@ -295,23 +261,22 @@
 }
 
 static void
-SiS310SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS310SetupPATFG(color)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
 	SiS310SetupROP(sisPatALUConv[rop])
-	SiS310SetupCMDFlag(PATFG | ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
 }
 
 static void
-SiS310SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS310SetupDSTBase(dstbase)
@@ -326,23 +291,23 @@
 
 /* The exported routines */
 
-int sisfb_initaccel(void)
+int sisfb_initaccel(struct sis_video_info *ivideo)
 {
 #ifdef SISFB_USE_SPINLOCKS
-    spin_lock_init(&ivideo.lockaccel);
+    spin_lock_init(&ivideo->lockaccel);
 #endif
     return(0);
 }
 
-void sisfb_syncaccel(void)
+void sisfb_syncaccel(struct sis_video_info *ivideo)
 {
-    if(ivideo.sisvga_engine == SIS_300_VGA) {
+    if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-    	SiS300Sync();
+    	SiS300Sync(ivideo);
 #endif
     } else {
 #ifdef CONFIG_FB_SIS_315
-    	SiS310Sync();
+    	SiS310Sync(ivideo);
 #endif
     }
 }
@@ -351,18 +316,19 @@
 
 int fbcon_sis_sync(struct fb_info *info)
 {
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
    CRITFLAGS
 
-   if(!ivideo.accel)
+   if(!ivideo->accel)
    	return 0;
    
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
    CRITEND
@@ -371,42 +337,53 @@
 
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-   int col=0;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 col = 0; 
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width, height;
    CRITFLAGS
+   
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
 
-   TWDEBUG("Inside sis_fillrect");
-   if(!rect->width || !rect->height)
-   	return;
-
-   if(!ivideo.accel) {
+   if(!ivideo->accel) {
 	cfb_fillrect(info, rect);
 	return;
    }
    
+   if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
+	return;
+   }
+	
+   /* Clipping */
+   width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+   height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+   
    switch(info->var.bits_per_pixel) {
 	case 8:  col = rect->color;
 		 break;
-	case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
-		 break;
+	case 16: 
 	case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
 		 break;
    }
 
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
-      SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 
@@ -414,38 +391,58 @@
 
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-   int xdir, ydir;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width = area->width;
+   int height = area->height;
    CRITFLAGS
+   
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
 
-   TWDEBUG("Inside sis_copyarea");
-   if(!ivideo.accel) {
+   if(!ivideo->accel) {
    	cfb_copyarea(info, area);
 	return;
    }
-
-   if(!area->width || !area->height)
+   
+   if(!width || !height ||
+      area->sx >= vxres || area->sy >= vyres ||
+      area->dx >= vxres || area->dy >= vyres) {
    	return;
+   }
+   
+   /* Clipping */
+   if((area->sx + width) > vxres) width = vxres - area->sx;
+   if((area->dx + width) > vxres) width = vxres - area->dx;
+   if((area->sy + height) > vyres) height = vyres - area->sy;
+   if((area->dy + height) > vyres) height = vyres - area->dy;
 
-   if(area->sx < area->dx) xdir = 0;
-   else                    xdir = 1;
-   if(area->sy < area->dy) ydir = 0;
-   else                    ydir = 1;
-
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+      int xdir, ydir;
+      
+      if(area->sx < area->dx) xdir = 0;
+      else                    xdir = 1;
+      if(area->sy < area->dy) ydir = 0;
+      else                    ydir = 1;
+      
       CRITBEGIN
-      SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS300SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+      SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 
+      					 width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+      SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 
+      					 width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 }
@@ -457,11 +454,12 @@
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
 			    int dsty, int dstx, int height, int width)
 {
-        int xdir, ydir;
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
+        
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 8:
 #ifdef FBCON_HAS_CFB8
 	       fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
@@ -488,26 +486,28 @@
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(srcx < dstx) xdir = 0;
-	else            xdir = 1;
-	if(srcy < dsty) ydir = 0;
-	else            ydir = 1;
-
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+	   int xdir, ydir;
+	   
+	   if(srcx < dstx) xdir = 0;
+	   else            xdir = 1;
+	   if(srcy < dsty) ydir = 0;
+	   else            ydir = 1;
+	   
 	   CRITBEGIN
-	   SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS300SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+	   SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+	   SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -515,28 +515,29 @@
 static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width, int color)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
-
+	
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(color, 3, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS300SetupForSolidFill(ivideo, color, 3);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(color, 3, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS310SetupForSolidFill(ivideo, color, 3);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -544,9 +545,10 @@
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB8
 	    fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -560,8 +562,10 @@
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
-	if(!ivideo.accel) {
+	
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB16
 	    fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -575,9 +579,10 @@
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB32
 	    fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -590,10 +595,11 @@
 
 void fbcon_sis_revc(struct display *p, int srcx, int srcy)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 16:
 #ifdef FBCON_HAS_CFB16
 	       fbcon_cfb16_revc(p, srcx, srcy);
@@ -611,59 +617,59 @@
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(0, 0x0a, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS300SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(0, 0x0a, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS310SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
 
 #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
 
diff -urN linux-2.4.27-pre5/drivers/video/sis/sis_accel.h linux-2.4.27-pre6/drivers/video/sis/sis_accel.h
--- linux-2.4.27-pre5/drivers/video/sis/sis_accel.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/sis_accel.h	2004-06-16 11:33:28.749112768 -0700
@@ -36,8 +36,8 @@
 
 #ifdef SISFB_USE_SPINLOCKS
 #include <linux/spinlock.h>
-#define CRITBEGIN  spin_lock_irqsave(&ivideo.lockaccel), critflags);
-#define CRITEND	   spin_unlock_irqrestore(&ivideo.lockaccel), critflags);
+#define CRITBEGIN  spin_lock_irqsave(&ivideo->lockaccel, critflags);
+#define CRITEND	   spin_unlock_irqrestore(&ivideo->lockaccel, critflags);
 #define CRITFLAGS  unsigned long critflags;
 #else
 #define CRITBEGIN
@@ -65,7 +65,6 @@
 #define A3D_FUNCTION		0x00000008  /* 3D command ? */
 #define	CLEAR_Z_BUFFER		0x00000009  /* ? */
 #define GRADIENT_FILL		0x0000000A  /* Gradient fill */
-#define STRETCH_BITBLT		0x0000000B  /* Stretched Blit */
 
 /* source select */
 #define SRCVIDEO                0x00000000  /* source is video RAM */
@@ -98,11 +97,6 @@
 #define DSTAGP                  0x02000000
 #define DSTVIDEO                0x02000000
 
-/* Line */
-#define LINE_STYLE              0x00800000
-#define NO_RESET_COUNTER        0x00400000
-#define NO_LAST_PIXEL           0x00200000
-
 /* Subfunctions for Color/Enhanced Color Expansion (315 only) */
 #define COLOR_TO_MONO		0x00100000
 #define AA_TEXT			0x00200000
@@ -134,221 +128,142 @@
 
 #define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
 
-/* Line registers */
-#define LINE_X0			SRC_Y
-#define LINE_X1			DST_Y
-#define LINE_Y0			SRC_X
-#define LINE_Y1			DST_X
-#define LINE_COUNT		RECT_WIDTH
-#define LINE_STYLE_PERIOD	RECT_HEIGHT
-#define LINE_STYLE_0		MONO_MASK
-#define LINE_STYLE_1		0x8230
-#define LINE_XN			PATTERN_REG
-#define LINE_YN			PATTERN_REG+2
-
 /* Transparent bitblit registers */
 #define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
 #define TRANS_DST_KEY_LOW	PAT_BGCOLOR
 #define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
 #define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
 
-/* Queue */
-#define Q_BASE_ADDR		0x85C0  /* Base address of software queue (?) */
-#define Q_WRITE_PTR		0x85C4  /* Current write pointer (?) */
-#define Q_READ_PTR		0x85C8  /* Current read pointer (?) */
-#define Q_STATUS		0x85CC  /* queue status */
-
-#define MMIO_IN8(base, offset)  readb((base+offset))
-#define MMIO_IN16(base, offset) readw((base+offset))
-#define MMIO_IN32(base, offset) readl((base+offset))
-
-#define MMIO_OUT8(base, offset, val)  writeb((val), (base+offset))
-#define MMIO_OUT16(base, offset, val) writew((val), (base+offset))
-#define MMIO_OUT32(base, offset, val) writel((val), (base+offset))
-
-#if 0
-#define MMIO_IN8(base, offset) \
-	*(volatile u8 *)(((u8*)(base)) + (offset))
-#define MMIO_IN16(base, offset) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_IN32(base, offset) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_OUT8(base, offset, val) \
-	*(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT16(base, offset, val) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT32(base, offset, val) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#endif
+/* Store queue length in par */
+#define CmdQueLen ivideo->cmdqueuelength
 
 /* ------------- SiS 300 series -------------- */
 
-/* Macros to do useful things with the SIS BitBLT engine */
-
-/* BR(16) (0x8420):
+/* BR(16) (0x8240):
 
    bit 31 2D engine: 1 is idle,
    bit 30 3D engine: 1 is idle,
    bit 29 Command queue: 1 is empty
-
    bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
-
    bits 15:0:  Current command queue length
 
 */
 
-/* TW: BR(16)+2 = 0x8242 */
-
-int     CmdQueLen;
-
 #define SiS300Idle \
   { \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  CmdQueLen=MMIO_IN16(ivideo.mmio_vbase, 0x8240); \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \
   }
-/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
 
 #define SiS300SetupSRCBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(0), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCPitch(pitch) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1), pitch);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(4), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\
+	CmdQueLen--;
 
 #define SiS300SetupDSTXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTRect(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(5), (y)<<16 | (x) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTColorDepth(bpp) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1)+2, bpp);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\
+	CmdQueLen--;
 
 #define SiS300SetupRect(w,h) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(6), (h)<<16 | (w) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS300SetupPATFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(7), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\
+	CmdQueLen--;
 
 #define SiS300SetupPATBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(8), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(9), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(10), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\
+	CmdQueLen--;
 
 /* 0x8224 src colorkey high */
 /* 0x8228 src colorkey low */
 /* 0x821c dest colorkey high */
 /* 0x8220 dest colorkey low */
 #define SiS300SetupSRCTrans(color) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, 0x8224, color);\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8228, color);\
-		CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupDSTTrans(color) \
-		if (CmdQueLen <= 1)  SiS300Idle;\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x821C, color); \
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8220, color); \
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \
+	CmdQueLen -= 2;
 
 #define SiS300SetupMONOPAT(p0,p1) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), p0);\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), p1);\
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupClipLT(left,top) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS300SetupClipRB(right,bottom) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 /* General */
 #define SiS300SetupROP(rop) \
-                ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS300SetupCMDFlag(flags) \
-                ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS300DoCMD \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(15), ivideo.CommandReg); \
-                MMIO_OUT32(ivideo.mmio_vbase, BR(16), 0);\
-                CmdQueLen -= 2;
-
-/* Line */
-#define SiS300SetupX0Y0(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupX1Y1(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupLineCount(c) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6), c);\
-                CmdQueLen--;
-
-#define SiS300SetupStylePeriod(p) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6)+2, p);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleLow(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), ls);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleHigh(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), ls);\
-                CmdQueLen--;
-
-
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\
+	CmdQueLen -= 2;
 
-/* -------------- SiS 315 series --------------- */
+/* -------------- SiS 315/330 series --------------- */
 
 /* Q_STATUS:
    bit 31 = 1: All engines idle and all queues empty
@@ -362,179 +277,131 @@
    bits 23:16: 2D counter 3
    bits 15:8:  2D counter 2
    bits 7:0:   2D counter 1
-
-   Where is the command queue length (current amount of commands the queue
-   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 = 0; \
-  /*CmdQueLen = ((128 * 1024) / 4) - 64; */ \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	CmdQueLen = 0; \
   }
 
 #define SiS310SetupSRCBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCPitch(pitch) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, SRC_PITCH, pitch);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupDSTXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTRect(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTColorDepth(bpp) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, AGP_BASE, bpp);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\
+	CmdQueLen--;
 
 #define SiS310SetupRect(w,h) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS310SetupPATFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupPATBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupDSTTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_LOW, color); \
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \
+	CmdQueLen -= 2;
 
 #define SiS310SetupMONOPAT(p0,p1) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK, p0);\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK+4, p1);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupClipLT(left,top) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupClipRB(right,bottom) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupROP(rop) \
-      ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS310SetupCMDFlag(flags) \
-      ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS310DoCMD \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, COMMAND_READY, ivideo.CommandReg); \
-      MMIO_OUT32(ivideo.mmio_vbase, FIRE_TRIGGER, 0); \
-      CmdQueLen -= 2;
-
-#define SiS310SetupX0Y0(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupX1Y1(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupLineCount(c) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_COUNT, c);\
-      CmdQueLen--;
-
-#define SiS310SetupStylePeriod(p) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_STYLE_PERIOD, p);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleLow(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_0, ls);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleHigh(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_1, ls);\
-      CmdQueLen--;
-
-int  sisfb_initaccel(void);
-void sisfb_syncaccel(void);
-
-extern struct video_info ivideo;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \
+	CmdQueLen -= 2;
+
+      
+int  sisfb_initaccel(struct sis_video_info *ivideo);
+void sisfb_syncaccel(struct sis_video_info *ivideo);
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty,
-                     int dstx, int height, int width);
+			int dstx, int height, int width);
 void fbcon_sis_revc(struct display *p, int srcy, int srcx);
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy,
-                      int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-extern int sisfb_accel;
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
 #endif
diff -urN linux-2.4.27-pre5/drivers/video/sis/sis_main.c linux-2.4.27-pre6/drivers/video/sis/sis_main.c
--- linux-2.4.27-pre5/drivers/video/sis/sis_main.c	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/sis_main.c	2004-06-16 11:33:28.765113434 -0700
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/M741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -20,8 +21,8 @@
  *
  * Author:   	Thomas Winischhofer <thomas@winischhofer.net>
  *
- * Author of code base:
- *		SiS (www.sis.com.tw)
+ * Author of (practically wiped) code base:
+ *		SiS (www.sis.com)
  *	 	Copyright (C) 1999 Silicon Integrated Systems, Inc.
  *
  * See http://www.winischhofer.net/ for more information and updates
@@ -34,7 +35,11 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/moduleparam.h>
+#endif
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -51,22 +56,8 @@
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
 #include <linux/types.h>
 #include <asm/uaccess.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <linux/spinlock.h>
-#endif
-
-#include "osdef.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <video/sisfb.h>
-#else
-#include <linux/sisfb.h>
-#endif
-
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
@@ -80,32 +71,16 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "vgatypes.h"
-#include "sis_main.h"
 #include "sis.h"
+#include "sis_main.h"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
 #error "This version of sisfb requires at least 2.6.3"
-#else
-#if 0
-#define NEWFBDEV		/* Define this as soon as sysfs support has returned */
-#endif
-#endif
 #endif
-
-/* -------------------- Macro definitions ---------------------------- */
-
-#undef SISFBDEBUG 	/* no debugging */
-
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#ifdef SISFBACCEL
 #ifdef FBCON_HAS_CFB8
 extern struct display_switch fbcon_sis8;
 #endif
@@ -116,24 +91,286 @@
 extern struct display_switch fbcon_sis32;
 #endif
 #endif
+
+/* ------------------ Internal helper routines ----------------- */
+
+static void __init
+sisfb_setdefaultparms(void)
+{
+	sisfb_off 		= 0;
+	sisfb_parm_mem 		= 0;
+	sisfb_accel 		= -1;
+	sisfb_ypan      	= -1;
+	sisfb_max 		= -1;
+	sisfb_userom    	= -1;
+        sisfb_useoem    	= -1;
+#ifdef MODULE
+	/* Module: "None" for 2.4, default mode for 2.5+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	sisfb_mode_idx 		= -1;
+#else	
+	sisfb_mode_idx  	= MODE_INDEX_NONE;
+#endif	
+#else	
+	/* Static: Default mode */
+	sisfb_mode_idx  	= -1;
+#endif	
+	sisfb_parm_rate 	= -1;
+	sisfb_crt1off 		= 0;
+	sisfb_forcecrt1 	= -1;
+	sisfb_crt2type  	= -1;
+	sisfb_crt2flags 	= 0;
+	sisfb_pdc 		= 0xff;
+	sisfb_pdca 		= 0xff;
+	sisfb_scalelcd  	= -1;
+	sisfb_specialtiming 	= CUT_NONE;
+	sisfb_lvdshl 		= -1;
+	sisfb_dstn     		= 0;
+	sisfb_fstn 		= 0;
+	sisfb_tvplug    	= -1;
+	sisfb_tvstd     	= -1;
+	sisfb_tvxposoffset 	= 0;
+	sisfb_tvyposoffset 	= 0;
+	sisfb_filter 		= -1;
+	sisfb_nocrt2rate 	= 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	sisfb_inverse   	= 0;
+	sisfb_fontname[0] 	= 0;
+#endif	
+#if !defined(__i386__) && !defined(__x86_64__)
+	sisfb_resetcard 	= 0;
+	sisfb_videoram  	= 0;
+#endif	
+}
+
+static void __init
+sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+{
+	int i = 0, j = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(vesamode == 0) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+		sisfb_mode_idx = MODE_INDEX_NONE;
+#else
+		if(!quiet) {
+		   printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+		}
+		sisfb_mode_idx = DEFAULT_MODE;
+#endif
+		return;
+	}
+
+	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
+
+	while(sisbios_mode[i++].mode_no[0] != 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[1] == 0x50 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	            } else {
+		       if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		          sisbios_mode[i-1].mode_no[1] == 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;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	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;
+	      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;
+	      }
+	   }
+	}
 
-/* --------------- Hardware Access Routines -------------------------- */
+	i = 0; j = 0;
+	while(sisbios_mode[i].mode_no[0] != 0) {
+		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+		   	if(sisfb_fstn) {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	           	} else {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
+		   	}
+		   	sisfb_mode_idx = i - 1;
+		   	j = 1;
+		   	break;
+		}
+	}
+	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+}
 
-/* These are used on x86 hardware during probe only */
+#ifndef MODULE
 static void __devinit
-sisfb_set_reg4(u16 port, u32 data)
+sisfb_get_vga_mode_from_kernel(void)
 {
-	outl((u32)(data & 0xffffffff), port);
+#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
+   	char mymode[32];
+	int  mydepth = screen_info.lfb_depth;
+	
+	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
+
+	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&	
+	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
+	    (mydepth >= 8) && (mydepth <= 32) ) {
+	    
+	    if(mydepth == 24) mydepth = 32;
+	    
+	    sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, 
+	    				screen_info.lfb_height,
+					mydepth);
+					
+	    printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+	    					
+	    sisfb_search_mode(mymode, TRUE);
+	}
+#endif
+	return;		    
 }
+#endif
 
-static u32 __devinit
-sisfb_get_reg3(u16 port)
+static void __init
+sisfb_search_crt2type(const char *name)
 {
-	return((u32)inl(port));
+	int i = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	while(sis_crt2type[i].type_no != -1) {
+	   	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_crt2flags = sis_crt2type[i].flags;
+	      		break;
+	   	}
+	   	i++;
+	}
+	
+	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
+	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
+	
+	if(sisfb_crt2type < 0) {
+		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
+	}
 }
 
-/* ------------------ Internal helper routines ----------------- */
+static void __init
+sisfb_search_tvstd(const char *name)
+{
+	int i = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	while(sis_tvtype[i].type_no != -1) {
+	   	if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+	      		sisfb_tvstd = sis_tvtype[i].type_no;
+	      		break;
+	   	}
+	   	i++;
+	}
+}
+
+static void __init
+sisfb_search_specialtiming(const char *name)
+{
+	int i = 0;
+	BOOLEAN found = FALSE;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	if(!strnicmp(name, "none", 4)) {
+	        sisfb_specialtiming = 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))) {
+		 sisfb_specialtiming = mycustomttable[i].SpecialID;
+		 found = TRUE;
+		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
+		 	mycustomttable[i].optionName);
+		 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 __devinit
 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
@@ -237,7 +474,7 @@
 }
 
 static void __devinit
-sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
+sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
 {
 	USHORT  temp, i, realcrtno = crtno;
    	u8      buffer[256];
@@ -245,14 +482,15 @@
 	monitor->datavalid = FALSE;
 
 	if(crtno) {
-       	   if(ivideo.vbflags & CRT2_LCD)      realcrtno = 1;
-      	   else if(ivideo.vbflags & CRT2_VGA) realcrtno = 2;
+       	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
+      	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
       	   else return;
    	}
 
-	if((sisfb_crt1off) && (!crtno)) return;
+	if((ivideo->sisfb_crt1off) && (!crtno)) return;
 
-    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, realcrtno, 0, &buffer[0]);
+    	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 
+				realcrtno, 0, &buffer[0]);
    	if((!temp) || (temp == 0xffff)) {
       	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
 	   return;
@@ -267,7 +505,7 @@
       	   if(temp & 0x02) {
 	      i = 3;  /* Number of retrys */
 	      do {
-	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine,
+	    	 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
 				     realcrtno, 1, &buffer[0]);
 	      } while((temp) && i--);
               if(!temp) {
@@ -287,218 +525,9 @@
 	}
 }
 
-static void __init
-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)
-		sisfb_mode_idx = MODE_INDEX_NONE;
-#else
-		if(!quiet)
-		   printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-		sisfb_mode_idx = DEFAULT_MODE;
-#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 __init
-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(!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;
-		}
-	}
-	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
-
-}
-
-static void __init
-sisfb_search_crt2type(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while(sis_crt2type[i].type_no != -1) {
-		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_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-        if(ivideo.chip != SIS_550) {
-	   sisfb_dstn = sisfb_fstn = 0;
-	}
-}
-
-static void __init
-sisfb_search_queuemode(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_queuemode[i].type_no != -1) {
-		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_ERR "sisfb: Invalid queuemode type: %s\n", name);
-}
-
-static void __init
-sisfb_search_tvstd(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_tvtype[i].type_no != -1) {
-		if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-		        ivideo.vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN);
-			ivideo.vbflags |= sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void __init
-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 (\"%s\")\n",
-		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
-		 	mycustomttable[i].optionName);
-		 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_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
+sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, 
+		int mode_idx, int rate_idx, int rate)
 {
 	int htotal, vtotal;
 	unsigned int dclock, hsync;
@@ -510,7 +539,8 @@
 	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,
+	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext, 
+				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
 	                          &htotal, &vtotal, rate_idx)) {
 		dclock = (htotal * vtotal * rate) / 1000;
 		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
@@ -524,90 +554,69 @@
 }
 
 static int
-sisfb_validate_mode(int myindex, unsigned long vbflags)
+sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
 {
    u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
    }
 #endif
 #ifdef CONFIG_FB_SIS_315
-   if(ivideo.sisvga_engine == SIS_315_VGA) {
+   if(ivideo->sisvga_engine == SIS_315_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
    }
 #endif
 
    myres = sisbios_mode[myindex].yres;
 
-   switch (vbflags & VB_DISPTYPE_DISP2) {
+   switch(vbflags & VB_DISPTYPE_DISP2) {
+   
      case CRT2_LCD:
-	switch(sishw_ext.ulCRT2LCDType) {
-	case LCD_640x480:  xres =  640; yres =  480;  break;
-	case LCD_800x600:  xres =  800; yres =  600;  break;
-        case LCD_1024x600: xres = 1024; yres =  600;  break;
-	case LCD_1024x768: xres = 1024; yres =  768;  break;
-	case LCD_1152x768: xres = 1152; yres =  768;  break;
-	case LCD_1280x960: xres = 1280; yres =  960;  break;
-	case LCD_1280x768: xres = 1280; yres =  768;  break;
-	case LCD_1280x1024:xres = 1280; yres = 1024;  break;
-	case LCD_1400x1050:xres = 1400; yres = 1050;  break;
-	case LCD_1600x1200:xres = 1600; yres = 1200;  break;
-	case LCD_320x480:  xres =  320; yres =  480;  break; /* FSTN (old) */
-	case LCD_640x480_2:
-	case LCD_640x480_3:xres =  640; yres =  480;  break; /* FSTN (new) */
-	case LCD_1680x1050:xres = 1680; yres = 1050;  break;
-	case LCD_1280x800: xres = 1280; yres =  800;  break;
-	case LCD_1280x720: yres = 1280; yres =  720;  break;
-	default:           xres =    0; yres =    0;  break;
-	}
 
-	if(SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
-	   xres = 1360; yres = 1024;
-	}
+        xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-	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(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
+	   	if(sisbios_mode[myindex].xres > xres) return(-1);
+           	if(myres > yres) return(-1);
 	}
 
 	if(vbflags & (VB_LVDS | VB_30xBDH)) {
 	   if(sisbios_mode[myindex].xres == 320) {
 	      if((myres == 240) || (myres == 480)) {
-		 if(!sisfb_fstn) {
-		    if(sisbios_mode[myindex].mode_no == 0x5a ||
-		       sisbios_mode[myindex].mode_no == 0x5b)
+		 if(!ivideo->sisfb_fstn) {
+		    if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
+		       sisbios_mode[myindex].mode_no[1] == 0x5b)
 		       return(-1);
 		 } else {
-		    if(sisbios_mode[myindex].mode_no == 0x50 ||
-		       sisbios_mode[myindex].mode_no == 0x56 ||
-		       sisbios_mode[myindex].mode_no == 0x53)
+		    if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x56 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x53)
 		       return(-1);
 		 }
 	      }
 	   }
 	}
 
-	if(SiS_GetModeID_LCD(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
-	                     0, sisfb_fstn, SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
-	   return(-1);
+	if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 
+			     sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, 
+			     ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
+	   	return(-1);
 	}
 	break;
 
      case CRT2_TV:
-	if(SiS_GetModeID_TV(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+	   	return(-1);
 	}
 	break;
 
      case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+        if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	                      sisbios_mode[myindex].yres, 0) < 0x14) {
+	   	return(-1);
 	}
 	break;
      }
@@ -615,9 +624,8 @@
      return(myindex);
 }
 
-
 static u8
-sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
 {
 	u16 xres, yres;
 	int i = 0;
@@ -625,55 +633,54 @@
 	xres = sisbios_mode[mode_idx].xres;
 	yres = sisbios_mode[mode_idx].yres;
 
-	ivideo.rate_idx = 0;
-	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
-		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
-			if (sisfb_vrate[i].refresh == rate) {
-				ivideo.rate_idx = sisfb_vrate[i].idx;
+	ivideo->rate_idx = 0;
+	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
+			if(sisfb_vrate[i].refresh == rate) {
+				ivideo->rate_idx = sisfb_vrate[i].idx;
 				break;
-			} else if (sisfb_vrate[i].refresh > rate) {
-				if ((sisfb_vrate[i].refresh - rate) <= 3) {
+			} else if(sisfb_vrate[i].refresh > rate) {
+				if((sisfb_vrate[i].refresh - rate) <= 3) {
 					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
 						rate, sisfb_vrate[i].refresh);
-					ivideo.rate_idx = sisfb_vrate[i].idx;
-					ivideo.refresh_rate = sisfb_vrate[i].refresh;
-				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)
+					ivideo->rate_idx = sisfb_vrate[i].idx;
+					ivideo->refresh_rate = sisfb_vrate[i].refresh;
+				} else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
 						&& (sisfb_vrate[i].idx != 1)) {
 					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i-1].refresh);
-					ivideo.rate_idx = sisfb_vrate[i-1].idx;
-					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;
+					ivideo->rate_idx = sisfb_vrate[i-1].idx;
+					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
 				} 
 				break;
 			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
 				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i].refresh);
-	           		ivideo.rate_idx = sisfb_vrate[i].idx;
+	           		ivideo->rate_idx = sisfb_vrate[i].idx;
 		   		break;
 	       		}
 		}
 		i++;
 	}
-	if(ivideo.rate_idx > 0) {
-		return ivideo.rate_idx;
+	if(ivideo->rate_idx > 0) {
+		return ivideo->rate_idx;
 	} else {
-		printk(KERN_INFO
-			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
+		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n", 
+				rate, xres, yres);
 		return 0;
 	}
 }
 
-
 static BOOLEAN
-sisfb_bridgeisslave(void)
+sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
    unsigned char P1_00;
 
-   if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
+   if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
 
    inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((ivideo.sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((ivideo.sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+   if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+       ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 	   return TRUE;
    } else {
            return FALSE;
@@ -681,7 +688,7 @@
 }
 
 static BOOLEAN
-sisfballowretracecrt1(void)
+sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
    u8 temp;
 
@@ -695,20 +702,20 @@
 }
 
 static BOOLEAN
-sisfbcheckvretracecrt1(void)
+sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
-   if(!sisfballowretracecrt1()) return FALSE;
+   if(!sisfballowretracecrt1(ivideo)) return FALSE;
 
    if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
    else 			   return FALSE;
 }
 
 static void
-sisfbwaitretracecrt1(void)
+sisfbwaitretracecrt1(struct sis_video_info *ivideo)
 {
    int watchdog;
 
-   if(!sisfballowretracecrt1()) return;
+   if(!sisfballowretracecrt1(ivideo)) return;
 
    watchdog = 65536;
    while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
@@ -717,19 +724,14 @@
 }
 
 static BOOLEAN
-sisfbcheckvretracecrt2(void)
+sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
    unsigned char temp, reg;
 
-   switch(ivideo.sisvga_engine) {
-   case SIS_300_VGA:
-   	reg = 0x25;
-	break;
-   case SIS_315_VGA:
-   	reg = 0x30;
-	break;
-   default:
-        return FALSE;
+   switch(ivideo->sisvga_engine) {
+   case SIS_300_VGA: reg = 0x25; break;
+   case SIS_315_VGA: reg = 0x30; break;
+   default:          return FALSE;
    }
 
    inSISIDXREG(SISPART1, reg, temp);
@@ -738,24 +740,70 @@
 }
 
 static BOOLEAN
-sisfb_CheckVBRetrace(void)
+sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
-   if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-      if(sisfb_bridgeisslave()) {
-         return(sisfbcheckvretracecrt1());
+   if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+      if(sisfb_bridgeisslave(ivideo)) {
+         return(sisfbcheckvretracecrt1(ivideo));
       } else {
-         return(sisfbcheckvretracecrt2());
+         return(sisfbcheckvretracecrt2(ivideo));
       }
    } 
-   return(sisfbcheckvretracecrt1());
+   return(sisfbcheckvretracecrt1(ivideo));
+}
+
+static u32
+sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
+{
+   u8 idx, reg1, reg2, reg3, reg4;
+   u32 ret = 0;
+   
+   (*vcount) = (*hcount) = 0;
+   
+   if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+      	      FB_VBLANK_HAVE_HBLANK | 
+              FB_VBLANK_HAVE_VBLANK | 
+	      FB_VBLANK_HAVE_VCOUNT | 
+	      FB_VBLANK_HAVE_HCOUNT);
+      switch(ivideo->sisvga_engine) {
+         case SIS_300_VGA: idx = 0x25; break;
+	 default:
+         case SIS_315_VGA: idx = 0x30; break;
+      }
+      inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+      inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+      inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+      inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+      if(!(reg1 & 0x01)) ret |= FB_VBLANK_VBLANKING;
+      if(!(reg1 & 0x02)) ret |= FB_VBLANK_VSYNCING;
+      if(!(reg4 & 0x80)) ret |= FB_VBLANK_HBLANKING;
+      (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+      (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+   } else if(sisfballowretracecrt1(ivideo)) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+              FB_VBLANK_HAVE_VBLANK | 
+	      FB_VBLANK_HAVE_VCOUNT | 
+	      FB_VBLANK_HAVE_HCOUNT);
+      reg1 = inSISREG(SISINPSTAT);
+      if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+      if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+      inSISIDXREG(SISCR,0x20,reg1);
+      inSISIDXREG(SISCR,0x1b,reg1);
+      inSISIDXREG(SISCR,0x1c,reg2);
+      inSISIDXREG(SISCR,0x1d,reg3);
+      (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+      (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+   }
+   return ret;
 }
 
 static int
-sisfb_myblank(int blank)
+sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
    u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
    BOOLEAN backlight = TRUE;
-
+   
    switch(blank) {
    case 0:	/* on */
       sr01  = 0x00;
@@ -806,63 +854,64 @@
       return 1;
    }
 
-   if(ivideo.currentvbflags & VB_DISPTYPE_CRT1) {
-
-      setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+   if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
 
-      if( (!sisfb_thismonitor.datavalid) ||
-          ((sisfb_thismonitor.datavalid) &&
-           (sisfb_thismonitor.feature & 0xe0))) {
+      if( (!ivideo->sisfb_thismonitor.datavalid) ||
+          ((ivideo->sisfb_thismonitor.datavalid) &&
+           (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 
-	 if(ivideo.sisvga_engine == SIS_315_VGA) {
-	    setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+	 if(ivideo->sisvga_engine == SIS_315_VGA) {
+	    setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 	 }
 
-	 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 if(!(sisfb_bridgeisslave(ivideo))) {
+	    setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+	    setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 }
       }
 
    }
 
-   if(ivideo.currentvbflags & CRT2_LCD) {
+   if(ivideo->currentvbflags & CRT2_LCD) {
 
-      if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+      if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
 	 if(backlight) {
-	    SiS_SiS30xBLOn(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 } else {
-	    SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 }
-      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
-	 if(ivideo.vbflags & VB_CHRONTEL) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	 if(ivideo->vbflags & VB_CHRONTEL) {
 	    if(backlight) {
-	       SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
+	       SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
 	    } else {
-	       SiS_Chrontel701xBLOff(&SiS_Pr);
+	       SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
 	    }
 	 }
       }
 
-      if(((ivideo.sisvga_engine == SIS_300_VGA) &&
-          (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((ivideo.sisvga_engine == SIS_315_VGA) &&
-          ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
+      if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+          (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
+         ((ivideo->sisvga_engine == SIS_315_VGA) &&
+          ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
           setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
       }
 
-      if(ivideo.sisvga_engine == SIS_300_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      if(ivideo->sisvga_engine == SIS_300_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
 	 }
-      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
 	 }
       }
 
-   } else if(ivideo.currentvbflags & CRT2_VGA) {
+   } else if(ivideo->currentvbflags & CRT2_VGA) {
 
-      if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) {
+      if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
          setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
       }
 
@@ -873,37 +922,77 @@
 
 /* ----------- FBDev related routines for all series ----------- */
 
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+	return (var->bits_per_pixel == 8) ? 256 : 16;
+}
+
 static void
-sisfb_set_vparms(void)
+sisfb_set_vparms(struct sis_video_info *ivideo)
 {
-   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;
-   }
+   	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 void
+sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
+	
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 6;
+		break;
+	case 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;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
 }
 
 static int
 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0; 
 	unsigned int drate = 0, hrate = 0;
 	int found_mode = 0;
@@ -933,47 +1022,51 @@
 	}
 
 	if(pixclock && htotal && vtotal) {
-	   drate = 1000000000 / pixclock;
-	   hrate = (drate * 1000) / htotal;
-	   ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else ivideo.refresh_rate = 60;
-
-	old_mode = sisfb_mode_idx;
-	sisfb_mode_idx = 0;
-
-	while( (sisbios_mode[sisfb_mode_idx].mode_no != 0) &&
-	       (sisbios_mode[sisfb_mode_idx].xres <= var->xres) ) {
-		if( (sisbios_mode[sisfb_mode_idx].xres == var->xres) &&
-		    (sisbios_mode[sisfb_mode_idx].yres == var->yres) &&
-		    (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {
-			ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+	   	drate = 1000000000 / pixclock;
+	   	hrate = (drate * 1000) / htotal;
+	   	ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else {
+	   	ivideo->refresh_rate = 60;
+	}
+
+	old_mode = ivideo->sisfb_mode_idx;
+	ivideo->sisfb_mode_idx = 0;
+
+	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
+	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
+		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
+			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 			found_mode = 1;
 			break;
 		}
-		sisfb_mode_idx++;
+		ivideo->sisfb_mode_idx++;
 	}
 
-	if(found_mode)
-		sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
-	else
-		sisfb_mode_idx = -1;
+	if(found_mode) {
+		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, 
+				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+	} else {
+		ivideo->sisfb_mode_idx = -1;
+	}
 
-       	if(sisfb_mode_idx < 0) {
+       	if(ivideo->sisfb_mode_idx < 0) {
 		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
 		       var->yres, var->bits_per_pixel);
-		sisfb_mode_idx = old_mode;
+		ivideo->sisfb_mode_idx = old_mode;
 		return -EINVAL;
 	}
 
-	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
-		ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-		ivideo.refresh_rate = 60;
+	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
+		ivideo->rate_idx = sisbios_mode[ivideo->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,
-	                         ivideo.rate_idx, ivideo.refresh_rate)) {
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+	                         ivideo->rate_idx, ivideo->refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
@@ -983,51 +1076,52 @@
 	if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
 #else
 	if(isactive) {
-#endif
-		sisfb_pre_setmode();
+#endif	
+		sisfb_pre_setmode(ivideo);
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
-			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo.mode_no);
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
 			return -EINVAL;
 		}
-
+		
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 		
-		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);
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
+		sisfb_post_setmode(ivideo);
+		
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_vwidth  = ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_vheight = ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+		ivideo->video_linelength = ivideo->video_width * (ivideo->video_bpp >> 3);
+		ivideo->org_x = ivideo->org_y = 0;
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
 		}
 
-		sisfb_set_vparms();
+		sisfb_set_vparms(ivideo);
 		
-		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;
+		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[ivideo.mode_no] = ivideo.refresh_rate;
+                ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
 #endif
 		
-		sisfb_post_setmode();
-
 	}
+
 	return 0;
 }
 
 static int
-sisfb_pan_var(struct fb_var_screeninfo *var)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	unsigned int base;
 
-	if (var->xoffset > (var->xres_virtual - var->xres)) {
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
 	}
 	if(var->yoffset > (var->yres_virtual - var->yres)) {
@@ -1038,11 +1132,11 @@
 		
         /* calculate base bpp dep. */
         switch(var->bits_per_pixel) {
+	case 32:
+            	break;
         case 16:
         	base >>= 1;
         	break;
-	case 32:
-            	break;
 	case 8:
         default:
         	base >>= 2;
@@ -1054,84 +1148,27 @@
         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
 	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
 	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
 	}
-        if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
+        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
         	outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
         	outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
         	outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
 			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
 		}
         }
 	return 0;
 }
 
-static void
-sisfb_bpp_to_var(struct fb_var_screeninfo *var)
-{
-	switch(var->bits_per_pixel) {
-	   case 8:
-	   	var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 6;
-		ivideo.video_cmap_len = 256;
-		break;
-	   case 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;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		ivideo.video_cmap_len = 16;
-		break;
-	   case 32:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		ivideo.video_cmap_len = 16;
-		break;
-	}
-}
-
-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->vbflags	    = ivideo.vbflags;
-	rec->currentvbflags = ivideo.currentvbflags;
-}
-
 /* ------------ FBDev related routines for 2.4 series ----------- */
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 
 static void
-sisfb_crtc_to_var(struct fb_var_screeninfo *var)
+sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	u16 VRE, VBE, VRS, VBS, VDE, VT;
 	u16 HRE, HBE, HRS, HBS, HDE, HT;
@@ -1146,50 +1183,55 @@
 	else
 	   var->vmode = FB_VMODE_NONINTERLACED;
 
-	switch ((sr_data & 0x1C) >> 2) {
-	   case SIS_8BPP_COLOR_MODE:
+	switch((sr_data & 0x1C) >> 2) {
+	case SIS_8BPP_COLOR_MODE:
 		var->bits_per_pixel = 8;
 		break;
-	   case SIS_16BPP_COLOR_MODE:
+	case SIS_16BPP_COLOR_MODE:
 		var->bits_per_pixel = 16;
 		break;
-	   case SIS_32BPP_COLOR_MODE:
+	case SIS_32BPP_COLOR_MODE:
 		var->bits_per_pixel = 32;
 		break;
 	}
 
-	sisfb_bpp_to_var(var);
+	sisfb_bpp_to_var(ivideo, var);
 	
 	inSISIDXREG(SISSR, 0x0A, sr_data);
-
         inSISIDXREG(SISCR, 0x06, cr_data);
-
         inSISIDXREG(SISCR, 0x07, cr_data2);
 
-	VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
-	     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+	VT = (cr_data & 0xFF) | 
+	     ((u16) (cr_data2 & 0x01) << 8) |
+	     ((u16) (cr_data2 & 0x20) << 4) | 
+	     ((u16) (sr_data  & 0x01) << 10);
 	A = VT + 2;
 
 	inSISIDXREG(SISCR, 0x12, cr_data);
 
-	VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
-	      ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+	VDE = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x02) << 7) |
+	      ((u16) (cr_data2 & 0x40) << 3) | 
+	      ((u16) (sr_data  & 0x02) << 9);
 	E = VDE + 1;
 
 	inSISIDXREG(SISCR, 0x10, cr_data);
 
-	VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
-	      ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+	VRS = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x04) << 6) |
+	      ((u16) (cr_data2 & 0x80) << 2) | 
+	      ((u16) (sr_data  & 0x08) << 7);
 	F = VRS + 1 - E;
 
 	inSISIDXREG(SISCR, 0x15, cr_data);
-
 	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);
+	VBS = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x08) << 5) |
+	      ((u16) (cr_data3 & 0x20) << 4) | 
+	      ((u16) (sr_data & 0x04) << 8);
 
 	inSISIDXREG(SISCR, 0x16, cr_data);
 
@@ -1223,7 +1265,6 @@
 	}
 
 	inSISIDXREG(SISSR, 0x0b, sr_data);
-
 	inSISIDXREG(SISCR, 0x00, cr_data);
 
 	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
@@ -1244,13 +1285,12 @@
 	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
 
 	inSISIDXREG(SISSR, 0x0c, sr_data);
-
 	inSISIDXREG(SISCR, 0x03, cr_data);
-
 	inSISIDXREG(SISCR, 0x05, cr_data2);
 
-	HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
-	      ((u16) (sr_data & 0x03) << 6);
+	HBE = (cr_data & 0x1f) | 
+	      ((u16) (cr_data2 & 0x80) >> 2) |
+	      ((u16) (sr_data  & 0x03) << 6);
 	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 
 	temp = HBE - ((E - 1) & 255);
@@ -1298,14 +1338,14 @@
 	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 	   VT <<= 1;
 	}
-	hrate = ivideo.refresh_rate * VT / 2;
+	hrate = ivideo->refresh_rate * VT / 2;
 	drate = (hrate * HT) / 1000;
 	var->pixclock = (u32) (1000000000 / drate);
 
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+	if(ivideo->sisfb_ypan) {
+	   maxyres = ivideo->heapstart / (var->xres * (var->bits_per_pixel >> 3));
 	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -1315,44 +1355,48 @@
 	   if(var->yres_virtual <= var->yres) {
 	      var->yres_virtual = var->yres;
 	   }
-	} else
+	} else {
 	   var->yres_virtual = var->yres;
+	}
 
 }
 
 static int
 sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
-			 unsigned *transp, struct fb_info *fb_info)
+			 unsigned *transp, struct fb_info *info)
 {
-	if(regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= ivideo->video_cmap_len) return 1;
 
-	*red = sis_palette[regno].red;
-	*green = sis_palette[regno].green;
-	*blue = sis_palette[regno].blue;
+	*red   = ivideo->sis_palette[regno].red;
+	*green = ivideo->sis_palette[regno].green;
+	*blue  = ivideo->sis_palette[regno].blue;
 	*transp = 0;
+
 	return 0;
 }
 
 static int
 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *fb_info)
+                           unsigned transp, struct fb_info *info)
 {
-	if(regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= ivideo->video_cmap_len) return 1;
 
-	sis_palette[regno].red = red;
-	sis_palette[regno].green = green;
-	sis_palette[regno].blue = blue;
+	ivideo->sis_palette[regno].red   = red;
+	ivideo->sis_palette[regno].green = green;
+	ivideo->sis_palette[regno].blue  = blue;
 
-	switch(ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1362,328 +1406,266 @@
 #endif
 #ifdef FBCON_HAS_CFB16
 	case 16:
-		sis_fbcon_cmap.cfb16[regno] =
+		ivideo->sis_fbcon_cmap.cfb16[regno] =
 		    ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
-		red >>= 8;
+		red   >>= 8;
 		green >>= 8;
-		blue >>= 8;
-		sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
+		blue  >>= 8;
+		ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
 		break;
 #endif
 	}
+	
 	return 0;
 }
 
 static void
-sisfb_set_disp(int con, struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info    *ivideo = (struct sis_video_info *)info->par;
+	struct display           *display;
+	struct display_switch    *sw;
 	struct fb_fix_screeninfo fix;
 	long   flags;
-	struct display *display;
-	struct display_switch *sw;
 
-	if(con >= 0)
-		display = &fb_display[con];
-	else
-		display = &sis_disp;
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
 
-	sisfb_get_fix(&fix, con, 0);
+	sisfb_get_fix(&fix, con, info);
 
-	display->screen_base = ivideo.video_vbase;
+	display->var = *var;
+	display->screen_base = (char *)ivideo->video_vbase;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
 	display->ypanstep = fix.ypanstep;
 	display->ywrapstep = fix.ywrapstep;
 	display->line_length = fix.line_length;
-	display->next_line = fix.line_length;
 	display->can_soft_blank = 1;
-	display->inverse = sisfb_inverse;
-	display->var = *var;
+	display->inverse = ivideo->sisfb_inverse;
+	display->next_line = fix.line_length;
 
 	save_flags(flags);
 
-	switch(ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
-	   case 8:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis8 : &fbcon_cfb8;
-#else
-		sw = &fbcon_cfb8;
-#endif
+	case 8:
+		sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	   case 16:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis16 : &fbcon_cfb16;
-#else
-		sw = &fbcon_cfb16;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb16;
+	case 16:
+		sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	   case 32:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis32 : &fbcon_cfb32;
-#else
-		sw = &fbcon_cfb32;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb32;
+	case 32:
+		sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
 		break;
 #endif
-	   default:
+	default:
 		sw = &fbcon_dummy;
-		return;
+		break;
 	}
-	memcpy(&sisfb_sw, sw, sizeof(*sw));
-	display->dispsw = &sisfb_sw;
+	memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
+	display->dispsw = &ivideo->sisfb_sw;
+	
 	restore_flags(flags);
 
-        if(sisfb_ypan) {
+        if(ivideo->sisfb_ypan) {
   	    /* display->scrollmode = 0;  */
 	} else {
 	    display->scrollmode = SCROLL_YREDRAW;
-	    sisfb_sw.bmove = fbcon_redraw_bmove;
+	    ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
 	}
 }
 
 static void
 sisfb_do_install_cmap(int con, struct fb_info *info)
 {
-        if(con != currcon)
-		return;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+        if(con != ivideo->currcon) return;
 
-        if(fb_display[con].cmap.len)
+        if(fb_display[con].cmap.len) {
 		fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
-        else
-		fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1,
-			    sisfb_setcolreg, info);
+        } else {
+		int size = sisfb_get_cmap_len(&fb_display[con].var);
+		fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
+	}
 }
 
-
 static int
-sisfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-	if(con == -1)
-		memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
-	else
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(con == -1) {
+		memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
+	} else {
 		*var = fb_display[con].var;
+	}
 
-	if(sisfb_fstn) {
-	   if (var->xres == 320 && var->yres == 480)
-		var->yres = 240;
+	if(ivideo->sisfb_fstn) {
+	   	if(var->xres == 320 && var->yres == 480) var->yres = 240;
         }
 
 	return 0;
 }
 
 static int
-sisfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-	int err;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int cols, rows;
+	int err;
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
-        if(sisfb_do_set_var(var, con == currcon, info)) {
-		sisfb_crtc_to_var(var);
+	
+        if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
+		sisfb_crtc_to_var(ivideo, var);
 		return -EINVAL;
 	}
 
-	sisfb_crtc_to_var(var);
+	sisfb_crtc_to_var(ivideo, var);
 
 	sisfb_set_disp(con, var, info);
 
-	if(info->changevar)
-		(*info->changevar) (con);
+	if(info->changevar) {
+		(*info->changevar)(con);
+	}
 
-	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
 		return err;
+	}
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
-#if 0
-	/* Why was this called here? */
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
+	
+#if 0	/* Why was this called here? */
  	vc_resize_con(rows, cols, fb_display[con].conp->vc_num); 
 #endif	
-
 	return 0;
 }
 
 static int
-sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-        if(con == currcon)
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+	
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+	
+        if(con == ivideo->currcon) {
+	
 		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
-
-	else if (fb_display[con].cmap.len)
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);
+		
+	} else if(display->cmap.len) {
+	
+		fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
+		
+	} else {
+	
+		int size = sisfb_get_cmap_len(&display->var);
+		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+		
+	}
 
 	return 0;
 }
 
 static int
-sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-	int err;
-
-	if(!fb_display[con].cmap.len) {
-		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
-		if (err)
-			return err;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+	int err, size;
+	
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+	
+	size = sisfb_get_cmap_len(&display->var);
+	if(display->cmap.len != size) {
+		err = fb_alloc_cmap(&display->cmap, size, 0);
+		if(err)	return err;
 	}
         
-	if(con == currcon)
+	if(con == ivideo->currcon) {
 		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
-
-	else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	} else {
+		fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
+	}
 
 	return 0;
 }
 
 static int
-sisfb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info* info)
+sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
 	if(var->vmode & FB_VMODE_YWRAP) {
-		if(var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+		if((var->yoffset < 0) || 
+		   (var->yoffset >= fb_display[con].var.yres_virtual) || 
+		   (var->xoffset)) {
 			return -EINVAL;
+		}
 	} else {
-		if(var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-		   var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
+		   (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
 			return -EINVAL;
+		}
 	}
 
-        if(con == currcon) {
-	   if((err = sisfb_pan_var(var)) < 0) return err;
+        if(con == ivideo->currcon) {
+	   	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 	}
 
 	fb_display[con].var.xoffset = var->xoffset;
 	fb_display[con].var.yoffset = var->yoffset;
-	if(var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP) {
 		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-	else
+	} else {
 		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+	}
 
 	return 0;
 }
 
 static int
-sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	struct fb_var_screeninfo var;
-	unsigned long start;
-	unsigned long off;
-	unsigned long len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		sisfb_get_var(&var, currcon, info);
-		if(var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
-	}
-
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	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;
-
-	return 0;
-}
-
-static void
-sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
-{
-	struct display *p = &fb_display[currcon];
-	u16 c;
-	u8 *cdat;
-	int widthb;
-	u8 *gbuf = gly->gmask;
-	int size;
-
-	gly->fontheight = fontheight(p);
-	gly->fontwidth = fontwidth(p);
-	widthb = (fontwidth(p) + 7) / 8;
-
-	c = gly->ch & p->charmask;
-	if(fontwidth(p) <= 8)
-		cdat = p->fontdata + c * fontheight(p);
-	else
-		cdat = p->fontdata + (c * fontheight(p) << 1);
-
-	size = fontheight(p) * widthb;
-	memcpy(gbuf, cdat, size);
-	gly->ngmask = size;
-}
-
-static int
 sisfb_update_var(int con, struct fb_info *info)
 {
-        return(sisfb_pan_var(&fb_display[con].var));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+        return(sisfb_pan_var(ivideo, &fb_display[con].var));
 }
 
 static int
 sisfb_switch(int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int cols, rows;
 
-        if(fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+        if(fb_display[ivideo->currcon].cmap.len) {
+		fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
+	}
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 
-	if(!memcmp(&fb_display[con].var, &fb_display[currcon].var,
-	                           sizeof(struct fb_var_screeninfo))) {
-		currcon = con;
+	if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
+	                           	sizeof(struct fb_var_screeninfo))) {
+		ivideo->currcon = con;
 		return 1;
 	}
 
-	currcon = con;
+	ivideo->currcon = con;
 
 	sisfb_do_set_var(&fb_display[con].var, 1, info);
 
@@ -1691,8 +1673,8 @@
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
 	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
 
 	sisfb_update_var(con, info);
@@ -1703,49 +1685,35 @@
 static void
 sisfb_blank(int blank, struct fb_info *info)
 {
-	sisfb_myblank(blank);
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	sisfb_myblank(ivideo, blank);
 }
 #endif
 
-/* ------------ FBDev related routines for 2.5 series ----------- */
+/* ------------ FBDev related routines for 2.6 series ----------- */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
 static int
 sisfb_open(struct fb_info *info, int user)
 {
-    return 0;
+    	return 0;
 }
 
 static int
 sisfb_release(struct fb_info *info, int user)
 {
-    return 0;
-}
-
-static int
-sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
-{
-	int rc = 16;		
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		rc = 256;	
-		break;
-	case 16:
-	case 32:
-		rc = 16;
-		break;
-	}
-	return rc;
+    	return 0;
 }
 
 static int
 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
 		unsigned transp, struct fb_info *info)
 {
-	if(regno >= sisfb_get_cmap_len(&info->var))
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
 
 	switch(info->var.bits_per_pixel) {
 	case 8:
@@ -1753,7 +1721,7 @@
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1768,8 +1736,8 @@
 		red >>= 8;
 		green >>= 8;
 		blue >>= 8;
-		((u32 *) (info->pseudo_palette))[regno] =
-			(red << 16) | (green << 8) | (blue);
+		((u32 *)(info->pseudo_palette))[regno] =
+				(red << 16) | (green << 8) | (blue);
 		break;
 	}
 	return 0;
@@ -1780,8 +1748,9 @@
 {
 	int err;
 
-        if((err = sisfb_do_set_var(&info->var, 1, info)))
+        if((err = sisfb_do_set_var(&info->var, 1, info))) {
 		return err;
+	}
 
 	sisfb_get_fix(&info->fix, info->currcon, info);
 
@@ -1789,9 +1758,9 @@
 }
 
 static int
-sisfb_check_var(struct fb_var_screeninfo *var,
-                   struct fb_info *info)
+sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
 	unsigned int drate = 0, hrate = 0, maxyres;
 	int found_mode = 0;
@@ -1821,12 +1790,12 @@
 	}
 
 	search_idx = 0;
-	while( (sisbios_mode[search_idx].mode_no != 0) &&
+	while( (sisbios_mode[search_idx].mode_no[0] != 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, ivideo.currentvbflags) > 0) {
+		        if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
 			   found_mode = 1;
 			   break;
 			}
@@ -1836,11 +1805,11 @@
 
 	if(!found_mode) {
                 search_idx = 0;
-		while(sisbios_mode[search_idx].mode_no != 0) {
+		while(sisbios_mode[search_idx].mode_no[0] != 0) {
 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
 		       (var->yres <= sisbios_mode[search_idx].yres) &&
 		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
-		          if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+		          if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
 			     found_mode = 1;
 			     break;
 			  }
@@ -1864,24 +1833,25 @@
 		}
 	}
 
-	if( ((ivideo.vbflags & VB_LVDS) ||			/* Slave modes on LVDS and 301B-DH */
-	     ((ivideo.vbflags & VB_30xBDH) && (ivideo.currentvbflags & CRT2_LCD))) &&
+	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) ) {
+	} else if( (ivideo->current_htotal == htotal) &&	/* x=x & y=y & c=c -> assume depth change */
+	    	   (ivideo->current_vtotal == vtotal) &&
+	    	   (ivideo->current_pixclock == pixclock) ) {
 		drate = 1000000000 / pixclock;
 	        hrate = (drate * 1000) / htotal;
 	        refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} 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 if( ( (ivideo->current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */
+	    	     (ivideo->current_vtotal != vtotal) ) &&
+	    	   (ivideo->current_pixclock == var->pixclock) ) {
+		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
+			refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+		} else if(ivideo->sisfb_parm_rate != -1) {
+			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
+			refresh_rate = ivideo->sisfb_parm_rate;
 		} else {
 			refresh_rate = 60;
 		}
@@ -1890,56 +1860,53 @@
 		drate = 1000000000 / pixclock;
 	   	hrate = (drate * 1000) / htotal;
 	   	refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if(ivideo.current_refresh_rate) {
-		refresh_rate = ivideo.current_refresh_rate;
+	} 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);
+	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
 
 	/* Eventually recalculate timing and clock */
 	if(recalc_clock) {
 	   if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
-	   var->pixclock = (u32) (1000000000 / 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);
+	   var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, 
+	   					&ivideo->sishw_ext, 
+						sisbios_mode[search_idx].mode_no[ivideo->mni], 
+						myrateindex));
+	   sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+		 		    sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex,	var);
 	   if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		var->pixclock <<= 1;
+	      var->pixclock <<= 1;
 	   }
 	}
 
-	if(sisfb_thismonitor.datavalid) {
-	   if(!sisfb_verify_rate(&sisfb_thismonitor, search_idx,
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->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);	
+	sisfb_bpp_to_var(ivideo, var);	
 	
 	/* Sanity check for offsets */
-	if (var->xoffset < 0)
-		var->xoffset = 0;
-	if (var->yoffset < 0)
-		var->yoffset = 0;
+	if(var->xoffset < 0) var->xoffset = 0;
+	if(var->yoffset < 0) var->yoffset = 0;
 
 	/* Horiz-panning not supported */
-	if(var->xres != var->xres_virtual)
-		var->xres_virtual = var->xres;
+	if(var->xres != var->xres_virtual) {
+	   var->xres_virtual = var->xres;
+	}
 	
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+	if(ivideo->sisfb_ypan) {
+	   maxyres = ivideo->heapstart / (var->xres * (var->bits_per_pixel >> 3));
 	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -1958,319 +1925,251 @@
 	}
 	
 	/* Truncate offsets to maximum if too high */
-	if(var->xoffset > var->xres_virtual - var->xres)
-		var->xoffset = var->xres_virtual - var->xres - 1;
+	if(var->xoffset > var->xres_virtual - var->xres) {
+	   var->xoffset = var->xres_virtual - var->xres - 1;
+	}
 
-	if(var->yoffset > var->yres_virtual - var->yres)
-		var->yoffset = var->yres_virtual - var->yres - 1;
+	if(var->yoffset > var->yres_virtual - var->yres) {
+	   var->yoffset = var->yres_virtual - var->yres - 1;
+	}
 	
 	/* Set everything else to 0 */
 	var->red.msb_right = 
-	    var->green.msb_right =
-	    var->blue.msb_right =
-	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;		
+	var->green.msb_right =
+	var->blue.msb_right =
+	var->transp.offset = 
+	var->transp.length = 
+	var->transp.msb_right = 0;		
 
 	return 0;
 }
 
 static int
-sisfb_pan_display(struct fb_var_screeninfo *var,
-		     struct fb_info* info)
+sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
-	if(var->xoffset > (var->xres_virtual - var->xres))
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
-	if(var->yoffset > (var->yres_virtual - var->yres))
+	}
+	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)
+		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)
+		   var->yoffset + info->var.yres > info->var.yres_virtual) {
 			return -EINVAL;
+		}
 	}
 
-	if((err = sisfb_pan_var(var)) < 0) return err;
+	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
-	if(var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP) {
 		info->var.vmode |= FB_VMODE_YWRAP;
-	else
+	} else {
 		info->var.vmode &= ~FB_VMODE_YWRAP;
-
-	return 0;
-}
-
-static int
-sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	unsigned long start;
-	unsigned long off;
-	unsigned long len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		if(info->var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-	if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
-		return -EAGAIN;
-
 	return 0;
 }
 
 static int
 sisfb_blank(int blank, struct fb_info *info)
 {
-	return(sisfb_myblank(blank));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	return(sisfb_myblank(ivideo, blank));
 }
 
 #endif
 
 /* ----------- FBDev related routines for all series ---------- */
 
-
-#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, int con,
-		       struct fb_info *info)
-#endif
-{
-	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
+static int 
+sisfb_ioctl(struct inode *inode, struct file *file,
+            unsigned int cmd, unsigned long arg, 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		       
+	    int con,
+#endif		       
+	    struct fb_info *info)
+{
+	struct sis_video_info 	*ivideo = (struct sis_video_info *)info->par;
+	struct sis_memreq 	sismemreq;
+	struct fb_vblank  	sisvbblank;
+	sisfb_info        	x;
+	u32			gpu32 = 0;
+	static int 		count = 0;
 
 	switch (cmd) {
 	   case FBIO_ALLOC:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(copy_from_user(&sismemreq, (void *)arg, sizeof(sismemreq)))
+		}
+		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);
+			sis_free((u32)sismemreq.offset);
 		    	return -EFAULT;
 		}
 		break;
+		
 	   case FBIO_FREE:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(get_user(sismembase, (unsigned long *) arg))
+		}
+		if(get_user(gpu32, (u32 *)arg)) {
 			return -EFAULT;
-		sis_free(sismembase);
+		}
+		sis_free(gpu32);
 		break;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	   case FBIOGET_GLYPH:
-	        if(copy_from_user(&sisglyinfo, (void *)arg, sizeof(sisglyinfo)))
+		
+	   case FBIOGET_VBLANK:
+		sisvbblank.count = 0;
+		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
+		if(copy_to_user((void *)arg, &sisvbblank, sizeof(sisvbblank))) {
 			return -EFAULT;
-                sis_get_glyph(info, &sisglyinfo);
+		}
 		break;
-	   case FBIOPUT_MODEINFO:
-		{
-			struct mode_info x;
-
-			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 SISFB_GET_INFO_SIZE:
+	        return put_user(sizeof(sisfb_info), (u32 *)arg);
+		
+	   case SISFB_GET_INFO_OLD:
+	        if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
-#endif
-	   case FBIOGET_HWCINFO:
-		{
-			unsigned long myhwcoffset = 0;
-
-			if(ivideo.caps & HW_CURSOR_CAP)
-				myhwcoffset = ivideo.hwcursor_vbase -
-				    (unsigned long) ivideo.video_vbase;
-
-			return put_user(myhwcoffset, (unsigned long *)arg);
-
-			break;
+	   case SISFB_GET_INFO:  /* For communication with X driver */
+		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;
+		if(ivideo->modechanged) {
+		   x.fbvidmode = ivideo->mode_no;
+		} else {
+		   x.fbvidmode = ivideo->modeprechange;
 		}
-	   case FBIOGET_DISPINFO:
-	   	sis_dispinfo(&sisapdata);
-		if(copy_to_user((void *)arg, &sisapdata, sizeof(sisapdata)))
+		x.sisfb_caps = ivideo->caps;
+		x.sisfb_tqlen = 512; /* yet fixed */
+		x.sisfb_pcibus = ivideo->pcibus;
+		x.sisfb_pcislot = ivideo->pcislot;
+		x.sisfb_pcifunc = ivideo->pcifunc;
+		x.sisfb_lcdpdc = ivideo->detectedpdc;
+		x.sisfb_lcdpdca = ivideo->detectedpdca;
+		x.sisfb_lcda = ivideo->detectedlcda;
+		x.sisfb_vbflags = ivideo->vbflags;
+		x.sisfb_currentvbflags = ivideo->currentvbflags;
+		x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+		x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+		x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+		x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+		x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+		x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+		x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+		x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+		x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+		x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+			
+		if(copy_to_user((void *)arg, &x, sizeof(x))) {
 			return -EFAULT;
-		break;
-	   case SISFB_GET_INFO:  /* For communication with X driver */
-	        {
-			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;
-			if(ivideo.modechanged) {
-			   x.fbvidmode = ivideo.mode_no;
-			} else {
-			   x.fbvidmode = ivideo.modeprechange;
-			}
-			x.sisfb_caps = ivideo.caps;
-			x.sisfb_tqlen = 512; /* yet fixed */
-			x.sisfb_pcibus = ivideo.pcibus;
-			x.sisfb_pcislot = ivideo.pcislot;
-			x.sisfb_pcifunc = ivideo.pcifunc;
-			x.sisfb_lcdpdc = ivideo.detectedpdc;
-			x.sisfb_lcdpdca = ivideo.detectedpdca;
-			x.sisfb_lcda = ivideo.detectedlcda;
-			x.sisfb_vbflags = ivideo.vbflags;
-			x.sisfb_currentvbflags = ivideo.currentvbflags;
-			x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
-			x.sisfb_specialtiming = SiS_Pr.SiS_CustomT;
-			x.sisfb_haveemi = SiS_Pr.HaveEMI ? 1 : 0;
-			x.sisfb_haveemilcd = SiS_Pr.HaveEMILCD ? 1 : 0;
-			x.sisfb_emi30 = SiS_Pr.EMI_30;
-			x.sisfb_emi31 = SiS_Pr.EMI_31;
-			x.sisfb_emi32 = SiS_Pr.EMI_32;
-			x.sisfb_emi33 = SiS_Pr.EMI_33;
-			if(copy_to_user((void *)arg, &x, sizeof(x)))
-				return -EFAULT;
-	                break;
+		}
+	        break;
+		
+	   case SISFB_GET_VBRSTATUS_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_VBRSTATUS:
-	        {
-			if(sisfb_CheckVBRetrace())
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(sisfb_CheckVBRetrace(ivideo)) {
+			return put_user((u32)1, (u32 *) arg);
+		} else {
+			return put_user((u32)0, (u32 *) arg);
+		}
+		
+	   case SISFB_GET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_AUTOMAXIMIZE:
-	        {
-			if(sisfb_max)
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(ivideo->sisfb_max) return put_user((u32)1, (u32 *)arg);
+		else 	              return put_user((u32)0, (u32 *)arg);
+		
+	   case SISFB_SET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+		   printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_SET_AUTOMAXIMIZE:
-	        {
-			unsigned long newmax;
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		ivideo->sisfb_max = (gpu32) ? 1 : 0;
+		break;
 
-			if(copy_from_user(&newmax, (unsigned long *)arg, sizeof(newmax)))
-				return -EFAULT;
+	   case SISFB_SET_TVPOSOFFSET:
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
+		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
+		break;
 
-			if(newmax) sisfb_max = 1;
-			else	   sisfb_max = 0;
-			break;
+	   case SISFB_GET_TVPOSOFFSET:
+	        return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), (u32 *)arg);
+		
+	   case SISFB_SET_LOCK:
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
 		}
+		ivideo->sisfblocked = (gpu32) ? 1 : 0;
+		break;
+	        
 	   default:
 		return -EINVAL;
 	}
 	return 0;
 }
 
-
 static int
-sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-	      struct fb_info *info)
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-	strcpy(fix->id, sis_fb_info->modename);
-#else
-	strcpy(fix->id, myid);
-#endif	
-
-	fix->smem_start = ivideo.video_base;
-
-        if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-	    if(ivideo.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;
+	strcpy(fix->id, ivideo->myid);
 
+	fix->smem_start  = ivideo->video_base;
+	fix->smem_len    = ivideo->sisfb_mem;
 	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->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 	fix->xpanstep    = 0;
-
-        if(sisfb_ypan) 	 fix->ypanstep = 1;
-
+	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
 	fix->ywrapstep   = 0;
-	fix->line_length = ivideo.video_linelength;
-	fix->mmio_start  = ivideo.mmio_base;
-	fix->mmio_len    = ivideo.mmio_size;
-	if(ivideo.sisvga_engine == SIS_300_VGA) 
+	fix->line_length = ivideo->video_linelength;
+	fix->mmio_start  = ivideo->mmio_base;
+	fix->mmio_len    = ivideo->mmio_size;
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR;
-	else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_760))
+	} else if((ivideo->chip == SIS_330) || (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)
-	fix->reserved[0] = ivideo.video_size & 0xFFFF;
-	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = ivideo.caps;
-#endif
+	}
 
 	return 0;
 }
@@ -2286,437 +2185,414 @@
 	.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,
+	.fb_ioctl	= sisfb_ioctl
 };
 #endif
 
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static struct fb_ops sisfb_ops = {
-	.owner        =	THIS_MODULE,
-	.fb_open      = sisfb_open,
-	.fb_release   = sisfb_release,
-	.fb_check_var = sisfb_check_var,
-	.fb_set_par   = sisfb_set_par,
-	.fb_setcolreg = sisfb_setcolreg,
+	.owner          = THIS_MODULE,
+	.fb_open        = sisfb_open,
+	.fb_release     = sisfb_release,
+	.fb_check_var   = sisfb_check_var,
+	.fb_set_par     = sisfb_set_par,
+	.fb_setcolreg   = sisfb_setcolreg,
         .fb_pan_display = sisfb_pan_display,
-        .fb_blank     = sisfb_blank,
-	.fb_fillrect  = fbcon_sis_fillrect,
-	.fb_copyarea  = fbcon_sis_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor    = soft_cursor,	
-	.fb_sync      = fbcon_sis_sync,
-	.fb_ioctl     =	sisfb_ioctl,
-	.fb_mmap      =	sisfb_mmap,
+        .fb_blank       = sisfb_blank,
+	.fb_fillrect    = fbcon_sis_fillrect,
+	.fb_copyarea    = fbcon_sis_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_cursor      = soft_cursor,	
+	.fb_sync        = fbcon_sis_sync,
+	.fb_ioctl       = sisfb_ioctl
 };
 #endif
 
-
 /* ---------------- Chip generation dependent routines ---------------- */
 
-#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
-
-static int __devinit sisfb_get_dram_size_300(void)
+static struct pci_dev * sisfb_get_northbridge(int basechipid)
 {
 	struct pci_dev *pdev = NULL;
-	int pdev_valid = 0;
-	u8  pci_data, reg;
-	u16 nbridge_id;
-
-	switch(ivideo.chip) {
-	   case SIS_540:
-		nbridge_id = PCI_DEVICE_ID_SI_540;
-		break;
-	   case SIS_630:
-		nbridge_id = PCI_DEVICE_ID_SI_630;
-		break;
-	   case SIS_730:
-		nbridge_id = PCI_DEVICE_ID_SI_730;
-		break;
-	   default:
-		nbridge_id = 0;
-		break;
+	int nbridgenum, nbridgeidx, i;
+	const unsigned short nbridgeids[] = { 
+		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
+		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
+		PCI_DEVICE_ID_SI_730,
+		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
+		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
+		PCI_DEVICE_ID_SI_651,
+		PCI_DEVICE_ID_SI_740,
+		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760 VGA */
+		PCI_DEVICE_ID_SI_741,
+		PCI_DEVICE_ID_SI_660,
+		PCI_DEVICE_ID_SI_760
+	};
+		
+    	switch(basechipid) {
+#ifdef CONFIG_FB_SIS_300	
+	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
+	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
+#endif			
+#ifdef CONFIG_FB_SIS_315			
+	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
+	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
+	case SIS_660:	nbridgeidx = 7; nbridgenum = 4; break;
+#endif			
+	default:	return NULL;
 	}
-
-	if(nbridge_id == 0) {   /* 300 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
-		ivideo.video_size =
-		        ((unsigned int) ((reg & SIS_DRAM_SIZE_MASK) + 1) << 20);
-
-	} else {		/* 540, 630, 730 */
-
-#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;
-			}  
-		}   
-	
-		if (!pdev_valid)  return -1;
+	for(i = 0; i < nbridgenum; i++) {
+		if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
 	}
-	return 0;
+	return pdev;
 }
 
-#endif  /* CONFIG_FB_SIS_300 */
-
-
-#ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740/330/661/741/760 */
-
-static int __devinit sisfb_get_dram_size_315(void)
+static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
 {
-	u8  reg = 0;
-
-	if(ivideo.chip == SIS_550 ||
-	   ivideo.chip == SIS_650 ||
-	   ivideo.chip == SIS_740) {
-
-                inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		reg &= 0x3f;
-		reg++;
-		reg <<= 2;
-		ivideo.video_size = reg << 20;
-		return 0;
-
-	} else if(ivideo.chip == SIS_661 ||
-	          ivideo.chip == SIS_741) {
-
-		inSISIDXREG(SISCR, 0x79, reg);
-		reg &= 0xf0;
-		reg >>= 4;
-		ivideo.video_size = (1 << reg) << 20;
-		return 0;
-
-	} else if(ivideo.chip == SIS_660 ||
-		  ivideo.chip == SIS_760) {
+	u8 reg;
+	
+	ivideo->video_size = 0;
 
-		ivideo.video_size = 0;
+	switch(ivideo->chip) {
+#ifdef CONFIG_FB_SIS_300 
+	case SIS_300:
+	        inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
+		break;
+	case SIS_540:
+	case SIS_630:
+	case SIS_730:
+	   	if(!ivideo->nbridge) return -1;
+	   	pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
+		break;
+#endif  
+#ifdef CONFIG_FB_SIS_315
+	case SIS_315H:
+	case SIS_315PRO:
+	case SIS_315:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		switch((reg >> 2) & 0x03) {
+		case 0x01:
+		case 0x03:
+		   ivideo->video_size <<= 1;
+		   break;
+		case 0x02:
+		   ivideo->video_size += (ivideo->video_size/2);
+		}
+	   	break;	
+	case SIS_330:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		if(reg & 0x0c) ivideo->video_size <<= 1;
+	   	break;
+	case SIS_550:
+	case SIS_650:
+	case SIS_740:
+	    	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
+		break;
+	case SIS_661:
+	case SIS_741:
+	     	inSISIDXREG(SISCR, 0x79, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+	   	break;
+	case SIS_660:
+	case SIS_760:
 		inSISIDXREG(SISCR, 0x79, reg);
-		reg &= 0xf0;
-		reg >>= 4;
-		if(reg)	ivideo.video_size = (1 << reg) << 20;
+		reg = (reg & 0xf0) >> 4;
+		if(reg)	ivideo->video_size = (1 << reg) << 20;
 		inSISIDXREG(SISCR, 0x78, reg);
 		reg &= 0x30;
 		if(reg) {
-		   if(reg == 0x10) ivideo.video_size += (32 << 20);
-		   else		   ivideo.video_size += (64 << 20);
-		}
-		return 0;
-
-	} else {	/* 315, 330 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		ivideo.video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-
-		reg &= SIS315_DUAL_CHANNEL_MASK;
-		reg >>= 2;
-
-		if(ivideo.chip == SIS_330) {
-
-		   if(reg) ivideo.video_size <<= 1;
-		
-		} else {
-		   
-		   switch (reg) {
-		      case SIS315_SINGLE_CHANNEL_2_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_DUAL_CHANNEL_1_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_ASYM_DDR:		/* TW: DDR asymetric */
-			   ivideo.video_size += (ivideo.video_size/2);
-			   break;
-		   }
+		   if(reg == 0x10) ivideo->video_size += (32 << 20);
+		   else		   ivideo->video_size += (64 << 20);
 		}
-
-		return 0;
+	   	break;
+#endif		
+	default:
+		return -1;
 	}
-	
-	return -1;
-	
+	return 0;
 }
 
-#endif   /* CONFIG_FB_SIS_315 */
-
+/* -------------- video bridge device detection --------------- */
 
-/* -------------- video bridge detection --------------- */
-
-static void __devinit sisfb_detect_VB_connect()
+static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 {
-	u8 sr16, sr17, cr32, temp;
-
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
-	
-		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
-	      
-		if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+	u8 cr32, temp;
 
+#ifdef CONFIG_FB_SIS_300	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {	
+		inSISIDXREG(SISSR, 0x17, temp);	      
+		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
 			/* PAL/NTSC is stored on SR16 on such machines */
-			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-		   		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
-				if (sr16 & 0x20)
-					ivideo.vbflags |= TV_PAL;
+			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
+		   		inSISIDXREG(SISSR, 0x16, temp);
+				if(temp & 0x20)
+					ivideo->vbflags |= TV_PAL;
 				else
-					ivideo.vbflags |= TV_NTSC;
+					ivideo->vbflags |= TV_NTSC;
 			}
-
 		} 
-		
 	}
+#endif
 	
-	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
+	inSISIDXREG(SISCR, 0x32, cr32);
 
 	if(cr32 & SIS_CRT1) {
-		sisfb_crt1off = 0;
+		ivideo->sisfb_crt1off = 0;
 	} else {
-		if (cr32 & 0x5F) sisfb_crt1off = 1;
-		else		 sisfb_crt1off = 0;
+		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
 	}
 
-	ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
+	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;
+	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;
+	
+	/* Check given parms for hardware compatibility.
+	 * (Cannot do this in the search_xx routines since we don't 
+	 * know what hardware we are running on then)
+	 */ 
+	
+	if(ivideo->chip != SIS_550) {
+	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
+	}
+	
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) || 
+	       (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) || 
+	       (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: HiVision not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvstd != -1) {
+	   if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
+	       (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+	      if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
+	         ivideo->sisfb_tvstd = -1;
+	         printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+	      }
+	   }
+	}
 		
 	/* Detect/set TV plug & type */
-	if(sisfb_tvplug != -1) ivideo.vbflags |= sisfb_tvplug;
-
-	if(cr32 & SIS_VB_SVIDEO)	  ivideo.vbflags |= TV_SVIDEO;
-	else if (cr32 & SIS_VB_COMPOSITE) ivideo.vbflags |= TV_AVIDEO;
-	else if (cr32 & SIS_VB_SCART) {
-		ivideo.vbflags |= (TV_SCART | TV_PAL);
-		ivideo.vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN);
+	if(ivideo->sisfb_tvplug != -1) {
+		ivideo->vbflags |= ivideo->sisfb_tvplug;
+	} else {
+		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
+		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
+		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
+	 	else {
+			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
+			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
+		}
 	}
-
-	if(!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-		if(ivideo.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)) {
+	
+	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
+	    if(ivideo->sisfb_tvstd != -1) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ); 
+	       ivideo->vbflags |= ivideo->sisfb_tvstd;
+	    }
+	    if(ivideo->vbflags & TV_SCART) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= TV_PAL;
+	    }
+	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	        	inSISIDXREG(SISSR, 0x38, temp);
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
                 	inSISIDXREG(SISSR, 0x38, temp);
-			if(temp & 0x01) ivideo.vbflags |= TV_PAL;
-			else		ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	} else {
 	        	inSISIDXREG(SISCR, 0x79, temp);
-			if(temp & 0x20)	ivideo.vbflags |= TV_PAL;
-			else		ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	}
-	}
+	    }
+	} 
 
 	/* Copy forceCRT1 option to CRT1off if option is given */
-    	if(sisfb_forcecrt1 != -1) {
-    		if(sisfb_forcecrt1) sisfb_crt1off = 0;
-		else                sisfb_crt1off = 1;
+    	if(ivideo->sisfb_forcecrt1 != -1) {
+    	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
     	}
-
 }
 
-static void __devinit sisfb_get_VB_type(void)
+static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
 {
-	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;
+	u8 vb_chipid;
+	u8 reg;
 
 	inSISIDXREG(SISPART4, 0x00, vb_chipid);
-	switch (vb_chipid) {
-	   case 0x01:
-		ivideo.hasVB = HASVB_301;
+	switch(vb_chipid) {
+	case 0x01:
 		inSISIDXREG(SISPART4, 0x01, reg);
 		if(reg < 0xb0) {
-			ivideo.vbflags |= VB_301;
-			sishw_ext.ujVBChipID = VB_CHIP_301;
+			ivideo->vbflags |= VB_301;
 			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
 		} else if(reg < 0xc0) {
-		 	ivideo.vbflags |= VB_301B;
-			sishw_ext.ujVBChipID = VB_CHIP_301B;
+		 	ivideo->vbflags |= VB_301B;
 			inSISIDXREG(SISPART4,0x23,reg);
 			if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
+			   ivideo->vbflags |= VB_30xBDH;
 			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
 			} else {
 			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
 			}
 		} else if(reg < 0xd0) {
-		 	ivideo.vbflags |= VB_301C;
-			sishw_ext.ujVBChipID = VB_CHIP_301C;
+		 	ivideo->vbflags |= VB_301C;
 			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
 		} else if(reg < 0xe0) {
-			ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
+			ivideo->vbflags |= VB_301LV;
 			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
 		} else if(reg <= 0xe1) {
 		        inSISIDXREG(SISPART4,0x39,reg);
 			if(reg == 0xff) {
-			   ivideo.vbflags |= VB_302LV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302LV;
+			   ivideo->vbflags |= VB_302LV;
 			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
 			} else {
-			   ivideo.vbflags |= VB_302ELV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302ELV;
+			   ivideo->vbflags |= VB_301C;
+			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0			
+			   ivideo->vbflags |= VB_302ELV;
 			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif			   
 			}
 		}
 		break;
-	   case 0x02:
-		ivideo.hasVB = HASVB_302;
-		ivideo.vbflags |= VB_302B;
-		sishw_ext.ujVBChipID = VB_CHIP_302B;
+	case 0x02:
+		ivideo->vbflags |= VB_302B;
 		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
 		break;
 	}
 
-	if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) {
-		inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
+	if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+		inSISIDXREG(SISCR, 0x37, reg);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-			switch (reg) {
+			switch(reg) {
 			   case SIS_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 			   case SIS_EXTERNAL_CHIP_TRUMPION:
-				ivideo.hasVB = HASVB_TRUMPION;
-				ivideo.vbflags |= VB_TRUMPION;
-				printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
+				ivideo->vbflags |= VB_TRUMPION;
 				break;
 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
-				ivideo.hasVB = HASVB_CHRONTEL;
-				ivideo.vbflags |= VB_CHRONTEL;
-				printk(KERN_INFO "%s %s\n", stdstr, chrstr);
+				ivideo->vbflags |= VB_CHRONTEL;
 				break;
 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
 #endif
-		} else if(ivideo.chip < SIS_661) {
+		} else if(ivideo->chip < SIS_661) {
 #ifdef CONFIG_FB_SIS_315
 			switch (reg) {
 	 	   	   case SIS310_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 		   	   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
 #endif
-		} else if(ivideo.chip >= SIS_661) {
+		} else if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
 			inSISIDXREG(SISCR, 0x38, reg);
 			reg >>= 5;
 			switch(reg) {
 			   case 0x02:
-			   	ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 			   case 0x03:
-			   	ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			   case 0x04:
-			        ivideo.hasVB = HASVB_NONE;
-				ivideo.vbflags |= (VB_LVDS | VB_CONEXANT);
-				printk(KERN_INFO "%s Conexant video bridge\n", stdstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
 #endif
 		}
-
+		if(ivideo->vbflags & VB_LVDS) {
+		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_TRUMPION) {
+		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CHRONTEL) {
+		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CONEXANT) {
+		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
+		}
 	}
 	
-	if(ivideo.vbflags & VB_SISBRIDGE) {
-		SiS_Sense30x();
-	} else if(ivideo.vbflags & VB_CHRONTEL) {
-		SiS_SenseCh();
+	if(ivideo->vbflags & VB_SISBRIDGE) {
+		SiS_Sense30x(ivideo);
+	} else if(ivideo->vbflags & VB_CHRONTEL) {
+		SiS_SenseCh(ivideo);
 	}
-
 }
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN __devinit sisfb_test_DDC1(void)
+static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
     int count = 48;
 
-    old = SiS_ReadDDC1Bit(&SiS_Pr);
+    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
     do {
-       if(old != SiS_ReadDDC1Bit(&SiS_Pr)) break;
+       	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void __devinit sisfb_sense_crt1(void)
+static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    unsigned char SR1F, CR63=0, CR17;
-    unsigned short temp = 0xffff;
-    int i;
     BOOLEAN mustwait = FALSE;
+    u8  SR1F, CR17;
+#ifdef CONFIG_FB_SIS_315        
+    u8  CR63=0;
+#endif        
+    u16 temp = 0xffff;
+    int i;
 
     inSISIDXREG(SISSR,0x1F,SR1F);
     orSISIDXREG(SISSR,0x1F,0x04);
     andSISIDXREG(SISSR,0x1F,0x3F);
     if(SR1F & 0xc0) mustwait = TRUE;
 
-    if(ivideo.sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,CR63);
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,CR63);
        CR63 &= 0x40;
-       andSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF);
+       andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
     }
+#endif    
 
     inSISIDXREG(SISCR,0x17,CR17);
     CR17 &= 0x80;
@@ -2728,25 +2604,46 @@
     }
 
     if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1();
+       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
     }
+    
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->chip >= SIS_330) {
+       andSISIDXREG(SISCR,0x32,~0x20);
+       if(ivideo->chip >= SIS_340) {
+          outSISIDXREG(SISCR, 0x57, 0x4a);
+       } else {
+          outSISIDXREG(SISCR, 0x57, 0x5f);
+       }
+       orSISIDXREG(SISCR, 0x53, 0x02);
+       while((inSISREG(SISINPSTAT)) & 0x01)    break;
+       while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
+       if((inSISREG(SISMISCW)) & 0x10) temp = 1;
+       andSISIDXREG(SISCR, 0x53, 0xfd);
+       andSISIDXREG(SISCR, 0x57, 0x00);  
+    }
+#endif    
+    
+    if(temp == 0xffff) {
+       i = 3;
+       do {
+          temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+       } while(((temp == 0) || (temp == 0xffff)) && i--);
 
-    i = 3;
-    do {
-       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, 0, 0, NULL);
-    } while(((temp == 0) || (temp == 0xffff)) && i--);
-
-    if((temp == 0) || (temp == 0xffff)) {
-       if(sisfb_test_DDC1()) temp = 1;
+       if((temp == 0) || (temp == 0xffff)) {
+          if(sisfb_test_DDC1(ivideo)) temp = 1;
+       }
     }
 
     if((temp) && (temp != 0xffff)) {
        orSISIDXREG(SISCR,0x32,0x20);
     }
 
-    if(ivideo.sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF,CR63);
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,CR63);
     }
+#endif    
 
     setSISIDXREG(SISCR,0x17,0x7F,CR17);
 
@@ -2754,216 +2651,205 @@
 }
 
 /* Determine and detect attached devices on SiS30x */
-static int __devinit SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
-    int temp;
+    int temp, mytest, result, i, j;
+    
+    for(j = 0; j < 10; j++) {
+       result = 0;
+       for(i = 0; i < 3; i++) {
+          mytest = test;
+          outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+          temp = (type >> 8) | (mytest & 0x00ff);
+          setSISIDXREG(SISPART4,0x10,0xe0,temp);
+          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+          mytest >>= 8;
+          mytest &= 0x7f;
+          inSISIDXREG(SISPART4,0x03,temp);
+          temp ^= 0x0e;
+          temp &= mytest;
+          if(temp == mytest) result++;
+#if 1
+	  outSISIDXREG(SISPART4,0x11,0x00);
+	  andSISIDXREG(SISPART4,0x10,0xe0);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+#endif
+       }
+       if((result == 0) || (result >= 2)) break;
+    }
+    return(result);
+}
 
-    outSISIDXREG(SISPART4,0x11,tempbl);
-    temp = tempbh | tempcl;
-    setSISIDXREG(SISPART4,0x10,0xe0,temp);
-    SiS_DDC2Delay(&SiS_Pr, 0x1000);
-    tempch &= 0x7f;
-    inSISIDXREG(SISPART4,0x03,temp);
-    temp ^= 0x0e;
-    temp &= tempch;
-    return((temp == tempch));
-}
-
-static void __devinit SiS_Sense30x(void)
-{
-  u8 backupP4_0d,backupP2_00;
-  u8 svhs_bl, svhs_bh;
-  u8 svhs_cl, svhs_ch;
-  u8 cvbs_bl, cvbs_bh;
-  u8 cvbs_cl, cvbs_ch;
-  u8 vga2_bl, vga2_bh;
-  u8 vga2_cl, vga2_ch;
-  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(ivideo.sisvga_engine == SIS_300_VGA) {
-
-	if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x01; vga2_bl = 0x90;
-	   	svhs_bh = 0x01; svhs_bl = 0x6b;
-	   	cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-		inSISIDXREG(SISPART4,0x01,myflag);
-	        if(myflag & 0x04) {
-	           vga2_bh = 0x00; vga2_bl = 0xfd;
-	           svhs_bh = 0x00; svhs_bl = 0xdd;
-	      	   cvbs_bh = 0x00; cvbs_bl = 0xee;
-	        }
-	}
+static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
+{
+    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
+    u16 svhs=0, svhs_c=0;
+    u16 cvbs=0, cvbs_c=0;
+    u16 vga2=0, vga2_c=0;
+    int myflag, result;
+    char stdstr[] = "sisfb: Detected";
+    char tvstr[]  = "TV connected to";
+  
+    if(ivideo->vbflags & VB_301) {
+       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
+       inSISIDXREG(SISPART4,0x01,myflag);
+       if(myflag & 0x04) {
+	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
+       }
+    } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
+    } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+       svhs = 0x0200; cvbs = 0x0100;
+    } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
+    } else return;
+
+    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
+    if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+       svhs_c = 0x0408; cvbs_c = 0x0808;
+    }
+    biosflag = 2;
 
-	vga2_ch = 0x0e;	vga2_cl = 0x08;
-	svhs_ch = 0x04;	svhs_cl = 0x04;
-	cvbs_ch = 0x08; cvbs_cl = 0x04;
-	if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x00; vga2_bl = 0x00;
-	   	vga2_ch = 0x00; vga2_cl = 0x00;
-	}
-	if(ivideo.chip == SIS_300) {
-	   inSISIDXREG(SISSR,0x3b,myflag);
-	   if(!(myflag & 0x01)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	vga2_ch = 0x00; vga2_cl = 0x00;
-	   }
-	}
+    if(ivideo->chip == SIS_300) {
+       inSISIDXREG(SISSR,0x3b,myflag);
+       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
+    }
+  
+    inSISIDXREG(SISSR,0x1e,backupSR_1e);
+    orSISIDXREG(SISSR,0x1e,0x20);
+    
+    inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    if(ivideo->vbflags & VB_301C) {
+       setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+    } else {
+       orSISIDXREG(SISPART4,0x0d,0x04);
+    }
+    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
 
-  } else {
-
-	if(ivideo.vbflags & (VB_301B|VB_302B)) {
-		vga2_bh = 0x01; vga2_bl = 0x90;
-		svhs_bh = 0x01; svhs_bl = 0x6b;
-		cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
-	      	vga2_bh = 0x01; vga2_bl = 0x90;
-	      	svhs_bh = 0x01; svhs_bl = 0x6b;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x10;
-	} else if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	svhs_bh = 0x02; svhs_bl = 0x00;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x00;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-		inSISIDXREG(SISPART4,0x01,myflag);
-	        if(myflag & 0x04) {
-	           vga2_bh = 0x00; vga2_bl = 0xfd;
-	           svhs_bh = 0x00; svhs_bl = 0xdd;
-	           cvbs_bh = 0x00; cvbs_bl = 0xee;
-	        }
-	}
+    inSISIDXREG(SISPART2,0x00,backupP2_00);
+    outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
 
-	if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
-	   vga2_bh = 0x00; vga2_bl = 0x00;
-	   vga2_ch = 0x00; vga2_cl = 0x00;
-	   svhs_ch = 0x04; svhs_cl = 0x08;
-	   cvbs_ch = 0x08; cvbs_cl = 0x08;
-	} else {
-	   vga2_ch = 0x0e; vga2_cl = 0x08;
-	   svhs_ch = 0x04; svhs_cl = 0x04;
-	   cvbs_ch = 0x08; cvbs_cl = 0x04;
-	}
-    } 
-
-    if(vga2_ch || vga2_cl || vga2_bh || vga2_bl) {
-       haveresult = 0;
-       for(j = 0; j < 10; j++) {
-          result = 0;
-          for(i = 0; i < 3; i++) {
-             if(SISDoSense(vga2_bl, vga2_bh, vga2_cl, vga2_ch))
-	        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);
-       }
+    inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
     }
-
-    haveresult = 0;
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          if(SISDoSense(svhs_bl, svhs_bh, svhs_cl, svhs_ch))
-	        result++;
+    
+    if(!(ivideo->vbflags & VB_301C)) {
+       SISDoSense(ivideo, 0, 0);
+    }
+  
+    andSISIDXREG(SISCR, 0x32, ~0x14);
+  
+    if(vga2_c || vga2) {
+       if(SISDoSense(ivideo, vga2, vga2_c)) {
+          if(biosflag & 0x01) {
+	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);  
+	     orSISIDXREG(SISCR, 0x32, 0x04);
+	  } else {
+	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
+	     orSISIDXREG(SISCR, 0x32, 0x10);
+	  }
        }
-       if((result == 0) || (result >= 2)) break;
     }
-    if(result) {
-        printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-	ivideo.vbflags |= TV_SVIDEO;
-	orSISIDXREG(SISCR, 0x32, 0x02);
-	andSISIDXREG(SISCR, 0x32, ~0x05);
+  
+    andSISIDXREG(SISCR, 0x32, 0x3f);
+    
+    if(ivideo->vbflags & VB_301C) {
+       orSISIDXREG(SISPART4,0x0d,0x04);
     }
 
-    if(!result) {
+    if((ivideo->sisvga_engine == SIS_315_VGA) && 
+       (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
+          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
+	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);  
+	     orSISIDXREG(SISCR,0x32,0x80);
+	  }
+       }
+       outSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    }
+  
+    andSISIDXREG(SISCR, 0x32, ~0x03);
 
-	haveresult = 0;
-       	for(j = 0; j < 10; j++) {
-           result = 0;
-           for(i = 0; i < 3; i++) {
-              if(SISDoSense(cvbs_bl, cvbs_bh, cvbs_cl, cvbs_ch))
-	        result++;
-           }
-           if((result == 0) || (result >= 2)) break;
-        }
-	if(result) {
-	    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);
-	}
+    if(!(ivideo->vbflags & TV_YPBPR)) {
+       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
+          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
+          orSISIDXREG(SISCR, 0x32, 0x02);
+       }
+       if((biosflag & 0x02) || (!result)) {
+          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
+	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
+	     orSISIDXREG(SISCR, 0x32, 0x01);
+          }
+       }
     }
-    SISDoSense(0, 0, 0, 0);
+
+    SISDoSense(ivideo, 0, 0);
 
     outSISIDXREG(SISPART2,0x00,backupP2_00);
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    outSISIDXREG(SISSR,0x1e,backupSR_1e);
+    
+    if(ivideo->vbflags & VB_301C) {
+       inSISIDXREG(SISPART2,0x00,biosflag);
+       if(biosflag & 0x20) {
+          for(myflag = 2; myflag > 0; myflag--) {
+	     biosflag ^= 0x20;
+	     outSISIDXREG(SISPART2,0x00,biosflag);
+	  }
+       }
+    }
+    
+    outSISIDXREG(SISPART2,0x00,backupP2_00);
 }
 
 /* Determine and detect attached TV's on Chrontel */
-static void __devinit SiS_SenseCh(void)
+static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
 {
-   u8 temp1, temp2;
+    u8 temp1, temp2;
 #ifdef CONFIG_FB_SIS_300
-   unsigned char test[3];
-   int i;
+    unsigned char test[3];
+    int i;
 #endif
-   char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
+    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
 
-   if(ivideo.chip < SIS_315H) {
+    if(ivideo->chip < SIS_315H) {
 
 #ifdef CONFIG_FB_SIS_300
-       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);
+       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
+       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        /* See Chrontel TB31 for explanation */
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
        if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
-	  SiS_SetCH700x(&SiS_Pr, 0x0b0e);
-	  SiS_DDC2Delay(&SiS_Pr, 300);
+	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
        }
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x25);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        if(temp2 != temp1) temp1 = temp2;
 
        if((temp1 >= 0x22) && (temp1 <= 0x50)) {
 	   /* Read power status */
-	   temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
 	   if((temp1 & 0x03) != 0x03) {
      	        /* Power all outputs */
-		SiS_SetCH700x(&SiS_Pr, 0x0B0E);
-		SiS_DDC2Delay(&SiS_Pr, 300);
+		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
 	   }
 	   /* 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);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       temp1 = SiS_GetCH700x(&ivideo->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);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	   }
 
 	   if(test[0] == test[1])      temp1 = test[0];
@@ -2976,369 +2862,211 @@
 	   }
 	   if(temp1 == 0x02) {
 		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-		ivideo.vbflags |= TV_SVIDEO;
+		ivideo->vbflags |= TV_SVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x02);
 		andSISIDXREG(SISCR, 0x32, ~0x05);
 	   } else if (temp1 == 0x01) {
 		printk(KERN_INFO "%s CVBS output\n", stdstr);
-		ivideo.vbflags |= TV_AVIDEO;
+		ivideo->vbflags |= TV_AVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x01);
 		andSISIDXREG(SISCR, 0x32, ~0x06);
 	   } else {
- 		SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+ 		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 		andSISIDXREG(SISCR, 0x32, ~0x07);
 	   }
        } else if(temp1 == 0) {
-	  SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 	  andSISIDXREG(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
-       SiS_SetChrontelGPIO(&SiS_Pr, 0x00);
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
 #endif
 
-   } else {
+    } else {
 
 #ifdef CONFIG_FB_SIS_315
-	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);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
+	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
+        temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
 	temp2 |= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	temp2 ^= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
-	SiS_SetCH701x(&SiS_Pr, (temp1 << 8) | 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
         temp1 = 0;
 	if(temp2 & 0x02) temp1 |= 0x01;
 	if(temp2 & 0x10) temp1 |= 0x01;
 	if(temp2 & 0x04) temp1 |= 0x02;
 	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
 	switch(temp1) {
-	case 0x01:
-	     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 "%s SVIDEO output\n", stdstr);
-	     ivideo.vbflags |= TV_SVIDEO;
-	     orSISIDXREG(SISCR, 0x32, 0x02);
-	     andSISIDXREG(SISCR, 0x32, ~0x05);
-             break;
-	case 0x04:
-	     printk(KERN_INFO "%s SCART output\n", stdstr);
-	     orSISIDXREG(SISCR, 0x32, 0x04);
-	     andSISIDXREG(SISCR, 0x32, ~0x03);
-             break;
-	default:
-	     andSISIDXREG(SISCR, 0x32, ~0x07);
-	}
-#endif
-
-   }
-}
-
-
-/* ------------------------ Heap routines -------------------------- */
-
-static int __devinit
-sisfb_heap_init(void)
-{
-	SIS_OH *poh;
-	u8 temp=0;
-#ifdef CONFIG_FB_SIS_315
-	int            agp_enabled = 1;
-	u32            agp_size;
-	unsigned long  *cmdq_baseport = 0;
-	unsigned long  *read_port = 0;
-	unsigned long  *write_port = 0;
-	SIS_CMDTYPE    cmd_type;
-#ifndef AGPOFF
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-	struct agp_kern_info  *agp_info;
-	struct agp_memory     *agp;
-#else
-	agp_kern_info  *agp_info;
-	agp_memory     *agp;
-#endif
-	unsigned long  agp_phys;
-#endif
-#endif
-/*     The heap start is either set manually using the "mem" parameter, or
- *     defaults as follows:
- *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
- *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
- *     -) If 4MB or less is available, let it start at 4MB.
- *     This is for avoiding a clash with X driver which uses the beginning
- *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
- *     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.sisvga_engine == SIS_300_VGA) {
-           if (ivideo.video_size > 0x1000000) {
-	        ivideo.heapstart = 0xc00000;
-	   } else if (ivideo.video_size > 0x800000) {
-	        ivideo.heapstart = 0x800000;
-	   } else {
-		ivideo.heapstart = 0x400000;
-	   }
-	} else {
-	   ivideo.heapstart = ivideo.video_size - 0x100000;
-	}
-     } else {
-           ivideo.heapstart = sisfb_mem * 1024;
-     }
-     sisfb_heap_start = (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
-     printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",
-     					(int)(ivideo.heapstart / 1024));
-
-     sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
-     sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
-
-#ifdef CONFIG_FB_SIS_315
-     if(ivideo.sisvga_engine == SIS_315_VGA) {
-        /* Now initialize the 315/330 series' command queue mode.
-	 * 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
-	 *    on. This is the one comparable to the 300 series.
-	 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
-	 *    have to do queue management himself. Register 0x85c4 will
-	 *    hold the location of the next free queue slot, 0x85c8
-	 *    is the "queue read pointer" whose way of working is
-	 *    unknown to me. Anyway, this mode would require a
-	 *    translation of the MMIO commands to some kind of
-	 *    accelerator assembly and writing these commands
-	 *    to the memory location pointed to by 0x85c4.
-	 *    We will not use this, as nobody knows how this
-	 *    "assembly" works, and as it would require a complete
-	 *    re-write of the accelerator code.
-	 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
-	 *    queue in AGP memory space.
-	 *
-	 * SR26 bit 4 is called "Bypass H/W queue".
-	 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
-	 * SR26 bit 0 resets the queue
-	 * Size of queue memory is encoded in bits 3:2 like this:
-	 *    00  (0x00)  512K
-	 *    01  (0x04)  1M
-	 *    10  (0x08)  2M
-	 *    11  (0x0C)  4M
-	 * The queue location is to be written to 0x85C0.
-	 *
-         */
-	cmdq_baseport = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
-	write_port    = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
-	read_port     = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
-
-	DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
-
-	agp_size  = COMMAND_QUEUE_AREA_SIZE;
-
-#ifndef AGPOFF
-	if (sisfb_queuemode == AGP_CMD_QUEUE) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-		agp_info = vmalloc(sizeof(*agp_info));
-		memset((void*)agp_info, 0x00, sizeof(*agp_info));
-#else
-		agp_info = vmalloc(sizeof(agp_kern_info));
-		memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
-#endif
-		agp_copy_info(agp_info);
-
-		agp_backend_acquire();
-
-		agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
-					  AGP_NORMAL_MEMORY);
-		if (agp == NULL) {
-			DPRINTK("sisfb: Allocating AGP buffer failed.\n");
-			agp_enabled = 0;
-		} else {
-			if (agp_bind_memory(agp, agp->pg_start) != 0) {
-				DPRINTK("sisfb: AGP: Failed to bind memory\n");
-				/* TODO: Free AGP memory here */
-				agp_enabled = 0;
-			} else {
-				agp_enable(0);
-			}
-		}
+	case 0x01:
+	     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 "%s SVIDEO output\n", stdstr);
+	     ivideo->vbflags |= TV_SVIDEO;
+	     orSISIDXREG(SISCR, 0x32, 0x02);
+	     andSISIDXREG(SISCR, 0x32, ~0x05);
+             break;
+	case 0x04:
+	     printk(KERN_INFO "%s SCART output\n", stdstr);
+	     orSISIDXREG(SISCR, 0x32, 0x04);
+	     andSISIDXREG(SISCR, 0x32, ~0x03);
+             break;
+	default:
+	     andSISIDXREG(SISCR, 0x32, ~0x07);
 	}
-#else
-	agp_enabled = 0;
 #endif
+    }
+}
 
-	/* Now select the queue mode */
+/* ------------------------ Heap routines -------------------------- */
 
-	if((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
-		cmd_type = AGP_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using AGP queue mode\n");
-        } else if (sisfb_queuemode == VM_CMD_QUEUE) {
-		cmd_type = VM_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
+{	
+	u32 ret = ivideo->sisfb_parm_mem * 1024;
+	u32 max = ivideo->video_size - ivideo->hwcursor_size;
+	u32 def;
+	
+	/* Calculate heap start = end of memory for console
+	 * 
+	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
+	 * 
+	 * Basically given by "mem" parameter
+	 *
+	 * maximum = videosize - cmd_queue - hwcursor 
+	 *           (results in a heap of size 0)
+	 * default = SiS 300: depends on videosize 
+	 *           SiS 315/330: 32k below max   
+	 */
+	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   max -= TURBO_QUEUE_AREA_SIZE;
+	   if(ivideo->video_size > 0x1000000) {
+	      def = 0xc00000;
+	   } else if(ivideo->video_size > 0x800000) {
+	      def = 0x800000;
+	   } else {
+	      def = 0x400000;
+	   }
 	} else {
-		printk(KERN_INFO "sisfb: Using MMIO queue mode\n");
-		cmd_type = MMIO_CMD;
-	}
-
-	switch (agp_size) {
-	   case 0x80000:
-		temp = SIS_CMD_QUEUE_SIZE_512k;
-		break;
-	   case 0x100000:
-		temp = SIS_CMD_QUEUE_SIZE_1M;
-		break;
-	   case 0x200000:
-		temp = SIS_CMD_QUEUE_SIZE_2M;
-		break;
-	   case 0x400000:
-		temp = SIS_CMD_QUEUE_SIZE_4M;
-		break;
+	   max -= COMMAND_QUEUE_AREA_SIZE;
+	   def = max - 0x8000;
 	}
+	
+        if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
+	   ret = def;
+        } 
+	
+	return ret;
+}
 
-	switch (cmd_type) {
-	   case AGP_CMD_QUEUE:
-#ifndef AGPOFF
-		DPRINTK("sisfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
-			agp_info->aper_base, agp->physical, agp_size/1024);
-
-		agp_phys = agp_info->aper_base + agp->physical;
-
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, 0);
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, SIS_AGP_2X);
-
-                outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= SIS_AGP_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = agp_phys;
-
-		ivideo.caps |= AGP_CMD_QUEUE_CAP;
-#endif
-		break;
-
-	   case VM_CMD_QUEUE:
-		sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= SIS_VRAM_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
-
-		ivideo.caps |= VM_CMD_QUEUE_CAP;
-
-		break;
-
-	   default:  /* MMIO */
-	   	sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		/* Set Auto_Correction bit */
-		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+     SIS_OH *poh;
 
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
+     ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
+     
+     ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+     ivideo->sisfb_heap_end   = ivideo->video_vbase + ivideo->video_size;
+     
+     /* Initialize command queue (We use MMIO only) */
 
-		ivideo.caps |= MMIO_CMD_QUEUE_CAP;
+#ifdef CONFIG_FB_SIS_315
+     if(ivideo->sisvga_engine == SIS_315_VGA) {
+        u32 tempq = 0;
+	u8  temp = 0;
+	     
+        ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+	tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+	temp = SIS_CMD_QUEUE_SIZE_512k;
+	temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+	
+	tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
 
-		break;
-	}
-     } /* sisvga_engine = 315 */
+	ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+     } 
 #endif
 
 #ifdef CONFIG_FB_SIS_300
-     if(ivideo.sisvga_engine == SIS_300_VGA) {
-  	    /* Now initialize TurboQueue. TB is always located at the very
-	     * top of the video RAM. */
-	    if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
-		unsigned int  tqueue_pos;
-		u8 tq_state;
-
-		tqueue_pos = (ivideo.video_size -
-		       TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
-
-		temp = (u8) (tqueue_pos & 0xff);
-
-		inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-		tq_state |= 0xf0;
-		tq_state &= 0xfc;
-		tq_state |= (u8) (tqueue_pos >> 8);
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
-
-		ivideo.caps |= TURBO_QUEUE_CAP;
+     if(ivideo->sisvga_engine == SIS_300_VGA) {
+     	unsigned long tqueue_pos;
+	u8 tq_state;
+ 
+	ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+
+	tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+
+	inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+	tq_state |= 0xf0;
+	tq_state &= 0xfc;
+	tq_state |= (u8)(tqueue_pos >> 8);
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
 
-		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
 
-	    }
+	ivideo->caps |= TURBO_QUEUE_CAP;
      }
 #endif
-     /* Now reserve memory for the HWCursor. It is always located at the very
-        top of the videoRAM, right below the TB memory area (if used). */
-     if(sisfb_heap_size >= ivideo.hwcursor_size) {
-		sisfb_heap_end -= ivideo.hwcursor_size;
-		sisfb_heap_size -= ivideo.hwcursor_size;
-		ivideo.hwcursor_vbase = sisfb_heap_end;
-
-		ivideo.caps |= HW_CURSOR_CAP;
-     }
-
-     sisfb_heap.poha_chain = NULL;
-     sisfb_heap.poh_freelist = NULL;
 
-     poh = sisfb_poh_new_node();
-
-     if(poh == NULL)  return 1;
+     /* Reserve memory for the HWCursor */
+     ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
+     ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
+     ivideo->caps |= HW_CURSOR_CAP;
+     
+     ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
+     
+     if(ivideo->cardnumber == 0) {
+      
+     	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+     		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+     
+	sisfb_heap.vinfo = ivideo;
 	
-     poh->poh_next = &sisfb_heap.oh_free;
-     poh->poh_prev = &sisfb_heap.oh_free;
-     poh->size = sisfb_heap_end - sisfb_heap_start + 1;
-     poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
-
-     DPRINTK("sisfb: Heap start:0x%p, end:0x%p, len=%dk\n",
-		(char *) sisfb_heap_start, (char *) sisfb_heap_end,
-		(unsigned int) poh->size / 1024);
-
-     DPRINTK("sisfb: First Node offset:0x%x, size:%dk\n",
-		(unsigned int) poh->offset, (unsigned int) poh->size / 1024);
-
-     sisfb_heap.oh_free.poh_next = poh;
-     sisfb_heap.oh_free.poh_prev = poh;
-     sisfb_heap.oh_free.size = 0;
-     sisfb_heap.max_freesize = poh->size;
+     	sisfb_heap.poha_chain = NULL;
+     	sisfb_heap.poh_freelist = NULL;
 
-     sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.size = SENTINEL;
+     	poh = sisfb_poh_new_node();
+     	if(poh == NULL) return 1;
+	
+     	poh->poh_next = &sisfb_heap.oh_free;
+     	poh->poh_prev = &sisfb_heap.oh_free;
+     	poh->size = ivideo->sisfb_heap_size;
+     	poh->offset = ivideo->heapstart;
+
+     	sisfb_heap.oh_free.poh_next = poh;
+     	sisfb_heap.oh_free.poh_prev = poh;
+     	sisfb_heap.oh_free.size = 0;
+     	sisfb_heap.max_freesize = poh->size;
+
+     	sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.size = SENTINEL;
+	
+     } else {
+     
+        printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+	
+     }
 
      return 0;
 }
@@ -3352,13 +3080,13 @@
 	SIS_OH        *poh;
 
 	if(sisfb_heap.poh_freelist == NULL) {
-		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
 		if(!poha) return NULL;
 
 		poha->poha_next = sisfb_heap.poha_chain;
 		sisfb_heap.poha_chain = poha;
 
-		cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
 		for(i = cOhs - 1; i != 0; i--) {
@@ -3377,14 +3105,14 @@
 }
 
 static SIS_OH *
-sisfb_poh_allocate(unsigned long size)
+sisfb_poh_allocate(u32 size)
 {
 	SIS_OH *pohThis;
 	SIS_OH *pohRoot;
 	int     bAllocated = 0;
 
 	if(size > sisfb_heap.max_freesize) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
@@ -3400,7 +3128,7 @@
 	}
 
 	if(!bAllocated) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
@@ -3458,15 +3186,15 @@
 }
 
 static SIS_OH *
-sisfb_poh_free(unsigned long base)
+sisfb_poh_free(u32 base)
 {
 	SIS_OH *pohThis;
 	SIS_OH *poh_freed;
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
-	unsigned long ulUpper;
-	unsigned long ulLower;
-	int foundNode = 0;
+	u32     ulUpper;
+	u32     ulLower;
+	int     foundNode = 0;
 
 	poh_freed = sisfb_heap.oh_used.poh_next;
 
@@ -3479,7 +3207,7 @@
 		poh_freed = poh_freed->poh_next;
 	}
 
-	if(!foundNode)  return(NULL);
+	if(!foundNode) return(NULL);
 
 	sisfb_heap.max_freesize += poh_freed->size;
 
@@ -3492,8 +3220,7 @@
 	while(pohThis != &sisfb_heap.oh_free) {
 		if(pohThis->offset == ulUpper) {
 			poh_next = pohThis;
-		}
-			else if((pohThis->offset + pohThis->size) == ulLower) {
+		} else if((pohThis->offset + pohThis->size) == ulLower) {
 			poh_prev = pohThis;
 		}
 		pohThis = pohThis->poh_next;
@@ -3539,29 +3266,35 @@
 void
 sis_malloc(struct sis_memreq *req)
 {
-	SIS_OH *poh;
-
-	poh = sisfb_poh_allocate(req->size);
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
+	SIS_OH *poh = NULL;
+	
+	if((ivideo) && (!ivideo->havenoheap)) {
+	   poh = sisfb_poh_allocate((u32)req->size);
+	}
 
 	if(poh == NULL) {
-		req->offset = 0;
-		req->size = 0;
-		DPRINTK("sisfb: Video RAM allocation failed\n");
+	   req->offset = req->size = 0;
+	   DPRINTK("sisfb: Video RAM allocation failed\n");
 	} else {
-		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%p\n",
-			(char *) (poh->offset + (unsigned long) ivideo.video_vbase));
-
-		req->offset = poh->offset;
-		req->size = poh->size;
+	   req->offset = poh->offset;
+	   req->size = poh->size;
+	   DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+	   	    (poh->offset + ivideo->video_vbase));
 	}
 }
 
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+
 void
-sis_free(unsigned long base)
+sis_free(u32 base)
 {
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
 	SIS_OH *poh;
+	
+	if((!ivideo) || (ivideo->havenoheap)) return;
 
-	poh = sisfb_poh_free(base);
+	poh = sisfb_poh_free((u32)base);
 
 	if(poh == NULL) {
 		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3572,101 +3305,285 @@
 /* --------------------- SetMode routines ------------------------- */
 
 static void
-sisfb_pre_setmode(void)
+sisfb_pre_setmode(struct sis_video_info *ivideo)
 {
-	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
+	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
+	int tvregnum = 0;
 	
-	ivideo.currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
 	inSISIDXREG(SISCR, 0x31, cr31);
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 	
-	cr33 = ivideo.rate_idx & 0x0F;
+	cr33 = ivideo->rate_idx & 0x0F;
 
-	SiS_SetEnableDstn(&SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&SiS_Pr, FALSE);
+#ifdef CONFIG_FB_SIS_315			
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(ivideo->chip >= SIS_661) {
+	      inSISIDXREG(SISCR, 0x38, cr38);
+	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   } else {
+	      tvregnum = 0x38;
+	      inSISIDXREG(SISCR, tvregnum, cr38);
+	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   }
+	}
+#endif	   	
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   tvregnum = 0x35;
+	   inSISIDXREG(SISCR, tvregnum, cr38);
+	}
+#endif	
+	
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
 
-	switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+	
 	   case CRT2_TV:
-		ivideo.disp_state = DISPTYPE_TV;
-		if (ivideo.vbflags & TV_SVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_SVIDEO;
-			ivideo.TV_plug = TVPLUG_SVIDEO;
-		} else if (ivideo.vbflags & TV_AVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			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(!(ivideo.vbflags & TV_HIVISION)) {
-	        	if (ivideo.vbflags & TV_PAL) {
-		 		cr31 |= 0x01;
-				cr35 |= 0x01;
-				ivideo.currentvbflags |= TV_PAL;
-				ivideo.TV_type = TVMODE_PAL;
-                	} else {
-		       		cr31 &= ~0x01;
-				cr35 &= ~0x01;
-				ivideo.currentvbflags |= TV_NTSC;
-				ivideo.TV_type = TVMODE_NTSC;
-			}
-		}
-		break;
+	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
+	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+#ifdef CONFIG_FB_SIS_315	      
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
+		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 
+		    cr35 &= ~0x01;		    
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	            cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    cr38 |= 0x08;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
+		    cr31 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         }
+#endif		 
+	      } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            cr35 |= 0x60;
+	         } else {
+	            cr30 |= 0x80;
+	         }
+		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 
+	         cr31 |= 0x01;
+	         cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_HIVISION;
+	      } else if(ivideo->vbflags & TV_SCART) {
+		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		 cr31 |= 0x01;
+		 cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_SCART;
+	      } else {
+		 if(ivideo->vbflags & TV_SVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_SVIDEO;
+		 }
+		 if(ivideo->vbflags & TV_AVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_AVIDEO;
+		 }
+	      }
+	      cr31 |= SIS_DRIVER_MODE;
+
+	      if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
+	         if(ivideo->vbflags & TV_PAL) {
+		    cr31 |= 0x01; cr35 |= 0x01;
+		    ivideo->currentvbflags |= TV_PAL;
+		    if(ivideo->vbflags & TV_PALM) {
+		       cr38 |= 0x40; cr35 |= 0x04; 
+		       ivideo->currentvbflags |= TV_PALM;
+		    } else if(ivideo->vbflags & TV_PALN) {
+		       cr38 |= 0x80; cr35 |= 0x08; 
+		       ivideo->currentvbflags |= TV_PALN;
+	  	    }
+                 } else {
+		    cr31 &= ~0x01; cr35 &= ~0x01;
+		    ivideo->currentvbflags |= TV_NTSC;
+		    if(ivideo->vbflags & TV_NTSCJ) {
+		       cr38 |= 0x40; cr35 |= 0x02; 
+		       ivideo->currentvbflags |= TV_NTSCJ;
+	 	    }
+		 }
+	      }
+	      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;		
+	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
+	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->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 |= ((ivideo.rate_idx & 0x0F) << 4);
-		}
-		break;
+	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      if(ivideo->sisfb_nocrt2rate) {
+		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
+	      } else {
+		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
+	      }
+	      break;
+	      
 	   default:	/* disable CRT2 */
-		cr30 = 0x00;
-		cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
+	      cr30 = 0x00;
+	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 	}
 
-	if(ivideo.chip >= SIS_661) {
-	   cr31 &= ~0x01;
-	   /* Leave overscan bit alone */
-	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35);
-	}
-	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, 0x30, cr30);
+	outSISIDXREG(SISCR, 0x33, cr33);
 
-#ifdef CONFIG_FB_SIS_315
-        if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   /* Clear LCDA and PAL-N/M bits */
-	   andSISIDXREG(SISCR,0x38,~0x03);
-	   if(ivideo.chip < SIS_661) {
-	      andSISIDXREG(SISCR,0x38,~0xc0);
-	   }
-	}
+	if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315		
+	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
+	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
+	   setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
+#endif	   
+	} else if(ivideo->chip != SIS_300) {
+	   outSISIDXREG(SISCR, tvregnum, cr38);
+	}
+	outSISIDXREG(SISCR, 0x31, cr31);
+
+	if(ivideo->accel) sisfb_syncaccel(ivideo);
+
+	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+}
+
+/* Fix SR11 for 661 and later */
+#ifdef CONFIG_FB_SIS_315 
+static void    
+sisfb_fixup_SR11(struct sis_video_info *ivideo)
+{
+    u8  tmpreg;
+    
+    if(ivideo->chip >= SIS_661) {
+       inSISIDXREG(SISSR,0x11,tmpreg);
+       if(tmpreg & 0x20) {
+          inSISIDXREG(SISSR,0x3e,tmpreg);
+	  tmpreg = (tmpreg + 1) & 0xff;
+	  outSISIDXREG(SISSR,0x3e,tmpreg);   	  
+	  inSISIDXREG(SISSR,0x11,tmpreg);
+       }
+       if(tmpreg & 0xf0) {
+          andSISIDXREG(SISSR,0x11,0x0f);
+       }
+    }
+}    
 #endif
 
-	if(ivideo.accel) sisfb_syncaccel();
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvxpos = val;
+   
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int x = ivideo->tvx;
+
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	     x += val;
+	     if(x < 0) x = 0;
+	     outSISIDXREG(SISSR,0x05,0x86);
+	     SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
+	     SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
+	     break;
+	 case 2:
+	     /* Not supported by hardware */
+	     break;
+	 }
+
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
+
+	 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+	 unsigned short temp;
+
+	 p2_1f = ivideo->p2_1f;
+	 p2_20 = ivideo->p2_20;
+	 p2_2b = ivideo->p2_2b;
+	 p2_42 = ivideo->p2_42;
+	 p2_43 = ivideo->p2_43;
+
+	 temp = p2_1f | ((p2_20 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_1f = temp & 0xff;
+	 p2_20 = (temp & 0xf00) >> 4;
+	 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+	 temp = p2_43 | ((p2_42 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_43 = temp & 0xff;
+	 p2_42 = (temp & 0xf00) >> 4;
+	 outSISIDXREG(SISPART2,0x1f,p2_1f);
+	 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+	 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+	 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+	 outSISIDXREG(SISPART2,0x43,p2_43);
+      }
+   }
+}
+ 
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvypos = val;
+   
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+      
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int y = ivideo->tvy;
+	 
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	    y -= val;
+	    if(y < 0) y = 0;
+	    outSISIDXREG(SISSR,0x05,0x86);
+	    SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
+	    SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
+	    break;
+	 case 2:
+	    /* Not supported by hardware */
+	    break;
+	 }
 
-	SiS_Pr.SiS_UseOEM = sisfb_useoem;
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
+	 
+	 char p2_01, p2_02;
+	 val /= 2;  
+	 p2_01 = ivideo->p2_01;
+	 p2_02 = ivideo->p2_02;
+
+	 p2_01 += val; 
+	 p2_02 += val; 
+	 while((p2_01 <= 0) || (p2_02 <= 0)) {
+	    p2_01 += 2;
+	    p2_02 += 2;
+	 }
+	 outSISIDXREG(SISPART2,0x01,p2_01);
+	 outSISIDXREG(SISPART2,0x02,p2_02);
+      }
+   }
 }
 
 static void
-sisfb_post_setmode(void)
+sisfb_post_setmode(struct sis_video_info *ivideo)
 {
 	u8 reg;
 	BOOLEAN crt1isoff = FALSE;
@@ -3675,32 +3592,23 @@
 	u8 reg1;
 #endif
 
-	/* Now we actually HAVE changed the display mode */
-        ivideo.modechanged = 1;
-
-	/* We can't switch off CRT1 if bridge is in slave mode */
-	if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-		inSISIDXREG(SISPART1, 0x00, reg);
-#ifdef CONFIG_FB_SIS_300
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
-			if((reg & 0xa0) == 0x20) {
-				doit = FALSE;
-			}
-		}
-#endif
+	outSISIDXREG(SISSR,0x05,0x86);
+	
 #ifdef CONFIG_FB_SIS_315
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
-			if((reg & 0x50) == 0x10) {
-				doit = FALSE;
-			}
-		}
+	sisfb_fixup_SR11(ivideo);
 #endif
-	} else sisfb_crt1off = 0;
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	/* Now we actually HAVE changed the display mode */
+        ivideo->modechanged = 1;
+
+	/* We can't switch off CRT1 if bridge is in slave mode */
+	if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
+	} else ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
-	   if((sisfb_crt1off) && (doit)) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg = 0x00;
 	   } else {
@@ -3708,12 +3616,11 @@
 		reg = 0x80;
 	   }
 	   setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+	}
 #endif
-
-	} else {
-
 #ifdef CONFIG_FB_SIS_315
-	   if((sisfb_crt1off) && (doit)) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg  = 0x40;
 		reg1 = 0xc0;
@@ -3723,66 +3630,89 @@
 		reg1 = 0x00;
 
 	   }
-	   setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, ~0x40, reg);
+	   setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
 	   setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
-#endif
-
 	}
+#endif
 
 	if(crt1isoff) {
-	   ivideo.currentvbflags &= ~VB_DISPTYPE_CRT1;
-	   ivideo.currentvbflags |= VB_SINGLE_MODE;
-	   ivideo.disp_state |= DISPMODE_SINGLE;
+	   ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+	   ivideo->currentvbflags |= VB_SINGLE_MODE;
 	} 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;
+	   ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+	   if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+	  	ivideo->currentvbflags |= VB_MIRROR_MODE;
 	   } else {
-	 	ivideo.currentvbflags |= VB_SINGLE_MODE;
-		ivideo.disp_state |= DISPMODE_SINGLE;
+	 	ivideo->currentvbflags |= VB_SINGLE_MODE;
 	   }
 	}
 
         andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+	
+	if(ivideo->currentvbflags & CRT2_TV) {
+	   if(ivideo->vbflags & VB_SISBRIDGE) {
+	      inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+	      inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+	      inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+	      inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+	      inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+	      inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+	      inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+	   } else if(ivideo->vbflags & VB_CHRONTEL) {
+	      if(ivideo->chronteltype == 1) {
+	         ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+	         ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+	         ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+	         ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+ 	      }
+	   }
+	}
+
+	if(ivideo->tvxpos) {
+   	   sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+	}
+	if(ivideo->tvypos) {
+   	   sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+	}
 
-	if((ivideo.currentvbflags & CRT2_TV) && (ivideo.vbflags & VB_301)) {  /* Set filter for SiS301 */
+	if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) {  /* Set filter for SiS301 */
+	
+	   	unsigned char filter_tb = 0;
 
-		switch (ivideo.video_width) {
+		switch (ivideo->video_width) {
 		   case 320:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 4 : 12;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
 			break;
 		   case 640:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 5 : 13;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
 			break;
 		   case 720:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 6 : 14;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
 			break;
 		   case 400:
 		   case 800:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 7 : 15;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
 			break;
 		   default:
-			filter = -1;
+			ivideo->sisfb_filter = -1;
 			break;
 		}
 
-		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
 
-		if(ivideo.vbflags & TV_NTSC) {
+		if(ivideo->vbflags & TV_NTSC) {
 
 		        andSISIDXREG(SISPART2, 0x3a, 0x1f);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xdf);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 				        outSISIDXREG(SISPART2, 0x35, 0xEB);
 					outSISIDXREG(SISPART2, 0x36, 0x04);
@@ -3805,19 +3735,19 @@
 				}
 			}
 
-		} else if(ivideo.vbflags & TV_PAL) {
+		} else if(ivideo->vbflags & TV_PAL) {
 
 			andSISIDXREG(SISPART2, 0x3A, 0x1F);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xDF);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 					outSISIDXREG(SISPART2, 0x35, 0xF1);
 					outSISIDXREG(SISPART2, 0x36, 0xF7);
@@ -3841,11 +3771,11 @@
 			}
 		}
 
-		if((filter >= 0) && (filter <= 7)) {
-			outSISIDXREG(SISPART2, 0x35, (sis_TV_filter[filter_tb].filter[filter][0]));
-			outSISIDXREG(SISPART2, 0x36, (sis_TV_filter[filter_tb].filter[filter][1]));
-			outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
-			outSISIDXREG(SISPART2, 0x38, (sis_TV_filter[filter_tb].filter[filter][3]));
+		if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
+		   outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
+		   outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
+		   outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
+		   outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
 		}
 	  
 	}
@@ -3856,30 +3786,28 @@
 {
 	char *this_opt;
 	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	sisfb_fontname[0] = '\0';
-#endif
-
-	ivideo.refresh_rate = 0;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.CenterScreen = -1;
-	SiS_Pr.LVDSHL = -1;
-#if !defined(__i386__) && !defined(__x86_64__)
-       	sisfb_resetcard = 0;
-	sisfb_videoram = 0;
-#endif
+	sisfb_setdefaultparms();
 
         printk(KERN_DEBUG "sisfb: Options %s\n", options);
 
-	if(!options || !(*options))
+	if(!options || !(*options)) {
 		return 0;
+	}
 
 	while((this_opt = strsep(&options, ",")) != NULL) {
 
 		if(!(*this_opt)) continue;
-
-		if(!strnicmp(this_opt, "mode:", 5)) {
+		
+		if(!strnicmp(this_opt, "off", 3)) {
+			sisfb_off = 1;
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+			/* Need to check crt2 type first for fstn/dstn */
+			sisfb_search_crt2type(this_opt + 14);
+		} else if(!strnicmp(this_opt, "tvmode:",7)) {
+		        sisfb_search_tvstd(this_opt + 7);
+                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+			sisfb_search_tvstd(this_opt + 7);
+		} else 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);
@@ -3893,40 +3821,30 @@
 			   sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
 			}
 #endif
-		} else if(!strnicmp(this_opt, "vrate:", 6)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
 		} else if(!strnicmp(this_opt, "rate:", 5)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if(!strnicmp(this_opt, "off", 3)) {
-			sisfb_off = 1;
-		} else if(!strnicmp(this_opt, "crt1off", 7)) {
-			sisfb_crt1off = 1;
+			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "filter:", 7)) {
-			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
-			sisfb_search_crt2type(this_opt + 14);
+			sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
 		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if(!strnicmp(this_opt, "tvmode:",7)) {
-		        sisfb_search_tvstd(this_opt + 7);
-                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
-			sisfb_search_tvstd(this_opt + 7);
                 } else if(!strnicmp(this_opt, "mem:",4)) {
-		        sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if(!strnicmp(this_opt, "queuemode:", 10)) {
-			sisfb_search_queuemode(this_opt + 10);
+		        sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
 		} else if(!strnicmp(this_opt, "pdc:", 4)) {
 		        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
 		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
 		        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "noaccel", 7)) {
 			sisfb_accel = 0;
+		} else if(!strnicmp(this_opt, "accel", 5)) {
+			sisfb_accel = -1;			
 		} else if(!strnicmp(this_opt, "noypan", 6)) {
 		        sisfb_ypan = 0;
+		} else if(!strnicmp(this_opt, "ypan", 4)) {
+		        sisfb_ypan = -1;
 		} else if(!strnicmp(this_opt, "nomax", 5)) {
 		        sisfb_max = 0;
+		} else if(!strnicmp(this_opt, "max", 3)) {
+		        sisfb_max = -1;
 		} else if(!strnicmp(this_opt, "userom:", 7)) {
 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
 		} else if(!strnicmp(this_opt, "useoem:", 7)) {
@@ -3937,15 +3855,27 @@
 		        unsigned long temp = 2;
 		        temp = simple_strtoul(this_opt + 9, NULL, 0);
 		        if((temp == 0) || (temp == 1)) {
-			   SiS_Pr.UsePanelScaler = temp ^ 1;
+			   sisfb_scalelcd = temp ^ 1;
+		        }
+		} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvxposoffset = temp;
+		        }
+		} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvyposoffset = temp;
 		        }
 		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
 			sisfb_search_specialtiming(this_opt + 14);
 		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
-		        unsigned long temp = 4;
+		        int temp = 4;
 		        temp = simple_strtoul(this_opt + 7, NULL, 0);
 		        if((temp >= 0) && (temp <= 3)) {
-			   SiS_Pr.LVDSHL = temp;
+			   sisfb_lvdshl = temp;
 		        }
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
 			sisfb_search_mode(this_opt, TRUE);
@@ -3959,18 +3889,18 @@
 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
 		}
 
-		/* Acceleration only with MMIO mode */
-		if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-			sisfb_accel = 0;
-		}
-
 	}
+	
+	
+	
 	return 0;
 }
 #endif
 
 static char * __devinit sis_find_rom(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	
 #if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
         unsigned char *rom_base, *rom;
@@ -3979,38 +3909,38 @@
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-                rom_base = (unsigned char *)ioremap(segstart, 0x10000);
-		if(!rom_base) continue;
+            rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+	    if(!rom_base) continue;
 
-		if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
-		   iounmap(rom_base);
-                   continue;
-		}
+	    if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
+	       iounmap(rom_base);
+               continue;
+	    }
 
-		romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
-		if(romptr > (0x10000 - 8)) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	    if(romptr > (0x10000 - 8)) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		rom = rom_base + romptr;
+	    rom = rom_base + romptr;
 
-		if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
-		   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+	       (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = readb(rom + 4) | (readb(rom + 5) << 8);
-		if(pciid != 0x1039) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+	    if(pciid != 0x1039) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-		if(pciid == ivideo.chip_id) return rom_base;
+	    pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+	    if(pciid == ivideo->chip_id) return rom_base;
 
-		iounmap(rom_base);
+	    iounmap(rom_base);
         }
 #else
 	unsigned char *rom_base, *rom, *myrombase = NULL;
@@ -4020,12 +3950,12 @@
 
 	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &backup);
 	pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
-			(ivideo.video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+			(ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
 
-	rom_base = ioremap(ivideo.video_base, 65536);
+	rom_base = ioremap(ivideo->video_base, 65536);
 	if(rom_base) {
 	   if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
-	      romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	      romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
 	      if(romptr <= (0x10000 - 8)) {
 	         rom = rom_base + romptr;
 		 if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
@@ -4033,7 +3963,7 @@
 		    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
 		    if(pciid == 0x1039) {
 		       pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-		       if(pciid == ivideo.chip_id) {
+		       if(pciid == ivideo->chip_id) {
 		          if((myrombase = vmalloc(65536))) {
 			     memcpy_fromio(myrombase, rom_base, 65536);
 			  }
@@ -4052,8 +3982,9 @@
 
 #ifdef SIS300
 static int __devinit
-sisfb_chkbuswidth300(ULONG FBAddress)
+sisfb_chkbuswidth300(struct pci_dev *pdev, ULONG FBAddress)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	int i, j;
 	USHORT temp;
 	UCHAR reg;
@@ -4091,9 +4022,10 @@
 }
 
 static void __devinit
-sisfb_setramsize300(void)
+sisfb_setramsize300(struct pci_dev *pdev)
 {
-  	ULONG 	FBAddr = (ULONG)sishw_ext.pjVideoMemoryAddress, Addr;
+	struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
+  	ULONG 	FBAddr = (ULONG)ivideo->sishw_ext.pjVideoMemoryAddress, Addr;
 	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
 	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
    	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
@@ -4118,7 +4050,7 @@
 			{0x09,0x08,0x01,0x01,0x00}
 		};
 
-        buswidth = sisfb_chkbuswidth300(FBAddr);
+        buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
 
    	MB2Bank = 16;
    	Done = 0;
@@ -4180,38 +4112,39 @@
    	}  /* for i */
 }
 
-static void __devinit sisfb_post_sis300(void)
+static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
 	u16 index, rindex, memtype = 0;
 
-	outSISIDXREG(SISSR,0x05,SIS_PASSWORD);
+	outSISIDXREG(SISSR,0x05,0x86);
 
-	if(sishw_ext.UseROM) {
-	   if(sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
-	      memtype = sishw_ext.pjVirtualRomBase[0x52];
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
+	      memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
  	   } else {
 	      inSISIDXREG(SISSR,0x3a,memtype);
 	   }
 	   memtype &= 0x07;
 	}
 
-	if(ivideo.revision_id <= 0x13) {
+	if(ivideo->revision_id <= 0x13) {
 	   v1 = 0x44; v2 = 0x42; v3 = 0x80;
 	   v4 = 0x44; v5 = 0x42; v6 = 0x80;
 	} else {
 	   v1 = 0x68; v2 = 0x43; v3 = 0x80;  /* Assume 125Mhz MCLK */
 	   v4 = 0x68; v5 = 0x43; v6 = 0x80;  /* Assume 125Mhz ECLK */
-	   if(sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.UseROM) {
 	      index = memtype * 5;
 	      rindex = index + 0x54;
-	      v1 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v2 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v3 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
 	      rindex = index + 0x7c;
-	      v4 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v5 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v6 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
 	   }
 	}
 	outSISIDXREG(SISSR,0x28,v1);
@@ -4221,23 +4154,23 @@
 	outSISIDXREG(SISSR,0x2f,v5);
 	outSISIDXREG(SISSR,0x30,v6);
 	v1 = 0x10;
-	if(sishw_ext.UseROM) v1 = sishw_ext.pjVirtualRomBase[0xa4];
+	if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
 	outSISIDXREG(SISSR,0x07,v1);       /* DAC speed */
 	outSISIDXREG(SISSR,0x11,0x0f);     /* DDC, power save */
 	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
 	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
-	if(sishw_ext.UseROM) {
+	if(ivideo->sishw_ext.UseROM) {
 	   memtype += 0xa5;
-	   v1 = sishw_ext.pjVirtualRomBase[memtype];
-	   v2 = sishw_ext.pjVirtualRomBase[memtype + 8];
-	   v3 = sishw_ext.pjVirtualRomBase[memtype + 16];
-	   v4 = sishw_ext.pjVirtualRomBase[memtype + 24];
-	   v5 = sishw_ext.pjVirtualRomBase[memtype + 32];
-	   v6 = sishw_ext.pjVirtualRomBase[memtype + 40];
-	   v7 = sishw_ext.pjVirtualRomBase[memtype + 48];
-	   v8 = sishw_ext.pjVirtualRomBase[memtype + 56];
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
+	   v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
+	   v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
+	   v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
 	}
-	if(ivideo.revision_id >= 0x80) v3 &= 0xfd;
+	if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
 	outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
 	outSISIDXREG(SISSR,0x16,v2);
 	outSISIDXREG(SISSR,0x17,v3);
@@ -4248,20 +4181,20 @@
 	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
 	andSISIDXREG(SISSR,0x15,0xfb);
 	orSISIDXREG(SISSR,0x15,0x04);
-	if(sishw_ext.UseROM) {
-	   if(sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
 	      orSISIDXREG(SISSR,0x19,0x20);
 	   }
 	}
 	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
-	if(ivideo.revision_id >= 0x80) v1 |= 0x01;
+	if(ivideo->revision_id >= 0x80) v1 |= 0x01;
 	outSISIDXREG(SISSR,0x1f,v1);
 	outSISIDXREG(SISSR,0x20,0xa0);     /* linear & relocated io */
 	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xe8];
-	   v2 = sishw_ext.pjVirtualRomBase[0xe9];
-	   v3 = sishw_ext.pjVirtualRomBase[0xea];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
 	}
 	outSISIDXREG(SISSR,0x23,v1);
 	outSISIDXREG(SISSR,0x24,v2);
@@ -4272,21 +4205,21 @@
 	orSISIDXREG(SISPART1,0x24,0x01);   /* unlock crt2 */
 	outSISIDXREG(SISPART1,0x00,0x00);
 	v1 = 0x40; v2 = 0x11;
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xec];
-	   v2 = sishw_ext.pjVirtualRomBase[0xeb];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
 	}
 	outSISIDXREG(SISPART1,0x02,v1);
-	if(ivideo.revision_id >= 0x80) v2 &= ~0x01;
+	if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
 	inSISIDXREG(SISPART4,0x00,reg);
 	if((reg == 1) || (reg == 2)) {
 	   outSISIDXREG(SISCR,0x37,0x02);
 	   outSISIDXREG(SISPART2,0x00,0x1c);
 	   v4 = 0x00; v5 = 0x00; v6 = 0x10;
-	   if(sishw_ext.UseROM) {
-	      v4 = sishw_ext.pjVirtualRomBase[0xf5];
-	      v5 = sishw_ext.pjVirtualRomBase[0xf6];
-	      v6 = sishw_ext.pjVirtualRomBase[0xf7];
+	   if(ivideo->sishw_ext.UseROM) {
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
 	   }
 	   outSISIDXREG(SISPART4,0x0d,v4);
 	   outSISIDXREG(SISPART4,0x0e,v5);
@@ -4316,10 +4249,10 @@
 	} else {
 #endif
 	   /* Need to map max FB size for finding out about RAM size */
-	   sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x4000000);
-	   if(sishw_ext.pjVideoMemoryAddress) {
-	      sisfb_setramsize300();
-	      iounmap(sishw_ext.pjVideoMemoryAddress);
+	   ivideo->sishw_ext.pjVideoMemoryAddress = ioremap(ivideo->video_base, 0x4000000);
+	   if(ivideo->sishw_ext.pjVideoMemoryAddress) {
+	      sisfb_setramsize300(pdev);
+	      iounmap(ivideo->sishw_ext.pjVideoMemoryAddress);
 	   } else {
 	      printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
 	      outSISIDXREG(SISSR,0x13,0x28);  /* ? */
@@ -4328,9 +4261,9 @@
 #if !defined(__i386__) && !defined(__x86_64__)
 	}
 #endif
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xe6];
-	   v2 = sishw_ext.pjVirtualRomBase[0xe7];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
 	} else {
 	   inSISIDXREG(SISSR,0x3a,reg);
 	   if((reg & 0x30) == 0x30) {
@@ -4346,182 +4279,203 @@
 }
 #endif
 
-
 int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
-	u32 reg32;
+	struct sisfb_chip_info 	*chipinfo = &sisfb_chip_info[ent->driver_data];
+	struct sis_video_info 	*ivideo = NULL;
+	struct fb_info 		*sis_fb_info = NULL;
 	u16 reg16;
 	u8  reg;
-	int sisvga_enabled = 0;
+	int sisvga_enabled = 0, i;
 
 	if(sisfb_off) return -ENXIO;
 
-	sisfb_thismonitor.datavalid = FALSE;
-
-	memset(&sishw_ext, 0, sizeof(sishw_ext));
-	
-	memset(&ivideo, 0, sizeof(ivideo));
-	ivideo.detectedpdc  = 0xff;
-	ivideo.detectedpdca = 0xff;
-	ivideo.detectedlcda = 0xff;
-
-#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
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
-	sis_fb_info = framebuffer_alloc(0, &pdev->dev);
+	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
+	if(!sis_fb_info) return -ENOMEM;
 #else
-	sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
-#endif
+	sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
 	if(!sis_fb_info) return -ENOMEM;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3))
-	memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+	memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
+	sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-	strcpy(sis_fb_info->modename, chipinfo->chip_name);
-#else
-	strcpy(myid, chipinfo->chip_name);
-#endif
+	ivideo = (struct sis_video_info *)sis_fb_info->par;
+	ivideo->memyselfandi = sis_fb_info;
+	
+	if(card_list == NULL) {
+	   ivideo->cardnumber = 0;
+	} else { 
+	   struct sis_video_info *countvideo = card_list;
+	   ivideo->cardnumber = 1;
+	   while((countvideo = countvideo->next)) ivideo->cardnumber++;
+	}
 
-	ivideo.chip_id = pdev->device;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo.revision_id);
-	sishw_ext.jChipRevision = ivideo.revision_id;
+	strncpy(ivideo->myid, chipinfo->chip_name, 30);
+
+	ivideo->chip_id = pdev->device;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+	ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
 	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
 	sisvga_enabled = reg16 & 0x01;
-	ivideo.pcibus = pdev->bus->number;
-	ivideo.pcislot = PCI_SLOT(pdev->devfn);
-	ivideo.pcifunc = PCI_FUNC(pdev->devfn);
-	ivideo.subsysvendor = pdev->subsystem_vendor;
-	ivideo.subsysdevice = pdev->subsystem_device;
-
-	ivideo.chip = chipinfo->chip;
-	ivideo.sisvga_engine = chipinfo->vgaengine;
-	ivideo.hwcursor_size = chipinfo->hwcursor_size;
-	ivideo.CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->pcibus = pdev->bus->number;
+	ivideo->pcislot = PCI_SLOT(pdev->devfn);
+	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
+	ivideo->subsysvendor = pdev->subsystem_vendor;
+	ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_CONFIG_COMPAT				
+	ivideo->ioctl32registered = 0;
+	ivideo->ioctl32vblankregistered = 0;
+#endif	
 
-	/* Patch special cases */
-	switch(ivideo.chip_id) {
-#ifdef CONFIG_FB_SIS_300
-	   case PCI_DEVICE_ID_SI_630_VGA:
-		{
-			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)
-				strcpy(sis_fb_info->modename, "SIS 730");
-#else
-				strcpy(myid, "SIS 730");
-#endif
-			}
-			break;
-		}
-#endif
-#ifdef CONFIG_FB_SIS_315
-	   case PCI_DEVICE_ID_SI_650_VGA:
-	   	{
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07401039) {
-				ivideo.chip = SIS_740;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 740");
-#else
-				strcpy(myid, "SIS 740");
-#endif
-			}
-			break;
-		}
-	   case PCI_DEVICE_ID_SI_660_VGA:
-	   	{
-			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
-			} else if(reg32 == 0x06601039) {
-				ivideo.chip = SIS_660;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 660");
-#else
-				strcpy(myid, "SIS 660");
-#endif
-			} else if(reg32 == 0x07411039) {
-				ivideo.chip = SIS_741;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 741");
-#else
-				strcpy(myid, "SIS 741");
+#ifndef MODULE
+	if(sisfb_mode_idx == -1) {
+		sisfb_get_vga_mode_from_kernel();
+	}
 #endif
-			} else {
-				ivideo.chip = SIS_661;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 661");
-#else
-				strcpy(myid, "SIS 661");
+
+	ivideo->chip = chipinfo->chip;
+	ivideo->sisvga_engine = chipinfo->vgaengine;
+	ivideo->hwcursor_size = chipinfo->hwcursor_size;
+	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->mni = chipinfo->mni;
+	
+	ivideo->detectedpdc  = 0xff;
+	ivideo->detectedpdca = 0xff;
+	ivideo->detectedlcda = 0xff;
+	
+	ivideo->sisfb_thismonitor.datavalid = FALSE;
+	
+	ivideo->sisfb_parm_mem = sisfb_parm_mem;
+	ivideo->sisfb_accel = sisfb_accel;
+	ivideo->sisfb_ypan = sisfb_ypan;
+	ivideo->sisfb_max = sisfb_max;
+	ivideo->sisfb_userom = sisfb_userom;
+	ivideo->sisfb_useoem = sisfb_useoem;
+	ivideo->sisfb_mode_idx = sisfb_mode_idx;
+	ivideo->sisfb_parm_rate = sisfb_parm_rate;
+	ivideo->sisfb_crt1off = sisfb_crt1off;
+	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
+	ivideo->sisfb_crt2type = sisfb_crt2type;
+	ivideo->sisfb_crt2flags = sisfb_crt2flags;
+	/* pdc(a), scalelcd, special timing, lvdshl handled below */
+	ivideo->sisfb_dstn = sisfb_dstn;
+	ivideo->sisfb_fstn = sisfb_fstn;
+	ivideo->sisfb_tvplug = sisfb_tvplug;
+	ivideo->sisfb_tvstd = sisfb_tvstd;
+	ivideo->tvxpos = sisfb_tvxposoffset;
+	ivideo->tvypos = sisfb_tvyposoffset;
+	ivideo->sisfb_filter = sisfb_filter;
+	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)		
+	ivideo->sisfb_inverse = sisfb_inverse;
+#endif	
+	
+	ivideo->refresh_rate = 0;
+	if(ivideo->sisfb_parm_rate != -1) {
+	   ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+	}
+	
+	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
+	ivideo->SiS_Pr.CenterScreen = -1;
+	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
+	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
+	
+	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
+        ivideo->SiS_Pr.SiS_CHOverScan = -1;
+        ivideo->SiS_Pr.SiS_ChSW = FALSE;
+	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
+	ivideo->SiS_Pr.HaveEMI = FALSE;
+	ivideo->SiS_Pr.HaveEMILCD = FALSE;
+	ivideo->SiS_Pr.OverruleEMI = FALSE;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
+	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
+	ivideo->SiS_Pr.PDC  = -1;
+	ivideo->SiS_Pr.PDCA = -1;
+#ifdef CONFIG_FB_SIS_315	
+	if(ivideo->chip >= SIS_330) {
+	   ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+	   if(ivideo->chip >= SIS_661) {
+	      ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+	   }
+	}
 #endif
-			}
+	
+	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
+	
+	pci_set_drvdata(pdev, ivideo);
+	
+	/* Patch special cases */
+	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
+		switch(ivideo->nbridge->device) {
+#ifdef CONFIG_FB_SIS_300		
+		case PCI_DEVICE_ID_SI_730:
+		   	ivideo->chip = SIS_730;
+			strcpy(ivideo->myid, "SiS 730");
+		   	break;
+#endif			
+#ifdef CONFIG_FB_SIS_315
+		case PCI_DEVICE_ID_SI_651:
+			/* ivideo->chip is ok */
+			strcpy(ivideo->myid, "SiS 651");
+			break;
+		case PCI_DEVICE_ID_SI_740:
+		   	ivideo->chip = SIS_740;
+			strcpy(ivideo->myid, "SiS 740");
+			break;
+		case PCI_DEVICE_ID_SI_661:
+		   	ivideo->chip = SIS_661;
+			strcpy(ivideo->myid, "SiS 661");
+			break;
+		case PCI_DEVICE_ID_SI_741:
+		   	ivideo->chip = SIS_741;
+			strcpy(ivideo->myid, "SiS 741");
+			break;
+		case PCI_DEVICE_ID_SI_760:
+		   	ivideo->chip = SIS_760;
+			strcpy(ivideo->myid, "SiS 760");
 			break;
-		}
 #endif
+		}
 	}
+	
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	strcpy(sis_fb_info->modename, ivideo->myid);
+#endif
 
-	sishw_ext.jChipType = ivideo.chip;
+	ivideo->sishw_ext.jChipType = ivideo->chip;
 
-	if( (sishw_ext.jChipType == SIS_315PRO) ||
-	    (sishw_ext.jChipType == SIS_315) )
-		sishw_ext.jChipType = SIS_315H;
-
-	ivideo.video_base = pci_resource_start(pdev, 0);
-	ivideo.mmio_base = pci_resource_start(pdev, 1);
-	sishw_ext.ulIOAddress = SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-	ivideo.vga_base = sishw_ext.ulIOAddress;
+#ifdef CONFIG_FB_SIS_315	
+	if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
+	   (ivideo->sishw_ext.jChipType == SIS_315)) {
+		ivideo->sishw_ext.jChipType = SIS_315H;
+	}
+#endif		
 
-	ivideo.mmio_size =  pci_resource_len(pdev, 1);
+	ivideo->video_base = pci_resource_start(pdev, 0);
+	ivideo->mmio_base  = pci_resource_start(pdev, 1);
+	ivideo->mmio_size  = pci_resource_len(pdev, 1);
+	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+	ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
 
 	if(!sisvga_enabled) {
-	   if(pci_enable_device(pdev)) {
-	      kfree(sis_fb_info);
-	      return -EIO;
-	   }
+	   	if(pci_enable_device(pdev)) {
+	      		pci_set_drvdata(pdev, NULL);
+	      		kfree(sis_fb_info);
+	      		return -EIO;
+	   	}
 	} 
-
-	SiS_Pr.SiS_Backup70xx = 0xff;
-        SiS_Pr.SiS_CHOverScan = -1;
-        SiS_Pr.SiS_ChSW = FALSE;
-	SiS_Pr.SiS_UseLCDA = FALSE;
-	SiS_Pr.HaveEMI = FALSE;
-	SiS_Pr.HaveEMILCD = FALSE;
-	SiS_Pr.OverruleEMI = FALSE;
-	SiS_Pr.SiS_SensibleSR11 = FALSE;
-	SiS_Pr.SiS_MyCR63 = 0x63;
-	SiS_Pr.PDC = -1;
-	SiS_Pr.PDCA = -1;
-	if(ivideo.chip >= SIS_661) {
-	   SiS_Pr.SiS_SensibleSR11 = TRUE;
-	   SiS_Pr.SiS_MyCR63 = 0x53;
-	}
-	SiSRegInit(&SiS_Pr, sishw_ext.ulIOAddress);
+	
+	SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
 
 #ifdef CONFIG_FB_SIS_300
 	/* Find PCI systems for Chrontel/GPIO communication setup */
-	if(ivideo.chip == SIS_630) {
-	   int i=0;
+	if(ivideo->chip == SIS_630) {
+	   i=0;
            do {
-	      if(mychswtable[i].subsysVendor == ivideo.subsysvendor &&
-	         mychswtable[i].subsysCard   == ivideo.subsysdevice) {
-		 SiS_Pr.SiS_ChSW = TRUE;
+	      if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+	         mychswtable[i].subsysCard   == ivideo->subsysdevice) {
+		 ivideo->SiS_Pr.SiS_ChSW = TRUE;
 		 printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
 		        mychswtable[i].vendorName, mychswtable[i].cardName);
 		 break;
@@ -4531,26 +4485,26 @@
 	}
 #endif
 
-        outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+        outSISIDXREG(SISSR, 0x05, 0x86);
 
 	if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		  	      || (sisfb_resetcard)
 #endif
 			      			   ) {
-	   int i;
 	   for(i = 0x30; i <= 0x3f; i++) {
-	       outSISIDXREG(SISCR,i,0x00);
+	      outSISIDXREG(SISCR,i,0x00);
 	   }
 	}
 
 	inSISIDXREG(SISCR,0x34,reg);
-	ivideo.modeprechange = ((reg & 0x7f)) ? (reg & 0x7f) : 0x03;
+	ivideo->modeprechange = ((reg & 0x7f)) ? (reg & 0x7f) : 0x03;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
 #ifdef MODULE	
 	if((reg & 0x80) && (reg != 0xff)) {
-	   if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
+	   if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
 	      printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
+	      pci_set_drvdata(pdev, NULL);
 	      kfree(sis_fb_info);
 	      return -EBUSY;
 	   }
@@ -4558,84 +4512,82 @@
 #endif	
 #endif
 
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   	sishw_ext.bIntegratedMMEnabled = TRUE;
-	} else if(ivideo.sisvga_engine == SIS_300_VGA) {
-		if(ivideo.chip == SIS_300) {
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-		} else {
-		        inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, reg);
-			if(reg & SIS_SCRATCH_REG_1A_MASK)
-				sishw_ext.bIntegratedMMEnabled = TRUE;
-			else
-				sishw_ext.bIntegratedMMEnabled = FALSE;
-		}
+	ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
+#ifdef CONFIG_FB_SIS_300		   	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if(ivideo->chip != SIS_300) {
+	      inSISIDXREG(SISSR, 0x1a, reg);
+	      if(!(reg & 0x10)) {
+		 ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
+	      }
+	   }	
 	}
+#endif	
 
-	ivideo.bios_vbase = ivideo.bios_abase = NULL;
-	if(sisfb_userom) {
-	    sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
+	ivideo->bios_vbase = ivideo->bios_abase = NULL;
+	if(ivideo->sisfb_userom) {
+	    ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
 #if defined(__i386__) || defined(__x86_64__)
-	    ivideo.bios_vbase = sishw_ext.pjVirtualRomBase;	/* mapped */
+	    ivideo->bios_vbase = ivideo->sishw_ext.pjVirtualRomBase;	/* mapped */
 #else
-	    ivideo.bios_abase = sishw_ext.pjVirtualRomBase;	/* allocated */
+	    ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;	/* allocated */
 #endif
-	    if(sishw_ext.pjVirtualRomBase) {
-		printk(KERN_INFO "sisfb: Video ROM found and %s to %p\n",
-			ivideo.bios_vbase ? "mapped" : "copied",
-		        sishw_ext.pjVirtualRomBase);
-		sishw_ext.UseROM = TRUE;
+	    if(ivideo->sishw_ext.pjVirtualRomBase) {
+		printk(KERN_INFO "sisfb: Video ROM found and %s to 0x%p\n",
+			ivideo->bios_vbase ? "mapped" : "copied",
+		        ivideo->sishw_ext.pjVirtualRomBase);
+		ivideo->sishw_ext.UseROM = TRUE;
 	    } else {
-	        sishw_ext.UseROM = FALSE;
+	        ivideo->sishw_ext.UseROM = FALSE;
 	        printk(KERN_INFO "sisfb: Video ROM not found\n");
 	    }
 	} else {
-	    sishw_ext.pjVirtualRomBase = NULL;
-	    sishw_ext.UseROM = FALSE;
+	    ivideo->sishw_ext.pjVirtualRomBase = NULL;
+	    ivideo->sishw_ext.UseROM = FALSE;
 	    printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
 	}
-	sishw_ext.bSkipDramSizing = 0;
 
         /* Find systems for special custom timing */
-	if(SiS_Pr.SiS_CustomT == CUT_NONE) {
-	   int i=0, j;
+	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
+	   int j;
 	   unsigned char *biosver = NULL;
            unsigned char *biosdate = NULL;
 	   BOOLEAN footprint;
-	   unsigned long chksum = 0;
+	   u32 chksum = 0;
 
-	   if(sishw_ext.UseROM) {
-	      biosver = sishw_ext.pjVirtualRomBase + 0x06;
-	      biosdate = sishw_ext.pjVirtualRomBase + 0x2c;
-              for(i=0; i<32768; i++) chksum += sishw_ext.pjVirtualRomBase[i];
+	   if(ivideo->sishw_ext.UseROM) {
+	      biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
+	      biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
+              for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
 	   }
 
 	   i=0;
            do {
-	      if( (mycustomttable[i].chipID == ivideo.chip) &&
+	      if( (mycustomttable[i].chipID == ivideo->chip) &&
 	          ((!strlen(mycustomttable[i].biosversion)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
 	          ((!strlen(mycustomttable[i].biosdate)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
 		  ((!mycustomttable[i].bioschksum) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 	           (mycustomttable[i].bioschksum == chksum)))	&&
-		  (mycustomttable[i].pcisubsysvendor == ivideo.subsysvendor) &&
-		  (mycustomttable[i].pcisubsyscard == ivideo.subsysdevice) ) {
+		  (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+		  (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
 		 footprint = TRUE;
-	         for(j=0; j<5; j++) {
+	         for(j = 0; j < 5; j++) {
 	            if(mycustomttable[i].biosFootprintAddr[j]) {
-		       if(sishw_ext.UseROM) {
-	                  if(sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
-		      		mycustomttable[i].biosFootprintData[j])
-		          footprint = FALSE;
+		       if(ivideo->sishw_ext.UseROM) {
+	                  if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+		      		mycustomttable[i].biosFootprintData[j]) {
+		             footprint = FALSE;
+			  }
 		       } else footprint = FALSE;
 		    }
 	         }
 	         if(footprint) {
-	 	    SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+	 	    ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
 		    printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
 		        mycustomttable[i].vendorName,
 			mycustomttable[i].cardName);
@@ -4649,495 +4601,486 @@
 	}
 
 #ifdef CONFIG_FB_SIS_300
-	/* Mode numbers for 1280x768 are different for 300 and 315 series */
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
-		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) {
-		printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
-
-	sishw_ext.pCR = vmalloc(sizeof(SIS_DSReg) * CR_BUFFER_SIZE);
-	if(sishw_ext.pCR == NULL) {
-		printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		    		      || (sisfb_resetcard)
 #endif
 		  					   ) {
-			if(ivideo.chip == SIS_300) sisfb_post_sis300();
-		}
-		if(sisfb_get_dram_size_300()) {
-			printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM size\n");
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			kfree(sis_fb_info);
-			return -ENODEV;
+			if(ivideo->chip == SIS_300) sisfb_post_sis300(pdev);
 		}
 	}
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		    		     || (sisfb_resetcard)
 #endif
 		  					  ) {
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+			if((ivideo->sisfb_mode_idx < 0) || 
+			   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
 				/* TODO: POSTing 315/330 not supported yet */
-				/* Mapping Max FB Size for 315 Init */
-			      	sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x8000000);
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-				sishw_ext.bSkipDramSizing = TRUE;
-				sishw_ext.pSR[0].jIdx = 0x13;
-				sishw_ext.pSR[1].jIdx = 0x14;
-				sishw_ext.pSR[2].jIdx = 0xFF;
-				inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
-				inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
-				sishw_ext.pSR[2].jVal = 0xFF;
-				iounmap(sishw_ext.pjVideoMemoryAddress);
 			}
 		}
-		if(sisfb_get_dram_size_315()) {
-			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			kfree(sis_fb_info);
-			return -ENODEV;
-		}
 	}
 #endif
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
+	if(sisfb_get_dram_size(ivideo)) {
+		printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		pci_set_drvdata(pdev, NULL);
+		kfree(sis_fb_info);
+		return -ENODEV;
+	}
+
+	if((ivideo->sisfb_mode_idx < 0) || 
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 
 	        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
 	        orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
                 /* Enable 2D accelerator engine */
 	        orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
 	}
 
-	sishw_ext.ulVideoMemorySize = ivideo.video_size;
+	
 
 	if(sisfb_pdc != 0xff) {
-	   if(ivideo.sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-	   else				           sisfb_pdc &= 0x1f;
-	   SiS_Pr.PDC = sisfb_pdc;
+	   if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
+	   else				            sisfb_pdc &= 0x1f;
+	   ivideo->SiS_Pr.PDC = sisfb_pdc;
 	}
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   if(sisfb_pdca != 0xff) SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+#ifdef CONFIG_FB_SIS_315	
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
 	}
+#endif
 
-	if(!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
 		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	if(!request_mem_region(ivideo.mmio_base, ivideo.mmio_size, "sisfb MMIO")) {
+	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
-		release_mem_region(ivideo.video_base, ivideo.video_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		release_mem_region(ivideo->video_base, ivideo->video_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
-
-	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, ivideo.video_size);
-	if(!ivideo.video_vbase) {
+	
+	ivideo->video_vbase = (unsigned long)ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->sishw_ext.pjVideoMemoryAddress = (unsigned char *)ivideo->video_vbase;	
+	if(!ivideo->video_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, ivideo.mmio_size);
-	if(!ivideo.mmio_vbase) {
+	ivideo->mmio_vbase = (unsigned long)ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	if(!ivideo->mmio_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-	   	iounmap(ivideo.video_vbase);
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	iounmap((void *)ivideo->video_vbase);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       	ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
-
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-	       	ivideo.mmio_base, ivideo.mmio_vbase, ivideo.mmio_size / 1024);
+	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->video_base, ivideo->video_vbase, ivideo->video_size / 1024);
 
-	if(sisfb_heap_init()) {
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->mmio_base, ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+		
+	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
 	}
+	
+	/* Used for clearing the screen only, therefore respect our mem limit */
+	ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
 
-	ivideo.mtrr = (unsigned int) 0;
+	ivideo->mtrr = 0;
 	
-	ivideo.vbflags = 0;
+	ivideo->vbflags = 0;
+	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
+	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
+	ivideo->defmodeidx    = DEFAULT_MODE;
 
-	ivideo.newrom = SiSDetermineROMLayout661(&SiS_Pr, &sishw_ext);
+	ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
-	
-		sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-		sishw_ext.Is301BDH = FALSE;
+	if((ivideo->sisfb_mode_idx < 0) || 
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 
 
-		sisfb_sense_crt1();
+		sisfb_sense_crt1(ivideo);
 	
-		sisfb_get_VB_type();
+		sisfb_get_VB_type(ivideo);
 		
-		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-			sisfb_detect_VB_connect();
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+			sisfb_detect_VB_connect(ivideo);
 		}
 		
-		ivideo.currentvbflags = ivideo.vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
+		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 		
-		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;
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		   if(ivideo->sisfb_crt2type != -1) {
+		      if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
+		         ivideo->currentvbflags |= CRT2_LCD;
+		      } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+		         ivideo->currentvbflags |= ivideo->sisfb_crt2type;
 		      }
 		   } else {
 		      /* Chrontel 700x TV detection often unreliable, therefore use a
 		       * different default order on such machines
 		       */
-		      if((ivideo.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;
+		      if((ivideo->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->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.vbflags & CRT2_LCD) {
-		   inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
+		if(ivideo->vbflags & CRT2_LCD) {
+		   inSISIDXREG(SISCR, 0x36, reg);
 		   reg &= 0x0f;
-		   if(ivideo.sisvga_engine == SIS_300_VGA) {
-		      sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
-		   } else if(ivideo.chip >= SIS_661) {
-		      sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
+		   if(ivideo->sisvga_engine == SIS_300_VGA) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   } else if(ivideo->chip >= SIS_661) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
 		   } else {
-		      sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      ivideo->sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+		         if((ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_2) &&
+			    (ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_3)) {			 
+		      	    ivideo->sishw_ext.ulCRT2LCDType = LCD_320x480;
+			 }
+		      }
+		   }
+		   if(ivideo->sishw_ext.ulCRT2LCDType == LCD_UNKNOWN) {
+		      ivideo->sishw_ext.ulCRT2LCDType = LCD_1024x768;
+		      printk(KERN_DEBUG "sisfb: Illegal panel ID (%02x), assuming 1024x768\n", reg);
+		   }
+		   for(i = 0; i < SIS_LCD_NUMBER; i++) {
+		      if(ivideo->sishw_ext.ulCRT2LCDType == sis_lcd_data[i].lcdtype) {
+		         ivideo->lcdxres = sis_lcd_data[i].xres;
+			 ivideo->lcdyres = sis_lcd_data[i].yres;
+			 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+			 break;
+		      }
 		   }
+		   if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+	   		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
+		   } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+	   		ivideo->lcdxres =  848; ivideo->lcdyres =  480; ivideo->lcddefmodeidx = 47;
+		   }
+		   printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", 
+		   		ivideo->lcdxres, ivideo->lcdyres);
 		}
 	
 #ifdef CONFIG_FB_SIS_300
                 /* Save the current PanelDelayCompensation if the LCD is currently used */
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
-	           if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	           if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
 		       int tmp;
 		       inSISIDXREG(SISCR,0x30,tmp);
 		       if(tmp & 0x20) {
 		          /* Currently on LCD? If yes, read current pdc */
-		          inSISIDXREG(SISPART1,0x13,ivideo.detectedpdc);
-			  ivideo.detectedpdc &= 0x3c;
-			  if(SiS_Pr.PDC == -1) {
+		          inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+			  ivideo->detectedpdc &= 0x3c;
+			  if(ivideo->SiS_Pr.PDC == -1) {
 			     /* Let option override detection */
-			     SiS_Pr.PDC = ivideo.detectedpdc;
+			     ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
 			  }
 			  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
-  			         ivideo.detectedpdc);
+  			         ivideo->detectedpdc);
 		       }
-		       if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		       if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
 		          printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
-				 SiS_Pr.PDC);
+				 ivideo->SiS_Pr.PDC);
 		       }
 	           }
 		}
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
 
 		   /* Try to find about LCDA */
-		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
+		   if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISPART1,0x13,tmp);
 		      if(tmp & 0x04) {
-		         SiS_Pr.SiS_UseLCDA = TRUE;
-		         ivideo.detectedlcda = 0x03;
+		         ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+		         ivideo->detectedlcda = 0x03;
 		         printk(KERN_DEBUG
 			        "sisfb: BIOS uses LCDA for low resolution and text modes\n");
 		      }
 	           }
 
 		   /* Save PDC */
-		   if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
+		   if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISCR,0x30,tmp);
-		      if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
+		      if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
 		         /* Currently on LCD? If yes, read current pdc */
 			 u8 pdc;
 		         inSISIDXREG(SISPART1,0x2D,pdc);
-			 ivideo.detectedpdc  = (pdc & 0x0f) << 1;
-			 ivideo.detectedpdca = (pdc & 0xf0) >> 3;
+			 ivideo->detectedpdc  = (pdc & 0x0f) << 1;
+			 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
 			 inSISIDXREG(SISPART1,0x35,pdc);
-			 ivideo.detectedpdc |= ((pdc >> 7) & 0x01);
+			 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
 			 inSISIDXREG(SISPART1,0x20,pdc);
-			 ivideo.detectedpdca |= ((pdc >> 6) & 0x01);
-			 if(ivideo.newrom) {
+			 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+			 if(ivideo->newrom) {
 			    /* New ROM invalidates other PDC resp. */
-			    if(ivideo.detectedlcda != 0xff) {
-			       ivideo.detectedpdc = 0xff;
+			    if(ivideo->detectedlcda != 0xff) {
+			       ivideo->detectedpdc = 0xff;
 			    } else {
-			       ivideo.detectedpdca = 0xff;
+			       ivideo->detectedpdca = 0xff;
 			    }
 			 }
-			 if(SiS_Pr.PDC == -1) {
-			    if(ivideo.detectedpdc != 0xff) {
-			       SiS_Pr.PDC = ivideo.detectedpdc;
+			 if(ivideo->SiS_Pr.PDC == -1) {
+			    if(ivideo->detectedpdc != 0xff) {
+			       ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
 			    }
 			 }
-			 if(SiS_Pr.PDCA == -1) {
-			    if(ivideo.detectedpdca != 0xff) {
-			       SiS_Pr.PDCA = ivideo.detectedpdca;
+			 if(ivideo->SiS_Pr.PDCA == -1) {
+			    if(ivideo->detectedpdca != 0xff) {
+			       ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
 			    }
 			 }
-			 if(ivideo.detectedpdc != 0xff) {
+			 if(ivideo->detectedpdc != 0xff) {
 			    printk(KERN_INFO
 			         "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
-  			          ivideo.detectedpdc);
+  			          ivideo->detectedpdc);
 			 }
-			 if(ivideo.detectedpdca != 0xff) {
+			 if(ivideo->detectedpdca != 0xff) {
 			    printk(KERN_INFO
 			         "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
-  			          ivideo.detectedpdca);
+  			          ivideo->detectedpdca);
 			 }
 		      }
 
 		      /* Save EMI */
-		      if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
-		         inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
-			 inSISIDXREG(SISPART4,0x31,SiS_Pr.EMI_31);
-			 inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
-			 inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
-			 SiS_Pr.HaveEMI = TRUE;
-			 if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
-			  	SiS_Pr.HaveEMILCD = TRUE;
+		      if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
+		         inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+			 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+			 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+			 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+			 ivideo->SiS_Pr.HaveEMI = TRUE;
+			 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+			  	ivideo->SiS_Pr.HaveEMILCD = TRUE;
 			 }
 		      }
 		   }
 
 		   /* Let user override detected PDCs (all bridges) */
-		   if(ivideo.vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
-		      if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		   if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
+		      if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
 		         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
-				 SiS_Pr.PDC);
+				 ivideo->SiS_Pr.PDC);
 		      }
-		      if((SiS_Pr.PDCA != -1) && (SiS_Pr.PDCA != ivideo.detectedpdca)) {
+		      if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
 		         printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
-				 SiS_Pr.PDCA);
+				 ivideo->SiS_Pr.PDCA);
 		      }
 		   }
 
 		}
 #endif
 
-		if(!sisfb_crt1off) {
-		   	sisfb_handle_ddc(&sisfb_thismonitor, 0);
+		if(!ivideo->sisfb_crt1off) {
+		   	sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
 		} else {
-		   	if((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-		      	   (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
-		      		sisfb_handle_ddc(&sisfb_thismonitor, 1);
+		   	if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+		      	   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+		      		sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
 		   	}
 		}
 
-		if(sisfb_mode_idx >= 0)
-			sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
+		if(ivideo->sisfb_mode_idx >= 0) {
+			int bu = ivideo->sisfb_mode_idx;
+			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+			if(bu != ivideo->sisfb_mode_idx) {
+				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
+					sisbios_mode[bu].xres,
+					sisbios_mode[bu].yres,
+					sisbios_mode[bu].bpp);
+			}
+		}
 
-		if(sisfb_mode_idx < 0) {
-			switch(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->sisfb_mode_idx < 0) {
+			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 			   case CRT2_LCD:
-				sisfb_mode_idx = DEFAULT_LCDMODE;
+				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
 				break;
 			   case CRT2_TV:
-				sisfb_mode_idx = DEFAULT_TVMODE;
+				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
 				break;
 			   default:
-				sisfb_mode_idx = DEFAULT_MODE;
+				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
 				break;
 			}
 		}
 
-		ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 
-		if(ivideo.refresh_rate != 0)
-			sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
+		if(ivideo->refresh_rate != 0) {
+			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+		}
 
-		if(ivideo.rate_idx == 0) {
-			ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-			ivideo.refresh_rate = 60;
+		if(ivideo->rate_idx == 0) {
+			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+			ivideo->refresh_rate = 60;
 		}
 
-		if(sisfb_thismonitor.datavalid) {
-			if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-			                      ivideo.rate_idx, ivideo.refresh_rate)) {
+		if(ivideo->sisfb_thismonitor.datavalid) {
+			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+			                      ivideo->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);
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_vwidth = ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_vheight = ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+		ivideo->org_x = ivideo->org_y = 0;
+		ivideo->video_linelength = ivideo->video_width * (ivideo->video_bpp >> 3);
 		
-		sisfb_set_vparms();
+		sisfb_set_vparms(ivideo);
 		
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
 
 		/* ---------------- For 2.4: Now switch the mode ------------------ */		
 		
 		printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
-	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-			ivideo.refresh_rate);
+	       		ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
 
-		sisfb_pre_setmode();
+		sisfb_pre_setmode(ivideo);
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-				ivideo.mode_no);
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+									ivideo->mode_no);
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-		sisfb_post_setmode();
+		sisfb_post_setmode(ivideo);
 		
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+		   sisfb_initaccel(ivideo);
 		}
 
 		/* Maximize regardless of sisfb_max at startup */
-		default_var.yres_virtual = 32767;
-		sisfb_crtc_to_var(&default_var);
+		ivideo->default_var.yres_virtual = 32767;
+		sisfb_crtc_to_var(ivideo, &ivideo->default_var);
 		
-		sis_fb_info->node = -1;
+		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->disp  = &ivideo->sis_disp;
+		sis_fb_info->blank = &sisfb_blank;
 		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;
+		sis_fb_info->updatevar  = &sisfb_update_var;
+		sis_fb_info->changevar  = NULL;
 		strcpy(sis_fb_info->fontname, sisfb_fontname);
 			
-		sisfb_set_disp(-1, &default_var, sis_fb_info);
+		sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
 		
 #else		/* --------- For 2.6: 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);
+	       		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;
+		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
+		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
+		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
 
-		sisfb_bpp_to_var(&default_var);
+		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
 		
-		default_var.pixclock = (u32) (1000000000 /
-				sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						ivideo.mode_no, ivideo.rate_idx));
+		ivideo->default_var.pixclock = (u32) (1000000000 /
+				sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+						ivideo->mode_no, ivideo->rate_idx));
 						
-		if(sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-			 ivideo.mode_no, ivideo.rate_idx,
-			 &default_var.left_margin, &default_var.right_margin, 
-			 &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_DOUBLE) {
-		      default_var.pixclock <<= 1;
+		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+			 	ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
+		   if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		      ivideo->default_var.pixclock <<= 1;
 	   	   }
 	        }
-
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
+		
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+		   sisfb_initaccel(ivideo);
 		}
 		
-		if(sisfb_ypan) {
+		if(ivideo->sisfb_ypan) {
 		   /* Maximize regardless of sisfb_max at startup */
-	    	   default_var.yres_virtual =
-				ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
-		   if(default_var.yres_virtual > 32767) default_var.yres_virtual = 32767;
-	    	   if(default_var.yres_virtual <= default_var.yres) {
-	              default_var.yres_virtual = default_var.yres;
+	    	   ivideo->default_var.yres_virtual =
+				ivideo->heapstart / 
+				     (ivideo->default_var.xres * (ivideo->default_var.bits_per_pixel >> 3));
+		   if(ivideo->default_var.yres_virtual > 32767) ivideo->default_var.yres_virtual = 32767;
+	    	   if(ivideo->default_var.yres_virtual <= ivideo->default_var.yres) {
+	              ivideo->default_var.yres_virtual = ivideo->default_var.yres;
 	    	   }
 		}
-
+		
 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-		sis_fb_info->var = default_var;
-		sis_fb_info->fix = sisfb_fix;
-		sis_fb_info->par = &ivideo;
-		sis_fb_info->screen_base = ivideo.video_vbase;
+		sis_fb_info->var = ivideo->default_var;
+		sis_fb_info->fix = ivideo->sisfb_fix;
+		sis_fb_info->screen_base = (char *)ivideo->video_vbase;
 		sis_fb_info->fbops = &sisfb_ops;
-#ifdef NEWFBDEV
-		sis_fb_info->class_dev.dev = &pdev->dev;
-#endif
+
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
-		sis_fb_info->pseudo_palette = pseudo_palette;
+		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
 		
 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
-#endif
+#endif		/* 2.6 */
 
-		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
 
 #ifdef CONFIG_MTRR
-		ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
-				(unsigned int) ivideo.video_size,
-				MTRR_TYPE_WRCOMB, 1);
-		if(ivideo.mtrr) {
-			printk(KERN_DEBUG "sisfb: Added MTRRs\n");
+		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
+					MTRR_TYPE_WRCOMB, 1);
+		if(!ivideo->mtrr) {
+			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
 		}
 #endif
 
@@ -5146,38 +5089,72 @@
 #endif
 
 		if(register_framebuffer(sis_fb_info) < 0) {
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
-		ivideo.registered = 1;
-
-		pci_set_drvdata(pdev, sis_fb_info);
+		ivideo->registered = 1;
+		
+		/* Enlist us */
+		ivideo->next = card_list;
+		card_list = ivideo;
+		
+#ifdef SIS_CONFIG_COMPAT
+		{
+		int ret;
+		/* Our ioctls are all "32/64bit compatible" */
+		if(register_ioctl32_conversion(FBIOGET_VBLANK, NULL)) {
+		   printk(KERN_ERR "sisfb: Error registering FBIOGET_VBLANK ioctl32 translation\n");
+		} else {
+		   ivideo->ioctl32vblankregistered = 1;
+		}
+		ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
+		ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+		if(ret)	printk(KERN_ERR "sisfb: Error registering ioctl32 translations\n");
+		else    ivideo->ioctl32registered = 1;
+		}
+#endif
 
+#if 0
+		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO_SIZE ioctl (%x)\n", SISFB_GET_INFO_SIZE);
 		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
 		printk(KERN_DEBUG "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",
-		     sisfb_ypan  ? (sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
+		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_TVPOSOFFSET ioctl (%x)\n", SISFB_GET_TVPOSOFFSET);
+		printk(KERN_DEBUG "sisfb: Installed SISFB_SET_TVPOSOFFSET ioctl (%x)\n", SISFB_SET_TVPOSOFFSET);
+#endif		
+
+		printk(KERN_INFO "sisfb: 2D acceleration is %s, scroll-mode %s\n",
+		     ivideo->sisfb_accel ? "enabled" : "disabled",
+		     ivideo->sisfb_ypan  ? 
+		     	(ivideo->sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
 
 
 		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename,
+	       		GET_FB_IDX(sis_fb_info->node), 
 #else
-	       		sis_fb_info->node, myid,
+	       		sis_fb_info->node, 
 #endif
-			VER_MAJOR, VER_MINOR, VER_LEVEL);
+			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
 
 		printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
-
+		
 	}	/* if mode = "none" */
 
 	return 0;
@@ -5189,26 +5166,51 @@
 
 static void __devexit sisfb_remove(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	struct fb_info        *sis_fb_info = ivideo->memyselfandi;
+	int                   registered = ivideo->registered;
+	
+#ifdef SIS_CONFIG_COMPAT	
+	if(ivideo->ioctl32vblankregistered) {
+		if(unregister_ioctl32_conversion(FBIOGET_VBLANK)) {
+			printk(KERN_ERR "sisfb: Error unregistering FBIOGET_VBLANK ioctl32 translation\n");
+		}
+	}
+	if(ivideo->ioctl32registered) {
+		int ret;
+		ret =  unregister_ioctl32_conversion(FBIO_ALLOC);
+		ret |= unregister_ioctl32_conversion(FBIO_FREE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+		if(ret)	printk(KERN_ERR "sisfb: Error unregistering ioctl32 translations\n");
+	}
+#endif
+	
 	/* Unmap */
-	iounmap(ivideo.video_vbase);
-	iounmap(ivideo.mmio_vbase);
-	if(ivideo.bios_vbase) iounmap(ivideo.bios_vbase);
+	iounmap((void *)ivideo->video_vbase);
+	iounmap((void *)ivideo->mmio_vbase);
+	if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+	if(ivideo->bios_abase)    vfree(ivideo->bios_abase);
 
 	/* Release mem regions */
-	release_mem_region(ivideo.video_base, ivideo.video_size);
-	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+	release_mem_region(ivideo->video_base, ivideo->video_size);
+	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 
 #ifdef CONFIG_MTRR
 	/* Release MTRR region */
-	if(ivideo.mtrr) {
-		mtrr_del(ivideo.mtrr,
-		      (unsigned int)ivideo.video_base,
-	              (unsigned int)ivideo.video_size);
+	if(ivideo->mtrr) {
+		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
 	}
 #endif
-
+	
 	/* Unregister the framebuffer */
-	if(ivideo.registered) {
+	if(ivideo->registered) {
 		unregister_framebuffer(sis_fb_info);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
 		framebuffer_release(sis_fb_info);
@@ -5217,10 +5219,6 @@
 #endif
 	}
 
-	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
-	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
-	if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-
 	pci_set_drvdata(pdev, NULL);
 
 	/* TODO: Restore the initial mode
@@ -5230,7 +5228,7 @@
 	 * from machine to machine. Depends on the type
 	 * of integration between chipset and bridge.
 	 */
-	if(ivideo.registered) {
+	if(registered) {
 	   printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
 	}
 };
@@ -5260,7 +5258,6 @@
 static unsigned int mem = 0;
 static char         *forcecrt2type = NULL;
 static int          forcecrt1 = -1;
-static char         *queuemode = NULL;
 static int          pdc = -1;
 static int          pdc1 = -1;
 static int          noaccel = -1;
@@ -5269,232 +5266,249 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int          inverse = 0;
 #endif
-static int          userom = 1;
+static int          userom = -1;
 static int          useoem = -1;
 static char         *tvstandard = NULL;
 static int	    nocrt2rate = 0;
 static int          scalelcd = -1;
 static char	    *specialtiming = NULL;
 static int	    lvdshl = -1;
+static int	    tvxposoffset = 0, tvyposoffset = 0;
+static int	    filter = -1;
 #if !defined(__i386__) && !defined(__x86_64__)
 static int	    resetcard = 0;
 static int	    videoram = 0;
 #endif
 
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Others");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+MODULE_PARM(mem, "i");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM(noypan, "i");
+MODULE_PARM(nomax, "i");
+MODULE_PARM(userom, "i");
+MODULE_PARM(useoem, "i");
 MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
-       "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
-         "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)");
+MODULE_PARM(vesa, "i");
+MODULE_PARM(rate, "i");
+MODULE_PARM(forcecrt1, "i");
+MODULE_PARM(forcecrt2type, "s");
+MODULE_PARM(scalelcd, "i");
+MODULE_PARM(pdc, "i");
+MODULE_PARM(pdc1, "i");
+MODULE_PARM(specialtiming, "s");
+MODULE_PARM(lvdshl, "i");
+MODULE_PARM(tvstandard, "s");
+MODULE_PARM(tvxposoffset, "i");
+MODULE_PARM(tvyposoffset, "i");
+MODULE_PARM(filter, "i");
+MODULE_PARM(nocrt2rate, "i");
+MODULE_PARM(inverse, "i");
+#if !defined(__i386__) && !defined(__x86_64__)
+MODULE_PARM(resetcard, "i");
+MODULE_PARM(videoram, "i");
+#endif
 #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 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)");
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(filter, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
+#endif
 #endif
 
+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. 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 size is 32KB by default.\n"
+	  "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
+	  "for XFree86 4.x/X.org 6.7 and later.\n");
+
+MODULE_PARM_DESC(noaccel,
+        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+	  "(default: 0)\n");
+
+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. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
+	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
+	  "enable the user to positively specify a virtual Y size of the screen using\n"
+	  "fbset. (default: 0)\n");	  
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+        "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+          "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)\n");
 MODULE_PARM_DESC(vesa,
-       "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
-         "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
-	 "and the driver will only do the video memory management for eg. DRM/DRI;\n"
-	 "0x0103 if sisfb is in the kernel)");
-#endif
+        "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+          "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+	  "and the driver will only do the video memory management for eg. DRM/DRI;\n"
+	  "0x0103 if sisfb is in the kernel)\n");	
+#endif	  
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+       "\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)\n");
+
 MODULE_PARM_DESC(vesa,
        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-         "0x117 (default: 0x0103)");
+         "0x117 (default: 0x0103)\n");
 #endif
-
-MODULE_PARM(rate, "i");
+	  
 MODULE_PARM_DESC(rate,
 	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
 	  "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,
-	"(Deprecated, please use forcecrt1)");
-
-MODULE_PARM(filter, "i");
-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(queuemode,   "s");
-MODULE_PARM_DESC(queuemode,
-	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP,\n"
-  	  "VRAM and MMIO. AGP is only available if the kernel has AGP support. The queue\n"
-	  "mode is important to programs using the 2D/3D accelerator of the SiS chip.\n"
-	  "The modes require a totally different way of programming the engines. If any\n"
-	  "mode than MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
-	  "300/540/630/730, this option is ignored. (default: MMIO)");
-
-/* TW: "Import" the options from the X driver */
-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. 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\n"
-	  "for XFree 4.x (x>=2).");
+	  "will be ignored (default: 60)\n");
 
-MODULE_PARM(forcecrt2type, "s");
+MODULE_PARM_DESC(forcecrt1,
+	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+	  "0=CRT1 OFF) (default: [autodetected])\n");	  
+	  
 MODULE_PARM_DESC(forcecrt2type,
 	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
 	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
 	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
 	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
-	  "be used instead of TV to override the TV detection. (default: [autodetected])");
-
-MODULE_PARM(forcecrt1, "i");
-MODULE_PARM_DESC(forcecrt1,
-	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
-	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
-	  " 0=CRT1 off) (default: [autodetected])");
-
-MODULE_PARM(pdc, "i");
+	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+	  "depends on the very hardware in use. (default: [autodetected])\n");
+	  
+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; LVDS panels will\n"
+	  "show black bars around the image, TMDS panels will probably do the scaling\n"
+	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");	
+	  
 MODULE_PARM_DESC(pdc,
         "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
 	  "should detect this correctly in most cases; however, sometimes this is not\n"
 	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
 	  "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
 	  "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)");
+	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
 
-MODULE_PARM(pdc1, "i");
+#ifdef CONFIG_FB_SIS_315	  
 MODULE_PARM_DESC(pdc1,
-        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315 series\n"
-	  "only. (default: autodetected if LCD is in LCD-via-CRT1 mode during startup)");
-
-MODULE_PARM(noaccel, "i");
-MODULE_PARM_DESC(noaccel,
-        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
-	  "(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. (default: 0)");
-
-MODULE_PARM(nomax, "i");
-MODULE_PARM_DESC(nomax,
-        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
-	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
-	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
-	  "enable the user to positively specify a virtual Y size of the screen using\n"
-	  "fbset. (default: 0)\n");
-
-#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)");
-#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)");
-
-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])");
+        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+	  "implemented yet.\n");
+#endif
 
-MODULE_PARM(tvstandard, "s");
+MODULE_PARM_DESC(specialtiming,
+	"\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(lvdshl,
+	"\nPlease refer to documentation for more information on this option.\n");	
+		  
 MODULE_PARM_DESC(tvstandard,
 	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
-	  "pal and ntsc. (default: [auto])");
+	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");	  
+
+MODULE_PARM_DESC(tvxposoffset,	  
+	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+	
+MODULE_PARM_DESC(tvyposoffset,	  
+	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");	
+	  	  
+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])\n");
 
-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\n"
-	  "scale by itself, it will probably do this, otherwise you will see a black bar\n"
-	  "around the screen image. Default: [autodetect if panel can scale]");
-
-MODULE_PARM(specialtiming, "s");
-
-MODULE_PARM(lvdshl, "i");
+	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	 
+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)\n");
+#endif
+	  
 #if !defined(__i386__) && !defined(__x86_64__)
-MODULE_PARM(resetcard, "i");
+#ifdef CONFIG_FB_SIS_300
 MODULE_PARM_DESC(resetcard,
 	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
 	  "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
-	  "Default: 0");
-MODULE_PARM(videoram, "i");
+	  "Default: 0\n");
+
 MODULE_PARM_DESC(videoram,
 	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
 	  "some non-x86 architectures where the memory auto detection fails. Only\n"
-	  "relevant if resetcard is set, too. Default: [auto-detect]");
+	  "relevant if resetcard is set, too. Default: [auto-detect]\n");
+#endif	  
 #endif
 
 int __init sisfb_init_module(void)
 {
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.CenterScreen = -1;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.LVDSHL = -1;
+	sisfb_setdefaultparms();
 
-	ivideo.refresh_rate = sisfb_parm_rate = rate;
+	if(rate) sisfb_parm_rate = rate;
 
 	if((scalelcd == 0) || (scalelcd == 1)) {
-	   SiS_Pr.UsePanelScaler = scalelcd ^ 1;
+	   sisfb_scalelcd = scalelcd ^ 1;   
 	}
-
-	if(mode)
-		sisfb_search_mode(mode, FALSE);
-	else if(vesa != -1)
-		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 */
-		sisfb_mode_idx = DEFAULT_MODE;
-#endif
-
+	
+	/* Need to check crt2 type first for fstn/dstn */
+	
 	if(forcecrt2type)
 		sisfb_search_crt2type(forcecrt2type);
 
 	if(tvstandard)
 		sisfb_search_tvstd(tvstandard);
 
-	if(crt1off == 0)
-		sisfb_crt1off = 1;
-	else
-		sisfb_crt1off = 0;
+	if(mode)
+		sisfb_search_mode(mode, FALSE);
+	else if(vesa != -1)
+		sisfb_search_vesamode(vesa, FALSE);
+
+	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
 
 	sisfb_forcecrt1 = forcecrt1;
-	if(forcecrt1 == 1)
-		sisfb_crt1off = 0;
-	else if(forcecrt1 == 0)
-		sisfb_crt1off = 1;
+	if(forcecrt1 == 1)      sisfb_crt1off = 0;
+	else if(forcecrt1 == 0) sisfb_crt1off = 1;
 
 	if(noaccel == 1)      sisfb_accel = 0;
 	else if(noaccel == 0) sisfb_accel = 1;
@@ -5507,21 +5521,12 @@
 	
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	if(inverse)           sisfb_inverse = 1;
-	sisfb_fontname[0] = '\0';
 #endif
 
-	if(mem)		      sisfb_mem = mem;
-
-	sisfb_userom = userom;
-
-	sisfb_useoem = useoem;
-
-	if(queuemode)         sisfb_search_queuemode(queuemode);
+	if(mem)		      sisfb_parm_mem = mem;
 
-	/* If other queuemode than MMIO, disable 2D accel and ypan */
-	if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-	        sisfb_accel = 0;
-	}
+	if(userom != -1)      sisfb_userom = userom;
+	if(useoem != -1)      sisfb_useoem = useoem;
 
         if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
 	if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
@@ -5531,12 +5536,15 @@
 	if(specialtiming)
 		sisfb_search_specialtiming(specialtiming);
 
-	if((lvdshl >= 0) && (lvdshl <= 3)) SiS_Pr.LVDSHL = lvdshl;
+	if((lvdshl >= 0) && (lvdshl <= 3))  sisfb_lvdshl = lvdshl;
+	
+	if(filter != -1) sisfb_filter = filter;
+	
+	sisfb_tvxposoffset = tvxposoffset;
+	sisfb_tvyposoffset = tvyposoffset;
 
 #if !defined(__i386__) && !defined(__x86_64__)
-        if(resetcard)   sisfb_resetcard = 1;
-	else		sisfb_resetcard = 0;
-
+ 	sisfb_resetcard = (resetcard) ? 1 : 0;
 	if(videoram)    sisfb_videoram = videoram;
 #endif
 
@@ -5556,7 +5564,5 @@
 
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
-EXPORT_SYMBOL(sis_dispinfo);
 
-EXPORT_SYMBOL(ivideo);
 
diff -urN linux-2.4.27-pre5/drivers/video/sis/sis_main.h linux-2.4.27-pre6/drivers/video/sis/sis_main.h
--- linux-2.4.27-pre5/drivers/video/sis/sis_main.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/sis_main.h	2004-06-16 11:33:28.768113559 -0700
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -22,335 +23,15 @@
 #ifndef _SISFB_MAIN
 #define _SISFB_MAIN
 
-#include "vstruct.h"
-
-/* ------------------- Constant Definitions ------------------------- */
-
-#define AGPOFF     /* default is turn off AGP */
-
-#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
-
-#define VER_MAJOR                 1
-#define VER_MINOR                 6
-#define VER_LEVEL                 32
+#include <linux/spinlock.h>
 
+#include "vstruct.h"
 #include "sis.h"
 
-/* To be included in pci_ids.h */
-#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA  0x6325
-#endif
-#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650      0x0650
-#endif
-#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740      0x0740
-#endif
-#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330      0x0330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA  0x6330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0661
-#endif
-#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741      0x0741
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0660
-#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, 65x, 740, 661, 741  */
-#endif
-#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre"), 760 	*/
-#endif
-
-#define MAX_ROM_SCAN              0x10000
-
-#define HW_CURSOR_CAP             0x80
-#define TURBO_QUEUE_CAP           0x40
-#define AGP_CMD_QUEUE_CAP         0x20
-#define VM_CMD_QUEUE_CAP          0x10
-#define MMIO_CMD_QUEUE_CAP        0x08
-
-/* For 300 series */
-#ifdef CONFIG_FB_SIS_300
-#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
-#endif
-
-/* For 315/Xabre series */
-#ifdef CONFIG_FB_SIS_315
-#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD   0x1F
-#endif
-
-#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
-#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
-
-#define OH_ALLOC_SIZE             4000
-#define SENTINEL                  0x7fffffff
-
-#define SEQ_ADR                   0x14
-#define SEQ_DATA                  0x15
-#define DAC_ADR                   0x18
-#define DAC_DATA                  0x19
-#define CRTC_ADR                  0x24
-#define CRTC_DATA                 0x25
-#define DAC2_ADR                  (0x16-0x30)
-#define DAC2_DATA                 (0x17-0x30)
-#define VB_PART1_ADR              (0x04-0x30)
-#define VB_PART1_DATA             (0x05-0x30)
-#define VB_PART2_ADR              (0x10-0x30)
-#define VB_PART2_DATA             (0x11-0x30)
-#define VB_PART3_ADR              (0x12-0x30)
-#define VB_PART3_DATA             (0x13-0x30)
-#define VB_PART4_ADR              (0x14-0x30)
-#define VB_PART4_DATA             (0x15-0x30)
-
-#define SISSR			  SiS_Pr.SiS_P3c4
-#define SISCR                     SiS_Pr.SiS_P3d4
-#define SISDACA                   SiS_Pr.SiS_P3c8
-#define SISDACD                   SiS_Pr.SiS_P3c9
-#define SISPART1                  SiS_Pr.SiS_Part1Port
-#define SISPART2                  SiS_Pr.SiS_Part2Port
-#define SISPART3                  SiS_Pr.SiS_Part3Port
-#define SISPART4                  SiS_Pr.SiS_Part4Port
-#define SISPART5                  SiS_Pr.SiS_Part5Port
-#define SISDAC2A                  SISPART5
-#define SISDAC2D                  (SISPART5 + 1)
-#define SISMISCR                  (SiS_Pr.RelIO + 0x1c)
-#define SISMISCW                  SiS_Pr.SiS_P3c2
-#define SISINPSTAT		  (SiS_Pr.RelIO + 0x2a)
-#define SISPEL			  SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD          0x05  /* SRs */
-#define IND_SIS_COLOR_MODE        0x06
-#define IND_SIS_RAMDAC_CONTROL    0x07
-#define IND_SIS_DRAM_SIZE         0x14
-#define IND_SIS_SCRATCH_REG_16    0x16
-#define IND_SIS_SCRATCH_REG_17    0x17
-#define IND_SIS_SCRATCH_REG_1A    0x1A
-#define IND_SIS_MODULE_ENABLE     0x1E
-#define IND_SIS_PCI_ADDRESS_SET   0x20
-#define IND_SIS_TURBOQUEUE_ADR    0x26
-#define IND_SIS_TURBOQUEUE_SET    0x27
-#define IND_SIS_POWER_ON_TRAP     0x38
-#define IND_SIS_POWER_ON_TRAP2    0x39
-#define IND_SIS_CMDQUEUE_SET      0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
-
-#define IND_SIS_SCRATCH_REG_CR30  0x30  /* CRs */
-#define IND_SIS_SCRATCH_REG_CR31  0x31
-#define IND_SIS_SCRATCH_REG_CR32  0x32
-#define IND_SIS_SCRATCH_REG_CR33  0x33
-#define IND_SIS_LCD_PANEL         0x36
-#define IND_SIS_SCRATCH_REG_CR37  0x37
-#define IND_SIS_AGP_IO_PAD        0x48
-
-#define IND_BRI_DRAM_STATUS       0x63 /* PCI config memory size offset */
-
-#define MMIO_QUEUE_PHYBASE        0x85C0
-#define MMIO_QUEUE_WRITEPORT      0x85C4
-#define MMIO_QUEUE_READPORT       0x85C8
-
-#define SIS_CRT2_WENABLE_300 0x24
-#define SIS_CRT2_WENABLE_315 0x2F
-
-#define SIS_PASSWORD              0x86  /* SR05 */
-#define SIS_INTERLACED_MODE       0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE       0x0
-#define SIS_15BPP_COLOR_MODE      0x1 
-#define SIS_16BPP_COLOR_MODE      0x2 
-#define SIS_32BPP_COLOR_MODE      0x4 
-#define SIS_DRAM_SIZE_MASK        0x3F  /* 300/630/730 SR14 */
-#define SIS_DRAM_SIZE_1MB         0x00
-#define SIS_DRAM_SIZE_2MB         0x01
-#define SIS_DRAM_SIZE_4MB         0x03
-#define SIS_DRAM_SIZE_8MB         0x07
-#define SIS_DRAM_SIZE_16MB        0x0F
-#define SIS_DRAM_SIZE_32MB        0x1F
-#define SIS_DRAM_SIZE_64MB        0x3F
-#define SIS_DATA_BUS_MASK         0xC0
-#define SIS_DATA_BUS_32           0x00
-#define SIS_DATA_BUS_64           0x01
-#define SIS_DATA_BUS_128          0x02
-
-#define SIS315_DATA_BUS_MASK      0x02
-#define SIS315_DATA_BUS_64        0x00
-#define SIS315_DATA_BUS_128       0x01
-#define SIS315_DUAL_CHANNEL_MASK  0x0C
-#define SIS315_SINGLE_CHANNEL_1_RANK  	0x00
-#define SIS315_SINGLE_CHANNEL_2_RANK  	0x01
-#define SIS315_ASYM_DDR		  	0x02
-#define SIS315_DUAL_CHANNEL_1_RANK    	0x03
-
-#define SIS_SCRATCH_REG_1A_MASK   0x10
-
-#define SIS_ENABLE_2D             0x40  /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
-#define SIS_PCI_ADDR_ENABLE       0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/650/740 SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
-#define SIS_MMIO_CMD_ENABLE       0x20
-#define SIS_CMD_QUEUE_SIZE_512k   0x00
-#define SIS_CMD_QUEUE_SIZE_1M     0x04
-#define SIS_CMD_QUEUE_SIZE_2M     0x08
-#define SIS_CMD_QUEUE_SIZE_4M     0x0C
-#define SIS_CMD_QUEUE_RESET       0x01
-#define SIS_CMD_AUTO_CORR	  0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
-#define SIS_MODE_SELECT_CRT2      0x02
-#define SIS_VB_OUTPUT_COMPOSITE   0x04
-#define SIS_VB_OUTPUT_SVIDEO      0x08
-#define SIS_VB_OUTPUT_SCART       0x10
-#define SIS_VB_OUTPUT_LCD         0x20
-#define SIS_VB_OUTPUT_CRT2        0x40
-#define SIS_VB_OUTPUT_HIVISION    0x80
-
-#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
-#define SIS_DRIVER_MODE           0x40
-
-#define SIS_VB_COMPOSITE          0x01  /* CR32 */
-#define SIS_VB_SVIDEO             0x02
-#define SIS_VB_SCART              0x04
-#define SIS_VB_LCD                0x08
-#define SIS_VB_CRT2               0x10
-#define SIS_CRT1                  0x20
-#define SIS_VB_HIVISION           0x40
-#define SIS_VB_DVI                0x80
-#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
-                                   SIS_VB_SCART | SIS_VB_HIVISION)
-
-#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS             0x02  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_TRUMPION         0x03  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS          0x02  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  /* in CR37 << 1 ! */
-
-#define SIS_AGP_2X                0x20  /* CR48 */
-
-#define BRI_DRAM_SIZE_MASK        0x70  /* PCI bridge config data */
-#define BRI_DRAM_SIZE_2MB         0x00
-#define BRI_DRAM_SIZE_4MB         0x01
-#define BRI_DRAM_SIZE_8MB         0x02
-#define BRI_DRAM_SIZE_16MB        0x03
-#define BRI_DRAM_SIZE_32MB        0x04
-#define BRI_DRAM_SIZE_64MB        0x05
-
-#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
-
-#define SR_BUFFER_SIZE            5
-#define CR_BUFFER_SIZE            5
-
-/* entries for disp_state - deprecated as of 1.6.02 */
-#define DISPTYPE_CRT1       0x00000008L
-#define DISPTYPE_CRT2       0x00000004L
-#define DISPTYPE_LCD        0x00000002L
-#define DISPTYPE_TV         0x00000001L
-#define DISPTYPE_DISP1      DISPTYPE_CRT1
-#define DISPTYPE_DISP2      (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
-#define DISPMODE_SINGLE	    0x00000020L
-#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
-#define HASVB_TRUMPION  	0x04
-#define HASVB_LVDS_CHRONTEL	0x10
-#define HASVB_302       	0x20
-#define HASVB_303       	0x40
-#define HASVB_CHRONTEL  	0x80
-
-/* Useful macros */
-#define inSISREG(base)          inb(base)
-#define outSISREG(base,val)     outb(val,base)
-#define orSISREG(base,val)      do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp | (val)); \
-                                } while (0)
-#define andSISREG(base,val)     do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp & (val)); \
-                                } while (0)
-#define inSISIDXREG(base,idx,var)   do { \
-                                      outb(idx,base); var=inb((base)+1); \
-                                    } while (0)
-#define outSISIDXREG(base,idx,val)  do { \
-                                      outb(idx,base); outb((val),(base)+1); \
-                                    } while (0)
-#define orSISIDXREG(base,idx,val)   do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)|(val); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define andSISIDXREG(base,idx,and)  do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)&(and); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define setSISIDXREG(base,idx,and,or)   do { \
-                                          unsigned char __Temp; \
-                                          outb(idx,base);   \
-                                          __Temp = (inb((base)+1)&(and))|(or); \
-                                          outSISIDXREG(base,idx,__Temp); \
-                                        } while (0)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* Offscreen layout */
-typedef struct _SIS_GLYINFO {
-	unsigned char ch;
-	int fontwidth;
-	int fontheight;
-	u8 gmask[72];
-	int ngmask;
-} SIS_GLYINFO;
-
-static char sisfb_fontname[40];
-#endif
-
-typedef struct _SIS_OH {
-	struct _SIS_OH *poh_next;
-	struct _SIS_OH *poh_prev;
-	unsigned long offset;
-	unsigned long size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
-	struct _SIS_OHALLOC *poha_next;
-	SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
-	SIS_OH oh_free;
-	SIS_OH oh_used;
-	SIS_OH *poh_freelist;
-	SIS_OHALLOC *poha_chain;
-	unsigned long max_freesize;
-} SIS_HEAP;
+#define MODE_INDEX_NONE           0  /* index for mode=none */
 
 /* Fbcon stuff */
-static struct fb_info *sis_fb_info;
-
-static struct fb_var_screeninfo default_var = {
+static struct fb_var_screeninfo my_default_var = {
 	.xres            = 0,
 	.yres            = 0,
 	.xres_virtual    = 0,
@@ -377,103 +58,71 @@
 	.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
 };
 
+/* Boot-time parameters */
+static int sisfb_off = 0;
+static int sisfb_parm_mem = 0;
+static int sisfb_accel = -1;
+static int sisfb_ypan = -1;
+static int sisfb_max = -1;
+static int sisfb_userom = 1;
+static int sisfb_useoem = -1;
+#ifdef MODULE
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static struct fb_fix_screeninfo sisfb_fix = {
-	.id		= "SiS",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.xpanstep	= 0,
-	.ypanstep	= 1,
-};
-static char myid[40];
-static u32 pseudo_palette[17];
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static struct display sis_disp;
-
-static struct display_switch sisfb_sw;	
-
-static struct {
-	u16 blue, green, red, pad;
-} sis_palette[256];
-
-static union {
-#ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
+static int sisfb_mode_idx = -1;
+#else
+static int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
 #endif
-} sis_fbcon_cmap;
-
-static int sisfb_inverse = 0;
-static int currcon = 0;
+#else
+static int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
 #endif
-
-static int sisfb_off = 0;
+static int sisfb_parm_rate = -1;
 static int sisfb_crt1off = 0;
 static int sisfb_forcecrt1 = -1;
 static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-static int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
-static int sisfb_userom = 1;
-static int sisfb_useoem = -1;
-static int sisfb_parm_rate = -1;
-static int sisfb_mem = 0;
+static int sisfb_crt2flags = 0;
 static int sisfb_pdc = 0xff;
 static int sisfb_pdca = 0xff;
-static int sisfb_ypan = -1;
-static int sisfb_max = -1;
-static int sisfb_nocrt2rate = 0;
+static int sisfb_scalelcd = -1;
+static int sisfb_specialtiming = CUT_NONE;
+static int sisfb_lvdshl = -1;
 static int sisfb_dstn = 0;
 static int sisfb_fstn = 0;
-int 	   sisfb_accel = -1;
-int 	   sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
+static int sisfb_tvplug = -1;		/* Tv plug type (for overriding autodetection) */
+static int sisfb_tvstd  = -1;
+static int sisfb_tvxposoffset = 0;
+static int sisfb_tvyposoffset = 0;
+static int sisfb_filter = -1;
+static int sisfb_nocrt2rate = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int  sisfb_inverse = 0;
+static char sisfb_fontname[40];
+#endif
 #if !defined(__i386__) && !defined(__x86_64__)
 static int sisfb_resetcard = 0;
 static int sisfb_videoram = 0;
 #endif
 
-/* data for sis hardware ("par") */
-struct video_info ivideo;
-
-/* For ioctl SISFB_GET_INFO */
-sisfb_info sisfbinfo;
-
-/* Hardware info; contains data on hardware */
-SIS_HW_INFO sishw_ext;
-
-/* SiS private structure */
-SiS_Private  SiS_Pr;
-
-typedef enum _SIS_CMDTYPE {
-	MMIO_CMD = 0,
-	AGP_CMD_QUEUE,
-	VM_CMD_QUEUE,
-} SIS_CMDTYPE;
-
 /* List of supported chips */
 static struct sisfb_chip_info {
         int 		chip;
-	VGA_ENGINE 	vgaengine;
+	int 		vgaengine;
+	int		mni;
 	int 		hwcursor_size;
 	int		CRT2_write_enable;
 	const char 	*chip_name;
 } sisfb_chip_info[] __devinitdata = {
-	{ SIS_300,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
-	{ SIS_540,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
-	{ SIS_630,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
-	{ SIS_315H,   SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
-	{ SIS_315,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
-	{ SIS_315PRO, SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
-	{ SIS_550,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
-	{ SIS_650,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 65x" },
-	{ SIS_330,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
-	{ SIS_660,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+	{ SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
+	{ SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
+	{ SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
+	{ SIS_315H,   SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
+	{ SIS_315,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
+	{ SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
+	{ SIS_550,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
+	{ SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
+	{ SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
+	{ SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
 };
 
 static struct pci_device_id __devinitdata sisfb_pci_table[] = {
@@ -493,16 +142,26 @@
 #endif
 	{ 0 }
 };
+
 MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
 
+static struct sis_video_info *card_list = NULL;
+
+/* TODO: This is not handled card-wise because the DRM
+   does not refer to a unique fb when calling sis_alloc
+   or sis_free. Therefore, this is handled globally for
+   now (hoping that nobody is crazy enough to run two
+   SiS cards at the same time).
+ */
+SIS_HEAP       	sisfb_heap;
+
 #define MD_SIS300 1
 #define MD_SIS315 2
 
 /* Mode table */
-/* NOT const - will be patched for 1280x768 mode number chaos reasons */
-struct _sisbios_mode {
+static const struct _sisbios_mode {
 	char name[15];
-	u8 mode_no;
+	u8 mode_no[2];
 	u16 vesa_mode_no_1;  /* "SiS defined" VESA mode number */
 	u16 vesa_mode_no_2;  /* Real VESA mode numbers */
 	u16 xres;
@@ -513,202 +172,223 @@
 	u16 rows;
 	u8  chipset;
 } sisbios_mode[] = {
-#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},
-	{"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},
-	{"720x480x24",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x32",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x576x8",    0x32, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"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},
+/*0*/	{"none",         {0xff,0xff}, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
+	{"320x200x8",    {0x59,0x59}, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x16",   {0x41,0x41}, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x24",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* That's for people who mix up color- and fb depth */
+	{"320x200x32",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x50,0x50}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* FSTN */
+/*10*/	{"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* FSTN */
+	{"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x32",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"512x384x8",    {0x52,0x52}, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x16",   {0x58,0x58}, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x24",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x32",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"640x400x8",    {0x2f,0x2f}, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
+/*20*/	{"640x400x16",   {0x5d,0x5d}, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x24",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x32",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x480x8",    {0x2e,0x2e}, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x16",   {0x44,0x44}, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x24",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x32",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"720x480x8",    {0x31,0x31}, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x16",   {0x33,0x33}, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x24",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+/*30*/	{"720x480x32",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x576x8",    {0x32,0x32}, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x16",   {0x34,0x34}, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x24",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x32",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"768x576x8",    {0x5f,0x5f}, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x16",   {0x60,0x60}, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x24",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x32",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"800x480x8",    {0x70,0x70}, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*40*/	{"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
 #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          },
-	{"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},
-	{"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          },
-	{"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},
-#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},
-	{"1280x800x8",   0x14, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
-	{"1280x800x16",  0x15, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
-	{"1280x800x24",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
-	{"1280x800x32",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           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},
-	{"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},
-	{"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},
-	{"1680x1050x8",  0x17, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x16", 0x18, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x24", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x32", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           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},
-	{"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},
-	{"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+	{"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+/*50*/	{"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"1024x576x8",   {0x71,0x71}, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x16",  {0x74,0x74}, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x24",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x32",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x600x8",   {0x20,0x20}, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
+/*60*/	{"1024x600x16",  {0x21,0x21}, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
+	{"1024x600x24",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x600x32",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x768x8",   {0x38,0x38}, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x16",  {0x4a,0x4a}, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x24",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x32",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1152x768x8",   {0x23,0x23}, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
+	{"1152x768x16",  {0x24,0x24}, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
+	{"1152x768x24",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+/*70*/	{"1152x768x32",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x864x8",   {0x29,0x29}, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x16",  {0x2a,0x2a}, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x24",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x32",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1280x720x8",   {0x79,0x79}, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x16",  {0x75,0x75}, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x24",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x32",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x768x8",   {0x55,0x23}, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
+/*80*/	{"1280x768x16",  {0x5a,0x24}, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x24",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x32",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x800x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
+	{"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
+	{"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*90*/	{"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
+/*100*/	{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*110*/	{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
+};
+
+#define SIS_LCD_NUMBER 17
+static const struct _sis_lcd_data {
+	u32 lcdtype;
+	u16 xres; 
+	u16 yres; 
+	u8  default_mode_idx;
+} sis_lcd_data[] = {
+	{ LCD_640x480,    640,  480,  23 },
+	{ LCD_800x600,    800,  600,  43 },
+	{ LCD_1024x600,  1024,  600,  59 },
+	{ LCD_1024x768,  1024,  768,  63 },
+	{ LCD_1152x768,  1152,  768,  67 },
+	{ LCD_1152x864,  1152,  864,  71 },
+	{ LCD_1280x720,  1280,  720,  75 },
+	{ LCD_1280x768,  1280,  768,  79 },
+	{ LCD_1280x800,  1280,  800,  83 },
+	{ LCD_1280x960,  1280,  960,  87 },
+	{ LCD_1280x1024, 1280, 1024,  91 },
+	{ LCD_1400x1050, 1400, 1050, 103 },
+	{ LCD_1680x1050, 1680, 1050, 111 },
+	{ LCD_1600x1200, 1600, 1200, 107 },
+	{ LCD_640x480_2,  640,  480,  23 },
+	{ LCD_640x480_3,  640,  480,  23 },
+	{ LCD_320x480,    320,  480,   9 },
 };
 
-/* mode-related variables */
-#ifdef MODULE
-int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
-#else
-int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
-#endif
-
 /* CR36 evaluation */
 const USHORT sis300paneltype[] =
     { 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 };
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN };
 
 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_640x480_2, LCD_640x480_3, LCD_320x480,   LCD_1024x768 };
+      LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN,   LCD_UNKNOWN };
 
 const USHORT sis661paneltype[] =
     { 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_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_1024x768 };
+      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN };
 
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
+#define FL_300      0x04
+#define FL_315      0x08
 
 static struct _sis_crt2type {
-	char name[10];
-	int type_no;
-	int tvplug_no;
-	unsigned short flags;
+	char name[32];
+	u32 type_no;
+	u32 tvplug_no;
+	u16 flags;
 } sis_crt2type[] __initdata = {
-	{"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 */
-static struct _sis_queuemode {
-	char name[6];
-	int type_no;
-} sis_queuemode[] __initdata = {
-	{"AGP",  	AGP_CMD_QUEUE},
-	{"VRAM", 	VM_CMD_QUEUE},
-	{"MMIO", 	MMIO_CMD},
-	{"\0",   	-1}
+	{"NONE", 	     0, 	-1,                     FL_300|FL_315},
+	{"LCD",  	     CRT2_LCD, 	-1,                     FL_300|FL_315},
+	{"TV",   	     CRT2_TV, 	-1,                     FL_300|FL_315},
+	{"VGA",  	     CRT2_VGA, 	-1,                     FL_300|FL_315},
+	{"SVIDEO", 	     CRT2_TV, 	TV_SVIDEO,              FL_300|FL_315},
+	{"COMPOSITE", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"CVBS", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"SVIDEO+COMPOSITE", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"COMPOSITE+SVIDEO", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SVIDEO+CVBS",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"CVBS+SVIDEO",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SCART", 	     CRT2_TV, 	TV_SCART,               FL_300|FL_315},
+	{"HIVISION",	     CRT2_TV,   TV_HIVISION,            FL_315},
+	{"YPBPR480I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525I,  FL_315},
+	{"YPBPR480P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525P,  FL_315},
+	{"YPBPR720P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR750P,  FL_315},
+	{"YPBPR1080I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR1080I, FL_315},
+	{"DSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_DSTN},
+	{"FSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_FSTN},
+	{"\0",  	     -1, 	-1,                     0}
 };
 
 /* TV standard */
 static struct _sis_tvtype {
 	char name[6];
-	int type_no;
+	u32 type_no;
 } sis_tvtype[] __initdata = {
 	{"PAL",  	TV_PAL},
 	{"NTSC", 	TV_NTSC},
+	{"PALM",  	TV_PAL|TV_PALM},
+	{"PALN",  	TV_PAL|TV_PALN},
+	{"NTSCJ",  	TV_NTSC|TV_NTSCJ},
 	{"\0",   	-1}
 };
 
@@ -764,16 +444,6 @@
 	{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;
@@ -812,14 +482,10 @@
        { 1920, 1440, 75, 113,297000}
 };
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static u8 sisfb_lastrates[128];
-#endif
-
 #ifdef CONFIG_FB_SIS_300
 static struct _chswtable {
-    int subsysVendor;
-    int subsysCard;
+    u16  subsysVendor;
+    u16  subsysCard;
     char *vendorName;
     char *cardName;
 } mychswtable[] __devinitdata = {
@@ -830,18 +496,18 @@
 #endif
 
 static 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;
+    u16   chipID;
+    char  *biosversion;
+    char  *biosdate;
+    u32   bioschksum;
+    u16   biosFootprintAddr[5];
+    u8    biosFootprintData[5];
+    u16   pcisubsysvendor;
+    u16   pcisubsyscard;
+    char  *vendorName;
+    char  *cardName;
+    u32   SpecialID;
+    char  *optionName;
 } mycustomttable[] __devinitdata = {
 	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
 	  0x3240A8,
@@ -971,13 +637,6 @@
 	}
 };
 
-
-
-static unsigned long sisfb_heap_start;
-static unsigned long sisfb_heap_end;
-static unsigned long sisfb_heap_size;
-static SIS_HEAP      sisfb_heap;
-
 static const struct _sis_TV_filter {
 	u8 filter[9][4];
 } sis_TV_filter[] = {
@@ -1127,9 +786,6 @@
 	   {0xFF,0xFF,0xFF,0xFF} }}
 };
 
-static int           filter = -1;
-static unsigned char filter_tb;
-
 /* ---------------------- Prototypes ------------------------- */
 
 /* Interface used by the world */
@@ -1140,7 +796,11 @@
 /* Interface to the low level console driver */
 int             sisfb_init(void);
 
+
 /* fbdev routines */
+static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			      struct fb_info *info);
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, 
 			      int con,
@@ -1151,7 +811,8 @@
 static int      sisfb_set_var(struct fb_var_screeninfo *var, 
 			      int con,
 			      struct fb_info *info);
-static void     sisfb_crtc_to_var(struct fb_var_screeninfo *var);			      
+static void     sisfb_crtc_to_var(struct sis_video_info *ivideo, 
+			          struct fb_var_screeninfo *var);			      
 static int      sisfb_get_cmap(struct fb_cmap *cmap, 
 			       int kspc, 
 			       int con,
@@ -1174,104 +835,67 @@
 			      struct fb_info *fb_info);
 static void     sisfb_do_install_cmap(int con, 
                                       struct fb_info *info);
-static void     sis_get_glyph(struct fb_info *info, 
-                              SIS_GLYINFO *gly);
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);	
 static int      sisfb_ioctl(struct inode *inode, struct file *file,
 		       	    unsigned int cmd, unsigned long arg, int con,
 		       	    struct fb_info *info);		      
 #endif			
 
 #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);
 static int      sisfb_set_par(struct fb_info *info);
 static int      sisfb_blank(int blank, 
                             struct fb_info *info);			
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);			    
 extern void     fbcon_sis_fillrect(struct fb_info *info, 
                                    const struct fb_fillrect *rect);
 extern void     fbcon_sis_copyarea(struct fb_info *info, 
                                    const struct fb_copyarea *area);
 extern int      fbcon_sis_sync(struct fb_info *info);
-static int      sisfb_ioctl(struct inode *inode, 
-	 		    struct file *file,
-		       	    unsigned int cmd, 
-			    unsigned long arg, 
-		       	    struct fb_info *info);
-extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, 
-			      PSIS_HW_INFO HwDeviceExtension,
-			      unsigned char modeno, unsigned char rateindex);	
-extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
-			 unsigned char modeno, unsigned char rateindex,
-			 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);
 #endif
 			
-static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			      struct fb_info *info);
-
 /* Internal 2D accelerator functions */
-extern int      sisfb_initaccel(void);
-extern void     sisfb_syncaccel(void);
+extern int      sisfb_initaccel(struct sis_video_info *ivideo);
+extern void     sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
 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_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8       sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, 
+			int index);
 static int      sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			unsigned blue, unsigned transp,
 			struct fb_info *fb_info);
 static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      	struct fb_info *info);
-static void     sisfb_pre_setmode(void);
-static void     sisfb_post_setmode(void);
-
+static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void     sisfb_post_setmode(struct sis_video_info *ivideo);
 static char *   sis_find_rom(struct pci_dev *pdev);
-static BOOLEAN  sisfb_CheckVBRetrace(void);
-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 BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN  sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void     sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void     sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void     sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void     sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
 
-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);
+/* SiS-specific exported functions */
 void            sis_malloc(struct sis_memreq *req);
-void            sis_free(unsigned long base);
-
-/* Chipset-dependent internal routines */
-#ifdef CONFIG_FB_SIS_300
-static int      sisfb_get_dram_size_300(void);
-#endif
-#ifdef CONFIG_FB_SIS_315
-static int      sisfb_get_dram_size_315(void);
-#endif
+void            sis_free(u32 base);
 
 /* Internal heap routines */
-static int      sisfb_heap_init(void);
+static int      sisfb_heap_init(struct sis_video_info *ivideo);
 static SIS_OH   *sisfb_poh_new_node(void);
-static SIS_OH   *sisfb_poh_allocate(unsigned long size);
+static SIS_OH   *sisfb_poh_allocate(u32 size);
 static void     sisfb_delete_node(SIS_OH *poh);
 static void     sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH   *sisfb_poh_free(unsigned long base);
+static SIS_OH   *sisfb_poh_free(u32 base);
 static void     sisfb_free_node(SIS_OH *poh);
 
-/* Internal routines to access PCI configuration space */
-BOOLEAN         sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	          	unsigned long offset, unsigned long set, unsigned long *value);
-BOOLEAN         sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	         	unsigned long offset, unsigned long set, unsigned long *value);
-
 /* Sensing routines */
-static void     SiS_Sense30x(void);
-static int      SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
-static void     SiS_SenseCh(void);
+static void     SiS_Sense30x(struct sis_video_info *ivideo);
+static void     SiS_SenseCh(struct sis_video_info *ivideo);
 
 /* Routines from init.c/init301.c */
 extern USHORT   SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
@@ -1289,8 +913,16 @@
 
 extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		       
+extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, 
+		    	PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex);	
+extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex,
+			struct fb_var_screeninfo *var);		       
+#endif
 
-/* Chrontel TV functions */
+/* Chrontel TV, DDC and DPMS 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);
@@ -1298,7 +930,7 @@
 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,
+extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
 		              USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
 extern USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);			      
 extern void 	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
diff -urN linux-2.4.27-pre5/drivers/video/sis/vgatypes.h linux-2.4.27-pre6/drivers/video/sis/vgatypes.h
--- linux-2.4.27-pre5/drivers/video/sis/vgatypes.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/vgatypes.h	2004-06-16 11:33:28.769113601 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General type definitions for universal mode switching modules
  *
@@ -118,21 +119,17 @@
 #endif
 #endif
 
-#ifndef LINUX_KERNEL   /* For the linux kernel, this is defined in sisfb.h */
-#ifndef SIS_CHIP_TYPE
-typedef enum _SIS_CHIP_TYPE {
+enum _SIS_CHIP_TYPE {
     SIS_VGALegacy = 0,
-#ifdef LINUX_XF86
     SIS_530,
     SIS_OLD,
-#endif
     SIS_300,
     SIS_630,
     SIS_730,
     SIS_540,
     SIS_315H,   /* SiS 310 */
     SIS_315,
-    SIS_315PRO, /* SiS 325 */
+    SIS_315PRO,
     SIS_550,
     SIS_650,
     SIS_740,
@@ -141,29 +138,13 @@
     SIS_741,
     SIS_660,
     SIS_760,
+    SIS_761,
+    SIS_340,
     MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-#endif
-#endif
-
-#ifndef SIS_VB_CHIP_TYPE
-typedef enum _SIS_VB_CHIP_TYPE {
-    VB_CHIP_Legacy = 0,
-    VB_CHIP_301,
-    VB_CHIP_301B,
-    VB_CHIP_301LV,
-    VB_CHIP_302,
-    VB_CHIP_302B,
-    VB_CHIP_302LV,
-    VB_CHIP_301C,
-    VB_CHIP_302ELV,
-    VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
-    MAX_VB_CHIP
-} SIS_VB_CHIP_TYPE;
-#endif
+};
 
-#ifndef SIS_LCD_TYPE
-typedef enum _SIS_LCD_TYPE {
+#ifdef LINUX_KERNEL
+enum _SIS_LCD_TYPE {
     LCD_INVALID = 0,
     LCD_800x600,
     LCD_1024x768,
@@ -173,29 +154,22 @@
     LCD_1600x1200,
     LCD_1920x1440,
     LCD_2048x1536,
-    LCD_320x480,       /* FSTN, DSTN */
+    LCD_320x480,       /* FSTN */
     LCD_1400x1050,
     LCD_1152x864,
     LCD_1152x768,
     LCD_1280x768,
     LCD_1024x600,
-    LCD_640x480_2,     /* FSTN, DSTN */
-    LCD_640x480_3,     /* FSTN, DSTN */
+    LCD_640x480_2,     /* DSTN */
+    LCD_640x480_3,     /* DSTN */
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
     LCD_1280x720,
     LCD_CUSTOM,
     LCD_UNKNOWN
-} SIS_LCD_TYPE;
-#endif
-
-#ifndef PSIS_DSReg
-typedef struct _SIS_DSReg
-{
-  UCHAR  jIdx;
-  UCHAR  jVal;
-} SIS_DSReg, *PSIS_DSReg;
+};
+typedef unsigned int SIS_LCD_TYPE;
 #endif
 
 #ifndef SIS_HW_INFO
@@ -219,51 +193,38 @@
 
     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
 
-    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0) */
+    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0; relocated) */
 
     UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
-                                 /* defined in the data structure type  */
-                                 /* "SIS_CHIP_TYPE" */
+                                 /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
 
     UCHAR  jChipRevision;        /* Used to Identify SiS Graphics Chip Revision */
 
-    UCHAR  ujVBChipID;           /* the ID of video bridge */
-                                 /* defined in the data structure type */
-                                 /* "SIS_VB_CHIP_TYPE" */
-#ifdef LINUX_KERNEL
-    BOOLEAN Is301BDH;
-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
-                                 /* "SIS_LCD_TYPE" */
-#endif
-
-    USHORT usExternalChip;       /* NO VB or other video bridge (other than  */
-                                 /* SiS video bridge) */
-
     BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-                                      
-    BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
 
 #ifdef LINUX_KERNEL
-    PSIS_DSReg  pSR;             /* restore SR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF). */
-                                 /* Note : restore SR registers if  */
-                                 /* bSkipDramSizing = TRUE */
-
-    PSIS_DSReg  pCR;             /* restore CR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF) */
-                                 /* Note : restore cR registers if  */
-                                 /* bSkipDramSizing = TRUE */
+    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
+                                 /* "SIS_LCD_TYPE" */
 #endif
 };
 #endif
 
-/* Addtional IOCTL for communication sisfb <> X driver        */
+/* Addtional IOCTLs for communication sisfb <> X driver        */
 /* If changing this, sisfb.h must also be changed (for sisfb) */
 
 #ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
 
 /* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO    0x80046ef8  /* Wow, what a terrible hack... */
+#define SISFB_GET_INFO_SIZE	0x8004f300
+#define SISFB_GET_INFO		0x8000f301  /* Must be patched with result from ..._SIZE at D[29:16] */
+/* deprecated ioctl number (for older versions of sisfb) */
+#define SISFB_GET_INFO_OLD    	0x80046ef8  
+
+/* ioctls for tv parameters (position) */
+#define SISFB_SET_TVPOSOFFSET   0x4004f304
+
+/* lock sisfb from register access */
+#define SISFB_SET_LOCK		0x4004f306
 
 /* Structure argument for SISFB_GET_INFO ioctl  */
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
@@ -305,8 +266,10 @@
 	CARD8 	sisfb_haveemilcd;
 
 	CARD8 	sisfb_lcdpdca;
+	
+	CARD16  sisfb_tvxpos, sisfb_tvypos;  	/* Warning: Values + 32 ! */
 
-	CARD8 reserved[212]; 		/* for future use */
+	CARD8 reserved[208]; 			/* for future use */
 };
 #endif
 
diff -urN linux-2.4.27-pre5/drivers/video/sis/vstruct.h linux-2.4.27-pre6/drivers/video/sis/vstruct.h
--- linux-2.4.27-pre5/drivers/video/sis/vstruct.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/drivers/video/sis/vstruct.h	2004-06-16 11:33:28.770113642 -0700
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General structure definitions for universal mode switching modules
  *
@@ -168,6 +169,7 @@
 	UCHAR  VB_ExtTVYFilterIndex;
 	UCHAR  VB_ExtTVYFilterIndexROM661;
 	UCHAR  REFindex;
+	CHAR   ROMMODEIDX661;
 } SiS_ExtStruct;
 
 typedef struct _SiS_Ext2Struct
@@ -289,6 +291,7 @@
 #endif
 	BOOLEAN SiS_UseROM;
 	BOOLEAN SiS_ROMNew;
+	BOOLEAN SiS_NeedRomModeData;
 	BOOLEAN PanelSelfDetected;
 	int     SiS_CHOverScan;
 	BOOLEAN SiS_CHSOverScan;
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_btree.h linux-2.4.27-pre6/fs/jfs/jfs_btree.h
--- linux-2.4.27-pre5/fs/jfs/jfs_btree.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.27-pre6/fs/jfs/jfs_btree.h	2004-06-16 11:33:28.778113975 -0700
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2001
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   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
@@ -108,13 +108,12 @@
  * record the path traversed during the search;
  * top frame record the leaf page/entry selected.
  */
-#define	MAXTREEHEIGHT		8
 struct btframe {	/* stack frame */
 	s64 bn;			/* 8: */
 	s16 index;		/* 2: */
-	s16 lastindex;		/* 2: */
-	struct metapage *mp;	/* 4: */
-};				/* (16) */
+	s16 lastindex;		/* 2: unused */
+	struct metapage *mp;	/* 4/8: */
+};				/* (16/24) */
 
 struct btstack {
 	struct btframe *top;
@@ -125,12 +124,15 @@
 #define BT_CLR(btstack)\
 	(btstack)->top = (btstack)->stack
 
+#define BT_STACK_FULL(btstack)\
+	( (btstack)->top == &((btstack)->stack[MAXTREEHEIGHT-1]))
+
 #define BT_PUSH(BTSTACK, BN, INDEX)\
 {\
+	assert(!BT_STACK_FULL(BTSTACK));\
 	(BTSTACK)->top->bn = BN;\
 	(BTSTACK)->top->index = INDEX;\
 	++(BTSTACK)->top;\
-	assert((BTSTACK)->top != &((BTSTACK)->stack[MAXTREEHEIGHT]));\
 }
 
 #define BT_POP(btstack)\
@@ -139,6 +141,16 @@
 #define BT_STACK(btstack)\
 	( (btstack)->top == (btstack)->stack ? NULL : (btstack)->top )
 
+static inline void BT_STACK_DUMP(struct btstack *btstack)
+{
+	int i;
+	printk("btstack dump:\n");
+	for (i = 0; i < MAXTREEHEIGHT; i++)
+		printk(KERN_ERR "bn = %Lx, index = %d\n",
+		       btstack->stack[i].bn,
+		       btstack->stack[i].index);
+}
+
 /* retrieve search results */
 #define BT_GETSEARCH(IP, LEAF, BN, MP, TYPE, P, INDEX, ROOT)\
 {\
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_dmap.c linux-2.4.27-pre6/fs/jfs/jfs_dmap.c
--- linux-2.4.27-pre5/fs/jfs/jfs_dmap.c	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/fs/jfs/jfs_dmap.c	2004-06-16 11:33:28.780114059 -0700
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   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
@@ -382,7 +382,7 @@
 	IREAD_LOCK(ipbmap);
 
 	/* block to be freed better be within the mapsize. */
-	if (unlikely(blkno + nblocks > bmp->db_mapsize)) {
+	if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
 		IREAD_UNLOCK(ipbmap);
 		printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
 		       (unsigned long long) blkno,
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_dtree.c linux-2.4.27-pre6/fs/jfs/jfs_dtree.c
--- linux-2.4.27-pre5/fs/jfs/jfs_dtree.c	2004-06-16 11:33:26.400015006 -0700
+++ linux-2.4.27-pre6/fs/jfs/jfs_dtree.c	2004-06-16 11:33:28.783114183 -0700
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   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
@@ -374,16 +374,19 @@
 		return index;
 	}
 	if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
+		struct dir_table_slot temp_table[12];
+
 		/*
 		 * It's time to move the inline table to an external
 		 * page and begin to build the xtree
 		 */
+		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
+			goto clean_up;	/* No space */
 
 		/*
 		 * Save the table, we're going to overwrite it with the
 		 * xtree root
 		 */
-		struct dir_table_slot temp_table[12];
 		memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table));
 
 		/*
@@ -394,8 +397,8 @@
 		/*
 		 * Allocate the first block & add it to the xtree
 		 */
-		xaddr = 0;
 		if (xtInsert(tid, ip, 0, 0, sbi->nbperpage, &xaddr, 0)) {
+			/* This really shouldn't fail */
 			jfs_warn("add_index: xtInsert failed!");
 			memcpy(&jfs_ip->i_dirtable, temp_table,
 			       sizeof (temp_table));
@@ -764,11 +767,12 @@
 		 */
 	      getChild:
 		/* update max. number of pages to split */
-		if (btstack->nsplit >= 8) {
+		if (BT_STACK_FULL(btstack)) {
 			/* Something's corrupted, mark filesytem dirty so
 			 * chkdsk will fix it.
 			 */
 			jfs_error(sb, "stack overrun in dtSearch!");
+			BT_STACK_DUMP(btstack);
 			rc = -EIO;
 			goto out;
 		}
@@ -975,8 +979,10 @@
 		n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */
 		if (n <= split->nslot)
 			xlen++;
-		if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)))
+		if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) {
+			DT_PUTPAGE(smp);
 			goto freeKeyName;
+		}
 
 		pxdlist.maxnpxd = 1;
 		pxdlist.npxd = 0;
@@ -3342,6 +3348,12 @@
 		/*
 		 * descend down to leftmost child page
 		 */
+		if (BT_STACK_FULL(btstack)) {
+			DT_PUTPAGE(mp);
+			jfs_error(ip->i_sb, "dtReadFirst: btstack overrun");
+			BT_STACK_DUMP(btstack);
+			return -EIO;
+		}
 		/* push (bn, index) of the parent page/entry */
 		BT_PUSH(btstack, bn, 0);
 
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_metapage.c linux-2.4.27-pre6/fs/jfs/jfs_metapage.c
--- linux-2.4.27-pre5/fs/jfs/jfs_metapage.c	2004-06-16 11:33:26.402015089 -0700
+++ linux-2.4.27-pre6/fs/jfs/jfs_metapage.c	2004-06-16 11:33:28.786114308 -0700
@@ -281,8 +281,16 @@
 
 	if (absolute)
 		mapping = inode->i_sb->s_bdev->bd_inode->i_mapping;
-	else
+	else {
+		/*
+		 * If an nfs client tries to read an inode that is larger
+		 * than any existing inodes, we may try to read past the
+		 * end of the inode map
+		 */
+		if ((lblock << inode->i_blkbits) >= inode->i_size)
+			return NULL;
 		mapping = inode->i_mapping;
+	}
 
 	hash_ptr = meta_hash(mapping, lblock);
 again:
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_txnmgr.c linux-2.4.27-pre6/fs/jfs/jfs_txnmgr.c
--- linux-2.4.27-pre5/fs/jfs/jfs_txnmgr.c	2004-06-16 11:33:26.404015172 -0700
+++ linux-2.4.27-pre6/fs/jfs/jfs_txnmgr.c	2004-06-16 11:33:28.788114391 -0700
@@ -1705,7 +1705,10 @@
 
 		if (lwm == next)
 			goto out;
-		assert(lwm < next);
+		if (lwm > next) {
+			jfs_err("xtLog: lwm > next\n");
+			goto out;
+		}
 		tlck->flag |= tlckUPDATEMAP;
 		xadlock->flag = mlckALLOCXADLIST;
 		xadlock->count = next - lwm;
@@ -1871,25 +1874,18 @@
 		/*
 		 *      write log records
 		 */
-		/*
-		 * allocate entries XAD[lwm:next]:
-		 */
-		if (lwm < next) {
-			/* log after-image for logredo():
-			 * logredo() will update bmap for alloc of new/extended
-			 * extents (XAD_NEW|XAD_EXTEND) of XAD[lwm:next) from
-			 * after-image of XADlist;
-			 * logredo() resets (XAD_NEW|XAD_EXTEND) flag when
-			 * applying the after-image to the meta-data page.
-			 */
-			lrd->type = cpu_to_le16(LOG_REDOPAGE);
-			PXDaddress(pxd, mp->index);
-			PXDlength(pxd,
-				  mp->logical_size >> tblk->sb->
-				  s_blocksize_bits);
-			lrd->backchain =
-			    cpu_to_le32(lmLog(log, tblk, lrd, tlck));
-		}
+		/* log after-image for logredo():
+		 *
+		 * logredo() will update bmap for alloc of new/extended
+		 * extents (XAD_NEW|XAD_EXTEND) of XAD[lwm:next) from
+		 * after-image of XADlist;
+		 * logredo() resets (XAD_NEW|XAD_EXTEND) flag when
+		 * applying the after-image to the meta-data page.
+		 */
+		lrd->type = cpu_to_le16(LOG_REDOPAGE);
+		PXDaddress(pxd, mp->index);
+		PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
+		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
 
 		/*
 		 * truncate entry XAD[twm == next - 1]:
@@ -2588,6 +2584,7 @@
 	lid_t lid, next;
 	struct metapage *mp;
 	struct tblock *tblk = tid_to_tblock(tid);
+	struct tlock *tlck;
 
 	jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty);
 
@@ -2595,9 +2592,10 @@
 	 * free tlocks of the transaction
 	 */
 	for (lid = tblk->next; lid; lid = next) {
-		next = lid_to_tlock(lid)->next;
-
-		mp = lid_to_tlock(lid)->mp;
+		tlck = lid_to_tlock(lid);
+		next = tlck->next;
+		mp = tlck->mp;
+		JFS_IP(tlck->ip)->xtlid = 0;
 
 		if (mp) {
 			mp->lid = 0;
diff -urN linux-2.4.27-pre5/fs/jfs/jfs_types.h linux-2.4.27-pre6/fs/jfs/jfs_types.h
--- linux-2.4.27-pre5/fs/jfs/jfs_types.h	2004-06-16 11:33:26.405015214 -0700
+++ linux-2.4.27-pre6/fs/jfs/jfs_types.h	2004-06-16 11:33:28.789114433 -0700
@@ -111,11 +111,12 @@
 #define	addressPXD(pxd)\
 	( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2))
 
+#define MAXTREEHEIGHT 8
 /* pxd list */
 struct pxdlist {
 	s16 maxnpxd;
 	s16 npxd;
-	pxd_t pxd[8];
+	pxd_t pxd[MAXTREEHEIGHT];
 };
 
 
diff -urN linux-2.4.27-pre5/fs/jfs/namei.c linux-2.4.27-pre6/fs/jfs/namei.c
--- linux-2.4.27-pre5/fs/jfs/namei.c	2004-06-16 11:33:26.406015255 -0700
+++ linux-2.4.27-pre6/fs/jfs/namei.c	2004-06-16 11:33:28.790114475 -0700
@@ -849,7 +849,7 @@
 	unchar *i_fastsymlink;
 	s64 xlen = 0;
 	int bmask = 0, xsize;
-	s64 xaddr;
+	s64 extent = 0, xaddr;
 	struct metapage *mp;
 	struct super_block *sb;
 	struct tblock *tblk;
@@ -883,28 +883,10 @@
 	down(&JFS_IP(dip)->commit_sem);
 	down(&JFS_IP(ip)->commit_sem);
 
-	if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE)))
-		goto out3;
-
 	tblk = tid_to_tblock(tid);
 	tblk->xflag |= COMMIT_CREATE;
 	tblk->ip = ip;
 
-	/*
-	 * create entry for symbolic link in parent directory
-	 */
-
-	ino = ip->i_ino;
-
-
-
-	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-		jfs_err("jfs_symlink: dtInsert returned %d", rc);
-		/* discard ne inode */
-		goto out3;
-
-	}
-
 	/* fix symlink access permission
 	 * (dir_create() ANDs in the u.u_cmask, 
 	 * but symlinks really need to be 777 access)
@@ -912,7 +894,7 @@
 	ip->i_mode |= 0777;
 
 	/*
-	   *       write symbolic link target path name
+	 * write symbolic link target path name
 	 */
 	xtInitRoot(tid, ip);
 
@@ -956,39 +938,48 @@
 		xsize = (ssize + bmask) & ~bmask;
 		xaddr = 0;
 		xlen = xsize >> JFS_SBI(sb)->l2bsize;
-		if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0)) == 0) {
-			ip->i_size = ssize - 1;
-			while (ssize) {
-				int copy_size = min(ssize, PSIZE);
-
-				mp = get_metapage(ip, xaddr, PSIZE, 1);
-
-				if (mp == NULL) {
-					dtDelete(tid, dip, &dname, &ino,
-						 JFS_REMOVE);
-					rc = -EIO;
-					goto out3;
-				}
-				memcpy(mp->data, name, copy_size);
-				flush_metapage(mp);
-#if 0
-				mark_buffer_uptodate(bp, 1);
-				mark_buffer_dirty(bp, 1);
-				if (IS_SYNC(dip)) {
-					ll_rw_block(WRITE, 1, &bp);
-					wait_on_buffer(bp);
-				}
-				brelse(bp);
-#endif				/* 0 */
-				ssize -= copy_size;
-				xaddr += JFS_SBI(sb)->nbperpage;
-			}
-			ip->i_blocks = LBLK2PBLK(sb, xlen);
-		} else {
-			dtDelete(tid, dip, &dname, &ino, JFS_REMOVE);
+		if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {
+			txAbort(tid, 0);
 			rc = -ENOSPC;
 			goto out3;
 		}
+		extent = xaddr;
+		ip->i_size = ssize - 1;
+		while (ssize) {
+			/* This is kind of silly since PATH_MAX == 4K */
+			int copy_size = min(ssize, PSIZE);
+
+			mp = get_metapage(ip, xaddr, PSIZE, 1);
+
+			if (mp == NULL) {
+				dbFree(ip, extent, xlen);
+				rc = -EIO;
+				txAbort(tid, 0);
+				goto out3;
+			}
+			memcpy(mp->data, name, copy_size);
+			flush_metapage(mp);
+			ssize -= copy_size;
+			name += copy_size;
+			xaddr += JFS_SBI(sb)->nbperpage;
+		}
+		ip->i_blocks = LBLK2PBLK(sb, xlen);
+	}
+
+	/*
+	 * create entry for symbolic link in parent directory
+	 */
+	rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);
+	if (rc == 0) {
+		ino = ip->i_ino;
+		rc = dtInsert(tid, dip, &dname, &ino, &btstack);
+	}
+	if (rc) {
+		if (xlen)
+			dbFree(ip, extent, xlen);
+		txAbort(tid, 0);
+		/* discard new inode */
+		goto out3;
 	}
 
 	insert_inode_hash(ip);
@@ -996,23 +987,11 @@
 
 	/*
 	 * commit update of parent directory and link object
-	 *
-	 * if extent allocation failed (ENOSPC),
-	 * the parent inode is committed regardless to avoid
-	 * backing out parent directory update (by dtInsert())
-	 * and subsequent dtDelete() which is harmless wrt 
-	 * integrity concern.  
-	 * the symlink inode will be freed by iput() at exit
-	 * as it has a zero link count (by dtDelete()) and 
-	 * no permanant resources. 
 	 */
 
 	iplist[0] = dip;
-	if (rc == 0) {
-		iplist[1] = ip;
-		rc = txCommit(tid, 2, &iplist[0], 0);
-	} else
-		rc = txCommit(tid, 1, &iplist[0], 0);
+	iplist[1] = ip;
+	rc = txCommit(tid, 2, &iplist[0], 0);
 
       out3:
 	txEnd(tid);
@@ -1212,7 +1191,7 @@
 			/* Linelock header of dtree */
 			tlck = txLock(tid, old_ip,
 				    (struct metapage *) &JFS_IP(old_ip)->bxflag,
-				      tlckDTREE | tlckBTROOT);
+				      tlckDTREE | tlckBTROOT | tlckRELINK);
 			dtlck = (struct dt_lock *) & tlck->lock;
 			ASSERT(dtlck->index == 0);
 			lv = & dtlck->lv[0];
diff -urN linux-2.4.27-pre5/fs/namei.c linux-2.4.27-pre6/fs/namei.c
--- linux-2.4.27-pre5/fs/namei.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.27-pre6/fs/namei.c	2004-06-16 11:33:28.791114516 -0700
@@ -583,9 +583,9 @@
 			if (err < 0)
 				break;
 		}
-		dentry = cached_lookup(nd->dentry, &this, 0);
+		dentry = cached_lookup(nd->dentry, &this, nd->flags);
 		if (!dentry) {
-			dentry = real_lookup(nd->dentry, &this, 0);
+			dentry = real_lookup(nd->dentry, &this, nd->flags);
 			err = PTR_ERR(dentry);
 			if (IS_ERR(dentry))
 				break;
diff -urN linux-2.4.27-pre5/include/asm-i386/bitops.h linux-2.4.27-pre6/include/asm-i386/bitops.h
--- linux-2.4.27-pre5/include/asm-i386/bitops.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.27-pre6/include/asm-i386/bitops.h	2004-06-16 11:33:28.891118678 -0700
@@ -266,7 +266,6 @@
 
 	if (!size)
 		return 0;
-	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
 	__asm__ __volatile__(
 		"movl $-1,%%eax\n\t"
 		"xorl %%edx,%%edx\n\t"
@@ -279,7 +278,7 @@
 		"shll $3,%%edi\n\t"
 		"addl %%edi,%%edx"
 		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
-		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
+		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
 	return res;
 }
 
diff -urN linux-2.4.27-pre5/include/asm-i386/i387.h linux-2.4.27-pre6/include/asm-i386/i387.h
--- linux-2.4.27-pre5/include/asm-i386/i387.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.27-pre6/include/asm-i386/i387.h	2004-06-16 11:33:28.891118678 -0700
@@ -34,7 +34,7 @@
 
 #define clear_fpu( tsk ) do { \
 	if ( tsk->flags & PF_USEDFPU ) { \
-		asm volatile("fwait"); \
+		asm volatile("fnclex ; fwait"); \
 		tsk->flags &= ~PF_USEDFPU; \
 		stts(); \
 	} \
diff -urN linux-2.4.27-pre5/include/asm-x86_64/bluesmoke.h linux-2.4.27-pre6/include/asm-x86_64/bluesmoke.h
--- linux-2.4.27-pre5/include/asm-x86_64/bluesmoke.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.27-pre6/include/asm-x86_64/bluesmoke.h	2004-06-16 11:33:28.897118928 -0700
@@ -0,0 +1,16 @@
+#ifndef _bluesmoke_h
+#define _bluesmoke_h
+
+/* Notifier to allow an external module to read machine check events */
+
+extern struct notifier_block *mc_notifier_list;
+struct notifier_mc_err {
+	unsigned int cpunum;
+	unsigned int banknum;
+	u64 mci_ctl;
+	u64 mci_status;
+	u64 mci_addr;
+	u64 mci_misc;
+};
+
+#endif 
diff -urN linux-2.4.27-pre5/include/asm-x86_64/desc.h linux-2.4.27-pre6/include/asm-x86_64/desc.h
--- linux-2.4.27-pre5/include/asm-x86_64/desc.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.27-pre6/include/asm-x86_64/desc.h	2004-06-16 11:33:28.898118970 -0700
@@ -121,7 +121,6 @@
 	dst->base1 = PTR_MIDDLE(ptr) & 0xFF; 
 	dst->type = type;
 	dst->p = 1; 
-	dst->g = 1;
 	dst->limit1 = (size >> 16) & 0xF;
 	dst->base2 = (PTR_MIDDLE(ptr) >> 8) & 0xFF; 
 	dst->base3 = PTR_HIGH(ptr); 
@@ -134,7 +133,7 @@
 
 static inline void set_ldt_desc(unsigned n, void *addr, int size)
 { 
-	set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,ldt), (unsigned long)addr, DESC_LDT, size); 
+	set_tssldt_descriptor((void *)&gdt_table + __CPU_DESC_INDEX(n,ldt), (unsigned long)addr, DESC_LDT, size * 8); 
 }	
 
 /*
diff -urN linux-2.4.27-pre5/include/asm-x86_64/i387.h linux-2.4.27-pre6/include/asm-x86_64/i387.h
--- linux-2.4.27-pre5/include/asm-x86_64/i387.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.27-pre6/include/asm-x86_64/i387.h	2004-06-16 11:33:28.898118970 -0700
@@ -34,7 +34,7 @@
 
 #define clear_fpu( tsk ) do { \
 	if ( tsk->flags & PF_USEDFPU ) { \
-		asm volatile("fwait"); \
+		asm volatile("fnclex ; fwait"); \
 		tsk->flags &= ~PF_USEDFPU; \
 		stts(); \
 	} \
diff -urN linux-2.4.27-pre5/include/linux/cciss_ioctl.h linux-2.4.27-pre6/include/linux/cciss_ioctl.h
--- linux-2.4.27-pre5/include/linux/cciss_ioctl.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.27-pre6/include/linux/cciss_ioctl.h	2004-06-16 11:33:28.900119053 -0700
@@ -208,4 +208,31 @@
 #define CCISS_GETLUNINFO  _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct)
 #define CCISS_BIG_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL_Command_struct)
 
+#ifdef __KERNEL__
+#ifdef __x86_64__
+
+/* 32 bit compatible ioctl structs */ 
+typedef struct _IOCTL32_Command_struct {
+  LUNAddr_struct	   LUN_info;
+  RequestBlock_struct      Request;
+  ErrorInfo_struct  	   error_info; 
+  WORD			   buf_size;  /* size in bytes of the buf */
+  __u32			   buf; /* 32 bit pointer to data buffer */
+} IOCTL32_Command_struct;
+
+typedef struct _BIG_IOCTL32_Command_struct {
+  LUNAddr_struct	   LUN_info;
+  RequestBlock_struct      Request;
+  ErrorInfo_struct  	   error_info; 
+  DWORD			   malloc_size; /* < MAX_KMALLOC_SIZE in cciss.c */
+  DWORD			   buf_size;    /* size in bytes of the buf */
+  				        /* < malloc_size * MAXSGENTRIES */
+  __u32 		buf;	/* 32 bit pointer to data buffer */
+} BIG_IOCTL32_Command_struct;
+
+#define CCISS_PASSTHRU32   _IOWR(CCISS_IOC_MAGIC, 11, IOCTL32_Command_struct)
+#define CCISS_BIG_PASSTHRU32 _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL32_Command_struct)
+
+#endif /* __x86_64__ */
+#endif /* __KERNEL__ */
 #endif  
diff -urN linux-2.4.27-pre5/include/linux/cdrom.h linux-2.4.27-pre6/include/linux/cdrom.h
--- linux-2.4.27-pre5/include/linux/cdrom.h	2001-11-22 11:47:04.000000000 -0800
+++ linux-2.4.27-pre6/include/linux/cdrom.h	2004-06-16 11:33:28.900119053 -0700
@@ -5,7 +5,8 @@
  *               1994, 1995   Eberhard Moenkeberg, emoenke@gwdg.de
  *               1996         David van Leeuwen, david@tm.tno.nl
  *               1997, 1998   Erik Andersen, andersee@debian.org
- *               1998-2000    Jens Axboe, axboe@suse.de
+ *               1998-2004    Jens Axboe, axboe@suse.de
+ *               2004         Iomega Corp
  */
  
 #ifndef	_LINUX_CDROM_H
@@ -387,6 +388,7 @@
 #define CDC_DVD			0x8000	/* drive is a DVD */
 #define CDC_DVD_R		0x10000	/* drive can write DVD-R */
 #define CDC_DVD_RAM		0x20000	/* drive can write DVD-RAM */
+#define CDC_RAM			0x100000 /* ok to open WRITE */
 
 /* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
 #define CDS_NO_INFO		0	/* if not implemented */
@@ -714,16 +716,43 @@
 	__u8 asb[46];
 };
 
-#ifdef __KERNEL__
-#include <linux/devfs_fs_kernel.h>
+/*
+ * feature profile
+ */
+#define CDF_RWRT	0x0020
+#define CDF_HWDM	0x0024
 
-struct cdrom_write_settings {
-	unsigned char fpacket;		/* fixed/variable packets */
-	unsigned long packet_size;	/* write out this number of packets */
-	unsigned long nwa;		/* next writeable address */
-	unsigned char writeable;	/* cdrom is writeable */
+/* cf. mmc4r02g.pdf 5.3.10 Random Writable Feature (0020h) pg 197 of 635 */
+struct rwrt_feature_desc {
+	__u16 feature_code;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1		: 2;
+	__u8 feature_version	: 4;
+	__u8 persistent		: 1;
+	__u8 curr		: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 curr		: 1;
+	__u8 persistent		: 1;
+	__u8 feature_version	: 4;
+	__u8 reserved1		: 2;
+#endif
+	__u8 add_len;
+	__u32 last_lba;
+	__u32 block_size;
+	__u16 blocking;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2		: 7;
+	__u8 page_present	: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 page_present	: 1;
+	__u8 reserved2		: 7;
+#endif
+	__u8 reserved3;
 };
 
+#ifdef __KERNEL__
+#include <linux/devfs_fs_kernel.h>
+
 /* Uniform cdrom data structures for cdrom.c */
 struct cdrom_device_info {
 	struct cdrom_device_ops  *ops;  /* link to device_ops */
@@ -744,7 +773,6 @@
 /* per-device flags */
         __u8 sanyo_slot		: 2;	/* Sanyo 3 CD changer support */
         __u8 reserved		: 6;	/* not used yet */
-	struct cdrom_write_settings write;
 };
 
 struct cdrom_device_ops {
@@ -1053,6 +1081,17 @@
 	__u8 reserved3;
 } rpc_state_t;
 
-#endif  /* End of kernel only stuff */ 
+struct feature_header {
+	__u32 data_len;
+	__u8 reserved1;
+	__u8 reserved2;
+	__u16 curr_profile;
+};
+
+extern int cdrom_get_disc_info(kdev_t dev, disc_information *di);
+extern int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
+				track_information *ti);
+extern int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write);
+#endif /* __KERNEL__ */
 
 #endif  /* _LINUX_CDROM_H */
diff -urN linux-2.4.27-pre5/include/linux/if_arp.h linux-2.4.27-pre6/include/linux/if_arp.h
--- linux-2.4.27-pre5/include/linux/if_arp.h	2002-02-25 11:38:13.000000000 -0800
+++ linux-2.4.27-pre6/include/linux/if_arp.h	2004-06-16 11:33:28.902119136 -0700
@@ -85,6 +85,7 @@
 #define ARPHRD_IEEE80211_PRISM 802	/* IEEE 802.11 + Prism2 header  */
 
 #define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
+#define ARPHRD_NONE	  0xFFFE	/* zero header length */
 
 /* ARP protocol opcodes. */
 #define	ARPOP_REQUEST	1		/* ARP request			*/
diff -urN linux-2.4.27-pre5/include/linux/netfilter.h linux-2.4.27-pre6/include/linux/netfilter.h
--- linux-2.4.27-pre5/include/linux/netfilter.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.27-pre6/include/linux/netfilter.h	2004-06-16 11:33:28.905119261 -0700
@@ -146,6 +146,12 @@
 			struct nf_info *info,
 			unsigned int verdict);
 
+extern inline struct ipt_target *
+ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
+extern inline struct ip6t_target *
+ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
+extern inline struct arpt_target *
+arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
 extern void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
 
 #ifdef CONFIG_NETFILTER_DEBUG
diff -urN linux-2.4.27-pre5/include/linux/netfilter_arp.h linux-2.4.27-pre6/include/linux/netfilter_arp.h
--- linux-2.4.27-pre5/include/linux/netfilter_arp.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.27-pre6/include/linux/netfilter_arp.h	2004-06-16 11:33:28.905119261 -0700
@@ -16,4 +16,5 @@
 #define NF_ARP_OUT	1
 #define NF_ARP_NUMHOOKS	2
 
+static DECLARE_MUTEX(arpt_mutex);
 #endif /* __LINUX_ARP_NETFILTER_H */
diff -urN linux-2.4.27-pre5/include/linux/netfilter_ipv4/ip_tables.h linux-2.4.27-pre6/include/linux/netfilter_ipv4/ip_tables.h
--- linux-2.4.27-pre5/include/linux/netfilter_ipv4/ip_tables.h	2002-02-25 11:38:13.000000000 -0800
+++ linux-2.4.27-pre6/include/linux/netfilter_ipv4/ip_tables.h	2004-06-16 11:33:28.906119303 -0700
@@ -283,6 +283,8 @@
 	struct ipt_entry entrytable[0];
 };
 
+extern struct semaphore ipt_mutex;
+
 /* Standard return verdict, or do jump. */
 #define IPT_STANDARD_TARGET ""
 /* Error verdict. */
@@ -334,6 +336,7 @@
 /*
  *	Main firewall chains definitions and global var's definitions.
  */
+static DECLARE_MUTEX(ipt_mutex);
 #ifdef __KERNEL__
 
 #include <linux/init.h>
@@ -403,6 +406,11 @@
 	struct module *me;
 };
 
+extern struct ipt_target *
+ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
+extern struct arpt_target *
+arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
+
 extern int ipt_register_target(struct ipt_target *target);
 extern void ipt_unregister_target(struct ipt_target *target);
 
diff -urN linux-2.4.27-pre5/include/linux/netfilter_ipv6/ip6_tables.h linux-2.4.27-pre6/include/linux/netfilter_ipv6/ip6_tables.h
--- linux-2.4.27-pre5/include/linux/netfilter_ipv6/ip6_tables.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.27-pre6/include/linux/netfilter_ipv6/ip6_tables.h	2004-06-16 11:33:28.906119303 -0700
@@ -106,6 +106,8 @@
 	u_int64_t pcnt, bcnt;			/* Packet and byte counters */
 };
 
+static DECLARE_MUTEX(ip6t_mutex);
+
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
 #define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
 					   protocols */
diff -urN linux-2.4.27-pre5/include/linux/pci_ids.h linux-2.4.27-pre6/include/linux/pci_ids.h
--- linux-2.4.27-pre5/include/linux/pci_ids.h	2004-06-16 11:33:26.520020000 -0700
+++ linux-2.4.27-pre6/include/linux/pci_ids.h	2004-06-16 11:33:28.909119427 -0700
@@ -978,6 +978,12 @@
 #define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
 #define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA	0x0036
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
@@ -1692,8 +1698,11 @@
 #define PCI_DEVICE_ID_TIGON3_5750	0x1676
 #define PCI_DEVICE_ID_TIGON3_5751	0x1677
 #define PCI_DEVICE_ID_TIGON3_5750M	0x167c
+#define PCI_DEVICE_ID_TIGON3_5751M	0x167d
+#define PCI_DEVICE_ID_TIGON3_5751F	0x167e
 #define PCI_DEVICE_ID_TIGON3_5782	0x1696
 #define PCI_DEVICE_ID_TIGON3_5788	0x169c
+#define PCI_DEVICE_ID_TIGON3_5789	0x169d
 #define PCI_DEVICE_ID_TIGON3_5702X	0x16a6
 #define PCI_DEVICE_ID_TIGON3_5703X	0x16a7
 #define PCI_DEVICE_ID_TIGON3_5704S	0x16a8
@@ -2020,8 +2029,12 @@
 #define PCI_DEVICE_ID_HOLTEK_6565	0x6565
 
 #define PCI_VENDOR_ID_NETMOS		0x9710
+#define PCI_DEVICE_ID_NETMOS_9705	0x9705
 #define PCI_DEVICE_ID_NETMOS_9735	0x9735
+#define PCI_DEVICE_ID_NETMOS_9805	0x9805
+#define PCI_DEVICE_ID_NETMOS_9815	0x9815
 #define PCI_DEVICE_ID_NETMOS_9835	0x9835
+#define PCI_DEVICE_ID_NETMOS_9855	0x9855
 
 #define PCI_SUBVENDOR_ID_EXSYS		0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
diff -urN linux-2.4.27-pre5/include/linux/sisfb.h linux-2.4.27-pre6/include/linux/sisfb.h
--- linux-2.4.27-pre5/include/linux/sisfb.h	2004-04-14 06:05:40.000000000 -0700
+++ linux-2.4.27-pre6/include/linux/sisfb.h	2004-06-16 11:33:28.912119552 -0700
@@ -87,228 +87,112 @@
 #define VB_DISPMODE_DUAL	VB_DUALVIEW_MODE
 #define VB_DISPLAY_MODE       	(SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
 
-/* *Never* change the order of the following enum */
-typedef enum _SIS_CHIP_TYPE {
-	SIS_VGALegacy = 0,	/* chip_id in sisfb_info */
-	SIS_300,
-	SIS_630,
-	SIS_540,
-	SIS_730,
-	SIS_315H,
-	SIS_315,
-	SIS_315PRO,
-	SIS_550,
-	SIS_650,
-	SIS_740,
-	SIS_330,
-	SIS_661,
-	SIS_741,
-	SIS_660,
-	SIS_760,
-	MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-
-/* Addtional IOCTLs for communication sisfb <> X driver                */
-/* If changing this, vgatypes.h must also be changed (for X driver)    */
-
-/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO	  	_IOR('n',0xF8,__u32)
-/* ioctrl to get current vertical retrace status */
-#define SISFB_GET_VBRSTATUS  	_IOR('n',0xF9,__u32)
-/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
-#define SISFB_GET_AUTOMAXIMIZE 	_IOR('n',0xFA,__u32)
-#define SISFB_SET_AUTOMAXIMIZE 	_IOW('n',0xFA,__u32)
-
-/* TW: Structure argument for SISFB_GET_INFO ioctl  */
+/* Structure argument for SISFB_GET_INFO ioctl  */
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	u32    	sisfb_id;         	/* for identifying sisfb */
+	__u32   sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	u32    	chip_id;		/* PCI ID of detected chip */
-	u32    	memory;			/* video memory in KB which sisfb manages */
-	u32    	heapstart;            	/* heap start (= sisfb "mem" argument) in KB */
-	u8     	fbvidmode;		/* current sisfb mode */
+ 	__u32   chip_id;		/* PCI-ID of detected chip */
+	__u32   memory;			/* video memory in KB which sisfb manages */
+	__u32   heapstart;            	/* heap start (= sisfb "mem" argument) in KB */
+	__u8    fbvidmode;		/* current sisfb mode */
 
-	u8     	sisfb_version;
-	u8     	sisfb_revision;
-	u8 	sisfb_patchlevel;
+	__u8    sisfb_version;
+	__u8    sisfb_revision;
+	__u8 	sisfb_patchlevel;
 
-	u8 	sisfb_caps;		/* Sisfb capabilities */
+	__u8 	sisfb_caps;		/* sisfb capabilities */
 
-	u32    	sisfb_tqlen;		/* turbo queue length (in KB) */
+	__u32	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	u32 	sisfb_pcibus;      	/* The card's PCI ID */
-	u32 	sisfb_pcislot;
-	u32 	sisfb_pcifunc;
+	__u32 	sisfb_pcibus;      	/* The card's PCI ID */
+	__u32 	sisfb_pcislot;
+	__u32 	sisfb_pcifunc;
 
-	u8 	sisfb_lcdpdc;		/* PanelDelayCompensation */
+	__u8 	sisfb_lcdpdc;		/* PanelDelayCompensation */
 
-	u8 	sisfb_lcda;		/* Detected status of LCDA for low res/text modes */
+	__u8 	sisfb_lcda;		/* Detected status of LCDA for low res/text modes */
 
-	u32 	sisfb_vbflags;
-	u32 	sisfb_currentvbflags;
+	__u32 	sisfb_vbflags;
+	__u32 	sisfb_currentvbflags;
 
-	u32 	sisfb_scalelcd;
-	u32 	sisfb_specialtiming;
+	__u32 	sisfb_scalelcd;
+	__u32 	sisfb_specialtiming;
 
-	u8 	sisfb_haveemi;
-	u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	u8 	sisfb_haveemilcd;
+	__u8 	sisfb_haveemi;
+	__u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	__u8 	sisfb_haveemilcd;
 
-	u8 	sisfb_lcdpdca;		/* PanelDelayCompensation for LCD-via-CRT1 */
+	__u8 	sisfb_lcdpdca;		/* PanelDelayCompensation for LCD-via-CRT1 */
+	
+	__u16	sisfb_tvxpos, sisfb_tvypos;  /* Warning: Values + 32 ! */
 
-	u8 	reserved[212]; 		/* for future use */
+	__u8 	reserved[208]; 		/* for future use */
 };
 
-/* For fb memory manager */
-struct sis_memreq {
-	unsigned long offset;
-	unsigned long size;
-};
+/* Addtional IOCTLs for communication sisfb <> X driver                */
+/* If changing this, vgatypes.h must also be changed (for X driver)    */
 
-/* More or less deprecated stuff follows: */
-typedef enum _TVTYPE {
-	TVMODE_NTSC = 0,
-	TVMODE_PAL,
-	TVMODE_HIVISION,
-	TVMODE_TOTAL
-} SIS_TV_TYPE;
-
-typedef enum _TVPLUGTYPE {
-	TVPLUG_Legacy = 0,
-	TVPLUG_COMPOSITE,
-	TVPLUG_SVIDEO,
-	TVPLUG_SCART,
-	TVPLUG_TOTAL
-} SIS_TV_PLUG;
-
-struct mode_info {
-	int    bpp;
-	int    xres;
-	int    yres;
-	int    v_xres;		/* deprecated - use var instead */
-	int    v_yres;		/* deprecated - use var instead */
-	int    org_x;		/* deprecated - use var instead */
-	int    org_y;		/* deprecated - use var instead */
-	unsigned int  vrate;
-};
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define SISFB_GET_INFO_SIZE  	_IOR(0xF3,0x00,__u32)
+#define SISFB_GET_INFO	  	_IOR(0xF3,0x01,struct _SISFB_INFO)
+
+/* ioctrl to get current vertical retrace status */
+#define SISFB_GET_VBRSTATUS  	_IOR(0xF3,0x02,__u32)
 
-struct ap_data {
-	struct mode_info minfo;
-	unsigned long iobase;
-	unsigned int  mem_size;
-	unsigned long disp_state;  /* deprecated */
-	SIS_CHIP_TYPE chip;
-	unsigned char hasVB;
-	SIS_TV_TYPE TV_type;	   /* deprecated */
-	SIS_TV_PLUG TV_plug;	   /* deprecated */
-	unsigned long version;
-	unsigned long vbflags;	   /* replaces deprecated entries above */
-	unsigned long currentvbflags;
-	char reserved[248];
+/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
+#define SISFB_GET_AUTOMAXIMIZE 	_IOR(0xF3,0x03,__u32)
+#define SISFB_SET_AUTOMAXIMIZE 	_IOW(0xF3,0x03,__u32)
+
+/* ioctls to relocate TV output (x=D[31:16], y=D[15:0], + 32)*/
+#define SISFB_GET_TVPOSOFFSET   _IOR(0xF3,0x04,__u32)
+#define SISFB_SET_TVPOSOFFSET   _IOW(0xF3,0x04,__u32)
+
+/* ioctl for locking sisfb (no register access during lock) */
+/* As of now, only used to avoid register access during
+ * the ioctls listed above.
+ */
+#define SISFB_SET_LOCK  	_IOW(0xF3,0x06,__u32)
+
+/* more to come soon */
+
+/* ioctls 0xF3 up to 0x3F reserved for sisfb */
+
+/****************************************************************/
+/* The following are deprecated and should not be used anymore: */
+/****************************************************************/
+/* ioctl for identifying and giving some info (esp. memory heap start) */
+#define SISFB_GET_INFO_OLD  	   _IOR('n',0xF8,__u32)
+/* ioctrl to get current vertical retrace status */
+#define SISFB_GET_VBRSTATUS_OLD	   _IOR('n',0xF9,__u32)
+/* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
+#define SISFB_GET_AUTOMAXIMIZE_OLD _IOR('n',0xFA,__u32)
+#define SISFB_SET_AUTOMAXIMIZE_OLD _IOW('n',0xFA,__u32)
+/****************************************************************/
+/*               End of deprecated ioctl numbers                */
+/****************************************************************/
+
+/* For fb memory manager (FBIO_ALLOC, FBIO_FREE) */
+struct sis_memreq {
+	__u32 	offset;
+	__u32 	size;
 };
 
 /**********************************************/
 /*                  PRIVATE                   */
+/*         (for IN-KERNEL usage only)         */
 /**********************************************/
 
 #ifdef __KERNEL__
-#include <linux/spinlock.h>
-
-typedef enum _VGA_ENGINE {
-	UNKNOWN_VGA = 0,
-	SIS_300_VGA,
-	SIS_315_VGA,
-} VGA_ENGINE;
-
-struct video_info {
-	int           	chip_id;
-	unsigned int  	video_size;
-	unsigned long 	video_base;
-	char  *       	video_vbase;
-	unsigned long 	mmio_size;
-	unsigned long 	mmio_base;
-	char  *       	mmio_vbase;
-	unsigned long 	vga_base;
-	unsigned long 	mtrr;
-	unsigned long 	heapstart;
-	char  *	      	bios_vbase;
-	char  *	      	bios_abase;
-
-	int    		video_bpp;
-	int    		video_cmap_len;
-	int    		video_width;
-	int    		video_height;
-	int    		video_vwidth;		/* DEPRECATED - use var instead */
-	int    		video_vheight;		/* DEPRECATED - use var instead */
-	int    		org_x;			/* DEPRECATED - use var instead */
-	int    		org_y;			/* DEPRECATED - use var instead */
-	int    		video_linelength;
-	unsigned int 	refresh_rate;
-
-	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;
-
-        unsigned short 	DstColor;		/* For 2d acceleration */
-	unsigned long  	SiS310_AccelDepth;
-	unsigned long  	CommandReg;
-
-	spinlock_t     	lockaccel;		/* Do not use outside of kernel! */
-
-        unsigned int   	pcibus;
-	unsigned int   	pcislot;
-	unsigned int   	pcifunc;
-
-	int 	       	accel;
-
-	unsigned short 	subsysvendor;
-	unsigned short 	subsysdevice;
-
-	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;
-	
-	u8  		mode_no;
-	u8  		rate_idx;
-	int    		modechanged;
-	unsigned char 	modeprechange;
-	
-	int  		newrom;
-	int  		registered;
-	
-	VGA_ENGINE 	sisvga_engine;
-	int 		hwcursor_size;
-	int 		CRT2_write_enable;
-	u8            	caps;
-	
-	unsigned char 	detectedpdc;
-	unsigned char 	detectedpdca;
-	unsigned char 	detectedlcda;
-	
-	unsigned long 	hwcursor_vbase;
-
-	char reserved[166];
-};
-
-extern struct video_info ivideo;
+#define	UNKNOWN_VGA  0
+#define	SIS_300_VGA  1
+#define	SIS_315_VGA  2
 
 extern void sis_malloc(struct sis_memreq *req);
-extern void sis_free(unsigned long base);
-extern void sis_dispinfo(struct ap_data *rec);
+extern void sis_free(u32 base);
 #endif
+
 #endif
diff -urN linux-2.4.27-pre5/include/net/sctp/command.h linux-2.4.27-pre6/include/net/sctp/command.h
--- linux-2.4.27-pre5/include/net/sctp/command.h	2004-06-16 11:33:26.523020125 -0700
+++ linux-2.4.27-pre6/include/net/sctp/command.h	2004-06-16 11:33:28.913119594 -0700
@@ -93,6 +93,7 @@
 	SCTP_CMD_PROCESS_OPERR,  /* Process an ERROR chunk. */
 	SCTP_CMD_REPORT_FWDTSN,	 /* Report new cumulative TSN Ack. */
 	SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
+	SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff -urN linux-2.4.27-pre5/include/net/sctp/sm.h linux-2.4.27-pre6/include/net/sctp/sm.h
--- linux-2.4.27-pre5/include/net/sctp/sm.h	2004-06-16 11:33:26.525020208 -0700
+++ linux-2.4.27-pre6/include/net/sctp/sm.h	2004-06-16 11:33:28.915119677 -0700
@@ -440,6 +440,23 @@
 		BUG();
 }
 
+/* Check VTAG of the packet matches the sender's own tag. */
+static inline int
+sctp_vtag_verify(const struct sctp_chunk *chunk,
+		 const struct sctp_association *asoc)
+{
+	/* RFC 2960 Sec 8.5 When receiving an SCTP packet, the endpoint
+	 * MUST ensure that the value in the Verification Tag field of
+	 * the received SCTP packet matches its own Tag. If the received
+	 * Verification Tag value does not match the receiver's own
+	 * tag value, the receiver shall silently discard the packet...
+	 */
+        if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
+                return 1;
+
+	return 0;
+}
+
 /* Check VTAG of the packet matches the sender's own tag OR its peer's
  * tag and the T bit is set in the Chunk Flags.
  */
diff -urN linux-2.4.27-pre5/lib/rwsem-spinlock.c linux-2.4.27-pre6/lib/rwsem-spinlock.c
--- linux-2.4.27-pre5/lib/rwsem-spinlock.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.27-pre6/lib/rwsem-spinlock.c	2004-06-16 11:33:28.922119968 -0700
@@ -9,6 +9,7 @@
  */
 #include <linux/rwsem.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 
 struct rwsem_waiter {
@@ -52,6 +53,7 @@
 static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter *waiter;
+	struct task_struct *tsk;
 	int woken;
 
 	rwsemtrace(sem,"Entering __rwsem_do_wake");
@@ -64,8 +66,11 @@
 	if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
 		sem->activity = -1;
 		list_del(&waiter->list);
-		waiter->flags = 0;
-		wake_up_process(waiter->task);
+		tsk = waiter->task;
+		mb();
+		waiter->task = NULL;
+		wake_up_process(tsk);
+		free_task_struct(tsk);
 		goto out;
 	}
 
@@ -73,8 +78,11 @@
 	woken = 0;
 	do {
 		list_del(&waiter->list);
-		waiter->flags = 0;
-		wake_up_process(waiter->task);
+		tsk = waiter->task;
+		mb();
+		waiter->task = NULL;
+		wake_up_process(tsk);
+		free_task_struct(tsk);
 		woken++;
 		if (list_empty(&sem->wait_list))
 			break;
@@ -100,8 +108,11 @@
 	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
 	list_del(&waiter->list);
 
-	waiter->flags = 0;
-	wake_up_process(waiter->task);
+	tsk = waiter->task;
+	mb();
+	waiter->task = NULL;
+	wake_up_process(tsk);
+	free_task_struct(tsk);
 	return sem;
 }
 
@@ -130,6 +141,7 @@
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
 	waiter.flags = RWSEM_WAITING_FOR_READ;
+	get_task_struct(tsk);
 
 	list_add_tail(&waiter.list,&sem->wait_list);
 
@@ -138,7 +150,7 @@
 
 	/* wait to be given the lock */
 	for (;;) {
-		if (!waiter.flags)
+		if (!waiter.task)
 			break;
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
@@ -198,6 +210,7 @@
 	/* set up my own style of waitqueue */
 	waiter.task = tsk;
 	waiter.flags = RWSEM_WAITING_FOR_WRITE;
+	get_task_struct(tsk);
 
 	list_add_tail(&waiter.list,&sem->wait_list);
 
@@ -206,7 +219,7 @@
 
 	/* wait to be given the lock */
 	for (;;) {
-		if (!waiter.flags)
+		if (!waiter.task)
 			break;
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
diff -urN linux-2.4.27-pre5/lib/rwsem.c linux-2.4.27-pre6/lib/rwsem.c
--- linux-2.4.27-pre5/lib/rwsem.c	2001-07-10 20:08:51.000000000 -0700
+++ linux-2.4.27-pre6/lib/rwsem.c	2004-06-16 11:33:28.922119968 -0700
@@ -5,6 +5,7 @@
  */
 #include <linux/rwsem.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 
 struct rwsem_waiter {
@@ -38,9 +39,9 @@
 static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter *waiter;
+	struct task_struct *tsk;
 	struct list_head *next;
-	signed long oldcount;
-	int woken, loop;
+	signed long oldcount, woken, loop;
 
 	rwsemtrace(sem,"Entering __rwsem_do_wake");
 
@@ -60,8 +61,11 @@
 		goto readers_only;
 
 	list_del(&waiter->list);
-	waiter->flags = 0;
-	wake_up_process(waiter->task);
+	tsk = waiter->task;
+	mb();
+	waiter->task = NULL;
+	wake_up_process(tsk);
+	free_task_struct(tsk);
 	goto out;
 
 	/* grant an infinite number of read locks to the readers at the front of the queue
@@ -89,8 +93,11 @@
 	for (; loop>0; loop--) {
 		waiter = list_entry(next,struct rwsem_waiter,list);
 		next = waiter->list.next;
-		waiter->flags = 0;
-		wake_up_process(waiter->task);
+		tsk = waiter->task;
+		mb();
+		waiter->task = NULL;
+		wake_up_process(tsk);
+		free_task_struct(tsk);
 	}
 
 	sem->wait_list.next = next;
@@ -122,6 +129,7 @@
 	/* set up my own style of waitqueue */
 	spin_lock(&sem->wait_lock);
 	waiter->task = tsk;
+	get_task_struct(tsk);
 
 	list_add_tail(&waiter->list,&sem->wait_list);
 
@@ -138,7 +146,7 @@
 
 	/* wait to be given the lock */
 	for (;;) {
-		if (!waiter->flags)
+		if (!waiter->task)
 			break;
 		schedule();
 		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
diff -urN linux-2.4.27-pre5/net/ipv4/netfilter/arp_tables.c linux-2.4.27-pre6/net/ipv4/netfilter/arp_tables.c
--- linux-2.4.27-pre5/net/ipv4/netfilter/arp_tables.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.27-pre6/net/ipv4/netfilter/arp_tables.c	2004-06-16 11:33:28.930120301 -0700
@@ -52,7 +52,6 @@
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
-static DECLARE_MUTEX(arpt_mutex);
 
 #define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
@@ -175,11 +174,10 @@
 		return 0;
 	}
 
-	/* Look for ifname matches; this should unroll nicely. */
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)indev)[i]
-			^ ((const unsigned long *)arpinfo->iniface)[i])
-			& ((const unsigned long *)arpinfo->iniface_mask)[i];
+	/* Look for ifname matches.  */
+	for (i = 0, ret = 0; i < IFNAMSIZ; i++) {
+		ret |= (indev[i] ^ arpinfo->iniface[i])
+			& arpinfo->iniface_mask[i];
 	}
 
 	if (FWINV(ret != 0, ARPT_INV_VIA_IN)) {
@@ -380,12 +378,12 @@
 }
 #endif
 
-static inline struct arpt_table *find_table_lock(const char *name, int *error, struct semaphore *mutex)
+static inline struct arpt_table *arpt_find_table_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex);
 }
 
-static inline struct arpt_target *find_target_lock(const char *name, int *error, struct semaphore *mutex)
+struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex);
 }
@@ -535,7 +533,7 @@
 	}
 
 	t = arpt_get_target(e);
-	target = find_target_lock(t->u.user.name, &ret, &arpt_mutex);
+	target = arpt_find_target_lock(t->u.user.name, &ret, &arpt_mutex);
 	if (!target) {
 		duprintf("check_entry: `%s' not found\n", t->u.user.name);
 		goto out;
@@ -834,7 +832,7 @@
 	int ret;
 	struct arpt_table *t;
 
-	t = find_table_lock(entries->name, &ret, &arpt_mutex);
+	t = arpt_find_table_lock(entries->name, &ret, &arpt_mutex);
 	if (t) {
 		duprintf("t->private->number = %u\n",
 			 t->private->number);
@@ -900,7 +898,7 @@
 
 	duprintf("arp_tables: Translated table\n");
 
-	t = find_table_lock(tmp.name, &ret, &arpt_mutex);
+	t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex);
 	if (!t)
 		goto free_newinfo_counters_untrans;
 
@@ -985,7 +983,7 @@
 		goto free;
 	}
 
-	t = find_table_lock(tmp.name, &ret, &arpt_mutex);
+	t = arpt_find_table_lock(tmp.name, &ret, &arpt_mutex);
 	if (!t)
 		goto free;
 
@@ -1058,7 +1056,7 @@
 			break;
 		}
 		name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
-		t = find_table_lock(name, &ret, &arpt_mutex);
+		t = arpt_find_table_lock(name, &ret, &arpt_mutex);
 		if (t) {
 			struct arpt_getinfo info;
 
@@ -1306,6 +1304,7 @@
 EXPORT_SYMBOL(arpt_register_table);
 EXPORT_SYMBOL(arpt_unregister_table);
 EXPORT_SYMBOL(arpt_do_table);
+EXPORT_SYMBOL(arpt_find_target_lock);
 EXPORT_SYMBOL(arpt_register_target);
 EXPORT_SYMBOL(arpt_unregister_target);
 
diff -urN linux-2.4.27-pre5/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.27-pre6/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.27-pre5/net/ipv4/netfilter/ip_conntrack_core.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.27-pre6/net/ipv4/netfilter/ip_conntrack_core.c	2004-06-16 11:33:28.931120343 -0700
@@ -326,8 +326,9 @@
 		ip_conntrack_destroyed(ct);
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	/* Delete us from our own list to prevent corruption later */
-	list_del(&ct->sibling_list);
+	/* Make sure don't leave any orphaned expectations lying around */
+	if (ct->expecting)
+		remove_expectations(ct, 1);
 
 	/* Delete our master expectation */
 	if (ct->master) {
@@ -1115,10 +1116,8 @@
 	DUMP_TUPLE(newreply);
 
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	if (!conntrack->master)
-		conntrack->helper = LIST_FIND(&helpers, helper_cmp,
-					      struct ip_conntrack_helper *,
-					      newreply);
+	if (!conntrack->master && list_empty(&conntrack->sibling_list))
+		conntrack->helper = ip_ct_find_helper(newreply);
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
 	return 1;
diff -urN linux-2.4.27-pre5/net/ipv4/netfilter/ip_tables.c linux-2.4.27-pre6/net/ipv4/netfilter/ip_tables.c
--- linux-2.4.27-pre5/net/ipv4/netfilter/ip_tables.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.27-pre6/net/ipv4/netfilter/ip_tables.c	2004-06-16 11:33:28.932120385 -0700
@@ -53,9 +53,6 @@
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
-/* Mutex protects lists (only traversed in user context). */
-static DECLARE_MUTEX(ipt_mutex);
-
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
@@ -418,7 +415,7 @@
 {
 	void *ret;
 
-#if 0
+#if 0 
 	duprintf("find_inlist: searching for `%s' in %s.\n",
 		 name, head == &ipt_target ? "ipt_target"
 		 : head == &ipt_match ? "ipt_match"
@@ -464,7 +461,7 @@
 #endif
 
 static inline struct ipt_table *
-find_table_lock(const char *name, int *error, struct semaphore *mutex)
+ipt_find_table_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ipt_tables, name, "iptable_", error, mutex);
 }
@@ -475,8 +472,8 @@
 	return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex);
 }
 
-static inline struct ipt_target *
-find_target_lock(const char *name, int *error, struct semaphore *mutex)
+struct ipt_target *
+ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
 }
@@ -693,7 +690,7 @@
 		goto cleanup_matches;
 
 	t = ipt_get_target(e);
-	target = find_target_lock(t->u.user.name, &ret, &ipt_mutex);
+	target = ipt_find_target_lock(t->u.user.name, &ret, &ipt_mutex);
 	if (!target) {
 		duprintf("check_entry: `%s' not found\n", t->u.user.name);
 		goto cleanup_matches;
@@ -1030,7 +1027,7 @@
 	int ret;
 	struct ipt_table *t;
 
-	t = find_table_lock(entries->name, &ret, &ipt_mutex);
+	t = ipt_find_table_lock(entries->name, &ret, &ipt_mutex);
 	if (t) {
 		duprintf("t->private->number = %u\n",
 			 t->private->number);
@@ -1097,7 +1094,7 @@
 
 	duprintf("ip_tables: Translated table\n");
 
-	t = find_table_lock(tmp.name, &ret, &ipt_mutex);
+	t = ipt_find_table_lock(tmp.name, &ret, &ipt_mutex);
 	if (!t)
 		goto free_newinfo_counters_untrans;
 
@@ -1191,7 +1188,7 @@
 		goto free;
 	}
 
-	t = find_table_lock(tmp.name, &ret, &ipt_mutex);
+	t = ipt_find_table_lock(tmp.name, &ret, &ipt_mutex);
 	if (!t)
 		goto free;
 
@@ -1266,7 +1263,7 @@
 			break;
 		}
 		name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-		t = find_table_lock(name, &ret, &ipt_mutex);
+		t = ipt_find_table_lock(name, &ret, &ipt_mutex);
 		if (t) {
 			struct ipt_getinfo info;
 
@@ -1838,6 +1835,7 @@
 EXPORT_SYMBOL(ipt_do_table);
 EXPORT_SYMBOL(ipt_register_target);
 EXPORT_SYMBOL(ipt_unregister_target);
+EXPORT_SYMBOL(ipt_find_target_lock);
 
 module_init(init);
 module_exit(fini);
diff -urN linux-2.4.27-pre5/net/ipv4/udp.c linux-2.4.27-pre6/net/ipv4/udp.c
--- linux-2.4.27-pre5/net/ipv4/udp.c	2004-04-14 06:05:41.000000000 -0700
+++ linux-2.4.27-pre6/net/ipv4/udp.c	2004-06-16 11:33:28.941120759 -0700
@@ -290,7 +290,7 @@
 		    ipv6_only_sock(s)					||
 		    (s->bound_dev_if && s->bound_dev_if != dif))
 			continue;
-		if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, dif))
+		if (!ip_mc_sf_allow(s, loc_addr, rmt_addr, dif))
 			continue;
 		break;
   	}
diff -urN linux-2.4.27-pre5/net/ipv6/netfilter/ip6_tables.c linux-2.4.27-pre6/net/ipv6/netfilter/ip6_tables.c
--- linux-2.4.27-pre5/net/ipv6/netfilter/ip6_tables.c	2004-04-14 06:05:41.000000000 -0700
+++ linux-2.4.27-pre6/net/ipv6/netfilter/ip6_tables.c	2004-06-16 11:33:28.943120842 -0700
@@ -57,8 +57,6 @@
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
-/* Mutex protects lists (only traversed in user context). */
-static DECLARE_MUTEX(ip6t_mutex);
 
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
@@ -535,7 +533,7 @@
 #endif
 
 static inline struct ip6t_table *
-find_table_lock(const char *name, int *error, struct semaphore *mutex)
+ip6t_find_table_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex);
 }
@@ -546,8 +544,8 @@
 	return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
 }
 
-static inline struct ip6t_target *
-find_target_lock(const char *name, int *error, struct semaphore *mutex)
+struct ip6t_target *
+ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
 }
@@ -764,7 +762,7 @@
 		goto cleanup_matches;
 
 	t = ip6t_get_target(e);
-	target = find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
+	target = ip6t_find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
 	if (!target) {
 		duprintf("check_entry: `%s' not found\n", t->u.user.name);
 		goto cleanup_matches;
@@ -1101,7 +1099,7 @@
 	int ret;
 	struct ip6t_table *t;
 
-	t = find_table_lock(entries->name, &ret, &ip6t_mutex);
+	t = ip6t_find_table_lock(entries->name, &ret, &ip6t_mutex);
 	if (t) {
 		duprintf("t->private->number = %u\n",
 			 t->private->number);
@@ -1164,7 +1162,7 @@
 
 	duprintf("ip_tables: Translated table\n");
 
-	t = find_table_lock(tmp.name, &ret, &ip6t_mutex);
+	t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
 	if (!t)
 		goto free_newinfo_counters_untrans;
 
@@ -1258,7 +1256,7 @@
 		goto free;
 	}
 
-	t = find_table_lock(tmp.name, &ret, &ip6t_mutex);
+	t = ip6t_find_table_lock(tmp.name, &ret, &ip6t_mutex);
 	if (!t)
 		goto free;
 
@@ -1333,7 +1331,7 @@
 			break;
 		}
 		name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
-		t = find_table_lock(name, &ret, &ip6t_mutex);
+		t = ip6t_find_table_lock(name, &ret, &ip6t_mutex);
 		if (t) {
 			struct ip6t_getinfo info;
 
@@ -1940,6 +1938,7 @@
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
+EXPORT_SYMBOL(ip6t_find_target_lock);
 EXPORT_SYMBOL(ip6t_register_match);
 EXPORT_SYMBOL(ip6t_unregister_match);
 EXPORT_SYMBOL(ip6t_register_target);
diff -urN linux-2.4.27-pre5/net/sctp/sm_sideeffect.c linux-2.4.27-pre6/net/sctp/sm_sideeffect.c
--- linux-2.4.27-pre5/net/sctp/sm_sideeffect.c	2004-06-16 11:33:26.560021664 -0700
+++ linux-2.4.27-pre6/net/sctp/sm_sideeffect.c	2004-06-16 11:33:28.957121425 -0700
@@ -429,6 +429,9 @@
 		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
 				SCTP_ULPEVENT(event));
 
+	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+			SCTP_STATE(SCTP_STATE_CLOSED));
+
 	/* SEND_FAILED sent later when cleaning up the association. */
 	asoc->outqueue.error = error;
 	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -457,6 +460,10 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
 
+	/* Set sk_err to ECONNRESET on a 1-1 style socket. */
+	if (!sctp_style(asoc->base.sk, UDP))
+		asoc->base.sk->sk_err = ECONNRESET; 
+
 	/* SEND_FAILED sent later when cleaning up the association. */
 	asoc->outqueue.error = error;
 	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -1272,6 +1279,9 @@
 		case SCTP_CMD_PROCESS_OPERR:
 			sctp_cmd_process_operr(commands, asoc, chunk);
 			break;
+		case SCTP_CMD_CLEAR_INIT_TAG:
+			asoc->peer.i.init_tag = 0;
+			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
diff -urN linux-2.4.27-pre5/net/sctp/sm_statefuns.c linux-2.4.27-pre6/net/sctp/sm_statefuns.c
--- linux-2.4.27-pre5/net/sctp/sm_statefuns.c	2004-06-16 11:33:26.563021789 -0700
+++ linux-2.4.27-pre6/net/sctp/sm_statefuns.c	2004-06-16 11:33:28.960121550 -0700
@@ -171,7 +171,7 @@
  *    Verification Tag field to Tag_A, and also provide its own
  *    Verification Tag (Tag_Z) in the Initiate Tag field.
  *
- * Verification Tag: No checking.
+ * Verification Tag: Must be 0. 
  *
  * Inputs
  * (endpoint, asoc, chunk)
@@ -219,6 +219,12 @@
 	     (sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 
+	/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
+	 * Tag. 
+	 */
+	if (chunk->sctp_hdr->vtag != 0)
+		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+
 	/* Verify the INIT chunk before processing it. */
 	err_chunk = NULL;
 	if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -377,6 +383,9 @@
 	if (!chunk->singleton)
 		return SCTP_DISPOSITION_VIOLATION;
 
+	if (!sctp_vtag_verify(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
 	/* Grab the INIT header.  */
 	chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
 
@@ -659,8 +668,12 @@
 				      const sctp_subtype_t type, void *arg,
 				      sctp_cmd_seq_t *commands)
 {
+	struct sctp_chunk *chunk = arg;
 	struct sctp_ulpevent *ev;
 
+	if (!sctp_vtag_verify(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
 	 * E) Upon reception of the COOKIE ACK, endpoint "A" will move
@@ -807,13 +820,7 @@
 	struct sctp_chunk *reply;
 	size_t paylen = 0;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. If the received
-	 * Verification Tag value does not match the receiver's own
-	 * tag value, the receiver shall silently discard the packet...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* 8.3 The receiver of the HEARTBEAT should immediately
@@ -876,11 +883,7 @@
 	sctp_sender_hb_info_t *hbinfo;
 	unsigned long max_interval;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. ...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
@@ -1130,6 +1133,12 @@
 	if (!chunk->singleton)
 		return SCTP_DISPOSITION_VIOLATION;
 
+	/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
+	 * Tag. 
+	 */
+	if (chunk->sctp_hdr->vtag != 0)
+		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+
 	/* Grab the INIT header.  */
 	chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
 
@@ -1386,6 +1395,8 @@
 	sctp_init_chunk_t *peer_init;
 	struct sctp_ulpevent *ev;
 	struct sctp_chunk *repl;
+	struct sctp_chunk *err;
+	sctp_disposition_t disposition;
 
 	/* new_asoc is a brand-new association, so these are not yet
 	 * side effects--it is safe to run them here.
@@ -1405,6 +1416,29 @@
 		return SCTP_DISPOSITION_CONSUME;
 	}
 
+	/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
+	 * the peer has restarted (Action A), it MUST NOT setup a new
+	 * association but instead resend the SHUTDOWN ACK and send an ERROR
+	 * chunk with a "Cookie Received while Shutting Down" error cause to
+	 * its peer.
+	*/
+	if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {
+		disposition = sctp_sf_do_9_2_reshutack(ep, asoc,
+				SCTP_ST_CHUNK(chunk->chunk_hdr->type),
+				chunk, commands);
+		if (SCTP_DISPOSITION_NOMEM == disposition)
+			goto nomem;
+
+		err = sctp_make_op_error(asoc, chunk,
+					 SCTP_ERROR_COOKIE_IN_SHUTDOWN,
+					 NULL, 0);
+		if (err)
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+
+		return SCTP_DISPOSITION_CONSUME;
+	}
+
 	/* For now, fail any unsent/unacked data.  Consider the optional
 	 * choice of resending of this data.
 	 */
@@ -1883,6 +1917,9 @@
 
 	sctp_addto_chunk(reply, sizeof(bht), &bht);
 
+	/* Clear peer's init_tag cached in assoc as we are sending a new INIT */
+	sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());
+
 	/* Cast away the const modifier, as we want to just
 	 * rerun it through as a sideffect.
 	 */
@@ -2071,13 +2108,7 @@
 	skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
 	chunk->subh.shutdown_hdr = sdh;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. If the received
-	 * Verification Tag value does not match the receiver's own
-	 * tag value, the receiver shall silently discard the packet...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* Upon the reception of the SHUTDOWN, the peer endpoint shall
@@ -2190,13 +2221,7 @@
 	sctp_cwrhdr_t *cwr;
 	struct sctp_chunk *chunk = arg;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. If the received
-	 * Verification Tag value does not match the receiver's own
-	 * tag value, the receiver shall silently discard the packet...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	cwr = (sctp_cwrhdr_t *) chunk->skb->data;
@@ -2246,13 +2271,7 @@
 	sctp_ecnehdr_t *ecne;
 	struct sctp_chunk *chunk = arg;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. If the received
-	 * Verification Tag value does not match the receiver's own
-	 * tag value, the receiver shall silently discard the packet...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	ecne = (sctp_ecnehdr_t *) chunk->skb->data;
@@ -2309,13 +2328,7 @@
 	int tmp;
 	__u32 tsn;
 
-	/* RFC 2960 8.5 Verification Tag
-	 *
-	 * When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag.
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
+	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
 				SCTP_NULL());
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2569,13 +2582,7 @@
 	int tmp;
 	__u32 tsn;
 
-	/* RFC 2960 8.5 Verification Tag
-	 *
-	 * When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag.
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
+	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
 				SCTP_NULL());
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2745,11 +2752,7 @@
 	sctp_sackhdr_t *sackh;
 	__u32 ctsn;
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag. ...
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	/* Pull the SACK chunk from the data buffer */
@@ -2895,6 +2898,9 @@
 	struct sctp_chunk *reply;
 	struct sctp_ulpevent *ev;
 
+	if (!sctp_vtag_verify(chunk, asoc))
+		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
 	/* 10.2 H) SHUTDOWN COMPLETE notification
 	 *
 	 * When SCTP completes the shutdown procedures (section 9.2) this
@@ -3229,13 +3235,7 @@
 	__u16 len;
 	__u32 tsn;
 
-	/* RFC 2960 8.5 Verification Tag
-	 *
-	 * When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag.
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
+	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
 				SCTP_NULL());
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3293,13 +3293,7 @@
 	__u16 len;
 	__u32 tsn;
 
-	/* RFC 2960 8.5 Verification Tag
-	 *
-	 * When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag.
-	 */
-	if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
+	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
 				SCTP_NULL());
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3376,13 +3370,7 @@
 
 	SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
 
-	/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
-	 * that the value in the Verification Tag field of the
-	 * received SCTP packet matches its own Tag.  If the received
-	 * Verification Tag value does not match the receiver's own
-	 * tag value, the receiver shall silently discard the packet.
-	 */
-	if (ntohl(unk_chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
+	if (!sctp_vtag_verify(unk_chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
 	switch (type.chunk & SCTP_CID_ACTION_MASK) {
diff -urN linux-2.4.27-pre5/net/sctp/socket.c linux-2.4.27-pre6/net/sctp/socket.c
--- linux-2.4.27-pre5/net/sctp/socket.c	2004-06-16 11:33:26.567021956 -0700
+++ linux-2.4.27-pre6/net/sctp/socket.c	2004-06-16 11:33:28.964121716 -0700
@@ -1155,6 +1155,11 @@
 	if (!asoc) {
 		SCTP_DEBUG_PRINTK("There is no association yet.\n");
 
+		if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
+			err = -EINVAL;
+			goto out_unlock;
+		}
+
 		/* Check for invalid stream against the stream counts,
 		 * either the default or the user specified stream counts.
 		 */
@@ -4386,7 +4391,11 @@
 	return err;
 
 do_error:
-	err = -ECONNREFUSED;
+	if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
+					 	asoc->max_init_attempts)
+		err = -ETIMEDOUT;
+	else
+		err = -ECONNREFUSED;
 	goto out;
 
 do_interrupted:
