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

diff -urN linux-2.4.26-pre2/MAINTAINERS linux-2.4.26-pre3/MAINTAINERS
--- linux-2.4.26-pre2/MAINTAINERS	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/MAINTAINERS	2004-03-13 07:43:23.000000000 -0800
@@ -1081,8 +1081,8 @@
 P:      Andrew Stanley-Jones
 M:      asj@lanmedia.com
 W:      http://www.lanmedia.com/
-S:      Supported
- 
+S:      Orphan
+
 LAPB module
 P:	Henner Eisen
 M:	eis@baty.hanse.de
diff -urN linux-2.4.26-pre2/Makefile linux-2.4.26-pre3/Makefile
--- linux-2.4.26-pre2/Makefile	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/Makefile	2004-03-13 07:43:23.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 26
-EXTRAVERSION = -pre2
+EXTRAVERSION = -pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.26-pre2/arch/ia64/ia32/ia32_signal.c linux-2.4.26-pre3/arch/ia64/ia32/ia32_signal.c
--- linux-2.4.26-pre2/arch/ia64/ia32/ia32_signal.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/ia32/ia32_signal.c	2004-03-13 07:43:22.000000000 -0800
@@ -615,7 +615,7 @@
 			return -EFAULT;
 	}
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, sigsetsize);
 	set_fs(old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_siginfo_to_user32(uinfo, &info))
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/Makefile linux-2.4.26-pre3/arch/ia64/kernel/Makefile
--- linux-2.4.26-pre2/arch/ia64/kernel/Makefile	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/Makefile	2004-03-13 07:43:22.000000000 -0800
@@ -11,7 +11,7 @@
 
 O_TARGET := kernel.o
 
-export-objs := ia64_ksyms.o
+export-objs := ia64_ksyms.o unwind.o
 
 obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \
 	 machvec.o pal.o process.o perfmon.o ptrace.o sal.o salinfo.o semaphore.o setup.o	 \
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/ia64_ksyms.c linux-2.4.26-pre3/arch/ia64/kernel/ia64_ksyms.c
--- linux-2.4.26-pre2/arch/ia64/kernel/ia64_ksyms.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/ia64_ksyms.c	2004-03-13 07:43:22.000000000 -0800
@@ -170,6 +170,8 @@
 EXPORT_SYMBOL(pfm_remove_alternate_syswide_subsystem);
 #endif
 
+#ifdef CONFIG_ACPI
 #include <linux/acpi.h>
 extern acpi_status acpi_hp_csr_space(acpi_handle, u64 *, u64 *);
 EXPORT_SYMBOL(acpi_hp_csr_space);
+#endif
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/mca.c linux-2.4.26-pre3/arch/ia64/kernel/mca.c
--- linux-2.4.26-pre2/arch/ia64/kernel/mca.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/mca.c	2004-03-13 07:43:22.000000000 -0800
@@ -6,7 +6,7 @@
  * Copyright (C) 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
- * Copyright (C) 2002 Dell Computer Corporation
+ * Copyright (C) 2002 Dell Inc.
  * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
  *
  * Copyright (C) 2002 Intel
@@ -18,7 +18,7 @@
  * Copyright (C) 2000 Intel
  * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com)
  *
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  *
  * 03/04/15 D. Mosberger Added INIT backtrace support.
@@ -40,6 +40,14 @@
  * 2003-12-08 Keith Owens <kaos@sgi.com>
  *            smp_call_function() must not be called from interrupt context (can
  *            deadlock on tasklist_lock).  Use keventd to call smp_call_function().
+ *
+ * 2004-02-01 Keith Owens <kaos@sgi.com>
+ *            Avoid deadlock when using printk() for MCA and INIT records.
+ *            Delete all record printing code, moved to salinfo_decode in user space.
+ *            Mark variables and functions static where possible.
+ *            Delete dead variables and functions.
+ *            Reorder to remove the need for forward declarations and to consolidate
+ *            related code.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -67,9 +75,12 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
-#undef MCA_PRT_XTRA_DATA
+#if defined(IA64_MCA_DEBUG_INFO)
+# define IA64_MCA_DEBUG(fmt...)	printk(fmt)
+#else
+# define IA64_MCA_DEBUG(fmt...)
+#endif
 
-#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
 extern void show_stack(struct task_struct *);
 
 typedef struct ia64_fptr {
@@ -77,7 +88,7 @@
 	unsigned long gp;
 } ia64_fptr_t;
 
-ia64_mc_info_t			ia64_mc_info;
+/* Used by mca_asm.S */
 ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
 ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
 u64				ia64_mca_proc_state_dump[512];
@@ -85,54 +96,17 @@
 u64				ia64_mca_stackframe[32];
 u64				ia64_mca_bspstore[1024];
 u64				ia64_init_stack[INIT_TASK_SIZE/8] __attribute__((aligned(16)));
-u64				ia64_os_mca_recovery_successful;
 u64				ia64_mca_serialize;
-static void			ia64_mca_wakeup_ipi_wait(void);
-static void			ia64_mca_wakeup(int cpu);
-static void			ia64_mca_wakeup_all(void);
-static void			ia64_log_init(int);
+
+/* In mca_asm.S */
 extern void			ia64_monarch_init_handler (void);
 extern void			ia64_slave_init_handler (void);
-static u64			ia64_log_get(int sal_info_type, u8 **buffer);
-extern struct hw_interrupt_type	irq_type_iosapic_level;
-
-struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
-
-static struct irqaction cmci_irqaction = {
-	.handler =	ia64_mca_cmc_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"cmc_hndlr"
-};
-
-static struct irqaction cmcp_irqaction = {
-	.handler =	ia64_mca_cmc_int_caller,
-	.flags =	SA_INTERRUPT,
-	.name =		"cmc_poll"
-};
-
-static struct irqaction mca_rdzv_irqaction = {
-	.handler =	ia64_mca_rendez_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"mca_rdzv"
-};
 
-static struct irqaction mca_wkup_irqaction = {
-	.handler =	ia64_mca_wakeup_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"mca_wkup"
-};
+static ia64_mc_info_t		ia64_mc_info;
 
-static struct irqaction mca_cpe_irqaction = {
-	.handler =	ia64_mca_cpe_int_handler,
-	.flags =	SA_INTERRUPT,
-	.name =		"cpe_hndlr"
-};
+extern struct hw_interrupt_type	irq_type_iosapic_level;
 
-static struct irqaction mca_cpep_irqaction = {
-	.handler =	ia64_mca_cpe_int_caller,
-	.flags =	SA_INTERRUPT,
-	.name =		"cpe_poll"
-};
+struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS];
 
 #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
 #define MIN_CPE_POLL_INTERVAL (2*60*HZ)  /* 2 minutes */
@@ -156,69 +130,163 @@
  */
 static int cpe_poll_enabled = 1;
 
-extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size);
+extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
 
 static struct tq_struct	cmc_disable_tq, cmc_enable_tq;
 
 /*
+ * IA64_MCA log support
+ */
+#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */
+#define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */
+
+typedef struct ia64_state_log_s
+{
+	spinlock_t	isl_lock;
+	int		isl_index;
+	unsigned long	isl_count;
+	ia64_err_rec_t  *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
+} ia64_state_log_t;
+
+static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
+
+#define IA64_LOG_ALLOCATE(it, size) \
+	{ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
+		(ia64_err_rec_t *)alloc_bootmem(size); \
+	ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
+		(ia64_err_rec_t *)alloc_bootmem(size);}
+#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
+#define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
+#define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
+#define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index
+#define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index
+#define IA64_LOG_INDEX_INC(it) \
+    {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \
+    ia64_state_log[it].isl_count++;}
+#define IA64_LOG_INDEX_DEC(it) \
+    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
+#define IA64_LOG_NEXT_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
+#define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
+#define IA64_LOG_COUNT(it)         ia64_state_log[it].isl_count
+
+/*
+ * ia64_log_init
+ *	Reset the OS ia64 log buffer
+ * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ * Outputs	:	None
+ */
+static void
+ia64_log_init(int sal_info_type)
+{
+	u64	max_size = 0;
+
+	IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
+	IA64_LOG_LOCK_INIT(sal_info_type);
+
+	// SAL will tell us the maximum size of any error record of this type
+	max_size = ia64_sal_get_state_info_size(sal_info_type);
+	if (!max_size)
+		/* alloc_bootmem() doesn't like zero-sized allocations! */
+		return;
+
+	// set up OS data structures to hold error info
+	IA64_LOG_ALLOCATE(sal_info_type, max_size);
+	memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
+	memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
+}
+
+/*
+ * ia64_log_get
+ *
+ *	Get the current MCA log from SAL and copy it into the OS log buffer.
+ *
+ *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
+ *              irq_safe    whether you can use printk at this point
+ *  Outputs :   size        (total record length)
+ *              *buffer     (ptr to error record)
+ *
+ */
+static u64
+ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
+{
+	sal_log_record_header_t     *log_buffer;
+	u64                         total_len = 0;
+	int                         s;
+
+	IA64_LOG_LOCK(sal_info_type);
+
+	/* Get the process state information */
+	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
+
+	total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
+
+	if (total_len) {
+		IA64_LOG_INDEX_INC(sal_info_type);
+		IA64_LOG_UNLOCK(sal_info_type);
+		if (irq_safe) {
+			IA64_MCA_DEBUG("%s: SAL error record type %d retrieved. "
+				       "Record length = %ld\n", __FUNCTION__, sal_info_type, total_len);
+		}
+		*buffer = (u8 *) log_buffer;
+		return total_len;
+	} else {
+		IA64_LOG_UNLOCK(sal_info_type);
+		return 0;
+	}
+}
+
+/*
  *  ia64_mca_log_sal_error_record
  *
- *  This function retrieves a specified error record type from SAL,
- *  wakes up any processes waiting for error records, and sends it to
- *  the system log.
+ *  This function retrieves a specified error record type from SAL
+ *  and wakes up any processes waiting for error records.
  *
  *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
- *  Outputs :   platform error status
  */
-int
-ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init)
+static void
+ia64_mca_log_sal_error_record(int sal_info_type)
 {
 	u8 *buffer;
 	u64 size;
-	int platform_err;
+	int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;
+	static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
 
-	size = ia64_log_get(sal_info_type, &buffer);
+	size = ia64_log_get(sal_info_type, &buffer, irq_safe);
 	if (!size)
-		return 0;
+		return;
 
-	/* TODO:
-	 * 1. analyze error logs to determine recoverability
-	 * 2. perform error recovery procedures, if applicable
-	 * 3. set ia64_os_mca_recovery_successful flag, if applicable
-	 */
+	salinfo_log_wakeup(sal_info_type, buffer, size, irq_safe);
+
+	if (irq_safe)
+		printk(KERN_INFO "CPU %d: SAL log contains %s error record\n",
+			smp_processor_id(),
+			sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN");
 
-	salinfo_log_wakeup(sal_info_type, buffer, size);
-	platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk);
 	/* Clear logs from corrected errors in case there's no user-level logger */
 	if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC)
 		ia64_sal_clear_state_info(sal_info_type);
-
-	return platform_err;
 }
 
 /*
  * platform dependent error handling
  */
 #ifndef PLATFORM_MCA_HANDLERS
-void
-mca_handler_platform (void)
-{
-
-}
 
-void
+static void
 ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
-	IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n",
-		       smp_processor_id(), cpe_irq);
+	IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n",
+		       __FUNCTION__, smp_processor_id(), cpe_irq);
 
 	/* SAL spec states this should run w/ interrupts enabled */
 	local_irq_enable();
 
 	/* Get the CMC error record and log it */
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0);
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
 }
 
+#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
+
 static void
 show_min_state (pal_min_state_area_t *minstate)
 {
@@ -357,7 +425,7 @@
 	PUT_NAT_BIT(sw->caller_unat, &pt->r30);	PUT_NAT_BIT(sw->caller_unat, &pt->r31);
 }
 
-void
+static void
 init_handler_platform (pal_min_state_area_t *ms,
 		       struct pt_regs *pt, struct switch_stack *sw)
 {
@@ -404,45 +472,7 @@
 	while (1);			/* hang city if no debugger */
 }
 
-/*
- * ia64_mca_init_platform
- *
- *  External entry for platform specific MCA initialization.
- *
- *  Inputs
- *      None
- *
- *  Outputs
- *      None
- */
-void
-ia64_mca_init_platform (void)
-{
-
-}
-
-/*
- *  ia64_mca_check_errors
- *
- *  External entry to check for error records which may have been posted by SAL
- *  for a prior failure.
- *
- *  Inputs  :   None
- *
- *  Outputs :   None
- */
-int
-ia64_mca_check_errors (void)
-{
-	/*
-	 *  If there is an MCA error record pending, get it and log it.
-	 */
-	printk("CPU %d: checking for saved MCA error records\n", smp_processor_id());
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 1);
-
-	return 0;
-}
-
+#ifdef CONFIG_ACPI
 /*
  * ia64_mca_register_cpev
  *
@@ -462,14 +492,15 @@
 
 	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0);
 	if (isrv.status) {
-		printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected "
-		       "Platform Error interrupt vector with SAL.\n");
+		printk(KERN_ERR "Failed to register Corrected Platform "
+		       "Error interrupt vector with SAL (status %ld)\n", isrv.status);
 		return;
 	}
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
-		       "vector %#x setup and enabled\n", cpev);
+	IA64_MCA_DEBUG("%s: corrected platform error "
+		       "vector %#x setup and enabled\n", __FUNCTION__, cpev);
 }
+#endif /* CONFIG_ACPI */
 
 #endif /* PLATFORM_MCA_HANDLERS */
 
@@ -495,12 +526,12 @@
 	cmcv.cmcv_vector	= IA64_CMC_VECTOR;
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x setup and enabled.\n",
-		       smp_processor_id(), IA64_CMC_VECTOR);
+		       __FUNCTION__, smp_processor_id(), IA64_CMC_VECTOR);
 
-	IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n",
-		       smp_processor_id(), ia64_get_cmcv());
+	IA64_MCA_DEBUG("%s: CPU %d CMCV = %#016lx\n",
+		       __FUNCTION__, smp_processor_id(), ia64_get_cmcv());
 }
 
 /*
@@ -515,7 +546,7 @@
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_vector_disable (void *dummy)
 {
 	cmcv_reg_t	cmcv;
@@ -525,9 +556,9 @@
 	cmcv.cmcv_mask = 1; /* Mask/disable interrupt */
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_vector_disable: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x disabled.\n",
-		       smp_processor_id(), cmcv.cmcv_vector);
+		       __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector);
 }
 
 /*
@@ -542,7 +573,7 @@
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_vector_enable (void *dummy)
 {
 	cmcv_reg_t	cmcv;
@@ -552,63 +583,9 @@
 	cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */
 	ia64_set_cmcv(cmcv.cmcv_regval);
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_vector_enable: CPU %d corrected "
+	IA64_MCA_DEBUG("%s: CPU %d corrected "
 		       "machine check vector %#x enabled.\n",
-		       smp_processor_id(), cmcv.cmcv_vector);
-}
-
-
-#if defined(MCA_TEST)
-
-sal_log_processor_info_t	slpi_buf;
-
-void
-mca_test(void)
-{
-	slpi_buf.valid.psi_static_struct = 1;
-	slpi_buf.valid.num_cache_check = 1;
-	slpi_buf.valid.num_tlb_check = 1;
-	slpi_buf.valid.num_bus_check = 1;
-	slpi_buf.valid.processor_static_info.minstate = 1;
-	slpi_buf.valid.processor_static_info.br = 1;
-	slpi_buf.valid.processor_static_info.cr = 1;
-	slpi_buf.valid.processor_static_info.ar = 1;
-	slpi_buf.valid.processor_static_info.rr = 1;
-	slpi_buf.valid.processor_static_info.fr = 1;
-
-	ia64_os_mca_dispatch();
-}
-
-#endif /* #if defined(MCA_TEST) */
-
-
-/*
- *  verify_guid
- *
- *  Compares a test guid to a target guid and returns result.
- *
- *  Inputs
- *      test_guid *     (ptr to guid to be verified)
- *      target_guid *   (ptr to standard guid to be verified against)
- *
- *  Outputs
- *      0               (test verifies against target)
- *      non-zero        (test guid does not verify)
- */
-static int
-verify_guid (efi_guid_t *test, efi_guid_t *target)
-{
-	int     rc;
-#ifdef IA64_MCA_DEBUG_INFO
-	char out[40];
-#endif
-
-	if ((rc = efi_guidcmp(*test, *target))) {
-		IA64_MCA_DEBUG(KERN_DEBUG
-			       "verify_guid: invalid GUID = %s\n",
-			       efi_guid_unparse(test, out));
-	}
-	return rc;
+		       __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector);
 }
 
 /*
@@ -642,225 +619,39 @@
 }
 
 /*
- * ia64_mca_init
- *
- *  Do all the system level mca specific initialization.
- *
- *	1. Register spinloop and wakeup request interrupt vectors
- *
- *	2. Register OS_MCA handler entry point
- *
- *	3. Register OS_INIT handler entry point
- *
- *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
+ * ia64_mca_wakeup_ipi_wait
  *
- *  Note that this initialization is done very early before some kernel
- *  services are available.
+ *	Wait for the inter-cpu interrupt to be sent by the
+ *	monarch processor once it is done with handling the
+ *	MCA.
  *
  *  Inputs  :   None
- *
  *  Outputs :   None
  */
-void __init
-ia64_mca_init(void)
+static void
+ia64_mca_wakeup_ipi_wait(void)
 {
-	ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
-	ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
-	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
-	int i;
-	s64 rc;
-	struct ia64_sal_retval isrv;
-	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
+	int	irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
+	int	irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
+	u64	irr = 0;
 
-	IA64_MCA_DEBUG("ia64_mca_init: begin\n");
-
-	INIT_TQUEUE(&cmc_disable_tq, ia64_mca_cmc_vector_disable_keventd, NULL);
-	INIT_TQUEUE(&cmc_enable_tq, ia64_mca_cmc_vector_enable_keventd, NULL);
-
-	/* initialize recovery success indicator */
-	ia64_os_mca_recovery_successful = 0;
-
-	/* Clear the Rendez checkin flag for all cpus */
-	for(i = 0 ; i < NR_CPUS; i++)
-		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
-
-	/*
-	 * Register the rendezvous spinloop and wakeup mechanism with SAL
-	 */
-
-	/* Register the rendezvous interrupt vector with SAL */
-	while (1) {
-		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
-					      SAL_MC_PARAM_MECHANISM_INT,
-					      IA64_MCA_RENDEZ_VECTOR,
-					      timeout,
-					      SAL_MC_PARAM_RZ_ALWAYS);
-		rc = isrv.status;
-		if (rc == 0)
-			break;
-		if (rc == -2) {
-			printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from "
-				"%ld to %ld\n", timeout, isrv.v0);
-			timeout = isrv.v0;
-			continue;
-		}
-		printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt "
-		       "with SAL.  rc = %ld\n", rc);
-		return;
-	}
-
-	/* Register the wakeup interrupt vector with SAL */
-	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
-				      SAL_MC_PARAM_MECHANISM_INT,
-				      IA64_MCA_WAKEUP_VECTOR,
-				      0, 0);
-	rc = isrv.status;
-	if (rc) {
-		printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL.  "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");
-
-	ia64_mc_info.imi_mca_handler        = ia64_tpa(mca_hldlr_ptr->fp);
-	/*
-	 * XXX - disable SAL checksum by setting size to 0; should be
-	 *	ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
-	 */
-	ia64_mc_info.imi_mca_handler_size	= 0;
-
-	/* Register the os mca handler with SAL */
-	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
-				       ia64_mc_info.imi_mca_handler,
-				       ia64_tpa(mca_hldlr_ptr->gp),
-				       ia64_mc_info.imi_mca_handler_size,
-				       0, 0, 0)))
-	{
-		printk(KERN_ERR "ia64_mca_init: Failed to register os mca handler with SAL.  "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
-		       ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
-
-	/*
-	 * XXX - disable SAL checksum by setting size to 0, should be
-	 * IA64_INIT_HANDLER_SIZE
-	 */
-	ia64_mc_info.imi_monarch_init_handler		= ia64_tpa(mon_init_ptr->fp);
-	ia64_mc_info.imi_monarch_init_handler_size	= 0;
-	ia64_mc_info.imi_slave_init_handler		= ia64_tpa(slave_init_ptr->fp);
-	ia64_mc_info.imi_slave_init_handler_size	= 0;
-
-	IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",
-		       ia64_mc_info.imi_monarch_init_handler);
-
-	/* Register the os init handler with SAL */
-	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
-				       ia64_mc_info.imi_monarch_init_handler,
-				       ia64_tpa(ia64_get_gp()),
-				       ia64_mc_info.imi_monarch_init_handler_size,
-				       ia64_mc_info.imi_slave_init_handler,
-				       ia64_tpa(ia64_get_gp()),
-				       ia64_mc_info.imi_slave_init_handler_size)))
-	{
-		printk(KERN_ERR "ia64_mca_init: Failed to register m/s init handlers with SAL. "
-		       "rc = %ld\n", rc);
-		return;
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");
-
-	/*
-	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
-	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
-	 */
-	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
-	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
-	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
-
-	/* Setup the MCA rendezvous interrupt vector */
-	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
-
-	/* Setup the MCA wakeup interrupt vector */
-	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
-
-	/* Setup the CPE interrupt vector */
-	{
-		irq_desc_t *desc;
-		unsigned int irq;
-		int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
-
-		if (cpev >= 0) {
-			for (irq = 0; irq < NR_IRQS; ++irq)
-				if (irq_to_vector(irq) == cpev) {
-					desc = irq_desc(irq);
-					desc->status |= IRQ_PER_CPU;
-					desc->handler = &irq_type_iosapic_level;
-					setup_irq(irq, &mca_cpe_irqaction);
-				}
-			ia64_mca_register_cpev(cpev);
-		}
-	}
-
-	/* Initialize the areas set aside by the OS to buffer the
-	 * platform/processor error states for MCA/INIT/CMC
-	 * handling.
-	 */
-	ia64_log_init(SAL_INFO_TYPE_MCA);
-	ia64_log_init(SAL_INFO_TYPE_INIT);
-	ia64_log_init(SAL_INFO_TYPE_CMC);
-	ia64_log_init(SAL_INFO_TYPE_CPE);
-
-#if defined(MCA_TEST)
-	mca_test();
-#endif /* #if defined(MCA_TEST) */
-
-	printk(KERN_INFO "Mca related initialization done\n");
-
-	/* commented out because this is done elsewhere */
-#if 0
-	/* Do post-failure MCA error logging */
-	ia64_mca_check_errors();
-#endif
-}
-
-/*
- * ia64_mca_wakeup_ipi_wait
- *
- *	Wait for the inter-cpu interrupt to be sent by the
- *	monarch processor once it is done with handling the
- *	MCA.
- *
- *  Inputs  :   None
- *  Outputs :   None
- */
-void
-ia64_mca_wakeup_ipi_wait(void)
-{
-	int	irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
-	int	irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
-	u64	irr = 0;
-
-	do {
-		switch(irr_num) {
-		      case 0:
-			irr = ia64_get_irr0();
-			break;
-		      case 1:
-			irr = ia64_get_irr1();
-			break;
-		      case 2:
-			irr = ia64_get_irr2();
-			break;
-		      case 3:
-			irr = ia64_get_irr3();
-			break;
-		}
-	} while (!(irr & (1UL << irr_bit))) ;
-}
+	do {
+		switch(irr_num) {
+		      case 0:
+			irr = ia64_get_irr0();
+			break;
+		      case 1:
+			irr = ia64_get_irr1();
+			break;
+		      case 2:
+			irr = ia64_get_irr2();
+			break;
+		      case 3:
+			irr = ia64_get_irr3();
+			break;
+		}
+	} while (!(irr & (1UL << irr_bit))) ;
+}
 
 /*
  * ia64_mca_wakeup
@@ -871,7 +662,7 @@
  *  Inputs  :   cpuid
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_wakeup(int cpu)
 {
 	platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0);
@@ -887,7 +678,7 @@
  *  Inputs  :   None
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_wakeup_all(void)
 {
 	int cpu;
@@ -912,7 +703,7 @@
  *  Inputs  :   None
  *  Outputs :   None
  */
-void
+static void
 ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
 {
 	unsigned long flags;
@@ -937,7 +728,6 @@
 	local_irq_restore(flags);
 }
 
-
 /*
  * ia64_mca_wakeup_int_handler
  *
@@ -953,7 +743,7 @@
  *  Outputs :   None
  *
  */
-void
+static void
 ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
 {
 }
@@ -972,11 +762,9 @@
  *  Outputs :   None
  */
 
-void
-ia64_return_to_sal_check(void)
+static void
+ia64_return_to_sal_check(int recover)
 {
-	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
-		&ia64_sal_to_os_handoff_state.proc_state_param;
 
 	/* Copy over some relevant stuff from the sal_to_os_mca_handoff
 	 * so that it can be used at the time of os_mca_to_sal_handoff
@@ -987,15 +775,10 @@
 	ia64_os_to_sal_handoff_state.imots_sal_check_ra =
 		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
 
-	/*
-	 * Did we correct the error? At the moment the only error that
-	 * we fix is a TLB error, if any other kind of error occurred
-	 * we must reboot.
-	 */
-	if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1)
-		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
-	else
+	if (recover)
 		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
+	else
+		ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
 
 	/* Default = tell SAL to return to same context */
 	ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
@@ -1024,16 +807,12 @@
 void
 ia64_mca_ucmc_handler(void)
 {
-	int platform_err = 0;
+	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
+		&ia64_sal_to_os_handoff_state.proc_state_param;
+	int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc);
 
 	/* Get the MCA error record and log it */
-	platform_err = ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 0);
-
-	/*
-	 *  Do Platform-specific mca error handling if required.
-	 */
-	if (platform_err)
-		mca_handler_platform();
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
 
 	/*
 	 *  Wakeup all the processors which are spinning in the rendezvous
@@ -1042,7 +821,7 @@
 	ia64_mca_wakeup_all();
 
 	/* Return to SAL */
-	ia64_return_to_sal_check();
+	ia64_return_to_sal_check(recover);
 }
 
 /*
@@ -1060,21 +839,21 @@
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
 {
 	static unsigned long	cmc_history[CMC_HISTORY_LENGTH];
 	static int		index;
 	static spinlock_t	cmc_history_lock = SPIN_LOCK_UNLOCKED;
 
-	IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",
-		       cmc_irq, smp_processor_id());
+	IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n",
+		       __FUNCTION__, cmc_irq, smp_processor_id());
 
 	/* SAL spec states this should run w/ interrupts enabled */
 	local_irq_enable();
 
 	/* Get the CMC error record and log it */
-	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC, 0);
+	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
 
 	spin_lock(&cmc_history_lock);
 	if (!cmc_polling_enabled) {
@@ -1098,7 +877,7 @@
 			 * make sure there's a log somewhere that indicates
 			 * something is generating more than we can handle.
 			 */
-			printk(KERN_WARNING "%s: WARNING: Switching to polling CMC handler, error records may be lost\n", __FUNCTION__);
+			printk(KERN_WARNING "WARNING: Switching to polling CMC handler; error records may be lost\n");
 
 			mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
@@ -1114,41 +893,6 @@
 }
 
 /*
- * IA64_MCA log support
- */
-#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */
-#define IA64_MAX_LOG_TYPES      4   /* MCA, INIT, CMC, CPE */
-
-typedef struct ia64_state_log_s
-{
-	spinlock_t	isl_lock;
-	int		isl_index;
-	unsigned long	isl_count;
-	ia64_err_rec_t  *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */
-} ia64_state_log_t;
-
-static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
-
-#define IA64_LOG_ALLOCATE(it, size) \
-	{ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
-		(ia64_err_rec_t *)alloc_bootmem(size); \
-	ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
-		(ia64_err_rec_t *)alloc_bootmem(size);}
-#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
-#define IA64_LOG_LOCK(it)      spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
-#define IA64_LOG_UNLOCK(it)    spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
-#define IA64_LOG_NEXT_INDEX(it)    ia64_state_log[it].isl_index
-#define IA64_LOG_CURR_INDEX(it)    1 - ia64_state_log[it].isl_index
-#define IA64_LOG_INDEX_INC(it) \
-    {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \
-    ia64_state_log[it].isl_count++;}
-#define IA64_LOG_INDEX_DEC(it) \
-    ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index
-#define IA64_LOG_NEXT_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)]))
-#define IA64_LOG_CURR_BUFFER(it)   (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)]))
-#define IA64_LOG_COUNT(it)         ia64_state_log[it].isl_count
-
-/*
  *  ia64_mca_cmc_int_caller
  *
  * 	Triggered by sw interrupt from CMC polling routine.  Calls
@@ -1162,7 +906,7 @@
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
@@ -1177,14 +921,14 @@
 	ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs);
 
 	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
-		
+
 	if (cpuid < NR_CPUS) {
 		platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
 	} else {
-		/* If no log recored, switch out of polling mode */
+		/* If no log record, switch out of polling mode */
 		if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
 
-			printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__);
+			printk(KERN_WARNING "Returning to interrupt driven CMC handler\n");
 			schedule_task(&cmc_enable_tq);
 			cmc_polling_enabled = 0;
 
@@ -1227,7 +971,7 @@
  * Outputs
  *	None
  */
-void
+static void
 ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
 	static int start_count = -1;
@@ -1279,57 +1023,26 @@
 }
 
 /*
- * ia64_mca_late_init
+ * C portion of the OS INIT handler
  *
- *	Opportunity to setup things that require initialization later
- *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
- *	platform doesn't support an interrupt driven mechanism.
+ * Called from ia64_monarch_init_handler
+ *
+ * Inputs: pointer to pt_regs where processor info was saved.
+ *
+ * Returns:
+ *   0 if SAL must warm boot the System
+ *   1 if SAL must return to interrupted context using PAL_MC_RESUME
  *
- *  Inputs  :   None
- *  Outputs :   Status
  */
-static int __init
-ia64_mca_late_init(void)
+void
+ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
 {
-	init_timer(&cmc_poll_timer);
-	cmc_poll_timer.function = ia64_mca_cmc_poll;
+	pal_min_state_area_t *ms;
 
-	/* Reset to the correct state */
-	cmc_polling_enabled = 0;
+	oops_in_progress = 1;	/* avoid deadlock in printk, but it makes recovery dodgy */
 
-	init_timer(&cpe_poll_timer);
-	cpe_poll_timer.function = ia64_mca_cpe_poll;
-
-	/* If platform doesn't support CPEI, get the timer going. */
-	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
-		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
-		ia64_mca_cpe_poll(0UL);
-	}
-
-	return 0;
-}
-
-module_init(ia64_mca_late_init);
-
-/*
- * C portion of the OS INIT handler
- *
- * Called from ia64_monarch_init_handler
- *
- * Inputs: pointer to pt_regs where processor info was saved.
- *
- * Returns:
- *   0 if SAL must warm boot the System
- *   1 if SAL must return to interrupted context using PAL_MC_RESUME
- *
- */
-void
-ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
-{
-	pal_min_state_area_t *ms;
-
-	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
-		ia64_sal_to_os_handoff_state.proc_state_param);
+	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
+		ia64_sal_to_os_handoff_state.proc_state_param);
 
 	/*
 	 * Address of minstate area provided by PAL is physical,
@@ -1341,1080 +1054,259 @@
 	init_handler_platform(ms, pt, sw);	/* call platform specific routines */
 }
 
-/*
- *  ia64_log_prt_guid
- *
- *  Print a formatted GUID.
- *
- * Inputs   :   p_guid      (ptr to the GUID)
- *              prfunc      (print function)
- * Outputs  :   None
- *
- */
-void
-ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
-{
-	char out[40];
-	printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out));
-}
-
-static void
-ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
+static int __init
+ia64_mca_disable_cpe_polling(char *str)
 {
-	unsigned long i;
-	int j;
-
-	if (!p)
-		return;
-
-	for (i = 0; i < n_ch;) {
-		prfunc("%p ", (void *)p);
-		for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) {
-			prfunc("%02x ", *p);
-		}
-		prfunc("\n");
-	}
+	cpe_poll_enabled = 0;
+	return 1;
 }
 
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
+__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
 
-static void
-ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc)
-{
-	prfunc("SAL RECORD HEADER:  Record buffer = %p,  header size = %ld\n",
-	       (void *)rh, sizeof(sal_log_record_header_t));
-	ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t),
-			 (prfunc_t)prfunc);
-	prfunc("Total record length = %d\n", rh->len);
-	ia64_log_prt_guid(&rh->platform_guid, prfunc);
-	prfunc("End of SAL RECORD HEADER\n");
-}
+static struct irqaction cmci_irqaction = {
+	.handler =	ia64_mca_cmc_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_hndlr"
+};
 
-static void
-ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc)
-{
-	prfunc("SAL SECTION HEADER:  Record buffer = %p,  header size = %ld\n",
-	       (void *)sh, sizeof(sal_log_section_hdr_t));
-	ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t),
-			 (prfunc_t)prfunc);
-	prfunc("Length of section & header = %d\n", sh->len);
-	ia64_log_prt_guid(&sh->guid, prfunc);
-	prfunc("End of SAL SECTION HEADER\n");
-}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
+static struct irqaction cmcp_irqaction = {
+	.handler =	ia64_mca_cmc_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_poll"
+};
 
-/*
- * ia64_log_init
- *	Reset the OS ia64 log buffer
- * Inputs   :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- * Outputs	:	None
- */
-void
-ia64_log_init(int sal_info_type)
-{
-	u64	max_size = 0;
+static struct irqaction mca_rdzv_irqaction = {
+	.handler =	ia64_mca_rendez_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_rdzv"
+};
 
-	IA64_LOG_NEXT_INDEX(sal_info_type) = 0;
-	IA64_LOG_LOCK_INIT(sal_info_type);
+static struct irqaction mca_wkup_irqaction = {
+	.handler =	ia64_mca_wakeup_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_wkup"
+};
 
-	// SAL will tell us the maximum size of any error record of this type
-	max_size = ia64_sal_get_state_info_size(sal_info_type);
+#ifdef CONFIG_ACPI
+static struct irqaction mca_cpe_irqaction = {
+	.handler =	ia64_mca_cpe_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_hndlr"
+};
 
-	// set up OS data structures to hold error info
-	IA64_LOG_ALLOCATE(sal_info_type, max_size);
-	memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size);
-	memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size);
-}
+static struct irqaction mca_cpep_irqaction = {
+	.handler =	ia64_mca_cpe_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_poll"
+};
+#endif /* CONFIG_ACPI */
 
 /*
- * ia64_log_get
+ * ia64_mca_init
  *
- *	Get the current MCA log from SAL and copy it into the OS log buffer.
+ *  Do all the system level mca specific initialization.
  *
- *  Inputs  :   info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *  Outputs :   size        (total record length)
- *              *buffer     (ptr to error record)
+ *	1. Register spinloop and wakeup request interrupt vectors
  *
- */
-u64
-ia64_log_get(int sal_info_type, u8 **buffer)
-{
-	sal_log_record_header_t     *log_buffer;
-	u64                         total_len = 0;
-	int                         s;
-
-	IA64_LOG_LOCK(sal_info_type);
-
-	/* Get the process state information */
-	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type);
-
-	total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer);
-
-	if (total_len) {
-		IA64_LOG_INDEX_INC(sal_info_type);
-		IA64_LOG_UNLOCK(sal_info_type);
-		IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. "
-			       "Record length = %ld\n", sal_info_type, total_len);
-		*buffer = (u8 *) log_buffer;
-		return total_len;
-	} else {
-		IA64_LOG_UNLOCK(sal_info_type);
-		return 0;
-	}
-}
-
-/*
- *  ia64_log_prt_oem_data
+ *	2. Register OS_MCA handler entry point
  *
- *  Print OEM specific data if included.
+ *	3. Register OS_INIT handler entry point
  *
- * Inputs   :   header_len  (length passed in section header)
- *              sect_len    (default length of section type)
- *              p_data      (ptr to data)
- *			prfunc		(print function)
- * Outputs	:	None
+ *  4. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
  *
- */
-void
-ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
-{
-	int oem_data_len, i;
-
-	if ((oem_data_len = header_len - sect_len) > 0) {
-		prfunc(" OEM Specific Data:");
-		for (i = 0; i < oem_data_len; i++, p_data++)
-			prfunc(" %02x", *p_data);
-	}
-	prfunc("\n");
-}
-
-/*
- *  ia64_log_rec_header_print
+ *  Note that this initialization is done very early before some kernel
+ *  services are available.
  *
- *  Log info from the SAL error record header.
+ *  Inputs  :   None
  *
- *  Inputs  :   lh *    (ptr to SAL log error record header)
- *              prfunc  (fn ptr of log output function to use)
  *  Outputs :   None
  */
-void
-ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc)
-{
-	prfunc("+Err Record ID: %ld    SAL Rev: %2x.%02x\n", lh->id,
-			lh->revision.major, lh->revision.minor);
-	prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x    Severity %d\n",
-			lh->timestamp.slh_month, lh->timestamp.slh_day,
-			lh->timestamp.slh_century, lh->timestamp.slh_year,
-			lh->timestamp.slh_hour, lh->timestamp.slh_minute,
-			lh->timestamp.slh_second, lh->severity);
-}
-
-/*
- * ia64_log_processor_regs_print
- *	Print the contents of the saved processor register(s) in the format
- *		<reg_prefix>[<index>] <value>
- *
- * Inputs	:	regs		(Register save buffer)
- *			reg_num	(# of registers)
- *			reg_class	(application/banked/control/bank1_general)
- *			reg_prefix	(ar/br/cr/b1_gr)
- * Outputs	:	None
- *
- */
-void
-ia64_log_processor_regs_print(u64	*regs,
-			      int	reg_num,
-			      char	*reg_class,
-			      char	*reg_prefix,
-			      prfunc_t	prfunc)
-{
-	int i;
-
-	prfunc("+%s Registers\n", reg_class);
-	for (i = 0; i < reg_num; i++)
-		prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]);
-}
-
-/*
- * ia64_log_processor_fp_regs_print
- *  Print the contents of the saved floating page register(s) in the format
- *      <reg_prefix>[<index>] <value>
- *
- * Inputs:  ia64_fpreg  (Register save buffer)
- *          reg_num     (# of registers)
- *          reg_class   (application/banked/control/bank1_general)
- *          reg_prefix  (ar/br/cr/b1_gr)
- * Outputs: None
- *
- */
-void
-ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs,
-                                  int               reg_num,
-                                  char              *reg_class,
-                                  char              *reg_prefix,
-                                  prfunc_t          prfunc)
+void __init
+ia64_mca_init(void)
 {
+	ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
+	ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
+	ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
 	int i;
+	s64 rc;
+	struct ia64_sal_retval isrv;
+	u64 timeout = IA64_MCA_RENDEZ_TIMEOUT;	/* platform specific */
 
-	prfunc("+%s Registers\n", reg_class);
-	for (i = 0; i < reg_num; i++)
-		prfunc("+ %s[%d] 0x%lx%016lx\n", reg_prefix, i, regs[i].u.bits[1],
-		       regs[i].u.bits[0]);
-}
-
-static char *pal_mesi_state[] = {
-	"Invalid",
-	"Shared",
-	"Exclusive",
-	"Modified",
-	"Reserved1",
-	"Reserved2",
-	"Reserved3",
-	"Reserved4"
-};
-
-static char *pal_cache_op[] = {
-	"Unknown",
-	"Move in",
-	"Cast out",
-	"Coherency check",
-	"Internal",
-	"Instruction fetch",
-	"Implicit Writeback",
-	"Reserved"
-};
-
-/*
- * ia64_log_cache_check_info_print
- *	Display the machine check information related to cache error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          cc_info *   (Ptr to cache check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_cache_check_info_print (int                      i,
-                                 sal_log_mod_error_info_t *cache_check_info,
-				 prfunc_t		prfunc)
-{
-	pal_cache_check_info_t  *info;
-	u64                     target_addr;
-
-	if (!cache_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i);
-		return;                 /* If check info data not valid, skip it */
-	}
-
-	info        = (pal_cache_check_info_t *)&cache_check_info->check_info;
-	target_addr = cache_check_info->target_identifier;
-
-	prfunc("+ Cache check info[%d]\n+", i);
-	prfunc("  Level: L%d,",info->level);
-	if (info->mv)
-		prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]);
-	prfunc(" Index: %d,", info->index);
-	if (info->ic)
-		prfunc(" Cache: Instruction,");
-	if (info->dc)
-		prfunc(" Cache: Data,");
-	if (info->tl)
-		prfunc(" Line: Tag,");
-	if (info->dl)
-		prfunc(" Line: Data,");
-	prfunc(" Operation: %s,", pal_cache_op[info->op]);
-	if (info->wiv)
-		prfunc(" Way: %d,", info->way);
-	if (cache_check_info->valid.target_identifier)
-		/* Hope target address is saved in target_identifier */
-		if (info->tv)
-			prfunc(" Target Addr: 0x%lx,", target_addr);
-	if (info->mcc)
-		prfunc(" MC: Corrected");
-	prfunc("\n");
-}
-
-/*
- * ia64_log_tlb_check_info_print
- *	Display the machine check information related to tlb error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          tlb_info *  (Ptr to machine check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_tlb_check_info_print (int                      i,
-                               sal_log_mod_error_info_t *tlb_check_info,
-                               prfunc_t                 prfunc)
-
-{
-	pal_tlb_check_info_t    *info;
-
-	if (!tlb_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i);
-		return;                 /* If check info data not valid, skip it */
-	}
-
-	info = (pal_tlb_check_info_t *)&tlb_check_info->check_info;
-
-	prfunc("+ TLB Check Info [%d]\n+", i);
-	if (info->itc)
-		prfunc("  Failure: Instruction Translation Cache");
-	if (info->dtc)
-		prfunc("  Failure: Data Translation Cache");
-	if (info->itr) {
-		prfunc("  Failure: Instruction Translation Register");
-		prfunc(" ,Slot: %ld", info->tr_slot);
-	}
-	if (info->dtr) {
-		prfunc("  Failure: Data Translation Register");
-		prfunc(" ,Slot: %ld", info->tr_slot);
-	}
-	if (info->mcc)
-		prfunc(" ,MC: Corrected");
-	prfunc("\n");
-}
-
-/*
- * ia64_log_bus_check_info_print
- *	Display the machine check information related to bus error(s).
- * Inputs:  i           (Multiple errors are logged, i - index of logged error)
- *          bus_info *  (Ptr to machine check info logged by the PAL and later
- *					 captured by the SAL)
- *          prfunc      (fn ptr of print function to be used for output)
- * Outputs: None
- */
-void
-ia64_log_bus_check_info_print (int                      i,
-                               sal_log_mod_error_info_t *bus_check_info,
-                               prfunc_t                 prfunc)
-{
-	pal_bus_check_info_t *info;
-	u64         req_addr;   /* Address of the requestor of the transaction */
-	u64         resp_addr;  /* Address of the responder of the transaction */
-	u64         targ_addr;  /* Address where the data was to be delivered to */
-	/* or obtained from */
-
-	if (!bus_check_info->valid.check_info) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i);
-		return;                 /* If check info data not valid, skip it */
-	}
+	IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__);
 
-	info      = (pal_bus_check_info_t *)&bus_check_info->check_info;
-	req_addr  = bus_check_info->requestor_identifier;
-	resp_addr = bus_check_info->responder_identifier;
-	targ_addr = bus_check_info->target_identifier;
-
-	prfunc("+ BUS Check Info [%d]\n+", i);
-	prfunc(" Status Info: %d", info->bsi);
-	prfunc(" ,Severity: %d", info->sev);
-	prfunc(" ,Transaction Type: %d", info->type);
-	prfunc(" ,Transaction Size: %d", info->size);
-	if (info->cc)
-		prfunc(" ,Cache-cache-transfer");
-	if (info->ib)
-		prfunc(" ,Error: Internal");
-	if (info->eb)
-		prfunc(" ,Error: External");
-	if (info->mcc)
-		prfunc(" ,MC: Corrected");
-	if (info->tv)
-		prfunc(" ,Target Address: 0x%lx", targ_addr);
-	if (info->rq)
-		prfunc(" ,Requestor Address: 0x%lx", req_addr);
-	if (info->tv)
-		prfunc(" ,Responder Address: 0x%lx", resp_addr);
-	prfunc("\n");
-}
+	INIT_TQUEUE(&cmc_disable_tq, ia64_mca_cmc_vector_disable_keventd, NULL);
+	INIT_TQUEUE(&cmc_enable_tq, ia64_mca_cmc_vector_enable_keventd, NULL);
 
-/*
- *  ia64_log_mem_dev_err_info_print
- *
- *  Format and log the platform memory device error record section data.
- *
- *  Inputs:  mem_dev_err_info * (Ptr to memory device error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei,
-                                 prfunc_t                   prfunc)
-{
-	prfunc("+ Mem Error Detail: ");
+	/* Clear the Rendez checkin flag for all cpus */
+	for(i = 0 ; i < NR_CPUS; i++)
+		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
 
-	if (mdei->valid.error_status)
-		prfunc(" Error Status: %#lx,", mdei->error_status);
-	if (mdei->valid.physical_addr)
-		prfunc(" Physical Address: %#lx,", mdei->physical_addr);
-	if (mdei->valid.addr_mask)
-		prfunc(" Address Mask: %#lx,", mdei->addr_mask);
-	if (mdei->valid.node)
-		prfunc(" Node: %d,", mdei->node);
-	if (mdei->valid.card)
-		prfunc(" Card: %d,", mdei->card);
-	if (mdei->valid.module)
-		prfunc(" Module: %d,", mdei->module);
-	if (mdei->valid.bank)
-		prfunc(" Bank: %d,", mdei->bank);
-	if (mdei->valid.device)
-		prfunc(" Device: %d,", mdei->device);
-	if (mdei->valid.row)
-		prfunc(" Row: %d,", mdei->row);
-	if (mdei->valid.column)
-		prfunc(" Column: %d,", mdei->column);
-	if (mdei->valid.bit_position)
-		prfunc(" Bit Position: %d,", mdei->bit_position);
-	if (mdei->valid.target_id)
-		prfunc(" ,Target Address: %#lx,", mdei->target_id);
-	if (mdei->valid.requestor_id)
-		prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id);
-	if (mdei->valid.responder_id)
-		prfunc(" ,Responder Address: %#lx,", mdei->responder_id);
-	if (mdei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data);
-	prfunc("\n");
-
-	if (mdei->valid.oem_id) {
-		u8  *p_data = &(mdei->oem_id[0]);
-		int i;
-
-		prfunc(" OEM Memory Controller ID:");
-		for (i = 0; i < 16; i++, p_data++)
-			prfunc(" %02x", *p_data);
-		prfunc("\n");
-	}
+	/*
+	 * Register the rendezvous spinloop and wakeup mechanism with SAL
+	 */
 
-	if (mdei->valid.oem_data) {
-		platform_mem_dev_err_print((int)mdei->header.len,
-				      (int)sizeof(sal_log_mem_dev_err_info_t) - 1,
-				      &(mdei->oem_data[0]), prfunc);
+	/* Register the rendezvous interrupt vector with SAL */
+	while (1) {
+		isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+					      SAL_MC_PARAM_MECHANISM_INT,
+					      IA64_MCA_RENDEZ_VECTOR,
+					      timeout,
+					      SAL_MC_PARAM_RZ_ALWAYS);
+		rc = isrv.status;
+		if (rc == 0)
+			break;
+		if (rc == -2) {
+			printk(KERN_INFO "Increasing MCA rendezvous timeout from "
+				"%ld to %ld milliseconds\n", timeout, isrv.v0);
+			timeout = isrv.v0;
+			continue;
+		}
+		printk(KERN_ERR "Failed to register rendezvous interrupt "
+		       "with SAL (status %ld)\n", rc);
+		return;
 	}
-}
 
-/*
- *  ia64_log_sel_dev_err_info_print
- *
- *  Format and log the platform SEL device error record section data.
- *
- *  Inputs:  sel_dev_err_info * (Ptr to the SEL device error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei,
-                                 prfunc_t                   prfunc)
-{
-	int     i;
-
-	prfunc("+ SEL Device Error Detail: ");
-
-	if (sdei->valid.record_id)
-		prfunc(" Record ID: %#x", sdei->record_id);
-	if (sdei->valid.record_type)
-		prfunc(" Record Type: %#x", sdei->record_type);
-	prfunc(" Time Stamp: ");
-	for (i = 0; i < 4; i++)
-		prfunc("%1d", sdei->timestamp[i]);
-	if (sdei->valid.generator_id)
-		prfunc(" Generator ID: %#x", sdei->generator_id);
-	if (sdei->valid.evm_rev)
-		prfunc(" Message Format Version: %#x", sdei->evm_rev);
-	if (sdei->valid.sensor_type)
-		prfunc(" Sensor Type: %#x", sdei->sensor_type);
-	if (sdei->valid.sensor_num)
-		prfunc(" Sensor Number: %#x", sdei->sensor_num);
-	if (sdei->valid.event_dir)
-		prfunc(" Event Direction Type: %#x", sdei->event_dir);
-	if (sdei->valid.event_data1)
-		prfunc(" Data1: %#x", sdei->event_data1);
-	if (sdei->valid.event_data2)
-		prfunc(" Data2: %#x", sdei->event_data2);
-	if (sdei->valid.event_data3)
-		prfunc(" Data3: %#x", sdei->event_data3);
-	prfunc("\n");
-
-}
-
-/*
- *  ia64_log_pci_bus_err_info_print
- *
- *  Format and log the platform PCI bus error record section data.
- *
- *  Inputs:  pci_bus_err_info * (Ptr to the PCI bus error record section
- *                               returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei,
-                                 prfunc_t                   prfunc)
-{
-	prfunc("+ PCI Bus Error Detail: ");
-
-	if (pbei->valid.err_status)
-		prfunc(" Error Status: %#lx", pbei->err_status);
-	if (pbei->valid.err_type)
-		prfunc(" Error Type: %#x", pbei->err_type);
-	if (pbei->valid.bus_id)
-		prfunc(" Bus ID: %#x", pbei->bus_id);
-	if (pbei->valid.bus_address)
-		prfunc(" Bus Address: %#lx", pbei->bus_address);
-	if (pbei->valid.bus_data)
-		prfunc(" Bus Data: %#lx", pbei->bus_data);
-	if (pbei->valid.bus_cmd)
-		prfunc(" Bus Command: %#lx", pbei->bus_cmd);
-	if (pbei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", pbei->requestor_id);
-	if (pbei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", pbei->responder_id);
-	if (pbei->valid.target_id)
-		prfunc(" Target ID: %#lx", pbei->target_id);
-	if (pbei->valid.oem_data)
-		prfunc("\n");
-
-	if (pbei->valid.oem_data) {
-		platform_pci_bus_err_print((int)pbei->header.len,
-				      (int)sizeof(sal_log_pci_bus_err_info_t) - 1,
-				      &(pbei->oem_data[0]), prfunc);
+	/* Register the wakeup interrupt vector with SAL */
+	isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+				      SAL_MC_PARAM_MECHANISM_INT,
+				      IA64_MCA_WAKEUP_VECTOR,
+				      0, 0);
+	rc = isrv.status;
+	if (rc) {
+		printk(KERN_ERR "Failed to register wakeup interrupt with SAL "
+		       "(status %ld)\n", rc);
+		return;
 	}
-}
 
-/*
- *  ia64_log_smbios_dev_err_info_print
- *
- *  Format and log the platform SMBIOS device error record section data.
- *
- *  Inputs:  smbios_dev_err_info * (Ptr to the SMBIOS device error record
- *                                  section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei,
-                                    prfunc_t                      prfunc)
-{
-	u8      i;
+	IA64_MCA_DEBUG("%s: registered MCA rendezvous spinloop and wakeup mech.\n", __FUNCTION__);
 
-	prfunc("+ SMBIOS Device Error Detail: ");
-
-	if (sdei->valid.event_type)
-		prfunc(" Event Type: %#x", sdei->event_type);
-	if (sdei->valid.time_stamp) {
-		prfunc(" Time Stamp: ");
-		for (i = 0; i < 6; i++)
-			prfunc("%d", sdei->time_stamp[i]);
-	}
-	if ((sdei->valid.data) && (sdei->valid.length)) {
-		prfunc(" Data: ");
-		for (i = 0; i < sdei->length; i++)
-			prfunc(" %02x", sdei->data[i]);
-	}
-	prfunc("\n");
-}
+	ia64_mc_info.imi_mca_handler        = ia64_tpa(mca_hldlr_ptr->fp);
+	/*
+	 * XXX - disable SAL checksum by setting size to 0; should be
+	 *	ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
+	 */
+	ia64_mc_info.imi_mca_handler_size	= 0;
 
-/*
- *  ia64_log_pci_comp_err_info_print
- *
- *  Format and log the platform PCI component error record section data.
- *
- *  Inputs:  pci_comp_err_info * (Ptr to the PCI component error record section
- *                                returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei,
-				 prfunc_t                     prfunc)
-{
-	u32     n_mem_regs, n_io_regs;
-	u64     i, n_pci_data;
-	u64     *p_reg_data;
-	u8      *p_oem_data;
-
-	prfunc("+ PCI Component Error Detail: ");
-
-	if (pcei->valid.err_status)
-		prfunc(" Error Status: %#lx\n", pcei->err_status);
-	if (pcei->valid.comp_info)
-		prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x,"
-		       " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%d\n",
-		       pcei->comp_info.vendor_id, pcei->comp_info.device_id,
-		       pcei->comp_info.class_code, pcei->comp_info.seg_num,
-		       pcei->comp_info.bus_num, pcei->comp_info.dev_num,
-		       pcei->comp_info.func_num);
-
-	n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0;
-	n_io_regs =  (pcei->valid.num_io_regs)  ? pcei->num_io_regs  : 0;
-	p_reg_data = &(pcei->reg_data_pairs[0]);
-	p_oem_data = (u8 *)p_reg_data +
-		(n_mem_regs + n_io_regs) * 2 * sizeof(u64);
-	n_pci_data = p_oem_data - (u8 *)pcei;
-
-	if (n_pci_data > pcei->header.len) {
-		prfunc(" Invalid PCI Component Error Record format: length = %ld, "
-		       " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ld\n",
-		       pcei->header.len, n_pci_data, n_mem_regs, n_io_regs);
+	/* Register the os mca handler with SAL */
+	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
+				       ia64_mc_info.imi_mca_handler,
+				       ia64_tpa(mca_hldlr_ptr->gp),
+				       ia64_mc_info.imi_mca_handler_size,
+				       0, 0, 0)))
+	{
+		printk(KERN_ERR "Failed to register OS MCA handler with SAL "
+		       "(status %ld)\n", rc);
 		return;
 	}
 
-	if (n_mem_regs) {
-		prfunc(" Memory Mapped Registers\n Address \tValue\n");
-		for (i = 0; i < pcei->num_mem_regs; i++) {
-			prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
-			p_reg_data += 2;
-		}
-	}
-	if (n_io_regs) {
-		prfunc(" I/O Mapped Registers\n Address \tValue\n");
-		for (i = 0; i < pcei->num_io_regs; i++) {
-			prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]);
-			p_reg_data += 2;
-		}
-	}
-	if (pcei->valid.oem_data) {
-		platform_pci_comp_err_print((int)pcei->header.len, n_pci_data,
-				      p_oem_data, prfunc);
-		prfunc("\n");
-	}
-}
-
-/*
- *  ia64_log_plat_specific_err_info_print
- *
- *  Format and log the platform specifie error record section data.
- *
- *  Inputs:  sel_dev_err_info * (Ptr to the platform specific error record
- *                               section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei,
-                                       prfunc_t                         prfunc)
-{
-	prfunc("+ Platform Specific Error Detail: ");
+	IA64_MCA_DEBUG("%s: registered OS MCA handler with SAL at 0x%lx, gp = 0x%lx\n", __FUNCTION__,
+		       ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
 
-	if (psei->valid.err_status)
-		prfunc(" Error Status: %#lx", psei->err_status);
-	if (psei->valid.guid) {
-		prfunc(" GUID: ");
-		ia64_log_prt_guid(&psei->guid, prfunc);
-	}
-	if (psei->valid.oem_data) {
-		platform_plat_specific_err_print((int) psei->header.len,
-				      (char *) psei->oem_data - (char *) psei,
-				      &psei->oem_data[0], prfunc);
-	}
-	prfunc("\n");
-}
+	/*
+	 * XXX - disable SAL checksum by setting size to 0, should be
+	 * size of the actual init handler in mca_asm.S.
+	 */
+	ia64_mc_info.imi_monarch_init_handler		= ia64_tpa(mon_init_ptr->fp);
+	ia64_mc_info.imi_monarch_init_handler_size	= 0;
+	ia64_mc_info.imi_slave_init_handler		= ia64_tpa(slave_init_ptr->fp);
+	ia64_mc_info.imi_slave_init_handler_size	= 0;
 
-/*
- *  ia64_log_host_ctlr_err_info_print
- *
- *  Format and log the platform host controller error record section data.
- *
- *  Inputs:  host_ctlr_err_info * (Ptr to the host controller error record
- *                                 section returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei,
-                                   prfunc_t                     prfunc)
-{
-	prfunc("+ Host Controller Error Detail: ");
+	IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__,
+		       ia64_mc_info.imi_monarch_init_handler);
 
-	if (hcei->valid.err_status)
-		prfunc(" Error Status: %#lx", hcei->err_status);
-	if (hcei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", hcei->requestor_id);
-	if (hcei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", hcei->responder_id);
-	if (hcei->valid.target_id)
-		prfunc(" Target ID: %#lx", hcei->target_id);
-	if (hcei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data);
-	if (hcei->valid.oem_data) {
-		platform_host_ctlr_err_print((int)hcei->header.len,
-				      (int)sizeof(sal_log_host_ctlr_err_info_t) - 1,
-				      &(hcei->oem_data[0]), prfunc);
+	/* Register the os init handler with SAL */
+	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
+				       ia64_mc_info.imi_monarch_init_handler,
+				       ia64_tpa(ia64_get_gp()),
+				       ia64_mc_info.imi_monarch_init_handler_size,
+				       ia64_mc_info.imi_slave_init_handler,
+				       ia64_tpa(ia64_get_gp()),
+				       ia64_mc_info.imi_slave_init_handler_size)))
+	{
+		printk(KERN_ERR "Failed to register m/s INIT handlers with SAL "
+		       "(status %ld)\n", rc);
+		return;
 	}
-	prfunc("\n");
-}
 
-/*
- *  ia64_log_plat_bus_err_info_print
- *
- *  Format and log the platform bus error record section data.
- *
- *  Inputs:  plat_bus_err_info * (Ptr to the platform bus error record section
- *                                returned by SAL)
- *           prfunc             (fn ptr of print function to be used for output)
- *  Outputs: None
- */
-void
-ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei,
-                                  prfunc_t                    prfunc)
-{
-	prfunc("+ Platform Bus Error Detail: ");
+	IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__);
 
-	if (pbei->valid.err_status)
-		prfunc(" Error Status: %#lx", pbei->err_status);
-	if (pbei->valid.requestor_id)
-		prfunc(" Requestor ID: %#lx", pbei->requestor_id);
-	if (pbei->valid.responder_id)
-		prfunc(" Responder ID: %#lx", pbei->responder_id);
-	if (pbei->valid.target_id)
-		prfunc(" Target ID: %#lx", pbei->target_id);
-	if (pbei->valid.bus_spec_data)
-		prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data);
-	if (pbei->valid.oem_data) {
-		platform_plat_bus_err_print((int)pbei->header.len,
-				      (int)sizeof(sal_log_plat_bus_err_info_t) - 1,
-				      &(pbei->oem_data[0]), prfunc);
-	}
-	prfunc("\n");
-}
+	/*
+	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
+	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
+	 */
+	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
+	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
 
-/*
- *  ia64_log_proc_dev_err_info_print
- *
- *  Display the processor device error record.
- *
- *  Inputs:  sal_log_processor_info_t * (Ptr to processor device error record
- *                                       section body).
- *           prfunc                     (fn ptr of print function to be used
- *                                       for output).
- *  Outputs: None
- */
-void
-ia64_log_proc_dev_err_info_print (sal_log_processor_info_t  *slpi,
-                                  prfunc_t                  prfunc)
-{
-#ifdef MCA_PRT_XTRA_DATA
-	size_t  d_len = slpi->header.len - sizeof(sal_log_section_hdr_t);
-#endif
-	sal_processor_static_info_t *spsi;
-	int                         i;
-	sal_log_mod_error_info_t    *p_data;
+	/* Setup the MCA rendezvous interrupt vector */
+	register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction);
 
-	prfunc("+Processor Device Error Info Section\n");
+	/* Setup the MCA wakeup interrupt vector */
+	register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
 
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
+#ifdef CONFIG_ACPI
+	/* Setup the CPE interrupt vector */
 	{
-		char    *p_data = (char *)&slpi->valid;
+		irq_desc_t *desc;
+		unsigned int irq;
+		int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
 
-		prfunc("SAL_PROC_DEV_ERR SECTION DATA:  Data buffer = %p, "
-		       "Data size = %ld\n", (void *)p_data, d_len);
-		ia64_log_hexdump(p_data, d_len, prfunc);
-		prfunc("End of SAL_PROC_DEV_ERR SECTION DATA\n");
+		if (cpev >= 0) {
+			for (irq = 0; irq < NR_IRQS; ++irq)
+				if (irq_to_vector(irq) == cpev) {
+					desc = irq_desc(irq);
+					desc->status |= IRQ_PER_CPU;
+					desc->handler = &irq_type_iosapic_level;
+					setup_irq(irq, &mca_cpe_irqaction);
+				}
+			ia64_mca_register_cpev(cpev);
+		}
 	}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if (slpi->valid.proc_error_map)
-		prfunc(" Processor Error Map: %#lx\n", slpi->proc_error_map);
-
-	if (slpi->valid.proc_state_param)
-		prfunc(" Processor State Param: %#lx\n", slpi->proc_state_parameter);
-
-	if (slpi->valid.proc_cr_lid)
-		prfunc(" Processor LID: %#lx\n", slpi->proc_cr_lid);
+#endif
 
-	/*
-	 *  Note: March 2001 SAL spec states that if the number of elements in any
-	 *  of  the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is
-	 *  absent. Also, current implementations only allocate space for number of
-	 *  elements used.  So we walk the data pointer from here on.
+	/* Initialize the areas set aside by the OS to buffer the
+	 * platform/processor error states for MCA/INIT/CMC
+	 * handling.
 	 */
-	p_data = &slpi->info[0];
-
-	/* Print the cache check information if any*/
-	for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
-		ia64_log_cache_check_info_print(i, p_data, prfunc);
-
-	/* Print the tlb check information if any*/
-	for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++)
-		ia64_log_tlb_check_info_print(i, p_data, prfunc);
-
-	/* Print the bus check information if any*/
-	for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++)
-		ia64_log_bus_check_info_print(i, p_data, prfunc);
-
-	/* Print the reg file check information if any*/
-	for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++)
-		ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
-				 prfunc);    /* Just hex dump for now */
-
-	/* Print the ms check information if any*/
-	for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++)
-		ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t),
-				 prfunc);    /* Just hex dump for now */
-
-	/* Print CPUID registers if any*/
-	if (slpi->valid.cpuid_info) {
-		u64     *p = (u64 *)p_data;
-
-		prfunc(" CPUID Regs: %#lx %#lx %#lx %#lx\n", p[0], p[1], p[2], p[3]);
-		p_data++;
-	}
+	ia64_log_init(SAL_INFO_TYPE_MCA);
+	ia64_log_init(SAL_INFO_TYPE_INIT);
+	ia64_log_init(SAL_INFO_TYPE_CMC);
+	ia64_log_init(SAL_INFO_TYPE_CPE);
 
-	/* Print processor static info if any */
-	if (slpi->valid.psi_static_struct) {
-		spsi = (sal_processor_static_info_t *)p_data;
-
-		/* Print branch register contents if valid */
-		if (spsi->valid.br)
-			ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br",
-						      prfunc);
-
-		/* Print control register contents if valid */
-		if (spsi->valid.cr)
-			ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr",
-						      prfunc);
-
-		/* Print application register contents if valid */
-		if (spsi->valid.ar)
-			ia64_log_processor_regs_print(spsi->ar, 128, "Application",
-						      "ar", prfunc);
-
-		/* Print region register contents if valid */
-		if (spsi->valid.rr)
-			ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr",
-						      prfunc);
-
-		/* Print floating-point register contents if valid */
-		if (spsi->valid.fr)
-			ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr",
-							 prfunc);
-	}
+	printk(KERN_INFO "MCA related initialization done\n");
 }
 
 /*
- * ia64_log_processor_info_print
+ * ia64_mca_late_init
  *
- *	Display the processor-specific information logged by PAL as a part
- *	of MCA or INIT or CMC.
+ *	Opportunity to setup things that require initialization later
+ *	than ia64_mca_init.  Setup a timer to poll for CPEs if the
+ *	platform doesn't support an interrupt driven mechanism.
  *
- *  Inputs   :  lh      (Pointer of the sal log header which specifies the
- *                       format of SAL state info as specified by the SAL spec).
- *              prfunc  (fn ptr of print function to be used for output).
- * Outputs	:	None
+ *  Inputs  :   None
+ *  Outputs :   Status
  */
-void
-ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc)
+static int __init
+ia64_mca_late_init(void)
 {
-	sal_log_section_hdr_t       *slsh;
-	int                         n_sects;
-	u32                         ercd_pos;
-
-	if (!lh)
-		return;
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-	ia64_log_prt_record_header(lh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: "
-			       "truncated SAL CMC error record. len = %d\n",
-			       lh->len);
-		return;
-	}
-
-	/* Print record header info */
-	ia64_log_rec_header_print(lh, prfunc);
-
-	for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
-		/* point to next section header */
-		slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-		ia64_log_prt_section_header(slsh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-		if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) {
-			IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
-			continue;
-		}
-
-		/*
-		 *  Now process processor device error record section
-		 */
-		ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, printk);
-	}
-
-	IA64_MCA_DEBUG("ia64_mca_log_print: "
-		       "found %d sections in SAL CMC error record. len = %d\n",
-		       n_sects, lh->len);
-	if (!n_sects) {
-		prfunc("No Processor Device Error Info Section found\n");
-		return;
-	}
-}
-
-/*
- *  ia64_log_platform_info_print
- *
- *  Format and Log the SAL Platform Error Record.
- *
- *  Inputs  :   lh      (Pointer to the sal error record header with format
- *                       specified by the SAL spec).
- *              prfunc  (fn ptr of log output function to use)
- *  Outputs :	platform error status
- */
-int
-ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc)
-{
-	sal_log_section_hdr_t	*slsh;
-	int			n_sects;
-	u32			ercd_pos;
-	int			platform_err = 0;
-
-	if (!lh)
-		return platform_err;
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-	ia64_log_prt_record_header(lh, prfunc);
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
-
-	if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
-		IA64_MCA_DEBUG("ia64_mca_log_print: "
-			       "truncated SAL error record. len = %d\n",
-			       lh->len);
-		return platform_err;
-	}
-
-	/* Print record header info */
-	ia64_log_rec_header_print(lh, prfunc);
-
-	for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) {
-		/* point to next section header */
-		slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos);
-
-#ifdef MCA_PRT_XTRA_DATA    // for test only @FVL
-		ia64_log_prt_section_header(slsh, prfunc);
-
-		if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) {
-			size_t  d_len = slsh->len - sizeof(sal_log_section_hdr_t);
-			char    *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid;
-
-			prfunc("Start of Platform Err Data Section:  Data buffer = %p, "
-			       "Data size = %ld\n", (void *)p_data, d_len);
-			ia64_log_hexdump(p_data, d_len, prfunc);
-			prfunc("End of Platform Err Data Section\n");
-		}
-#endif  // MCA_PRT_XTRA_DATA for test only @FVL
+	init_timer(&cmc_poll_timer);
+	cmc_poll_timer.function = ia64_mca_cmc_poll;
 
-		/*
-		 *  Now process CPE error record section
-		 */
-		if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) {
-			ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh,
-							 prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Memory Device Error Info Section\n");
-			ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform SEL Device Error Info Section\n");
-			ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform PCI Bus Error Info Section\n");
-			ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh,
-							prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform SMBIOS Device Error Info Section\n");
-			ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh,
-							   prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform PCI Component Error Info Section\n");
-			ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh,
-							 prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Specific Error Info Section\n");
-			ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *)
-							      slsh,
-							      prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Host Controller Error Info Section\n");
-			ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh,
-							  prfunc);
-		} else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) {
-			platform_err = 1;
-			prfunc("+Platform Bus Error Info Section\n");
-			ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh,
-							 prfunc);
-		} else {
-			IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
-			continue;
-		}
-	}
+	/* Reset to the correct state */
+	cmc_polling_enabled = 0;
 
-	IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n",
-		       n_sects, lh->len);
-	if (!n_sects) {
-		prfunc("No Platform Error Info Sections found\n");
-		return platform_err;
-	}
-	return platform_err;
-}
+	init_timer(&cpe_poll_timer);
+	cpe_poll_timer.function = ia64_mca_cpe_poll;
 
-/*
- * ia64_log_print
- *
- *  Displays the contents of the OS error log information
- *
- *  Inputs   :  info_type   (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE})
- *              prfunc      (fn ptr of log output function to use)
- * Outputs	:	platform error status
- */
-int
-ia64_log_print(int sal_info_type, prfunc_t prfunc)
-{
-	int platform_err = 0;
-
-	switch(sal_info_type) {
-	      case SAL_INFO_TYPE_MCA:
-		prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id());
-		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		break;
-	      case SAL_INFO_TYPE_INIT:
-		prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id());
-		ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		break;
-	      case SAL_INFO_TYPE_CMC:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n");
-		ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT CMC\n");
-		break;
-	      case SAL_INFO_TYPE_CPE:
-		prfunc("+BEGIN HARDWARE ERROR STATE AT CPE\n");
-		ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc);
-		prfunc("+END HARDWARE ERROR STATE AT CPE\n");
-		break;
-	      default:
-		prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)\n");
-		break;
+#ifdef CONFIG_ACPI
+	/* If platform doesn't support CPEI, get the timer going. */
+	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
+		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
+		ia64_mca_cpe_poll(0UL);
 	}
-	return platform_err;
-}
+#endif
 
-static int __init
-ia64_mca_disable_cpe_polling(char *str)
-{
-	cpe_poll_enabled = 0;
-	return 1;
+	return 0;
 }
 
-__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
+module_init(ia64_mca_late_init);
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/pci.c linux-2.4.26-pre3/arch/ia64/kernel/pci.c
--- linux-2.4.26-pre2/arch/ia64/kernel/pci.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/pci.c	2004-03-13 07:43:22.000000000 -0800
@@ -386,10 +386,6 @@
 void __init
 pcibios_init (void)
 {
-#ifdef CONFIG_IA64_MCA
-	ia64_mca_check_errors();    /* For post-failure MCA error logging */
-#endif
-
 	pcibios_config_init();
 
 	platform_pci_fixup(0);	/* phase 0 fixups (before buses scanned) */
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/ptrace.c linux-2.4.26-pre3/arch/ia64/kernel/ptrace.c
--- linux-2.4.26-pre2/arch/ia64/kernel/ptrace.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/ptrace.c	2004-03-13 07:43:22.000000000 -0800
@@ -63,12 +63,25 @@
 	({										\
 		unsigned long bit = ia64_unat_pos(&pt->r##first);			\
 		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
-		(ia64_rotl(unat, first) >> bit) & mask;					\
+		unsigned long dist;							\
+		if (bit < first)							\
+			dist = 64 + bit - first;					\
+		else									\
+			dist = bit - first;						\
+		ia64_rotr(unat, dist) & mask;						\
 	})
 	unsigned long val;
 
-	val  = GET_BITS( 1,  3, scratch_unat);
-	val |= GET_BITS(12, 15, scratch_unat);
+	/*
+	 * Registers that are stored consecutively in struct pt_regs can be handled in
+	 * parallel.  If the register order in struct_pt_regs changes, this code MUST be
+	 * updated.
+	 */
+	val  = GET_BITS( 1,  1, scratch_unat);
+	val |= GET_BITS( 2,  3, scratch_unat);
+	val |= GET_BITS(12, 13, scratch_unat);
+	val |= GET_BITS(14, 14, scratch_unat);
+	val |= GET_BITS(15, 15, scratch_unat);
 	val |= GET_BITS( 8, 11, scratch_unat);
 	val |= GET_BITS(16, 31, scratch_unat);
 	return val;
@@ -84,16 +97,29 @@
 unsigned long
 ia64_put_scratch_nat_bits (struct pt_regs *pt, unsigned long nat)
 {
+#	define PUT_BITS(first, last, nat)						\
+	({										\
+		unsigned long bit = ia64_unat_pos(&pt->r##first);			\
+		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
+		long dist;								\
+		if (bit < first)							\
+			dist = 64 + bit - first;					\
+		else									\
+			dist = bit - first;						\
+		ia64_rotl(nat & mask, dist);						\
+	})
 	unsigned long scratch_unat;
 
-#	define PUT_BITS(first, last, nat)					\
-	({									\
-		unsigned long bit = ia64_unat_pos(&pt->r##first);		\
-		unsigned long mask = ((1UL << (last - first + 1)) - 1) << bit;	\
-		(ia64_rotr(nat, first) << bit) & mask;				\
-	})
-	scratch_unat  = PUT_BITS( 1,  3, nat);
-	scratch_unat |= PUT_BITS(12, 15, nat);
+	/*
+	 * Registers that are stored consecutively in struct pt_regs can be handled in
+	 * parallel.  If the register order in struct_pt_regs changes, this code MUST be
+	 * updated.
+	 */
+	scratch_unat  = PUT_BITS( 1,  1, nat);
+	scratch_unat |= PUT_BITS( 2,  3, nat);
+	scratch_unat |= PUT_BITS(12, 13, nat);
+	scratch_unat |= PUT_BITS(14, 14, nat);
+	scratch_unat |= PUT_BITS(15, 15, nat);
 	scratch_unat |= PUT_BITS( 8, 11, nat);
 	scratch_unat |= PUT_BITS(16, 31, nat);
 
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/salinfo.c linux-2.4.26-pre3/arch/ia64/kernel/salinfo.c
--- linux-2.4.26-pre2/arch/ia64/kernel/salinfo.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/salinfo.c	2004-03-13 07:43:22.000000000 -0800
@@ -16,6 +16,13 @@
  *   Cache the record across multi-block reads from user space.
  *   Support > 64 cpus.
  *   Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
+ *
+ * Jan 28 2004	kaos@sgi.com
+ *   Periodically check for outstanding MCA or INIT records.
+ *
+ * Feb 21 2004	kaos@sgi.com
+ *   Copy record contents rather than relying on the mca.c buffers, to cope with
+ *   interrupts arriving in mca.c faster than salinfo.c can process them.
  */
 
 #include <linux/types.h>
@@ -23,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/timer.h>
 #include <linux/vmalloc.h>
 
 #include <asm/semaphore.h>
@@ -83,6 +91,7 @@
 	u64			size;
 	u64			id;
 	int			cpu;
+	int			kmalloced :1;	/* buffer was kmalloc'ed */
 };
 
 /* State transitions.  Actions are :-
@@ -178,6 +187,8 @@
 static void
 shift1_data_saved (struct salinfo_data *data, int shift)
 {
+	if (data->data_saved[shift].kmalloced)
+		kfree(data->data_saved[shift].buffer);
 	memcpy(data->data_saved+shift, data->data_saved+shift+1,
 	       (ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
 	memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
@@ -187,6 +198,8 @@
 /* This routine is invoked in interrupt context.  Note: mca.c enables
  * interrupts before calling this code for CMC/CPE.  MCA and INIT events are
  * not irq safe, do not call any routines that use spinlocks, they may deadlock.
+ * MCA and INIT records are recorded, a timer event will look for any
+ * outstanding events and wake up the user space code.
  *
  * The buffer passed from mca.c points to the output from ia64_log_get. This is
  * a persistent buffer but its contents can change between the interrupt and
@@ -194,12 +207,12 @@
  * changes.
  */
 void
-salinfo_log_wakeup(int type, u8 *buffer, u64 size)
+salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
 {
 	struct salinfo_data *data = salinfo_data + type;
 	struct salinfo_data_saved *data_saved;
 	unsigned long flags = 0;
-	int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+	int i;
 	int saved_size = ARRAY_SIZE(data->data_saved);
 
 	BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
@@ -221,7 +234,13 @@
 		data_saved->cpu = smp_processor_id();
 		data_saved->id = ((sal_log_record_header_t *)buffer)->id;
 		data_saved->size = size;
-		data_saved->buffer = buffer;
+		if (irqsafe && (data_saved->buffer = kmalloc(size, GFP_ATOMIC))) {
+			memcpy(data_saved->buffer, buffer, size);
+			data_saved->kmalloced = 1;
+		} else {
+			data_saved->buffer = buffer;
+			data_saved->kmalloced = 0;
+		}
 	}
 	if (irqsafe)
 		spin_unlock_irqrestore(&data_saved_lock, flags);
@@ -232,6 +251,35 @@
 	}
 }
 
+/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */
+#define SALINFO_TIMER_DELAY (5*60*HZ)
+static struct timer_list salinfo_timer;
+
+static void
+salinfo_timeout_check(struct salinfo_data *data)
+{
+	int i;
+	if (!data->open)
+		return;
+	for (i = 0; i < NR_CPUS; ++i) {
+		if (test_bit(i, &data->cpu_event)) {
+			/* double up() is not a problem, user space will see no
+			 * records for the additional "events".
+			 */
+			up(&data->sem);
+		}
+	}
+}
+
+static void 
+salinfo_timeout (unsigned long arg)
+{
+	salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
+	salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
+	salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
+	add_timer(&salinfo_timer);
+}
+
 static int
 salinfo_event_open(struct inode *inode, struct file *file)
 {
@@ -571,6 +619,11 @@
 
 	*sdir++ = salinfo_dir;
 
+	init_timer(&salinfo_timer);
+	salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
+	salinfo_timer.function = &salinfo_timeout;
+	add_timer(&salinfo_timer);
+
 	return 0;
 }
 
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/signal.c linux-2.4.26-pre3/arch/ia64/kernel/signal.c
--- linux-2.4.26-pre2/arch/ia64/kernel/signal.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/signal.c	2004-03-13 07:43:22.000000000 -0800
@@ -349,12 +349,6 @@
 		__copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16);
 	}
 
-	/*
-	 * Note: sw->ar_unat is UNDEFINED unless the process is being
-	 * PTRACED.  However, this is OK because the NaT bits of the
-	 * preserved registers (r4-r7) are never being looked at by
-	 * the signal handler (registers r4-r7 are used instead).
-	 */
 	nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat);
 
 	err  = __put_user(flags, &sc->sc_flags);
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/smpboot.c linux-2.4.26-pre3/arch/ia64/kernel/smpboot.c
--- linux-2.4.26-pre2/arch/ia64/kernel/smpboot.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/smpboot.c	2004-03-13 07:43:22.000000000 -0800
@@ -349,7 +349,6 @@
 
 #ifdef CONFIG_IA64_MCA
 	ia64_mca_cmc_vector_setup();	/* Setup vector on AP & enable */
-	ia64_mca_check_errors();	/* For post-failure MCA error logging */
 #endif
 
 #ifdef CONFIG_PERFMON
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/unwind.c linux-2.4.26-pre3/arch/ia64/kernel/unwind.c
--- linux-2.4.26-pre2/arch/ia64/kernel/unwind.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ia64/kernel/unwind.c	2004-03-13 07:43:22.000000000 -0800
@@ -1,9 +1,8 @@
 /*
- * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
- * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
- *
  * Copyright (C) 1999-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
+ * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
  */
 /*
  * This file implements call frame unwind support for the Linux
@@ -27,7 +26,9 @@
  *	o if both the unw.lock spinlock and a script's read-write lock must be
  *	  acquired, then the read-write lock must be acquired first.
  */
+#include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -58,15 +59,9 @@
 
 #ifdef UNW_DEBUG
   static unsigned int unw_debug_level = UNW_DEBUG;
-#  ifdef CONFIG_KDB
-#    include <linux/kdb.h>
-#    define UNW_DEBUG_ON(n)	(unw_debug_level >= n && !KDB_IS_RUNNING())
-#    define UNW_DPRINT(n, ...)	if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
-#  else	/* !CONFIG_KDB */
-#    define UNW_DEBUG_ON(n)	unw_debug_level >= n
-     /* Do not code a printk level, not all debug lines end in newline */
-#    define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
-#  endif /* CONFIG_KDB */
+#  define UNW_DEBUG_ON(n)	unw_debug_level >= n
+   /* Do not code a printk level, not all debug lines end in newline */
+#  define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
 #  define inline
 #else /* !UNW_DEBUG */
 #  define UNW_DEBUG_ON(n)  0
@@ -79,7 +74,7 @@
 # define STAT(x...)
 #endif
 
-#define alloc_reg_state()	kmalloc(sizeof(struct unw_state_record), GFP_ATOMIC)
+#define alloc_reg_state()	kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
 #define free_reg_state(usr)	kfree(usr)
 #define alloc_labeled_state()	kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
 #define free_labeled_state(usr)	kfree(usr)
@@ -87,8 +82,6 @@
 typedef unsigned long unw_word;
 typedef unsigned char unw_hash_index_t;
 
-#define struct_offset(str,fld)	((char *)&((str *)NULL)->fld - (char *) 0)
-
 static struct {
 	spinlock_t lock;			/* spinlock for unwind data */
 
@@ -107,6 +100,8 @@
 	/* index into unw_frame_info for preserved register i */
 	unsigned short preg_index[UNW_NUM_REGS];
 
+	short pt_regs_offsets[32];
+
 	/* unwind table for the kernel: */
 	struct unw_table kernel_table;
 
@@ -156,47 +151,78 @@
 		UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
 	},
 	.preg_index = {
-		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
-		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
-		struct_offset(struct unw_frame_info, bsp_loc)/8,
-		struct_offset(struct unw_frame_info, bspstore_loc)/8,
-		struct_offset(struct unw_frame_info, pfs_loc)/8,
-		struct_offset(struct unw_frame_info, rnat_loc)/8,
-		struct_offset(struct unw_frame_info, psp)/8,
-		struct_offset(struct unw_frame_info, rp_loc)/8,
-		struct_offset(struct unw_frame_info, r4)/8,
-		struct_offset(struct unw_frame_info, r5)/8,
-		struct_offset(struct unw_frame_info, r6)/8,
-		struct_offset(struct unw_frame_info, r7)/8,
-		struct_offset(struct unw_frame_info, unat_loc)/8,
-		struct_offset(struct unw_frame_info, pr_loc)/8,
-		struct_offset(struct unw_frame_info, lc_loc)/8,
-		struct_offset(struct unw_frame_info, fpsr_loc)/8,
-		struct_offset(struct unw_frame_info, b1_loc)/8,
-		struct_offset(struct unw_frame_info, b2_loc)/8,
-		struct_offset(struct unw_frame_info, b3_loc)/8,
-		struct_offset(struct unw_frame_info, b4_loc)/8,
-		struct_offset(struct unw_frame_info, b5_loc)/8,
-		struct_offset(struct unw_frame_info, f2_loc)/8,
-		struct_offset(struct unw_frame_info, f3_loc)/8,
-		struct_offset(struct unw_frame_info, f4_loc)/8,
-		struct_offset(struct unw_frame_info, f5_loc)/8,
-		struct_offset(struct unw_frame_info, fr_loc[16 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[17 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[18 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[19 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[20 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[21 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[22 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[23 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[24 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[25 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[26 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[27 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[28 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[29 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8,
-		struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
+		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
+		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
+		offsetof(struct unw_frame_info, bsp_loc)/8,
+		offsetof(struct unw_frame_info, bspstore_loc)/8,
+		offsetof(struct unw_frame_info, pfs_loc)/8,
+		offsetof(struct unw_frame_info, rnat_loc)/8,
+		offsetof(struct unw_frame_info, psp)/8,
+		offsetof(struct unw_frame_info, rp_loc)/8,
+		offsetof(struct unw_frame_info, r4)/8,
+		offsetof(struct unw_frame_info, r5)/8,
+		offsetof(struct unw_frame_info, r6)/8,
+		offsetof(struct unw_frame_info, r7)/8,
+		offsetof(struct unw_frame_info, unat_loc)/8,
+		offsetof(struct unw_frame_info, pr_loc)/8,
+		offsetof(struct unw_frame_info, lc_loc)/8,
+		offsetof(struct unw_frame_info, fpsr_loc)/8,
+		offsetof(struct unw_frame_info, b1_loc)/8,
+		offsetof(struct unw_frame_info, b2_loc)/8,
+		offsetof(struct unw_frame_info, b3_loc)/8,
+		offsetof(struct unw_frame_info, b4_loc)/8,
+		offsetof(struct unw_frame_info, b5_loc)/8,
+		offsetof(struct unw_frame_info, f2_loc)/8,
+		offsetof(struct unw_frame_info, f3_loc)/8,
+		offsetof(struct unw_frame_info, f4_loc)/8,
+		offsetof(struct unw_frame_info, f5_loc)/8,
+		offsetof(struct unw_frame_info, fr_loc[16 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[17 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[18 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[19 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[20 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[21 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[22 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[23 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[24 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[25 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[26 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[27 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[28 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[29 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[30 - 16])/8,
+		offsetof(struct unw_frame_info, fr_loc[31 - 16])/8,
+	},
+	.pt_regs_offsets = {
+		[0] = -1,
+		offsetof(struct pt_regs,  r1),
+		offsetof(struct pt_regs,  r2),
+		offsetof(struct pt_regs,  r3),
+		[4] = -1, [5] = -1, [6] = -1, [7] = -1,
+		offsetof(struct pt_regs,  r8),
+		offsetof(struct pt_regs,  r9),
+		offsetof(struct pt_regs, r10),
+		offsetof(struct pt_regs, r11),
+		offsetof(struct pt_regs, r12),
+		offsetof(struct pt_regs, r13),
+		offsetof(struct pt_regs, r14),
+		offsetof(struct pt_regs, r15),
+		offsetof(struct pt_regs, r16),
+		offsetof(struct pt_regs, r17),
+		offsetof(struct pt_regs, r18),
+		offsetof(struct pt_regs, r19),
+		offsetof(struct pt_regs, r20),
+		offsetof(struct pt_regs, r21),
+		offsetof(struct pt_regs, r22),
+		offsetof(struct pt_regs, r23),
+		offsetof(struct pt_regs, r24),
+		offsetof(struct pt_regs, r25),
+		offsetof(struct pt_regs, r26),
+		offsetof(struct pt_regs, r27),
+		offsetof(struct pt_regs, r28),
+		offsetof(struct pt_regs, r29),
+		offsetof(struct pt_regs, r30),
+		offsetof(struct pt_regs, r31),
 	},
 	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
 #ifdef UNW_DEBUG
@@ -212,11 +238,6 @@
 #endif
 };
 
-#define OFF_CASE(reg, reg_num) 					\
-	case reg:						\
-		off=struct_offset(struct pt_regs, reg_num);	\
-		break;
-
 /* Unwind accessors.  */
 
 /*
@@ -225,43 +246,16 @@
 static inline unsigned long
 pt_regs_off (unsigned long reg)
 {
-	unsigned long off =0;
+	short off = -1;
 
-	switch (reg)
-	{
-		OFF_CASE(1,r1)
-		OFF_CASE(2,r2)
-		OFF_CASE(3,r3)
-		OFF_CASE(8,r8)
-		OFF_CASE(9,r9)
-		OFF_CASE(10,r10)
-		OFF_CASE(11,r11)
-		OFF_CASE(12,r12)
-		OFF_CASE(13,r13)
-		OFF_CASE(14,r14)
-		OFF_CASE(15,r15)
-		OFF_CASE(16,r16)
-		OFF_CASE(17,r17)
-		OFF_CASE(18,r18)
-		OFF_CASE(19,r19)
-		OFF_CASE(20,r20)
-		OFF_CASE(21,r21)
-		OFF_CASE(22,r22)
-		OFF_CASE(23,r23)
-		OFF_CASE(24,r24)
-		OFF_CASE(25,r25)
-		OFF_CASE(26,r26)
-		OFF_CASE(27,r27)
-		OFF_CASE(28,r28)
-		OFF_CASE(29,r29)
-		OFF_CASE(30,r30)
-		OFF_CASE(31,r31)
-		default:
-			UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
-			break;
-	}
+	if (reg < ARRAY_SIZE(unw.pt_regs_offsets))
+		off = unw.pt_regs_offsets[reg];
 
-	return off;
+	if (off < 0) {
+		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
+		off = 0;
+	}
+	return (unsigned long) off;
 }
 
 static inline struct pt_regs *
@@ -398,6 +392,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_gr);
 
 int
 unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
@@ -429,6 +424,7 @@
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_br);
 
 int
 unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
@@ -473,6 +469,7 @@
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_fr);
 
 int
 unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
@@ -565,6 +562,7 @@
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_ar);
 
 int
 unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
@@ -581,6 +579,7 @@
 		*val = *addr;
 	return 0;
 }
+EXPORT_SYMBOL(unw_access_pr);
 
 
 /* Routines to manipulate the state stack.  */
@@ -826,7 +825,7 @@
 static inline void
 desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
 {
-	if (abi == 0 && context == 'i') {
+	if (abi == 3 && context == 'i') {
 		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
 		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);
 	}
@@ -1177,9 +1176,10 @@
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#	define magic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
+#	define hashmagic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
 
-	return (ip >> 4)*magic >> (64 - UNW_LOG_HASH_SIZE);
+	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
+#undef hashmagic
 }
 
 static inline long
@@ -1258,13 +1258,18 @@
 	spin_unlock(&unw.lock);
 
 	/*
-	 * XXX We'll deadlock here if we interrupt a thread that is
-	 * holding a read lock on script->lock.  A try_write_lock()
-	 * might be mighty handy here...  Alternatively, we could
-	 * disable interrupts whenever we hold a read-lock, but that
-	 * seems silly.
+	 * We'd deadlock here if we interrupted a thread that is holding a read lock on
+	 * script->lock.  Thus, if the write_trylock() fails, we simply bail out.  The
+	 * alternative would be to disable interrupts whenever we hold a read-lock, but
+	 * that seems silly.
 	 */
-	write_lock(&script->lock);
+	/* Kludge: 2.4 has down_write_trylock on semaphores but not write_trylock on
+	 * spinlocks, even though they are both in 2.6 and are identical.  Pretend
+	 * that script lock is a rw_semaphore so we can use the only 2.4 code that
+	 * avoids a deadlock.  KAO.
+	 */
+	if (!down_write_trylock((struct rw_semaphore *)(&script->lock)))
+		return NULL;
 
 	spin_lock(&unw.lock);
 	{
@@ -1415,13 +1420,13 @@
 
 	      case UNW_WHERE_FR:
 		if (rval <= 5)
-			val = unw.preg_index[UNW_REG_F2  + (rval -  1)];
+			val = unw.preg_index[UNW_REG_F2  + (rval -  2)];
 		else if (rval >= 16 && rval <= 31)
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
 			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval <= 11)
-				val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
+				val = offsetof(struct pt_regs, f6) + 16*(rval - 6);
 			else
 				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
 					   __FUNCTION__, rval);
@@ -1434,11 +1439,11 @@
 		else {
 			opc = UNW_INSN_MOVE_SCRATCH;
 			if (rval == 0)
-				val = struct_offset(struct pt_regs, b0);
+				val = offsetof(struct pt_regs, b0);
 			else if (rval == 6)
-				val = struct_offset(struct pt_regs, b6);
+				val = offsetof(struct pt_regs, b6);
 			else
-				val = struct_offset(struct pt_regs, b7);
+				val = offsetof(struct pt_regs, b7);
 		}
 		break;
 
@@ -1638,7 +1643,7 @@
 	    && sr.curr.reg[UNW_REG_PSP].val != 0) {
 		/* new psp is sp plus frame size */
 		insn.opc = UNW_INSN_ADD;
-		insn.dst = struct_offset(struct unw_frame_info, psp)/8;
+		insn.dst = offsetof(struct unw_frame_info, psp)/8;
 		insn.val = sr.curr.reg[UNW_REG_PSP].val;	/* frame size */
 		script_emit(script, insn);
 	}
@@ -1772,13 +1777,13 @@
   lazy_init:
 	off = unw.sw_off[val];
 	s[val] = (unsigned long) state->sw + off;
-	if (off >= struct_offset(struct switch_stack, r4) && off <= struct_offset(struct switch_stack, r7))
+	if (off >= offsetof(struct switch_stack, r4) && off <= offsetof(struct switch_stack, r7))
 		/*
 		 * We're initializing a general register: init NaT info, too.  Note that
 		 * the offset is a multiple of 8 which gives us the 3 bits needed for
 		 * the type field.
 		 */
-		s[val+1] = (struct_offset(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
+		s[val+1] = (offsetof(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
 	goto redo;
 }
 
@@ -1868,7 +1873,7 @@
 		if ((pr & (1UL << pNonSys)) != 0)
 			num_regs = *info->cfm_loc & 0x7f;		/* size of frame */
 		info->pfs_loc =
-			(unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
+			(unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
 		UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
 	} else
 		num_regs = (*info->cfm_loc >> 7) & 0x7f;	/* size of locals */
@@ -1906,6 +1911,7 @@
 	STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 	return retval;
 }
+EXPORT_SYMBOL(unw_unwind);
 
 int
 unw_unwind_to_user (struct unw_frame_info *info)
@@ -1930,6 +1936,7 @@
 	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
 	return -1;
 }
+EXPORT_SYMBOL(unw_unwind_to_user);
 
 static void
 init_frame_info (struct unw_frame_info *info, struct task_struct *t,
@@ -1987,6 +1994,8 @@
 
 	init_frame_info(info, t, sw, pt->r12);
 	info->cfm_loc = &pt->cr_ifs;
+	info->unat_loc = &pt->ar_unat;
+	info->pfs_loc = &pt->ar_pfs;
 	sof = *info->cfm_loc & 0x7f;
 	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof);
 	info->ip = pt->cr_iip + ia64_psr(pt)->ri;
@@ -2025,6 +2034,7 @@
 	UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
 	unw_init_frame_info(info, t, sw);
 }
+EXPORT_SYMBOL(unw_init_from_blocked_task);
 
 static void
 init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
diff -urN linux-2.4.26-pre2/arch/ia64/kernel/unwind_i.h linux-2.4.26-pre3/arch/ia64/kernel/unwind_i.h
--- linux-2.4.26-pre2/arch/ia64/kernel/unwind_i.h	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.26-pre3/arch/ia64/kernel/unwind_i.h	2004-03-13 07:43:22.000000000 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2002 Hewlett-Packard Co
+ * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Kernel unwind support.
@@ -45,12 +45,6 @@
 	/* personality routine and language-specific data follow behind descriptors */
 };
 
-struct unw_table_entry {
-	u64 start_offset;
-	u64 end_offset;
-	u64 info_offset;
-};
-
 struct unw_table {
 	struct unw_table *next;		/* must be first member! */
 	const char *name;
@@ -148,7 +142,7 @@
 };
 
 /*
- * Preserved general static registers (r2-r5) give rise to two script
+ * Preserved general static registers (r4-r7) give rise to two script
  * instructions; everything else yields at most one instruction; at
  * the end of the script, the psp gets popped, accounting for one more
  * instruction.
diff -urN linux-2.4.26-pre2/arch/ia64/sn/kernel/mca.c linux-2.4.26-pre3/arch/ia64/sn/kernel/mca.c
--- linux-2.4.26-pre2/arch/ia64/sn/kernel/mca.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.26-pre3/arch/ia64/sn/kernel/mca.c	2004-03-13 07:43:22.000000000 -0800
@@ -36,6 +36,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <asm/machvec.h>
 #include <asm/mca.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_sal.h>
@@ -53,6 +55,41 @@
 struct timer_list sn_cpei_timer;
 void sn_init_cpei_timer(void);
 
+/* Printing oemdata from mca uses data that is not passed through SAL, it is
+ * global.  Only one user at a time.
+ */
+static DECLARE_MUTEX(sn_oemdata_mutex);
+static u8 **sn_oemdata;
+static u64 *sn_oemdata_size, sn_oemdata_bufsize;
+
+/* Called as the "printk" routine via sn_platform_plat_specific_err_print,
+ * ia64_sn_plat_specific_err_print through SAL to print_hook.  It only handles
+ * a print of '"%s", buf'.  buf is appended to sn_oemdata, resizing as required.
+ */
+static int
+sn_oemdata_print(const char *fmt, ...)
+{
+	va_list args;
+	char *buf;
+	int len;
+	va_start(args, fmt);
+	buf = va_arg(args, char *);
+	va_end(args);
+	len = strlen(buf);
+	while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
+		u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
+		if (!newbuf) {
+			printk(KERN_ERR "%s: unable to extend sn_oemdata\n", __FUNCTION__);
+			return 0;
+		}
+		memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
+		vfree(*sn_oemdata);
+		*sn_oemdata = newbuf;
+	}
+	memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
+	*sn_oemdata_size += len;
+	return len;
+}
 
 /*
  * print_hook
@@ -86,25 +123,11 @@
 	newline = (p != 0);
 
 	va_end(args);
-	printk("%s", buf);
+	sn_oemdata_print("%s", buf);	/* args must be '"%s", buf' */
 	return len;
 }
 
 
-
-/*
- * ia64_sn2_platform_plat_specific_err_print
- *
- * Called by the MCA handler to log platform-specific errors.
- */
-void
-ia64_sn2_platform_plat_specific_err_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc)
-{
-	ia64_sn_plat_specific_err_print(print_hook, p_data - sect_len);
-}
-
-
-
 static void
 sn_cpei_handler(int irq, void *devid, struct pt_regs *regs)
 {
@@ -132,3 +155,42 @@
         sn_cpei_timer.function = sn_cpei_timer_handler;
         add_timer(&sn_cpei_timer);
 }
+
+static int
+sn_platform_plat_specific_err_print(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header;
+	if (!psei->valid.oem_data)
+		return 0;
+	down(&sn_oemdata_mutex);
+	sn_oemdata = oemdata;
+	sn_oemdata_size = oemdata_size;
+	ia64_sn_plat_specific_err_print(print_hook, (char *)psei);
+	up(&sn_oemdata_mutex);
+	return 0;
+}
+
+/* Callback when userspace salinfo wants to decode oem data via the platform
+ * kernel and/or prom.
+ */
+int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	efi_guid_t guid = *(efi_guid_t *)sect_header;
+	*oemdata_size = 0;
+	sn_oemdata_bufsize = 0;
+	vfree(*oemdata);
+	*oemdata = NULL;
+	if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0)
+		return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size);
+	return 0;
+}
+
+static int __init sn_salinfo_init(void)
+{
+	salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
+        return 0;
+}
+
+module_init(sn_salinfo_init)
+
+
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/Config.in linux-2.4.26-pre3/arch/ppc/8260_io/Config.in
--- linux-2.4.26-pre2/arch/ppc/8260_io/Config.in	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/8260_io/Config.in	1969-12-31 16:00:00.000000000 -0800
@@ -1,26 +0,0 @@
-#
-# MPC8260 Communication options
-#
-mainmenu_option next_comment
-comment 'MPC8260 CPM Options'
-bool 'Enable SCC Console' CONFIG_SCC_CONSOLE
-if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
-  bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
-  if [ "$CONFIG_SCC_ENET" = "y" ]; then
-  bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
-    if [ "$CONFIG_SCC1_ENET" != "y" ]; then
-      bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
-    fi
-  fi
-#
-#  CONFIG_FEC_ENET is only used to get netdevices to call our init
-#    function.  Any combination of FCC1,2,3 are supported.
-#
-  bool 'FCC Ethernet' CONFIG_FEC_ENET
-  if [ "$CONFIG_FEC_ENET" = "y" ]; then
-    bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
-    bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
-    bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
-  fi
-fi
-endmenu
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/Makefile linux-2.4.26-pre3/arch/ppc/8260_io/Makefile
--- linux-2.4.26-pre2/arch/ppc/8260_io/Makefile	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/8260_io/Makefile	1969-12-31 16:00:00.000000000 -0800
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux MPC8xx ppc-specific parts of comm processor
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-O_TARGET		:= 8260_io.o
-
-obj-y			:= commproc.o uart.o
-
-obj-$(CONFIG_FEC_ENET)	+= fcc_enet.o
-obj-$(CONFIG_SCC_ENET)	+= enet.o
-
-include $(TOPDIR)/Rules.make
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/commproc.c linux-2.4.26-pre3/arch/ppc/8260_io/commproc.c
--- linux-2.4.26-pre2/arch/ppc/8260_io/commproc.c	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/8260_io/commproc.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,179 +0,0 @@
-/*
- * General Purpose functions for the global management of the
- * 8260 Communication Processor Module.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
- *	2.3.99 Updates
- *
- * In addition to the individual control of the communication
- * channels, there are a few functions that globally affect the
- * communication processor.
- *
- * Buffer descriptors must be allocated from the dual ported memory
- * space.  The allocator for that is here.  When the communication
- * process is reset, we reclaim the memory available.  There is
- * currently no deallocator for this memory.
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/bootmem.h>
-#include <asm/irq.h>
-#include <asm/mpc8260.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/immap_8260.h>
-#include <asm/cpm_8260.h>
-
-static	uint	dp_alloc_base;	/* Starting offset in DP ram */
-static	uint	dp_alloc_top;	/* Max offset + 1 */
-static	uint	host_buffer;	/* One page of host buffer */
-static	uint	host_end;	/* end + 1 */
-cpm8260_t	*cpmp;		/* Pointer to comm processor space */
-
-/* We allocate this here because it is used almost exclusively for
- * the communication processor devices.
- */
-immap_t		*immr;
-
-void
-m8260_cpm_reset(void)
-{
-	volatile immap_t	 *imp;
-	volatile cpm8260_t	*commproc;
-	uint			vpgaddr;
-
-	immr = imp = (volatile immap_t *)IMAP_ADDR;
-	commproc = &imp->im_cpm;
-
-	/* Reclaim the DP memory for our use.
-	*/
-	dp_alloc_base = CPM_DATAONLY_BASE;
-	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
-
-	/* Set the host page for allocation.
-	*/
-	host_buffer =
-		(uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
-	host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
-
-	vpgaddr = host_buffer;
-
-	/* Tell everyone where the comm processor resides.
-	*/
-	cpmp = (cpm8260_t *)commproc;
-}
-
-/* Allocate some memory from the dual ported ram.
- * To help protocols with object alignment restrictions, we do that
- * if they ask.
- */
-uint
-m8260_cpm_dpalloc(uint size, uint align)
-{
-	uint	retloc;
-	uint	align_mask, off;
-	uint	savebase;
-
-	align_mask = align - 1;
-	savebase = dp_alloc_base;
-
-	if ((off = (dp_alloc_base & align_mask)) != 0)
-		dp_alloc_base += (align - off);
-
-	if ((dp_alloc_base + size) >= dp_alloc_top) {
-		dp_alloc_base = savebase;
-		return(CPM_DP_NOSPACE);
-	}
-
-	retloc = dp_alloc_base;
-	dp_alloc_base += size;
-
-	return(retloc);
-}
-
-/* We also own one page of host buffer space for the allocation of
- * UART "fifos" and the like.
- */
-uint
-m8260_cpm_hostalloc(uint size, uint align)
-{
-	uint	retloc;
-	uint	align_mask, off;
-	uint	savebase;
-
-	align_mask = align - 1;
-	savebase = host_buffer;
-
-	if ((off = (host_buffer & align_mask)) != 0)
-		host_buffer += (align - off);
-
-	if ((host_buffer + size) >= host_end) {
-		host_buffer = savebase;
-		return(0);
-	}
-
-	retloc = host_buffer;
-	host_buffer += size;
-
-	return(retloc);
-}
-
-/* Set a baud rate generator.  This needs lots of work.  There are
- * eight BRGs, which can be connected to the CPM channels or output
- * as clocks.  The BRGs are in two different block of internal
- * memory mapped space.
- * The baud rate clock is the system clock divided by something.
- * It was set up long ago during the initial boot phase and is
- * is given to us.
- * Baud rate clocks are zero-based in the driver code (as that maps
- * to port numbers).  Documentation uses 1-based numbering.
- */
-#define BRG_INT_CLK	(((bd_t *)__res)->bi_brgfreq)
-#define BRG_UART_CLK	(BRG_INT_CLK/16)
-
-/* This function is used by UARTS, or anything else that uses a 16x
- * oversampled clock.
- */
-void
-m8260_cpm_setbrg(uint brg, uint rate)
-{
-	volatile uint	*bp;
-
-	/* This is good enough to get SMCs running.....
-	*/
-	if (brg < 4) {
-		bp = (uint *)&immr->im_brgc1;
-	}
-	else {
-		bp = (uint *)&immr->im_brgc5;
-		brg -= 4;
-	}
-	bp += brg;
-	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
-}
-
-/* This function is used to set high speed synchronous baud rate
- * clocks.
- */
-void
-m8260_cpm_fastbrg(uint brg, uint rate, int div16)
-{
-	volatile uint	*bp;
-
-	if (brg < 4) {
-		bp = (uint *)&immr->im_brgc1;
-	}
-	else {
-		bp = (uint *)&immr->im_brgc5;
-		brg -= 4;
-	}
-	bp += brg;
-	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
-	if (div16)
-		*bp |= CPM_BRG_DIV16;
-}
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/enet.c linux-2.4.26-pre3/arch/ppc/8260_io/enet.c
--- linux-2.4.26-pre2/arch/ppc/8260_io/enet.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/8260_io/enet.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,857 +0,0 @@
-/*
- * Ethernet driver for Motorola MPC8260.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
- *	2.3.99 Updates
- *
- * I copied this from the 8xx CPM Ethernet driver, so follow the
- * credits back through that.
- *
- * This version of the driver is somewhat selectable for the different
- * processor/board combinations.  It works for the boards I know about
- * now, and should be easily modified to include others.  Some of the
- * configuration information is contained in <asm/commproc.h> and the
- * remainder is here.
- *
- * Buffer descriptors are kept in the CPM dual port RAM, and the frame
- * buffers are in the host memory.
- *
- * Right now, I am very watseful with the buffers.  I allocate memory
- * pages and then divide them into 2K frame buffers.  This way I know I
- * have buffers large enough to hold one frame within one buffer descriptor.
- * Once I get this working, I will use 64 or 128 byte CPM buffers, which
- * will be much more memory efficient and will easily handle lots of
- * small packets.
- *
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-
-#include <asm/immap_8260.h>
-#include <asm/pgtable.h>
-#include <asm/mpc8260.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/cpm_8260.h>
-#include <asm/irq.h>
-
-/*
- *				Theory of Operation
- *
- * The MPC8260 CPM performs the Ethernet processing on an SCC.  It can use
- * an aribtrary number of buffers on byte boundaries, but must have at
- * least two receive buffers to prevent constant overrun conditions.
- *
- * The buffer descriptors are allocated from the CPM dual port memory
- * with the data buffers allocated from host memory, just like all other
- * serial communication protocols.  The host memory buffers are allocated
- * from the free page pool, and then divided into smaller receive and
- * transmit buffers.  The size of the buffers should be a power of two,
- * since that nicely divides the page.  This creates a ring buffer
- * structure similar to the LANCE and other controllers.
- *
- * Like the LANCE driver:
- * The driver runs as two independent, single-threaded flows of control.  One
- * is the send-packet routine, which enforces single-threaded use by the
- * cep->tx_busy flag.  The other thread is the interrupt handler, which is
- * single threaded by the hardware and other software.
- */
-
-/* The transmitter timeout
- */
-#define TX_TIMEOUT	(2*HZ)
-
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it is best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define CPM_ENET_RX_PAGES	4
-#define CPM_ENET_RX_FRSIZE	2048
-#define CPM_ENET_RX_FRPPG	(PAGE_SIZE / CPM_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
-#define TX_RING_SIZE		8	/* Must be power of two */
-#define TX_RING_MOD_MASK	7	/*   for this to work */
-
-/* The CPM stores dest/src/type, data, and checksum for receive packets.
- */
-#define PKT_MAXBUF_SIZE		1518
-#define PKT_MINBUF_SIZE		64
-#define PKT_MAXBLR_SIZE		1520
-
-/* The CPM buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct scc_enet_private {
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
-	ushort	skb_cur;
-	ushort	skb_dirty;
-
-	/* CPM dual port RAM relative addresses.
-	*/
-	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
-	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
-	scc_t	*sccp;
-	struct	net_device_stats stats;
-	uint	tx_free;
-	spinlock_t lock;
-};
-
-static int scc_enet_open(struct net_device *dev);
-static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int scc_enet_rx(struct net_device *dev);
-static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
-static int scc_enet_close(struct net_device *dev);
-static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-/* These will be configurable for the SCC choice.
-*/
-#define CPM_ENET_BLOCK	CPM_CR_SCC1_SBLOCK
-#define CPM_ENET_PAGE	CPM_CR_SCC1_PAGE
-#define PROFF_ENET	PROFF_SCC1
-#define SCC_ENET	0
-#define SIU_INT_ENET	SIU_INT_SCC1
-
-/* These are both board and SCC dependent....
-*/
-#define PD_ENET_RXD	((uint)0x00000001)
-#define PD_ENET_TXD	((uint)0x00000002)
-#define PD_ENET_TENA	((uint)0x00000004)
-#define PC_ENET_RENA	((uint)0x00020000)
-#define PC_ENET_CLSN	((uint)0x00000004)
-#define PC_ENET_TXCLK	((uint)0x00000800)
-#define PC_ENET_RXCLK	((uint)0x00000400)
-#define CMX_CLK_ROUTE	((uint)0x25000000)
-#define CMX_CLK_MASK	((uint)0xff000000)
-
-/* Specific to a board.
-*/
-#define PC_EST8260_ENET_LOOPBACK	((uint)0x80000000)
-#define PC_EST8260_ENET_SQE		((uint)0x40000000)
-#define PC_EST8260_ENET_NOTFD		((uint)0x20000000)
-
-static int
-scc_enet_open(struct net_device *dev)
-{
-
-	/* I should reset the ring buffers here, but I don't yet know
-	 * a simple way to do that.
-	 */
-	netif_start_queue(dev);
-	return 0;					/* Always succeed */
-}
-
-static int
-scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-	volatile cbd_t	*bdp;
-
-
-	/* Fill in a Tx ring entry */
-	bdp = cep->cur_tx;
-
-#ifndef final_version
-	if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since the tx queue should be stopped.
-		 */
-		printk("%s: tx queue full!.\n", dev->name);
-		return 1;
-	}
-#endif
-
-	/* Clear all of the status flags.
-	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
-
-	/* If the frame is short, tell CPM to pad it.
-	*/
-	if (skb->len <= ETH_ZLEN)
-		bdp->cbd_sc |= BD_ENET_TX_PAD;
-	else
-		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
-
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_datlen = skb->len;
-	bdp->cbd_bufaddr = __pa(skb->data);
-
-	/* Save skb pointer.
-	*/
-	cep->tx_skbuff[cep->skb_cur] = skb;
-
-	cep->stats.tx_bytes += skb->len;
-	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
-
-	spin_lock_irq(&cep->lock);
-
-	/* Send it on its way.  Tell CPM its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
-	 */
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-
-	dev->trans_start = jiffies;
-
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = cep->tx_bd_base;
-	else
-		bdp++;
-
-	if (!--cep->tx_free)
-		netif_stop_queue(dev);
-
-	cep->cur_tx = (cbd_t *)bdp;
-
-	spin_unlock_irq(&cep->lock);
-
-	return 0;
-}
-
-static void
-scc_enet_timeout(struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-
-	printk("%s: transmit timed out.\n", dev->name);
-	cep->stats.tx_errors++;
-#ifndef final_version
-	{
-		int	i;
-		cbd_t	*bdp;
-		printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
-		       cep->cur_tx, cep->tx_free,
-		       cep->cur_rx);
-		bdp = cep->tx_bd_base;
-		printk(" Tx @base %p :\n", bdp);
-		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-		bdp = cep->rx_bd_base;
-		printk(" Rx @base %p :\n", bdp);
-		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-	}
-#endif
-	if (cep->tx_free)
-		netif_wake_queue(dev);
-}
-
-/* The interrupt handler.
- * This is called from the CPM handler, not the MPC core interrupt.
- */
-static void
-scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	struct	net_device *dev = dev_id;
-	volatile struct	scc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	ushort	int_events;
-	int	must_restart;
-
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* Get the interrupt events that caused us to be here.
-	*/
-	int_events = cep->sccp->scc_scce;
-	cep->sccp->scc_scce = int_events;
-	must_restart = 0;
-
-	/* Handle receive event in its own function.
-	*/
-	if (int_events & SCCE_ENET_RXF)
-		scc_enet_rx(dev_id);
-
-	/* Check for a transmit error.  The manual is a little unclear
-	 * about this, so the debug code until I get it figured out.  It
-	 * appears that if TXE is set, then TXB is not set.  However,
-	 * if carrier sense is lost during frame transmission, the TXE
-	 * bit is set, "and continues the buffer transmission normally."
-	 * I don't know if "normally" implies TXB is set when the buffer
-	 * descriptor is closed.....trial and error :-).
-	 */
-
-	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
-	*/
-	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
-	    spin_lock(&cep->lock);
-	    bdp = cep->dirty_tx;
-	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
-		if (cep->tx_free == TX_RING_SIZE)
-		    break;
-
-		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
-			cep->stats.tx_heartbeat_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
-			cep->stats.tx_window_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
-			cep->stats.tx_aborted_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
-			cep->stats.tx_fifo_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
-			cep->stats.tx_carrier_errors++;
-
-
-		/* No heartbeat or Lost carrier are not really bad errors.
-		 * The others require a restart transmit command.
-		 */
-		if (bdp->cbd_sc &
-		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-			must_restart = 1;
-			cep->stats.tx_errors++;
-		}
-
-		cep->stats.tx_packets++;
-
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
-			cep->stats.collisions++;
-
-		/* Free the sk buffer associated with this last transmit.
-		*/
-		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
-		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
-
-		/* Update pointer to next buffer descriptor to be transmitted.
-		*/
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-			bdp = cep->tx_bd_base;
-		else
-			bdp++;
-
-		/* I don't know if we can be held off from processing these
-		 * interrupts for more than one frame time.  I really hope
-		 * not.  In such a case, we would now want to check the
-		 * currently available BD (cur_tx) and determine if any
-		 * buffers between the dirty_tx and cur_tx have also been
-		 * sent.  We would want to process anything in between that
-		 * does not have BD_ENET_TX_READY set.
-		 */
-
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
-		 */
-		if (!cep->tx_free++) {
-			if (netif_queue_stopped(dev)) {
-				netif_wake_queue(dev);
-			}
-		}
-
-		cep->dirty_tx = (cbd_t *)bdp;
-	    }
-
-	    if (must_restart) {
-		volatile cpm8260_t *cp;
-
-		/* Some transmit errors cause the transmitter to shut
-		 * down.  We now issue a restart transmit.  Since the
-		 * errors close the BD and update the pointers, the restart
-		 * _should_ pick up without having to reset any of our
-		 * pointers either.
-		 */
-
-		cp = cpmp;
-		cp->cp_cpcr =
-		    mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
-		    			CPM_CR_RESTART_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	    }
-	    spin_unlock(&cep->lock);
-	}
-
-	/* Check for receive busy, i.e. packets coming but no place to
-	 * put them.
-	 */
-	if (int_events & SCCE_ENET_BSY)
-		cep->stats.rx_dropped++;
-
-	return;
-}
-
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-scc_enet_rx(struct net_device *dev)
-{
-	struct	scc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	struct	sk_buff *skb;
-	ushort	pkt_len;
-
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = cep->cur_rx;
-
-for (;;) {
-	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
-		break;
-
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame, both
-	 * the first and last indicators should be set.
-	 */
-	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
-		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
-			printk("CPM ENET: rcv is not first+last\n");
-#endif
-
-	/* Frame too long or too short.
-	*/
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-		cep->stats.rx_length_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
-		cep->stats.rx_frame_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
-		cep->stats.rx_crc_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-		cep->stats.rx_crc_errors++;
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		cep->stats.rx_frame_errors++;
-	}
-	else {
-
-		/* Process the incoming frame.
-		*/
-		cep->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		cep->stats.rx_bytes += pkt_len;
-
-		/* This does 16 byte alignment, much more than we need.
-		 * The packet length includes FCS, but we don't want to
-		 * include that when passing upstream as it messes up
-		 * bridging applications.
-		 */
-		skb = dev_alloc_skb(pkt_len-4);
-
-		if (skb == NULL) {
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-			cep->stats.rx_dropped++;
-		}
-		else {
-			skb->dev = dev;
-			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
-				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-		}
-	}
-
-	/* Clear the status flags for this buffer.
-	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
-
-	/* Mark the buffer empty.
-	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
-
-	/* Update BD pointer to next entry.
-	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
-		bdp = cep->rx_bd_base;
-	else
-		bdp++;
-
-   }
-	cep->cur_rx = (cbd_t *)bdp;
-
-	return 0;
-}
-
-static int
-scc_enet_close(struct net_device *dev)
-{
-	/* Don't know what to do yet.
-	*/
-	netif_stop_queue(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
-{
-	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
-
-	return &cep->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct	scc_enet_private *cep;
-	struct	dev_mc_list *dmi;
-	u_char	*mcptr, *tdptr;
-	volatile scc_enet_t *ep;
-	int	i, j;
-	cep = (struct scc_enet_private *)dev->priv;
-
-	/* Get pointer to SCC area in parameter RAM.
-	*/
-	ep = (scc_enet_t *)dev->base_addr;
-
-	if (dev->flags&IFF_PROMISC) {
-
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		cep->sccp->scc_pmsr |= SCC_PSMR_PRO;
-	} else {
-
-		cep->sccp->scc_pmsr &= ~SCC_PSMR_PRO;
-
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->sen_gaddr1 = 0xffff;
-			ep->sen_gaddr2 = 0xffff;
-			ep->sen_gaddr3 = 0xffff;
-			ep->sen_gaddr4 = 0xffff;
-		}
-		else {
-			/* Clear filter and add the addresses in the list.
-			*/
-			ep->sen_gaddr1 = 0;
-			ep->sen_gaddr2 = 0;
-			ep->sen_gaddr3 = 0;
-			ep->sen_gaddr4 = 0;
-
-			dmi = dev->mc_list;
-
-			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
-
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
-
-				/* The address in dmi_addr is LSB first,
-				 * and taddr is MSB first.  We have to
-				 * copy bytes MSB first from dmi_addr.
-				 */
-				mcptr = (u_char *)dmi->dmi_addr + 5;
-				tdptr = (u_char *)&ep->sen_taddrh;
-				for (j=0; j<6; j++)
-					*tdptr++ = *mcptr--;
-
-				/* Ask CPM to run CRC and set bit in
-				 * filter mask.
-				 */
-				cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
-						CPM_ENET_BLOCK, 0,
-						CPM_CR_SET_GADDR) | CPM_CR_FLG;
-				/* this delay is necessary here -- Cort */
-				udelay(10);
-				while (cpmp->cp_cpcr & CPM_CR_FLG);
-			}
-		}
-	}
-}
-
-/* Initialize the CPM Ethernet on SCC.
- */
-int __init scc_enet_init(void)
-{
-	struct net_device *dev;
-	struct scc_enet_private *cep;
-	int i, j;
-	unsigned char	*eap;
-	unsigned long	mem_addr;
-	bd_t		*bd;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	scc_t		*sccp;
-	volatile	scc_enet_t	*ep;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	cp = cpmp;	/* Get pointer to Communication Processor */
-
-	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
-	io = &immap->im_ioport;
-
-	bd = (bd_t *)__res;
-
-	/* Allocate some private information.
-	*/
-	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
-	if (cep == NULL)
-		return -ENOMEM;
-
-	__clear_user(cep,sizeof(*cep));
-	spin_lock_init(&cep->lock);
-
-	/* Create an Ethernet device instance.
-	*/
-	dev = init_etherdev(0, 0);
-
-	/* Get pointer to SCC area in parameter RAM.
-	*/
-	ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
-
-	/* And another to the SCC register area.
-	*/
-	sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
-	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
-
-	/* Disable receive and transmit in case someone left it running.
-	*/
-	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
-	/* Configure port C and D pins for SCC Ethernet.  This
-	 * won't work for all SCC possibilities....it will be
-	 * board/port specific.
-	 */
-	io->iop_pparc |=
-		(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_pdirc &=
-		~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_psorc &=
-		~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
-	io->iop_psorc |= PC_ENET_CLSN;
-
-	io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
-	io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
-	io->iop_pdird &= ~PD_ENET_RXD;
-	io->iop_psord |= PD_ENET_TXD;
-	io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all SCC bits to zero, then set the ones we want.
-	 */
-	immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
-	immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
-
-	/* Allocate space for the buffer descriptors in the DP ram.
-	 * These are relative offsets in the DP ram address space.
-	 * Initialize base addresses for the buffer descriptors.
-	 */
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->sen_genscc.scc_rbase = i;
-	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->sen_genscc.scc_tbase = i;
-	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
-	cep->tx_free = TX_RING_SIZE;
-	cep->cur_rx = cep->rx_bd_base;
-
-	ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-	ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-	/* Set maximum bytes per receive buffer.
-	 * This appears to be an Ethernet frame size, not the buffer
-	 * fragment size.  It must be a multiple of four.
-	 */
-	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
-
-	/* Set CRC preset and mask.
-	*/
-	ep->sen_cpres = 0xffffffff;
-	ep->sen_cmask = 0xdebb20e3;
-
-	ep->sen_crcec = 0;	/* CRC Error counter */
-	ep->sen_alec = 0;	/* alignment error counter */
-	ep->sen_disfc = 0;	/* discard frame counter */
-
-	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
-	ep->sen_retlim = 15;	/* Retry limit threshold */
-
-	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
-	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
-
-	ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
-	ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */
-
-	/* Clear hash tables.
-	*/
-	ep->sen_gaddr1 = 0;
-	ep->sen_gaddr2 = 0;
-	ep->sen_gaddr3 = 0;
-	ep->sen_gaddr4 = 0;
-	ep->sen_iaddr1 = 0;
-	ep->sen_iaddr2 = 0;
-	ep->sen_iaddr3 = 0;
-	ep->sen_iaddr4 = 0;
-
-	/* Set Ethernet station address.
-	 *
-	 * This is supplied in the board information structure, so we
-	 * copy that into the controller.
-	 */
-	eap = (unsigned char *)&(ep->sen_paddrh);
-	for (i=5; i>=0; i--)
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-
-	ep->sen_pper = 0;	/* 'cause the book says so */
-	ep->sen_taddrl = 0;	/* temp address (LSB) */
-	ep->sen_taddrm = 0;
-	ep->sen_taddrh = 0;	/* temp address (MSB) */
-
-	/* Now allocate the host memory pages and initialize the
-	 * buffer descriptors.
-	 */
-	bdp = cep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	bdp = cep->rx_bd_base;
-	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += CPM_ENET_RX_FRSIZE;
-			bdp++;
-		}
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* Let's re-initialize the channel now.  We have to do it later
-	 * than the manual describes because we have just now finished
-	 * the BD initialization.
-	 */
-	cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	cep->skb_cur = cep->skb_dirty = 0;
-
-	sccp->scc_scce = 0xffff;	/* Clear any pending events */
-
-	/* Enable interrupts for transmit error, complete frame
-	 * received, and any transmit buffer we have also set the
-	 * interrupt flag.
-	 */
-	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
-
-	/* Install our interrupt handler.
-	*/
-	request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
-
-	/* Set GSMR_H to enable all normal operating modes.
-	 * Set GSMR_L to enable Ethernet to MC68160.
-	 */
-	sccp->scc_gsmrh = 0;
-	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
-
-	/* Set sync/delimiters.
-	*/
-	sccp->scc_dsr = 0xd555;
-
-	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
-	 * start frame search 22 bit times after RENA.
-	 */
-	sccp->scc_pmsr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
-
-	/* It is now OK to enable the Ethernet transmitter.
-	 * Unfortunately, there are board implementation differences here.
-	 */
-	io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
-				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
-	io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
-	io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
-
-	dev->base_addr = (unsigned long)ep;
-	dev->priv = cep;
-
-	/* The CPM Ethernet specific entries in the device structure. */
-	dev->open = scc_enet_open;
-	dev->hard_start_xmit = scc_enet_start_xmit;
-	dev->tx_timeout = scc_enet_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->stop = scc_enet_close;
-	dev->get_stats = scc_enet_get_stats;
-	dev->set_multicast_list = set_multicast_list;
-
-	/* And last, enable the transmit and receive processing.
-	*/
-	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-
-	printk("%s: SCC ENET Version 0.1, ", dev->name);
-	for (i=0; i<5; i++)
-		printk("%02x:", dev->dev_addr[i]);
-	printk("%02x\n", dev->dev_addr[5]);
-
-	return 0;
-}
-
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/fcc_enet.c linux-2.4.26-pre3/arch/ppc/8260_io/fcc_enet.c
--- linux-2.4.26-pre2/arch/ppc/8260_io/fcc_enet.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/8260_io/fcc_enet.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,1613 +0,0 @@
-/*
- * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
- * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
- *
- * This version of the driver is a combination of the 8xx fec and
- * 8260 SCC Ethernet drivers.  People seem to be choosing common I/O
- * configurations, so this driver will work on the EST8260 boards and
- * others yet to be announced.
- *
- * Right now, I am very watseful with the buffers.  I allocate memory
- * pages and then divide them into 2K frame buffers.  This way I know I
- * have buffers large enough to hold one frame within one buffer descriptor.
- * Once I get this working, I will use 64 or 128 byte CPM buffers, which
- * will be much more memory efficient and will easily handle lots of
- * small packets.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-
-#include <asm/immap_8260.h>
-#include <asm/pgtable.h>
-#include <asm/mpc8260.h>
-#include <asm/irq.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/cpm_8260.h>
-
-/* The transmitter timeout
- */
-#define TX_TIMEOUT	(2*HZ)
-
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it is best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define FCC_ENET_RX_PAGES	16
-#define FCC_ENET_RX_FRSIZE	2048
-#define FCC_ENET_RX_FRPPG	(PAGE_SIZE / FCC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE		(FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
-#define TX_RING_SIZE		16	/* Must be power of two */
-#define TX_RING_MOD_MASK	15	/*   for this to work */
-
-/* The FCC stores dest/src/type, data, and checksum for receive packets.
- */
-#define PKT_MAXBUF_SIZE		1518
-#define PKT_MINBUF_SIZE		64
-
-/* Maximum input DMA size.  Must be a should(?) be a multiple of 4.
-*/
-#define PKT_MAXDMA_SIZE		1520
-
-/* Maximum input buffer size.  Must be a multiple of 32.
-*/
-#define PKT_MAXBLR_SIZE		1536
-
-static int fcc_enet_open(struct net_device *dev);
-static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int fcc_enet_rx(struct net_device *dev);
-static void fcc_enet_mii(struct net_device *dev);
-static	void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
-static int fcc_enet_close(struct net_device *dev);
-static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void restart_fcc(struct net_device *dev);
-
-/* These will be configurable for the FCC choice.
- * Multiple ports can be configured.  There is little choice among the
- * I/O pins to the PHY, except the clocks.  We will need some board
- * dependent clock selection.
- * Why in the hell did I put these inside #ifdef's?  I dunno, maybe to
- * help show what pins are used for each device.
- */
-
-/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PA1_COL		((uint)0x00000001)
-#define PA1_CRS		((uint)0x00000002)
-#define PA1_TXER	((uint)0x00000004)
-#define PA1_TXEN	((uint)0x00000008)
-#define PA1_RXDV	((uint)0x00000010)
-#define PA1_RXER	((uint)0x00000020)
-#define PA1_TXDAT	((uint)0x00003c00)
-#define PA1_RXDAT	((uint)0x0003c000)
-#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
-				PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
-
-/* CLK12 is receive, CLK11 is transmit.  These are board specific.
-*/
-#define PC_F1RXCLK	((uint)0x00000800)
-#define PC_F1TXCLK	((uint)0x00000400)
-#define CMX1_CLK_ROUTE	((uint)0x3e000000)
-#define CMX1_CLK_MASK	((uint)0xff000000)
-
-/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB2_TXER	((uint)0x00000001)
-#define PB2_RXDV	((uint)0x00000002)
-#define PB2_TXEN	((uint)0x00000004)
-#define PB2_RXER	((uint)0x00000008)
-#define PB2_COL		((uint)0x00000010)
-#define PB2_CRS		((uint)0x00000020)
-#define PB2_TXDAT	((uint)0x000003c0)
-#define PB2_RXDAT	((uint)0x00003c00)
-#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
-				PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1	(PB2_TXEN)
-#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
-
-/* CLK13 is receive, CLK14 is transmit.  These are board dependent.
-*/
-#define PC_F2RXCLK	((uint)0x00001000)
-#define PC_F2TXCLK	((uint)0x00002000)
-#define CMX2_CLK_ROUTE	((uint)0x00250000)
-#define CMX2_CLK_MASK	((uint)0x00ff0000)
-
-/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB3_RXDV	((uint)0x00004000)
-#define PB3_RXER	((uint)0x00008000)
-#define PB3_TXER	((uint)0x00010000)
-#define PB3_TXEN	((uint)0x00020000)
-#define PB3_COL		((uint)0x00040000)
-#define PB3_CRS		((uint)0x00080000)
-#define PB3_TXDAT	((uint)0x0f000000)
-#define PB3_RXDAT	((uint)0x00f00000)
-#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
-				PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1	(0)
-#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
-
-/* CLK15 is receive, CLK16 is transmit.  These are board dependent.
-*/
-#define PC_F3RXCLK	((uint)0x00004000)
-#define PC_F3TXCLK	((uint)0x00008000)
-#define CMX3_CLK_ROUTE	((uint)0x00003700)
-#define CMX3_CLK_MASK	((uint)0x0000ff00)
-
-/* MII status/control serial interface.
-*/
-#define PC_MDIO		((uint)0x00400000)
-#define PC_MDCK		((uint)0x00200000)
-
-/* A table of information for supporting FCCs.  This does two things.
- * First, we know how many FCCs we have and they are always externally
- * numbered from zero.  Second, it holds control register and I/O
- * information that could be different among board designs.
- */
-typedef struct fcc_info {
-	uint	fc_fccnum;
-	uint	fc_cpmblock;
-	uint	fc_cpmpage;
-	uint	fc_proff;
-	uint	fc_interrupt;
-	uint	fc_trxclocks;
-	uint	fc_clockroute;
-	uint	fc_clockmask;
-	uint	fc_mdio;
-	uint	fc_mdck;
-} fcc_info_t;
-
-static fcc_info_t fcc_ports[] = {
-#ifdef CONFIG_FCC1_ENET
-	{ 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
-		(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-#ifdef CONFIG_FCC2_ENET
-	{ 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
-		(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-#ifdef CONFIG_FCC3_ENET
-	{ 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
-		(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
-		PC_MDIO, PC_MDCK },
-#endif
-};
-
-/* The FCC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct fcc_enet_private {
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
-	ushort	skb_cur;
-	ushort	skb_dirty;
-
-	/* CPM dual port RAM relative addresses.
-	*/
-	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
-	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
-	volatile fcc_t	*fccp;
-	volatile fcc_enet_t	*ep;
-	struct	net_device_stats stats;
-	uint	tx_full;
-	spinlock_t lock;
-	uint	phy_address;
-	uint	phy_type;
-	uint	phy_duplex;
-	fcc_info_t	*fip;
-};
-
-static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
-	volatile immap_t *immap);
-static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
-static void init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
-	volatile immap_t *immap);
-static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
-	volatile immap_t *immap);
-
-/* MII processing.  We keep this as simple as possible.  Requests are
- * placed on the list (if there is room).  When the request is finished
- * by the MII, an optional function may be called.
- */
-typedef struct mii_list {
-	uint	mii_regval;
-	void	(*mii_func)(uint val, struct net_device *dev);
-	struct	mii_list *mii_next;
-} mii_list_t;
-
-#define		NMII	20
-mii_list_t	mii_cmds[NMII];
-mii_list_t	*mii_free;
-mii_list_t	*mii_head;
-mii_list_t	*mii_tail;
-
-static	int	phyaddr;
-static	uint	phytype;
-
-static int	mii_queue(int request, void (*func)(uint, struct net_device *));
-static void	mii_startup_cmds(void);
-static uint	mii_send_receive(fcc_info_t *fip, uint cmd);
-
-/* Make MII read/write commands for the FCC.
-*/
-
-#define mk_mii_phyaddr(ADDR)	(0x60020000 | ((ADDR) << 23) | (2 << 18))
-
-#define mk_mii_read(REG)	(0x60020000 | ((phyaddr << 23) | \
-						(REG & 0x1f) << 18))
-
-#define mk_mii_write(REG, VAL)	(0x50020000 | ((phyaddr << 23) | \
-						(REG & 0x1f) << 18) | \
-						(VAL & 0xffff))
-
-
-static int
-fcc_enet_open(struct net_device *dev)
-{
-	netif_start_queue(dev);
-	return 0;					/* Always succeed */
-}
-
-static int
-fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-	volatile cbd_t	*bdp;
-
-
-	/* Fill in a Tx ring entry */
-	bdp = cep->cur_tx;
-
-#ifndef final_version
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since cep->tx_full should be set.
-		 */
-		printk("%s: tx queue full!.\n", dev->name);
-		return 1;
-	}
-#endif
-
-	/* Clear all of the status flags.
-	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
-
-	/* If the frame is short, tell CPM to pad it.
-	*/
-	if (skb->len <= ETH_ZLEN)
-		bdp->cbd_sc |= BD_ENET_TX_PAD;
-	else
-		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
-
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_datlen = skb->len;
-	bdp->cbd_bufaddr = __pa(skb->data);
-
-	/* Save skb pointer.
-	*/
-	cep->tx_skbuff[cep->skb_cur] = skb;
-
-	cep->stats.tx_bytes += skb->len;
-	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
-
-	spin_lock_irq(&cep->lock);
-
-	/* Send it on its way.  Tell CPM its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
-	 */
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-
-#if 0
-	/* Errata says don't do this.
-	*/
-	cep->fccp->fcc_ftodr = 0x8000;
-#endif
-	dev->trans_start = jiffies;
-
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = cep->tx_bd_base;
-	else
-		bdp++;
-
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		netif_stop_queue(dev);
-		cep->tx_full = 1;
-	}
-
-	cep->cur_tx = (cbd_t *)bdp;
-
-	spin_unlock_irq(&cep->lock);
-
-	return 0;
-}
-
-
-static void
-fcc_enet_timeout(struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-
-	printk("%s: transmit timed out.\n", dev->name);
-	cep->stats.tx_errors++;
-#ifndef final_version
-	{
-		int	i;
-		cbd_t	*bdp;
-		printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
-		       cep->cur_tx, cep->tx_full ? " (full)" : "",
-		       cep->cur_rx);
-		bdp = cep->tx_bd_base;
-		printk(" Tx @base %p :\n", bdp);
-		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-		bdp = cep->rx_bd_base;
-		printk(" Rx @base %p :\n", bdp);
-		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
-			printk("%04x %04x %08x\n",
-			       bdp->cbd_sc,
-			       bdp->cbd_datlen,
-			       bdp->cbd_bufaddr);
-	}
-#endif
-	if (!cep->tx_full)
-		netif_wake_queue(dev);
-}
-
-/* The interrupt handler.
- */
-static void
-fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	struct	net_device *dev = dev_id;
-	volatile struct	fcc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	ushort	int_events;
-	int	must_restart;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-	/* Get the interrupt events that caused us to be here.
-	*/
-	int_events = cep->fccp->fcc_fcce;
-	cep->fccp->fcc_fcce = int_events;
-	must_restart = 0;
-
-	/* Handle receive event in its own function.
-	*/
-	if (int_events & FCC_ENET_RXF)
-		fcc_enet_rx(dev_id);
-
-	/* Check for a transmit error.  The manual is a little unclear
-	 * about this, so the debug code until I get it figured out.  It
-	 * appears that if TXE is set, then TXB is not set.  However,
-	 * if carrier sense is lost during frame transmission, the TXE
-	 * bit is set, "and continues the buffer transmission normally."
-	 * I don't know if "normally" implies TXB is set when the buffer
-	 * descriptor is closed.....trial and error :-).
-	 */
-
-	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
-	*/
-	if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
-	    spin_lock(&cep->lock);
-	    bdp = cep->dirty_tx;
-	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
-		if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
-		    break;
-
-		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
-			cep->stats.tx_heartbeat_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
-			cep->stats.tx_window_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
-			cep->stats.tx_aborted_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
-			cep->stats.tx_fifo_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
-			cep->stats.tx_carrier_errors++;
-
-
-		/* No heartbeat or Lost carrier are not really bad errors.
-		 * The others require a restart transmit command.
-		 */
-		if (bdp->cbd_sc &
-		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-			must_restart = 1;
-			cep->stats.tx_errors++;
-		}
-
-		cep->stats.tx_packets++;
-
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
-			cep->stats.collisions++;
-
-		/* Free the sk buffer associated with this last transmit.
-		*/
-		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
-		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
-
-		/* Update pointer to next buffer descriptor to be transmitted.
-		*/
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-			bdp = cep->tx_bd_base;
-		else
-			bdp++;
-
-		/* I don't know if we can be held off from processing these
-		 * interrupts for more than one frame time.  I really hope
-		 * not.  In such a case, we would now want to check the
-		 * currently available BD (cur_tx) and determine if any
-		 * buffers between the dirty_tx and cur_tx have also been
-		 * sent.  We would want to process anything in between that
-		 * does not have BD_ENET_TX_READY set.
-		 */
-
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
-		 */
-		if (cep->tx_full) {
-			cep->tx_full = 0;
-			if (netif_queue_stopped(dev)) {
-				netif_wake_queue(dev);
-			}
-		}
-
-		cep->dirty_tx = (cbd_t *)bdp;
-	    }
-
-	    if (must_restart) {
-		volatile cpm8260_t *cp;
-
-		/* Some transmit errors cause the transmitter to shut
-		 * down.  We now issue a restart transmit.  Since the
-		 * errors close the BD and update the pointers, the restart
-		 * _should_ pick up without having to reset any of our
-		 * pointers either.
-		 */
-
-		cp = cpmp;
-		cp->cp_cpcr =
-		    mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
-		    		0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	    }
-	    spin_unlock(&cep->lock);
-	}
-
-	/* Check for receive busy, i.e. packets coming but no place to
-	 * put them.
-	 */
-	if (int_events & FCC_ENET_BSY) {
-		cep->stats.rx_dropped++;
-	}
-	return;
-}
-
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-fcc_enet_rx(struct net_device *dev)
-{
-	struct	fcc_enet_private *cep;
-	volatile cbd_t	*bdp;
-	struct	sk_buff *skb;
-	ushort	pkt_len;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = cep->cur_rx;
-
-for (;;) {
-	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
-		break;
-
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame, both
-	 * the first and last indicators should be set.
-	 */
-	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
-		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
-			printk("CPM ENET: rcv is not first+last\n");
-#endif
-
-	/* Frame too long or too short.
-	*/
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-		cep->stats.rx_length_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
-		cep->stats.rx_frame_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
-		cep->stats.rx_crc_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-		cep->stats.rx_crc_errors++;
-
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
-	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		cep->stats.rx_frame_errors++;
-	}
-	else {
-
-		/* Process the incoming frame.
-		*/
-		cep->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		cep->stats.rx_bytes += pkt_len;
-
-		/* This does 16 byte alignment, much more than we need.
-		 * The packet length includes FCS, but we don't want to
-		 * include that when passing upstream as it messes up
-		 * bridging applications.
-		 */
-		skb = dev_alloc_skb(pkt_len-4);
-
-		if (skb == NULL) {
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-			cep->stats.rx_dropped++;
-		}
-		else {
-			skb->dev = dev;
-			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
-				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-		}
-	}
-
-	/* Clear the status flags for this buffer.
-	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
-
-	/* Mark the buffer empty.
-	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
-
-	/* Update BD pointer to next entry.
-	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
-		bdp = cep->rx_bd_base;
-	else
-		bdp++;
-
-   }
-	cep->cur_rx = (cbd_t *)bdp;
-
-	return 0;
-}
-
-static int
-fcc_enet_close(struct net_device *dev)
-{
-	/* Don't know what to do yet.
-	*/
-	netif_stop_queue(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
-{
-	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
-
-	return &cep->stats;
-}
-
-/* The MII is simulated from the 8xx FEC implementation.  The FCC
- * is not responsible for the MII control/status interface.
- */
-static void
-fcc_enet_mii(struct net_device *dev)
-{
-	struct	fcc_enet_private *fep;
-	mii_list_t	*mip;
-	uint		mii_reg;
-
-	fep = (struct fcc_enet_private *)dev->priv;
-#if 0
-	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
-	mii_reg = ep->fec_mii_data;
-#endif
-
-	if ((mip = mii_head) == NULL) {
-		printk("MII and no head!\n");
-		return;
-	}
-
-	if (mip->mii_func != NULL)
-		(*(mip->mii_func))(mii_reg, dev);
-
-	mii_head = mip->mii_next;
-	mip->mii_next = mii_free;
-	mii_free = mip;
-
-#if 0
-	if ((mip = mii_head) != NULL)
-		ep->fec_mii_data = mip->mii_regval;
-#endif
-}
-
-static int
-mii_queue(int regval, void (*func)(uint, struct net_device *))
-{
-	unsigned long	flags;
-	mii_list_t	*mip;
-	int		retval;
-
-	retval = 0;
-
-	save_flags(flags);
-	cli();
-
-	if ((mip = mii_free) != NULL) {
-		mii_free = mip->mii_next;
-		mip->mii_regval = regval;
-		mip->mii_func = func;
-		mip->mii_next = NULL;
-		if (mii_head) {
-			mii_tail->mii_next = mip;
-			mii_tail = mip;
-		}
-		else {
-			mii_head = mii_tail = mip;
-#if 0
-			(&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
-#endif
-		}
-	}
-	else {
-		retval = 1;
-	}
-
-	restore_flags(flags);
-
-	return(retval);
-}
-
-static	volatile uint	full_duplex;
-
-static void
-mii_status(uint mii_reg, struct net_device *dev)
-{
-	volatile uint	prev_duplex;
-
-	if (((mii_reg >> 18) & 0x1f) == 1) {
-		/* status register.
-		*/
-		printk("fec: ");
-		if (mii_reg & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_reg & 0x0010)
-			printk(",remote fault");
-		if (mii_reg & 0x0020)
-			printk(",auto complete");
-		printk("\n");
-	}
-	if (((mii_reg >> 18) & 0x1f) == 0x14) {
-		/* Extended chip status register.
-		*/
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_reg & 0x0800)
-			printk("100 Mbps");
-		else
-			printk("10 Mbps");
-
-		if (mii_reg & 0x1000) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-#if 0
-		if (prev_duplex != full_duplex)
-			restart_fec(dev);
-#endif
-	}
-	if (((mii_reg >> 18) & 0x1f) == 31) {
-		/* QS6612 PHY Control/Status.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-
-		mii_reg = (mii_reg >> 2) & 7;
-
-		if (mii_reg & 1)
-			printk("10 Mbps");
-		else
-			printk("100 Mbps");
-
-		if (mii_reg > 4) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-
-#if 0
-		if (prev_duplex != full_duplex)
-			restart_fec(dev);
-#endif
-	}
-}
-
-static	uint	phyno;
-
-static void
-mii_discover_phy3(uint mii_reg, struct net_device *dev)
-{
-	phytype <<= 16;
-	phytype |= (mii_reg & 0xffff);
-	printk("fec: Phy @ 0x%x, type 0x%08x\n", phyno, phytype);
-	mii_startup_cmds();
-}
-
-static void
-mii_discover_phy(uint mii_reg, struct net_device *dev)
-{
-	if (phyno < 32) {
-		if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
-			phyaddr = phyno;
-			mii_queue(mk_mii_read(3), mii_discover_phy3);
-		}
-		else {
-			phyno++;
-			mii_queue(mk_mii_phyaddr(phyno), mii_discover_phy);
-		}
-	}
-	else {
-		printk("FEC: No PHY device found.\n");
-	}
-}
-
-static void
-mii_discover_phy_poll(fcc_info_t *fip)
-{
-	uint	rv;
-	int	i;
-
-	for (i=0; i<32; i++) {
-		rv = mii_send_receive(fip, mk_mii_phyaddr(i));
-		if ((phytype = (rv & 0xffff)) != 0xffff) {
-			phyaddr = i;
-			rv = mii_send_receive(fip, mk_mii_read(3));
-			phytype <<= 16;
-			phytype |= (rv & 0xffff);
-			printk("fec: Phy @ 0x%x, type 0x%08x\n", phyaddr, phytype);
-		}
-	}
-}
-
-static	void
-mii_startup_cmds(void)
-{
-
-#if 1
-	/* Level One PHY.
-	*/
-
-	/* Read status registers to clear any pending interrupt.
-	*/
-	mii_queue(mk_mii_read(1), mii_status);
-	mii_queue(mk_mii_read(18), mii_status);
-
-	/* Read extended chip status register.
-	*/
-	mii_queue(mk_mii_read(0x14), mii_status);
-
-	/* Set default operation of 100-TX....for some reason
-	 * some of these bits are set on power up, which is wrong.
-	 */
-	mii_queue(mk_mii_write(0x13, 0), NULL);
-
-	/* Enable Link status change interrupts.
-	*/
-	mii_queue(mk_mii_write(0x11, 0x0002), NULL);
-
-	/* Don't advertize Full duplex.
-	mii_queue(mk_mii_write(0x04, 0x0021), NULL);
-	*/
-#endif
-
-}
-
-/* This supports the mii_link interrupt below.
- * We should get called three times.  Once for register 1, once for
- * register 18, and once for register 20.
- */
-static	uint mii_saved_reg1;
-
-static void
-mii_relink(uint mii_reg, struct net_device *dev)
-{
-	volatile uint	prev_duplex;
-	unsigned long	flags;
-
-	if (((mii_reg >> 18) & 0x1f) == 1) {
-		/* Just save the status register and get out.
-		*/
-		mii_saved_reg1 = mii_reg;
-		return;
-	}
-	if (((mii_reg >> 18) & 0x1f) == 18) {
-		/* Not much here, but has to be read to clear the
-		 * interrupt condition.
-		 */
-		if ((mii_reg & 0x8000) == 0)
-			printk("fec: re-link and no IRQ?\n");
-		if ((mii_reg & 0x4000) == 0)
-			printk("fec: no PHY power?\n");
-	}
-	if (((mii_reg >> 18) & 0x1f) == 20) {
-		/* Extended chip status register.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_saved_reg1 & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_saved_reg1 & 0x0010)
-			printk(", remote fault");
-		if (mii_saved_reg1 & 0x0020)
-			printk(", auto complete");
-
-		if (mii_reg & 0x0800)
-			printk(", 100 Mbps");
-		else
-			printk(", 10 Mbps");
-
-		if (mii_reg & 0x1000) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-		if (prev_duplex != full_duplex) {
-			save_flags(flags);
-			cli();
-#if 0
-			restart_fec(dev);
-#endif
-			restore_flags(flags);
-		}
-	}
-	if (((mii_reg >> 18) & 0x1f) == 31) {
-		/* QS6612 PHY Control/Status.
-		 * OK, now we have it all, so figure out what is going on.
-		 */
-		prev_duplex = full_duplex;
-		printk("fec: ");
-		if (mii_saved_reg1 & 0x0004)
-			printk("link up");
-		else
-			printk("link down");
-
-		if (mii_saved_reg1 & 0x0010)
-			printk(", remote fault");
-		if (mii_saved_reg1 & 0x0020)
-			printk(", auto complete");
-
-		mii_reg = (mii_reg >> 2) & 7;
-
-		if (mii_reg & 1)
-			printk(", 10 Mbps");
-		else
-			printk(", 100 Mbps");
-
-		if (mii_reg > 4) {
-			printk(", Full-Duplex\n");
-			full_duplex = 1;
-		}
-		else {
-			printk(", Half-Duplex\n");
-			full_duplex = 0;
-		}
-
-#if 0
-		if (prev_duplex != full_duplex) {
-			save_flags(flags);
-			cli();
-			restart_fec(dev);
-			restore_flags(flags);
-		}
-#endif
-	}
-}
-
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
-static void
-set_multicast_list(struct net_device *dev)
-{
-	struct	fcc_enet_private *cep;
-	struct	dev_mc_list *dmi;
-	u_char	*mcptr, *tdptr;
-	volatile fcc_enet_t *ep;
-	int	i, j;
-
-	cep = (struct fcc_enet_private *)dev->priv;
-
-return;
-	/* Get pointer to FCC area in parameter RAM.
-	*/
-	ep = (fcc_enet_t *)dev->base_addr;
-
-	if (dev->flags&IFF_PROMISC) {
-
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
-	} else {
-
-		cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
-
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->fen_gaddrh = 0xffffffff;
-			ep->fen_gaddrl = 0xffffffff;
-		}
-		else {
-			/* Clear filter and add the addresses in the list.
-			*/
-			ep->fen_gaddrh = 0;
-			ep->fen_gaddrl = 0;
-
-			dmi = dev->mc_list;
-
-			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
-
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
-
-				/* The address in dmi_addr is LSB first,
-				 * and taddr is MSB first.  We have to
-				 * copy bytes MSB first from dmi_addr.
-				 */
-				mcptr = (u_char *)dmi->dmi_addr + 5;
-				tdptr = (u_char *)&ep->fen_taddrh;
-				for (j=0; j<6; j++)
-					*tdptr++ = *mcptr--;
-
-				/* Ask CPM to run CRC and set bit in
-				 * filter mask.
-				 */
-				cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
-						cep->fip->fc_cpmblock, 0x0c,
-						CPM_CR_SET_GADDR) | CPM_CR_FLG;
-				udelay(10);
-				while (cpmp->cp_cpcr & CPM_CR_FLG);
-			}
-		}
-	}
-}
-
-/* Initialize the CPM Ethernet on FCC.
- */
-int __init fec_enet_init(void)
-{
-	struct net_device *dev;
-	struct fcc_enet_private *cep;
-	fcc_info_t	*fip;
-	int	i, np;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
-	io = &immap->im_ioport;
-
-	np = sizeof(fcc_ports) / sizeof(fcc_info_t);
-	fip = fcc_ports;
-
-	while (np-- > 0) {
-
-		/* Allocate some private information.
-		*/
-		cep = (struct fcc_enet_private *)
-					kmalloc(sizeof(*cep), GFP_KERNEL);
-		if (cep == NULL)
-			return -ENOMEM;
-
-		__clear_user(cep,sizeof(*cep));
-		spin_lock_init(&cep->lock);
-		cep->fip = fip;
-
-		/* Create an Ethernet device instance.
-		*/
-		dev = init_etherdev(0, 0);
-		dev->priv = cep;
-
-		init_fcc_shutdown(fip, cep, immap);
-		init_fcc_ioports(fip, io, immap);
-		init_fcc_param(fip, dev, immap);
-
-		dev->base_addr = (unsigned long)(cep->ep);
-
-		/* The CPM Ethernet specific entries in the device
-		 * structure.
-		 */
-		dev->open = fcc_enet_open;
-		dev->hard_start_xmit = fcc_enet_start_xmit;
-		dev->tx_timeout = fcc_enet_timeout;
-		dev->watchdog_timeo = TX_TIMEOUT;
-		dev->stop = fcc_enet_close;
-		dev->get_stats = fcc_enet_get_stats;
-		dev->set_multicast_list = set_multicast_list;
-
-		init_fcc_startup(fip, dev);
-
-		printk("%s: FCC ENET Version 0.2, ", dev->name);
-		for (i=0; i<5; i++)
-			printk("%02x:", dev->dev_addr[i]);
-		printk("%02x\n", dev->dev_addr[5]);
-
-		/* This is just a hack for now that works only on the EST
-		 * board, or anything else that has MDIO/CK configured.
-		 * It is mainly to test the MII software clocking.
-		 */
-		mii_discover_phy_poll(fip);
-
-		fip++;
-	}
-
-	return 0;
-}
-
-/* Make sure the device is shut down during initialization.
-*/
-static void __init
-init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
-						volatile immap_t *immap)
-{
-	volatile	fcc_enet_t	*ep;
-	volatile	fcc_t		*fccp;
-
-	/* Get pointer to FCC area in parameter RAM.
-	*/
-	ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
-
-	/* And another to the FCC register area.
-	*/
-	fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
-	cep->fccp = fccp;		/* Keep the pointers handy */
-	cep->ep = ep;
-
-	/* Disable receive and transmit in case someone left it running.
-	*/
-	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
-}
-
-/* Initialize the I/O pins for the FCC Ethernet.
-*/
-static void __init
-init_fcc_ioports(fcc_info_t *fip, volatile iop8260_t *io,
-						volatile immap_t *immap)
-{
-
-	/* FCC1 pins are on port A/C.  FCC2/3 are port B/C.
-	*/
-	if (fip->fc_proff == PROFF_FCC1) {
-		/* Configure port A and C pins for FCC1 Ethernet.
-		 */
-		io->iop_pdira &= ~PA1_DIRA0;
-		io->iop_pdira |= PA1_DIRA1;
-		io->iop_psora &= ~PA1_PSORA0;
-		io->iop_psora |= PA1_PSORA1;
-		io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
-	}
-	if (fip->fc_proff == PROFF_FCC2) {
-		/* Configure port B and C pins for FCC Ethernet.
-		 */
-		io->iop_pdirb &= ~PB2_DIRB0;
-		io->iop_pdirb |= PB2_DIRB1;
-		io->iop_psorb &= ~PB2_PSORB0;
-		io->iop_psorb |= PB2_PSORB1;
-		io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
-	}
-	if (fip->fc_proff == PROFF_FCC3) {
-		/* Configure port B and C pins for FCC Ethernet.
-		 */
-		io->iop_pdirb &= ~PB3_DIRB0;
-		io->iop_pdirb |= PB3_DIRB1;
-		io->iop_psorb &= ~PB3_PSORB0;
-		io->iop_psorb |= PB3_PSORB1;
-		io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
-	}
-
-	/* Port C has clocks......
-	*/
-	io->iop_psorc &= ~(fip->fc_trxclocks);
-	io->iop_pdirc &= ~(fip->fc_trxclocks);
-	io->iop_pparc |= fip->fc_trxclocks;
-
-	/* ....and the MII serial clock/data.
-	*/
-	io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
-	io->iop_podrc |= fip->fc_mdio;
-	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
-	io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all FCC bits to zero,
-	 * then set the ones we want.
-	 */
-	immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
-	immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
-}
-
-static void __init
-init_fcc_param(fcc_info_t *fip, struct net_device *dev,
-						volatile immap_t *immap)
-{
-	unsigned char	*eap;
-	unsigned long	mem_addr;
-	bd_t		*bd;
-	int		i, j;
-	struct		fcc_enet_private *cep;
-	volatile	fcc_enet_t	*ep;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-
-	cep = (struct fcc_enet_private *)(dev->priv);
-	ep = cep->ep;
-	cp = cpmp;
-
-	bd = (bd_t *)__res;
-
-	/* Zero the whole thing.....I must have missed some individually.
-	 * It works when I do this.
-	 */
-	memset((char *)ep, 0, sizeof(fcc_enet_t));
-
-	/* Allocate space for the buffer descriptors in the DP ram.
-	 * These are relative offsets in the DP ram address space.
-	 * Initialize base addresses for the buffer descriptors.
-	 */
-#if 0
-	/* I really want to do this, but for some reason it doesn't
-	 * work with the data cache enabled, so I allocate from the
-	 * main memory instead.
-	 */
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
-	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-
-	i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
-	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
-#else
-	cep->rx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
-	cep->tx_bd_base = (cbd_t *)m8260_cpm_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
-	ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
-#endif
-
-	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
-	cep->cur_rx = cep->rx_bd_base;
-
-	ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
-	ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
-
-	/* Set maximum bytes per receive buffer.
-	 * It must be a multiple of 32.
-	 */
-	ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
-
-	/* Allocate space in the reserved FCC area of DPRAM for the
-	 * internal buffers.  No one uses this space (yet), so we
-	 * can do this.  Later, we will add resource management for
-	 * this area.
-	 */
-	mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
-	ep->fen_genfcc.fcc_riptr = mem_addr;
-	ep->fen_genfcc.fcc_tiptr = mem_addr+32;
-	ep->fen_padptr = mem_addr+64;
-	memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
-
-	ep->fen_genfcc.fcc_rbptr = 0;
-	ep->fen_genfcc.fcc_tbptr = 0;
-	ep->fen_genfcc.fcc_rcrc = 0;
-	ep->fen_genfcc.fcc_tcrc = 0;
-	ep->fen_genfcc.fcc_res1 = 0;
-	ep->fen_genfcc.fcc_res2 = 0;
-
-	ep->fen_camptr = 0;	/* CAM isn't used in this driver */
-
-	/* Set CRC preset and mask.
-	*/
-	ep->fen_cmask = 0xdebb20e3;
-	ep->fen_cpres = 0xffffffff;
-
-	ep->fen_crcec = 0;	/* CRC Error counter */
-	ep->fen_alec = 0;	/* alignment error counter */
-	ep->fen_disfc = 0;	/* discard frame counter */
-	ep->fen_retlim = 15;	/* Retry limit threshold */
-	ep->fen_pper = 0;	/* Normal persistence */
-
-	/* Clear hash filter tables.
-	*/
-	ep->fen_gaddrh = 0;
-	ep->fen_gaddrl = 0;
-	ep->fen_iaddrh = 0;
-	ep->fen_iaddrl = 0;
-
-	/* Clear the Out-of-sequence TxBD.
-	*/
-	ep->fen_tfcstat = 0;
-	ep->fen_tfclen = 0;
-	ep->fen_tfcptr = 0;
-
-	ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
-	ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
-
-	/* Set Ethernet station address.
-	 *
-	 * This is supplied in the board information structure, so we
-	 * copy that into the controller.
-	 * So, far we have only been given one Ethernet address. We make
-	 * it unique by setting a few bits in the upper byte of the
-	 * non-static part of the address.
-	 */
-	eap = (unsigned char *)&(ep->fen_paddrh);
-	for (i=5; i>=0; i--) {
-
-/* 
- * The EP8260 only uses FCC3, so we can safely give it the real
- * MAC address.
- */
-#ifndef CONFIG_RPX6
-		if (i == 3) {
-			dev->dev_addr[i] = bd->bi_enetaddr[i];
-			dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
-			*eap++ = dev->dev_addr[i];
-		}
-		else {
-			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-		}
-#else
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
-#endif
-	}
-
-	ep->fen_taddrh = 0;
-	ep->fen_taddrm = 0;
-	ep->fen_taddrl = 0;
-
-	ep->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */
-	ep->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */
-
-	/* Clear stat counters, in case we ever enable RMON.
-	*/
-	ep->fen_octc = 0;
-	ep->fen_colc = 0;
-	ep->fen_broc = 0;
-	ep->fen_mulc = 0;
-	ep->fen_uspc = 0;
-	ep->fen_frgc = 0;
-	ep->fen_ospc = 0;
-	ep->fen_jbrc = 0;
-	ep->fen_p64c = 0;
-	ep->fen_p65c = 0;
-	ep->fen_p128c = 0;
-	ep->fen_p256c = 0;
-	ep->fen_p512c = 0;
-	ep->fen_p1024c = 0;
-
-	ep->fen_rfthr = 0;	/* Suggested by manual */
-	ep->fen_rfcnt = 0;
-	ep->fen_cftype = 0;
-
-	/* Now allocate the host memory pages and initialize the
-	 * buffer descriptors.
-	 */
-	bdp = cep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_datlen = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	bdp = cep->rx_bd_base;
-	for (i=0; i<FCC_ENET_RX_PAGES; i++) {
-
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
-			bdp->cbd_datlen = 0;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += FCC_ENET_RX_FRSIZE;
-			bdp++;
-		}
-	}
-
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
-
-	/* Let's re-initialize the channel now.  We have to do it later
-	 * than the manual describes because we have just now finished
-	 * the BD initialization.
-	 */
-	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	cep->skb_cur = cep->skb_dirty = 0;
-}
-
-/* Let 'er rip.
-*/
-static void __init
-init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
-{
-	volatile fcc_t	*fccp;
-	struct fcc_enet_private *cep;
-
-	cep = (struct fcc_enet_private *)(dev->priv);
-	fccp = cep->fccp;
-
-	fccp->fcc_fcce = 0xffff;	/* Clear any pending events */
-
-	/* Enable interrupts for transmit error, complete frame
-	 * received, and any transmit buffer we have also set the
-	 * interrupt flag.
-	 */
-	fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
-
-	/* Install our interrupt handler.
-	*/
-	if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
-				dev) < 0)
-		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
-
-	/* Set GFMR to enable Ethernet operating mode.
-	 */
-	fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
-
-	/* Set sync/delimiters.
-	*/
-	fccp->fcc_fdsr = 0xd555;
-
-	/* Set protocol specific processing mode for Ethernet.
-	 * This has to be adjusted for Full Duplex operation after we can
-	 * determine how to detect that.
-	 */
-	fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
-
-	/* And last, enable the transmit and receive processing.
-	*/
-	fccp->fcc_gfmr |= (FCC_GFMR_ENR | FCC_GFMR_ENT);
-}
-
-/* MII command/status interface.
- * I'm not going to describe all of the details.  You can find the
- * protocol definition in many other places, including the data sheet
- * of most PHY parts.
- * I wonder what "they" were thinking (maybe weren't) when they leave
- * the I2C in the CPM but I have to toggle these bits......
- */
-static uint
-mii_send_receive(fcc_info_t *fip, uint cmd)
-{
-	unsigned long	flags;
-	uint		retval;
-	int		read_op, i;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	immap = (immap_t *)IMAP_ADDR;
-	io = &immap->im_ioport;
-
-	/* When we get here, both clock and data are high, outputs.
-	 * Output is open drain.
-	 * Data transitions on high->low clock, is valid on low->high clock.
-	 * Spec says edge transitions no closer than 160 nSec, minimum clock
-	 * cycle 400 nSec.  I could only manage about 500 nSec edges with
-	 * an XOR loop, so I won't worry about delays yet.
-	 * I disable interrupts during bit flipping to ensure atomic
-	 * updates of the registers.  I do lots of interrupt disable/enable
-	 * to ensure we don't hang out too long with interrupts disabled.
-	 */
-
-	/* First, crank out 32 1-bits as preamble.
-	 * This is 64 transitions to clock the bits, with clock/data
-	 * left high.
-	 */
-	save_flags(flags);
-	cli();
-	for (i=0; i<64; i++) {
-		io->iop_pdatc ^= fip->fc_mdck;
-		udelay(0);
-	}
-	restore_flags(flags);
-
-	read_op = ((cmd & 0xf0000000) == 0x60000000);
-
-	/* We return the command word on a write op, or the command portion
-	 * plus the new data on a read op.  This is what the 8xx FEC does,
-	 * and it allows the functions to simply look at the returned value
-	 * and know the PHY/register as well.
-	 */
-	if (read_op)
-		retval = cmd;
-	else
-		retval = (cmd >> 16);
-
-	/* Clock out the first 16 MS bits of the command.
-	*/
-	save_flags(flags);
-	cli();
-	for (i=0; i<16; i++) {
-		io->iop_pdatc &= ~(fip->fc_mdck);
-		if (cmd & 0x80000000)
-			io->iop_pdatc |= fip->fc_mdio;
-		else
-			io->iop_pdatc &= ~(fip->fc_mdio);
-		cmd <<= 1;
-		io->iop_pdatc |= fip->fc_mdck;
-		udelay(0);
-	}
-
-	/* Do the turn-around.  If read op, we make the IO and input.
-	 * If write op, do the 1/0 thing.
-	 */
-	io->iop_pdatc &= ~(fip->fc_mdck);
-	if (read_op)
-		io->iop_pdirc &= ~(fip->fc_mdio);
-	else
-		io->iop_pdatc |= fip->fc_mdio;
-	io->iop_pdatc |= fip->fc_mdck;
-
-	/* I do this mainly to get just a little delay.
-	*/
-	restore_flags(flags);
-	save_flags(flags);
-	cli();
-	io->iop_pdatc &= ~(fip->fc_mdck);
-	io->iop_pdirc &= ~(fip->fc_mdio);
-	io->iop_pdatc |= fip->fc_mdck;
-
-	restore_flags(flags);
-	save_flags(flags);
-	cli();
-
-	/* For read, clock in 16 bits.  For write, clock out
-	 * rest of command.
-	 */
-	if (read_op) {
-		io->iop_pdatc &= ~(fip->fc_mdck);
-		udelay(0);
-		for (i=0; i<16; i++) {
-			io->iop_pdatc |= fip->fc_mdck;
-			udelay(0);
-			retval <<= 1;
-			if (io->iop_pdatc & fip->fc_mdio)
-				retval |= 1;
-			io->iop_pdatc &= ~(fip->fc_mdck);
-			udelay(0);
-		}
-	}
-	else {
-		for (i=0; i<16; i++) {
-			io->iop_pdatc &= ~(fip->fc_mdck);
-			if (cmd & 0x80000000)
-				io->iop_pdatc |= fip->fc_mdio;
-			else
-				io->iop_pdatc &= ~(fip->fc_mdio);
-			cmd <<= 1;
-			io->iop_pdatc |= fip->fc_mdck;
-			udelay(0);
-		}
-		io->iop_pdatc &= ~(fip->fc_mdck);
-	}
-	restore_flags(flags);
-
-	/* Some diagrams show two 1 bits for "idle".  I don't know if
-	 * this is really necessary or if it was just to indicate nothing
-	 * is going to happen for a while.
-	 * Make the data pin an output, set the data high, and clock it.
-	 */
-	save_flags(flags);
-	cli();
-	io->iop_pdatc |= fip->fc_mdio;
-	io->iop_pdirc |= fip->fc_mdio;
-	for (i=0; i<3; i++)
-		io->iop_pdatc ^= fip->fc_mdck;
-	restore_flags(flags);
-
-	/* We exit with the same conditions as entry.
-	*/
-	return(retval);
-}
diff -urN linux-2.4.26-pre2/arch/ppc/8260_io/uart.c linux-2.4.26-pre3/arch/ppc/8260_io/uart.c
--- linux-2.4.26-pre2/arch/ppc/8260_io/uart.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/8260_io/uart.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,2787 +0,0 @@
-/*
- *  UART driver for MPC8260 CPM SCC or SMC
- *  Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *  Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
- *	2.3.99 updates
- *
- * I used the 8xx uart.c driver as the framework for this driver.
- * The original code was written for the EST8260 board.  I tried to make
- * it generic, but there may be some assumptions in the structures that
- * have to be fixed later.
- *
- * The 8xx and 8260 are similar, but not identical.  Over time we
- * could probably merge these two drivers.
- * To save porting time, I did not bother to change any object names
- * that are not accessed outside of this file.
- * It still needs lots of work........When it was easy, I included code
- * to support the SCCs.
- * Only the SCCs support modem control, so that is not complete either.
- *
- * This module exports the following rs232 io functions:
- *
- *	int rs_8xx_init(void);
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <asm/immap_8260.h>
-#include <asm/mpc8260.h>
-#include <asm/cpm_8260.h>
-#include <asm/irq.h>
-
-#ifdef CONFIG_MAGIC_SYSRQ
-#include <linux/sysrq.h>
-#endif
-
-#ifdef CONFIG_SERIAL_CONSOLE
-#include <linux/console.h>
-
-/* this defines the index into rs_table for the port to use
-*/
-#ifndef CONFIG_SERIAL_CONSOLE_PORT
-#define CONFIG_SERIAL_CONSOLE_PORT	0
-#endif
-#endif
-
-#define TX_WAKEUP	ASYNC_SHARE_IRQ
-
-static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.01";
-
-static DECLARE_TASK_QUEUE(tq_serial);
-
-static struct tty_driver serial_driver, callout_driver;
-static int serial_refcount;
-static int serial_console_setup(struct console *co, char *options);
-
-static void serial_console_write(struct console *c, const char *s,
-		                                unsigned count);
-static kdev_t serial_console_device(struct console *c);
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-static unsigned long break_pressed; /* break, really ... */
-#endif
-
-/*
- * Serial driver configuration section.  Here are the various options:
- */
-#define SERIAL_PARANOIA_CHECK
-#define CONFIG_SERIAL_NOPAUSE_IO
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-#define _INLINE_ inline
-
-#define DBG_CNT(s)
-
-/* We overload some of the items in the data structure to meet our
- * needs.  For example, the port address is the CPM parameter ram
- * offset for the SCC or SMC.  The maximum number of ports is 4 SCCs and
- * 2 SMCs.  The "hub6" field is used to indicate the channel number, with
- * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
- * Since these ports are so versatile, I don't yet have a strategy for
- * their management.  For example, SCC1 is used for Ethernet.  Right
- * now, just don't put them in the table.  Of course, right now I just
- * want the SMC to work as a uart :-)..
- * The "type" field is currently set to 0, for PORT_UNKNOWN.  It is
- * not currently used.  I should probably use it to indicate the port
- * type of CMS or SCC.
- * The SMCs do not support any modem control signals.
- */
-#define smc_scc_num	hub6
-
-/* SMC2 is sometimes used for low performance TDM interfaces.  Define
- * this as 1 if you want SMC2 as a serial port UART managed by this driver.
- * Define this as 0 if you wish to use SMC2 for something else.
- */
-#define USE_SMC2 1
-
-/* Define SCC to ttySx mapping.
-*/
-#define SCC_NUM_BASE	(USE_SMC2 + 1)	/* SCC base tty "number" */
-
-/* Define which SCC is the first one to use for a serial port.  These
- * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
- * for Ethernet, and the first available SCC for serial UART is SCC2.
- * NOTE:  IF YOU CHANGE THIS, you have to change the PROFF_xxx and
- * interrupt vectors in the table below to match.
- */
-#define SCC_IDX_BASE	1	/* table index */
-
-static struct serial_state rs_table[] = {
-	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
-	{ 0,     0, PROFF_SMC1, SIU_INT_SMC1,   0,    0 },    /* SMC1 ttyS0 */
-#if USE_SMC2
-	{ 0,     0, PROFF_SMC2, SIU_INT_SMC2,   0,    1 },    /* SMC2 ttyS1 */
-#endif
-	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE},    /* SCC2 ttyS2 */
-	{ 0,     0, PROFF_SCC3, SIU_INT_SCC3,   0, SCC_NUM_BASE + 1},    /* SCC3 ttyS3 */
-};
-
-#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
-
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
-/* The number of buffer descriptors and their sizes.
-*/
-#define RX_NUM_FIFO	4
-#define RX_BUF_SIZE	32
-#define TX_NUM_FIFO	4
-#define TX_BUF_SIZE	32
-
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
-/* The async_struct in serial.h does not really give us what we
- * need, so define our own here.
- */
-typedef struct serial_info {
-	int			magic;
-	int			flags;
-	struct serial_state	*state;
-	struct tty_struct 	*tty;
-	int			read_status_mask;
-	int			ignore_status_mask;
-	int			timeout;
-	int			line;
-	int			x_char;	/* xon/xoff character */
-	int			close_delay;
-	unsigned short		closing_wait;
-	unsigned short		closing_wait2;
-	unsigned long		event;
-	unsigned long		last_active;
-	int			blocked_open; /* # of blocked opens */
-	long			session; /* Session of opening process */
-	long			pgrp; /* pgrp of opening process */
-	struct tq_struct	tqueue;
-	struct tq_struct	tqueue_hangup;
-	wait_queue_head_t	open_wait;
-	wait_queue_head_t	close_wait;
-
-	/* CPM Buffer Descriptor pointers.
-	*/
-	cbd_t			*rx_bd_base;
-	cbd_t			*rx_cur;
-	cbd_t			*tx_bd_base;
-	cbd_t			*tx_cur;
-} ser_info_t;
-
-static struct console sercons = {
-        name:           "ttyS",
-        write:          serial_console_write,
-        device:         serial_console_device,
-        setup:          serial_console_setup,
-        flags:          CON_PRINTBUFFER,
-        index:          CONFIG_SERIAL_CONSOLE_PORT,
-};
-
-
-static void change_speed(ser_info_t *info);
-static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static inline int serial_paranoia_check(ser_info_t *info,
-					kdev_t device, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null async_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, kdevname(device), routine);
-		return 1;
-	}
-	if (info->magic != SERIAL_MAGIC) {
-		printk(badmagic, kdevname(device), routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/*
- * This is used to figure out the divisor speeds and the timeouts,
- * indexed by the termio value.  The generic CPM functions are responsible
- * for setting and assigning baud rate generators for us.
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_8xx_stop(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	idx;
-	unsigned long flags;
-	volatile scc_t	*sccp;
-	volatile smc_t	*smcp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_stop"))
-		return;
-
-	save_flags(flags); cli();
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		smcp->smc_smcm &= ~SMCM_TX;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm &= ~UART_SCCM_TX;
-	}
-	restore_flags(flags);
-}
-
-static void rs_8xx_start(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	idx;
-	unsigned long flags;
-	volatile scc_t	*sccp;
-	volatile smc_t	*smcp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_stop"))
-		return;
-
-	save_flags(flags); cli();
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		smcp->smc_smcm |= SMCM_TX;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm |= UART_SCCM_TX;
-	}
-	restore_flags(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static _INLINE_ void rs_sched_event(ser_info_t *info,
-				  int event)
-{
-	info->event |= 1 << event;
-	queue_task(&info->tqueue, &tq_serial);
-	mark_bh(SERIAL_BH);
-}
-
-static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
-{
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, *cp;
-	/*int	ignored = 0;*/
-	int	i;
-	ushort	status;
-	struct	async_icount *icount;
-	volatile cbd_t	*bdp;
-
-	icount = &info->state->icount;
-
-	/* Just loop through the closed BDs and copy the characters into
-	 * the buffer.
-	 */
-	bdp = info->rx_cur;
-	for (;;) {
-		if (bdp->cbd_sc & BD_SC_EMPTY)	/* If this one is empty */
-			break;			/*   we are all done */
-
-		/* The read status mask tell us what we should do with
-		 * incoming characters, especially if errors occur.
-		 * One special case is the use of BD_SC_EMPTY.  If
-		 * this is not set, we are supposed to be ignoring
-		 * inputs.  In this case, just mark the buffer empty and
-		 * continue.
-		if (!(info->read_status_mask & BD_SC_EMPTY)) {
-			bdp->cbd_sc |= BD_SC_EMPTY;
-			bdp->cbd_sc &=
-				~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
-			if (bdp->cbd_sc & BD_SC_WRAP)
-				bdp = info->rx_bd_base;
-			else
-				bdp++;
-			continue;
-		}
-		 */
-
-		/* Get the number of characters and the buffer pointer.
-		*/
-		i = bdp->cbd_datlen;
-		cp = (unsigned char *)__va(bdp->cbd_bufaddr);
-		status = bdp->cbd_sc;
-
-		/* Check to see if there is room in the tty buffer for
-		 * the characters in our BD buffer.  If not, we exit
-		 * now, leaving the BD with the characters.  We'll pick
-		 * them up again on the next receive interrupt (which could
-		 * be a timeout).
-		 */
-		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
-			break;
-
-		while (i-- > 0) {
-			ch = *cp++;
-			*tty->flip.char_buf_ptr = ch;
-			icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
-			printk("DR%02x:%02x...", ch, *status);
-#endif
-			*tty->flip.flag_buf_ptr = 0;
-			if (status & (BD_SC_BR | BD_SC_FR |
-				       BD_SC_PR | BD_SC_OV)) {
-				/*
-				 * For statistics only
-				 */
-				if (status & BD_SC_BR)
-					icount->brk++;
-				else if (status & BD_SC_PR)
-					icount->parity++;
-				else if (status & BD_SC_FR)
-					icount->frame++;
-				if (status & BD_SC_OV)
-					icount->overrun++;
-
-				/*
-				 * Now check to see if character should be
-				 * ignored, and mask off conditions which
-				 * should be ignored.
-				if (status & info->ignore_status_mask) {
-					if (++ignored > 100)
-						break;
-					continue;
-				}
-				 */
-				status &= info->read_status_mask;
-
-				if (status & (BD_SC_BR)) {
-#ifdef SERIAL_DEBUG_INTR
-					printk("handling break....");
-#endif
-					*tty->flip.flag_buf_ptr = TTY_BREAK;
-					if (info->flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (status & BD_SC_PR)
-					*tty->flip.flag_buf_ptr = TTY_PARITY;
-				else if (status & BD_SC_FR)
-					*tty->flip.flag_buf_ptr = TTY_FRAME;
-				if (status & BD_SC_OV) {
-					/*
-					 * Overrun is special, since it's
-					 * reported immediately, and doesn't
-					 * affect the current character
-					 */
-					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-						tty->flip.count++;
-						tty->flip.flag_buf_ptr++;
-						tty->flip.char_buf_ptr++;
-						*tty->flip.flag_buf_ptr =
-								TTY_OVERRUN;
-					}
-				}
-			}
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-			if (break_pressed && info->line == sercons.index) {
-				if (ch != 0 && time_before(jiffies,
-							break_pressed + HZ*5)) {
-					handle_sysrq(ch, regs, NULL, NULL);
-					break_pressed = 0;
-					goto ignore_char;
-				} else
-					break_pressed = 0;
-			}
-#endif
-			
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-				break;
-
-			tty->flip.flag_buf_ptr++;
-			tty->flip.char_buf_ptr++;
-			tty->flip.count++;
-		}
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-	ignore_char:
-#endif
-
-		/* This BD is ready to be used again.  Clear status.
-		 * Get next BD.
-		 */
-		bdp->cbd_sc |= BD_SC_EMPTY;
-		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
-
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = info->rx_bd_base;
-		else
-			bdp++;
-	}
-
-	info->rx_cur = (cbd_t *)bdp;
-
-	queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
-{
-	struct tty_struct *tty = info->tty;
-
-	info->state->icount.brk++;
-
-#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-	if (info->line == sercons.index) {
-		if (!break_pressed) {
-			break_pressed = jiffies;
-			return;
-		} else
-			break_pressed = 0;
-	}
-#endif
-
-	/* Check to see if there is room in the tty buffer for
-	 * the break.  If not, we exit now, losing the break.  FIXME
-	 */
-	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
-		return;
-	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-	*(tty->flip.char_buf_ptr++) = 0;
-	tty->flip.count++;
-
-	queue_task(&tty->flip.tqueue, &tq_timer);
-}
-
-
-static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
-{
-
-	if (info->flags & TX_WAKEUP) {
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-	}
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("THRE...");
-#endif
-}
-
-#ifdef notdef
-	/* I need to do this for the SCCs, so it is left as a reminder.
-	*/
-static _INLINE_ void check_modem_status(struct async_struct *info)
-{
-	int	status;
-	struct	async_icount *icount;
-
-	status = serial_in(info, UART_MSR);
-
-	if (status & UART_MSR_ANY_DELTA) {
-		icount = &info->state->icount;
-		/* update input line counters */
-		if (status & UART_MSR_TERI)
-			icount->rng++;
-		if (status & UART_MSR_DDSR)
-			icount->dsr++;
-		if (status & UART_MSR_DDCD) {
-			icount->dcd++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    (status & UART_MSR_DCD))
-				hardpps();
-#endif
-		}
-		if (status & UART_MSR_DCTS)
-			icount->cts++;
-		wake_up_interruptible(&info->delta_msr_wait);
-	}
-
-	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttys%d CD now %s...", info->line,
-		       (status & UART_MSR_DCD) ? "on" : "off");
-#endif
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&info->open_wait);
-		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("scheduling hangup...");
-#endif
-			MOD_INC_USE_COUNT;
-			if (schedule_task(&info->tqueue_hangup) == 0)
-				MOD_DEC_USE_COUNT;
-		}
-	}
-	if (info->flags & ASYNC_CTS_FLOW) {
-		if (info->tty->hw_stopped) {
-			if (status & UART_MSR_CTS) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx start...");
-#endif
-				info->tty->hw_stopped = 0;
-				info->IER |= UART_IER_THRI;
-				serial_out(info, UART_IER, info->IER);
-				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-				return;
-			}
-		} else {
-			if (!(status & UART_MSR_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx stop...");
-#endif
-				info->tty->hw_stopped = 1;
-				info->IER &= ~UART_IER_THRI;
-				serial_out(info, UART_IER, info->IER);
-			}
-		}
-	}
-}
-#endif
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-{
-	u_char	events;
-	int	idx;
-	ser_info_t *info;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	info = (ser_info_t *)dev_id;
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-		events = smcp->smc_smce;
-		if (events & SMCM_BRKE)
-			receive_break(info, regs);
-		if (events & SMCM_RX)
-			receive_chars(info, regs);
-		if (events & SMCM_TX)
-			transmit_chars(info, regs);
-		smcp->smc_smce = events;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		events = sccp->scc_scce;
-		if (events & SMCM_BRKE)
-			receive_break(info, regs);
-		if (events & SCCM_RX)
-			receive_chars(info, regs);
-		if (events & SCCM_TX)
-			transmit_chars(info, regs);
-		sccp->scc_scce = events;
-	}
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("rs_interrupt_single(%d, %x)...",
-					info->state->smc_scc_num, events);
-#endif
-#ifdef modem_control
-	check_modem_status(info);
-#endif
-	info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	printk("end.\n");
-#endif
-}
-
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-static void do_serial_bh(void)
-{
-	run_task_queue(&tq_serial);
-}
-
-static void do_softint(void *private_)
-{
-	ser_info_t	*info = (ser_info_t *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
-}
-
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred.  The path of
- * hangup processing is:
- *
- * 	serial interrupt routine -> (scheduler tqueue) ->
- * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
- *
- */
-static void do_serial_hangup(void *private_)
-{
-	struct async_struct	*info = (struct async_struct *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (tty)
-		tty_hangup(tty);
-	MOD_DEC_USE_COUNT;
-}
-
-/*static void rs_8xx_timer(void)
-{
-	printk("rs_8xx_timer\n");
-}*/
-
-
-static int startup(ser_info_t *info)
-{
-	unsigned long flags;
-	int	retval=0;
-	int	idx;
-	struct serial_state *state= info->state;
-	volatile smc_t		*smcp;
-	volatile scc_t		*sccp;
-	volatile smc_uart_t	*up;
-	volatile scc_uart_t	*scup;
-
-
-	save_flags(flags); cli();
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		goto errout;
-	}
-
-#ifdef maybe
-	if (!state->port || !state->type) {
-		if (info->tty)
-			set_bit(TTY_IO_ERROR, &info->tty->flags);
-		goto errout;
-	}
-#endif
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttys%d (irq %d)...", info->line, state->irq);
-#endif
-
-
-#ifdef modem_control
-	info->MCR = 0;
-	if (info->tty->termios->c_cflag & CBAUD)
-		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-#endif
-
-	if (info->tty)
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	change_speed(info);
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Enable interrupts and I/O.
-		*/
-		smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
-		smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
-
-		/* We can tune the buffer length and idle characters
-		 * to take advantage of the entire incoming buffer size.
-		 * If mrblr is something other than 1, maxidl has to be
-		 * non-zero or we never get an interrupt.  The maxidl
-		 * is the number of character times we wait after reception
-		 * of the last character before we decide no more characters
-		 * are coming.
-		 */
-		up = (smc_uart_t *)&immr->im_dprambase[state->port];
-#if 0
-		up->smc_mrblr = 1;	/* receive buffer length */
-		up->smc_maxidl = 0;	/* wait forever for next char */
-#else
-		up->smc_mrblr = RX_BUF_SIZE;
-		up->smc_maxidl = RX_BUF_SIZE;
-#endif
-		up->smc_brkcr = 1;	/* number of break chars */
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		scup = (scc_uart_t *)&immr->im_dprambase[state->port];
-#if 0
-		scup->scc_genscc.scc_mrblr = 1;	/* receive buffer length */
-		scup->scc_maxidl = 0;	/* wait forever for next char */
-#else
-		scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
-		scup->scc_maxidl = RX_BUF_SIZE;
-#endif
-
-		sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
-		sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	}
-
-	info->flags |= ASYNC_INITIALIZED;
-	restore_flags(flags);
-	return 0;
-
-errout:
-	restore_flags(flags);
-	return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(ser_info_t * info)
-{
-	unsigned long	flags;
-	struct serial_state *state;
-	int		idx;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!(info->flags & ASYNC_INITIALIZED))
-		return;
-
-	state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d (irq %d)....", info->line,
-	       state->irq);
-#endif
-
-	save_flags(flags); cli(); /* Disable interrupts */
-
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Disable interrupts and I/O.
-		*/
-		smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-#ifdef CONFIG_SERIAL_CONSOLE
-		/* We can't disable the transmitter if this is the
-		 * system console.
-		 */
-		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
-#endif
-			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
-		sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	}
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	info->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(ser_info_t *info)
-{
-	int	baud_rate;
-	unsigned cflag, cval, scval, prev_mode;
-	int	i, bits, sbits, idx;
-	unsigned long	flags;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-
-	/* Character length programmed into the mode register is the
-	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
-	 * 1 or 2 stop bits, minus 1.
-	 * The value 'bits' counts this for us.
-	 */
-	cval = 0;
-	scval = 0;
-
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	      case CS5: bits = 5; break;
-	      case CS6: bits = 6; break;
-	      case CS7: bits = 7; break;
-	      case CS8: bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  bits = 8; break;
-	}
-	sbits = bits - 5;
-
-	if (cflag & CSTOPB) {
-		cval |= SMCMR_SL;	/* Two stops */
-		scval |= SCU_PMSR_SL;
-		bits++;
-	}
-	if (cflag & PARENB) {
-		cval |= SMCMR_PEN;
-		scval |= SCU_PMSR_PEN;
-		bits++;
-	}
-	if (!(cflag & PARODD)) {
-		cval |= SMCMR_PM_EVEN;
-		scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
-	}
-
-	/* Determine divisor based on baud rate */
-	i = cflag & CBAUD;
-	if (i >= (sizeof(baud_table)/sizeof(int)))
-		baud_rate = 9600;
-	else
-		baud_rate = baud_table[i];
-
-	info->timeout = (TX_BUF_SIZE*HZ*bits);
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-#ifdef modem_control
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	if (info->flags & ASYNC_HARDPPS_CD)
-		info->IER |= UART_IER_MSI;
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-	} else
-		info->flags &= ~ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else {
-		info->flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	serial_out(info, UART_IER, info->IER);
-#endif
-
-	/*
-	 * Set up parity check flag
-	 */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
-	if (I_INPCK(info->tty))
-		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
-	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-		info->read_status_mask |= BD_SC_BR;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(info->tty))
-		info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
-	if (I_IGNBRK(info->tty)) {
-		info->ignore_status_mask |= BD_SC_BR;
-		/*
-		 * If we're ignore parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->tty))
-			info->ignore_status_mask |= BD_SC_OV;
-	}
-	/*
-	 * !!! ignore all characters if CREAD is not set
-	 */
-	if ((cflag & CREAD) == 0)
-		info->read_status_mask &= ~BD_SC_EMPTY;
-	save_flags(flags); cli();
-
-	/* Start bit has not been added (so don't, because we would just
-	 * subtract it later), and we need to add one for the number of
-	 * stops bits (there is always at least one).
-	 */
-	bits++;
-	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		smcp = &immr->im_smc[idx];
-
-		/* Set the mode register.  We want to keep a copy of the
-		 * enables, because we want to put them back if they were
-		 * present.
-		 */
-		prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN);
-		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART
-			| prev_mode;
-	}
-	else {
-		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-		sccp->scc_pmsr = (sbits << 12) | scval;
-	}
-
-	m8260_cpm_setbrg(info->state->smc_scc_num, baud_rate);
-
-	restore_flags(flags);
-}
-
-static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	volatile cbd_t	*bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
-		return;
-
-	if (!tty)
-		return;
-
-	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
-	/* Get next BD.
-	*/
-	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
-	else
-		bdp++;
-
-	info->tx_cur = (cbd_t *)bdp;
-
-}
-
-static int rs_8xx_write(struct tty_struct * tty, int from_user,
-		    const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	volatile cbd_t *bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_write"))
-		return 0;
-
-	if (!tty)
-		return 0;
-
-	bdp = info->tx_cur;
-
-	while (1) {
-		c = MIN(count, TX_BUF_SIZE);
-
-		if (c <= 0)
-			break;
-
-		if (bdp->cbd_sc & BD_SC_READY) {
-			info->flags |= TX_WAKEUP;
-			break;
-		}
-
-		if (from_user) {
-			if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
-				if (!ret)
-					ret = -EFAULT;
-				break;
-			}
-		} else {
-			memcpy(__va(bdp->cbd_bufaddr), buf, c);
-		}
-
-		bdp->cbd_datlen = c;
-		bdp->cbd_sc |= BD_SC_READY;
-
-		buf += c;
-		count -= c;
-		ret += c;
-
-		/* Get next BD.
-		*/
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = info->tx_bd_base;
-		else
-			bdp++;
-		info->tx_cur = (cbd_t *)bdp;
-	}
-	return ret;
-}
-
-static int rs_8xx_write_room(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int	ret;
-
-	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
-		return 0;
-
-	if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
-		info->flags &= ~TX_WAKEUP;
-		ret = TX_BUF_SIZE;
-	}
-	else {
-		info->flags |= TX_WAKEUP;
-		ret = 0;
-	}
-	return ret;
-}
-
-/* I could track this with transmit counters....maybe later.
-*/
-static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
-		return 0;
-	return 0;
-}
-
-static void rs_8xx_flush_buffer(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
-		return;
-
-	/* There is nothing to "flush", whatever we gave the CPM
-	 * is on its way out.
-	 */
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-	info->flags &= ~TX_WAKEUP;
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
-{
-	volatile cbd_t	*bdp;
-
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
-		return;
-
-	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
-	/* Get next BD.
-	*/
-	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
-	else
-		bdp++;
-
-	info->tx_cur = (cbd_t *)bdp;
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_8xx_throttle(struct tty_struct * tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", _tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		rs_8xx_send_xchar(tty, STOP_CHAR(tty));
-
-#ifdef modem_control
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR &= ~UART_MCR_RTS;
-
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-}
-
-static void rs_8xx_unthrottle(struct tty_struct * tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			rs_8xx_send_xchar(tty, START_CHAR(tty));
-	}
-#ifdef modem_control
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR |= UART_MCR_RTS;
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-#ifdef maybe
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
-{
-	unsigned char status;
-	unsigned int result;
-
-	cli();
-	status = serial_in(info, UART_LSR);
-	sti();
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result,value);
-}
-#endif
-
-static int get_modem_info(ser_info_t *info, unsigned int *value)
-{
-	unsigned int result = 0;
-#ifdef modem_control
-	unsigned char control, status;
-
-	control = info->MCR;
-	cli();
-	status = serial_in(info, UART_MSR);
-	sti();
-	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-#ifdef TIOCM_OUT1
-		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
-		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
-#endif
-		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
-		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
-		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
-		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
-#endif
-	return put_user(result,value);
-}
-
-static int set_modem_info(ser_info_t *info, unsigned int cmd,
-			  unsigned int *value)
-{
-	int error;
-	unsigned int arg;
-
-	error = get_user(arg, value);
-	if (error)
-		return error;
-#ifdef modem_control
-	switch (cmd) {
-	case TIOCMBIS:
-		if (arg & TIOCM_RTS)
-			info->MCR |= UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR |= UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR |= UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR |= UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			info->MCR &= ~UART_MCR_RTS;
-		if (arg & TIOCM_DTR)
-			info->MCR &= ~UART_MCR_DTR;
-#ifdef TIOCM_OUT1
-		if (arg & TIOCM_OUT1)
-			info->MCR &= ~UART_MCR_OUT1;
-		if (arg & TIOCM_OUT2)
-			info->MCR &= ~UART_MCR_OUT2;
-#endif
-		break;
-	case TIOCMSET:
-		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
-#ifdef TIOCM_OUT1
-					    UART_MCR_OUT1 |
-					    UART_MCR_OUT2 |
-#endif
-					    UART_MCR_DTR))
-			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
-#ifdef TIOCM_OUT1
-			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
-			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
-#endif
-			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
-		break;
-	default:
-		return -EINVAL;
-	}
-	cli();
-	serial_out(info, UART_MCR, info->MCR);
-	sti();
-#endif
-	return 0;
-}
-
-/* Sending a break is a two step process on the SMC/SCC.  It is accomplished
- * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
- * command.  We take advantage of the begin/end functions to make this
- * happen.
- */
-static void begin_break(ser_info_t *info)
-{
-	volatile cpm8260_t *cp;
-	uint	page, sblock;
-	ushort	num;
-
-	cp = cpmp;
-
-	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		if (num == 0) {
-			page = CPM_CR_SMC1_PAGE;
-			sblock = CPM_CR_SMC1_SBLOCK;
-		}
-		else {
-			page = CPM_CR_SMC2_PAGE;
-			sblock = CPM_CR_SMC2_SBLOCK;
-		}
-	}
-	else {
-		num -= SCC_NUM_BASE;
-		switch (num) {
-		case 0:
-			page = CPM_CR_SCC1_PAGE;
-			sblock = CPM_CR_SCC1_SBLOCK;
-			break;
-		case 1:
-			page = CPM_CR_SCC2_PAGE;
-			sblock = CPM_CR_SCC2_SBLOCK;
-			break;
-		case 2:
-			page = CPM_CR_SCC3_PAGE;
-			sblock = CPM_CR_SCC3_SBLOCK;
-			break;
-		case 3:
-			page = CPM_CR_SCC4_PAGE;
-			sblock = CPM_CR_SCC4_SBLOCK;
-			break;
-		default: return;
-		}
-	}
-	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-}
-
-static void end_break(ser_info_t *info)
-{
-	volatile cpm8260_t *cp;
-	uint	page, sblock;
-	ushort	num;
-
-	cp = cpmp;
-
-	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
-		if (num == 0) {
-			page = CPM_CR_SMC1_PAGE;
-			sblock = CPM_CR_SMC1_SBLOCK;
-		}
-		else {
-			page = CPM_CR_SMC2_PAGE;
-			sblock = CPM_CR_SMC2_SBLOCK;
-		}
-	}
-	else {
-		num -= SCC_NUM_BASE;
-		switch (num) {
-		case 0:
-			page = CPM_CR_SCC1_PAGE;
-			sblock = CPM_CR_SCC1_SBLOCK;
-			break;
-		case 1:
-			page = CPM_CR_SCC2_PAGE;
-			sblock = CPM_CR_SCC2_SBLOCK;
-			break;
-		case 2:
-			page = CPM_CR_SCC3_PAGE;
-			sblock = CPM_CR_SCC3_SBLOCK;
-			break;
-		case 3:
-			page = CPM_CR_SCC4_PAGE;
-			sblock = CPM_CR_SCC4_SBLOCK;
-			break;
-		default: return;
-		}
-	}
-	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-}
-
-/*
- * This routine sends a break character out the serial port.
- */
-static void send_break(ser_info_t *info, int duration)
-{
-	current->state = TASK_INTERRUPTIBLE;
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
-#endif
-	begin_break(info);
-	schedule_timeout(duration);
-	end_break(info);
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("done jiffies=%lu\n", jiffies);
-#endif
-}
-
-
-static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	int error;
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	int retval;
-	struct async_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct *p_cuser;	/* user space */
-
-	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
-				if (signal_pending(current))
-					return -EINTR;
-			}
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			if (signal_pending(current))
-				return -EINTR;
-			return 0;
-		case TIOCSBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			begin_break(info);
-			return 0;
-		case TIOCCBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			end_break(info);
-			return 0;
-		case TIOCGSOFTCAR:
-			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-		case TIOCSSOFTCAR:
-			error = get_user(arg, (unsigned int *) arg);
-			if (error)
-				return error;
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				 (arg ? CLOCAL : 0));
-			return 0;
-		case TIOCMGET:
-			return get_modem_info(info, (unsigned int *) arg);
-		case TIOCMBIS:
-		case TIOCMBIC:
-		case TIOCMSET:
-			return set_modem_info(info, cmd, (unsigned int *) arg);
-#ifdef maybe
-		case TIOCSERGETLSR: /* Get line status register */
-			return get_lsr_info(info, (unsigned int *) arg);
-#endif
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
- 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-		 case TIOCMIWAIT:
-#ifdef modem_control
-			cli();
-			/* note the counters on entry */
-			cprev = info->state->icount;
-			sti();
-			while (1) {
-				interruptible_sleep_on(&info->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				cli();
-				cnow = info->state->icount; /* atomic copy */
-				sti();
-				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-					return -EIO; /* no change => error */
-				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-					return 0;
-				}
-				cprev = cnow;
-			}
-			/* NOTREACHED */
-#else
-			return 0;
-#endif
-
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-		case TIOCGICOUNT:
-			cli();
-			cnow = info->state->icount;
-			sti();
-			p_cuser = (struct serial_icounter_struct *) arg;
-			error = put_user(cnow.cts, &p_cuser->cts);
-			if (error) return error;
-			error = put_user(cnow.dsr, &p_cuser->dsr);
-			if (error) return error;
-			error = put_user(cnow.rng, &p_cuser->rng);
-			if (error) return error;
-			error = put_user(cnow.dcd, &p_cuser->dcd);
-			if (error) return error;
-			return 0;
-
-		default:
-			return -ENOIOCTLCMD;
-		}
-	return 0;
-}
-
-/* FIX UP modem control here someday......
-*/
-static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-
-	if (   (tty->termios->c_cflag == old_termios->c_cflag)
-	    && (   RELEVANT_IFLAG(tty->termios->c_iflag)
-		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
-
-	change_speed(info);
-
-#ifdef modem_control
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		cli();
-		serial_out(info, UART_MCR, info->MCR);
-		sti();
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    (tty->termios->c_cflag & CBAUD)) {
-		info->MCR |= UART_MCR_DTR;
-		if (!tty->hw_stopped ||
-		    !(tty->termios->c_cflag & CRTSCTS)) {
-			info->MCR |= UART_MCR_RTS;
-		}
-		cli();
-		serial_out(info, UART_MCR, info->MCR);
-		sti();
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rs_8xx_start(tty);
-	}
-#endif
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	struct serial_state *state;
-	unsigned long	flags;
-	int		idx;
-	volatile smc_t	*smcp;
-	volatile scc_t	*sccp;
-
-	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
-		return;
-
-	state = info->state;
-
-	save_flags(flags); cli();
-
-	if (tty_hung_up_p(filp)) {
-		DBG_CNT("before DEC-hung");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
-	if ((tty->count == 1) && (state->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  state->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("rs_close: bad serial port count; tty->count is 1, "
-		       "state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttys%d: %d\n",
-		       info->line, state->count);
-		state->count = 0;
-	}
-	if (state->count) {
-		DBG_CNT("before DEC-2");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-	info->flags |= ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
-	 * separate termios for callout and dialin.
-	 */
-	if (info->flags & ASYNC_NORMAL_ACTIVE)
-		info->state->normal_termios = *tty->termios;
-	if (info->flags & ASYNC_CALLOUT_ACTIVE)
-		info->state->callout_termios = *tty->termios;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->read_status_mask &= ~BD_SC_EMPTY;
-	if (info->flags & ASYNC_INITIALIZED) {
-		if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
-			smcp = &immr->im_smc[idx];
-			smcp->smc_smcm &= ~SMCM_RX;
-			smcp->smc_smcmr &= ~SMCMR_REN;
-		}
-		else {
-			sccp = &immr->im_scc[idx - SCC_IDX_BASE];
-			sccp->scc_sccm &= ~UART_SCCM_RX;
-			sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
-		}
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		rs_8xx_wait_until_sent(tty, info->timeout);
-	}
-	shutdown(info);
-	if (tty->driver.flush_buffer)
-		tty->driver.flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-	tty->closing = 0;
-	info->event = 0;
-	info->tty = 0;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(info->close_delay);
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
-			 ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-	MOD_DEC_USE_COUNT;
-	restore_flags(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	/*int lsr;*/
-	volatile cbd_t *bdp;
-
-	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
-		return;
-
-#ifdef maybe
-	if (info->state->type == PORT_UNKNOWN)
-		return;
-#endif
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = 1;
-	if (timeout)
-		char_time = MIN(char_time, timeout);
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-
-	/* We go through the loop at least once because we can't tell
-	 * exactly when the last character exits the shifter.  There can
-	 * be at least two characters waiting to be sent after the buffers
-	 * are empty.
-	 */
-	do {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		current->state = TASK_INTERRUPTIBLE;
-/*		current->counter = 0;	 make us low-priority */
-		schedule_timeout(char_time);
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-		bdp = info->tx_cur;
-	} while (bdp->cbd_sc & BD_SC_READY);
-	current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_8xx_hangup(struct tty_struct *tty)
-{
-	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	struct serial_state *state = info->state;
-
-	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
-		return;
-
-	state = info->state;
-
-	rs_8xx_flush_buffer(tty);
-	shutdown(info);
-	info->event = 0;
-	state->count = 0;
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
-	info->tty = 0;
-	wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   ser_info_t *info)
-{
-#ifdef DO_THIS_LATER
-	DECLARE_WAITQUEUE(wait, current);
-#endif
-	struct serial_state *state = info->state;
-	int		retval;
-	int		do_clocal = 0;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		if (info->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * If this is a callout device, then just make sure the normal
-	 * device isn't being used.
-	 */
-	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
-		if (info->flags & ASYNC_NORMAL_ACTIVE)
-			return -EBUSY;
-		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
-		    (info->session != current->session))
-		    return -EBUSY;
-		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
-		    (info->pgrp != current->pgrp))
-		    return -EBUSY;
-		info->flags |= ASYNC_CALLOUT_ACTIVE;
-		return 0;
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 * If this is an SMC port, we don't have modem control to wait
-	 * for, so just get out here.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR)) ||
-	    (info->state->smc_scc_num < SCC_NUM_BASE)) {
-		if (info->flags & ASYNC_CALLOUT_ACTIVE)
-			return -EBUSY;
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
-		if (state->normal_termios.c_cflag & CLOCAL)
-			do_clocal = 1;
-	} else {
-		if (tty->termios->c_cflag & CLOCAL)
-			do_clocal = 1;
-	}
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, state->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-#ifdef DO_THIS_LATER
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
-	       state->line, state->count);
-#endif
-	cli();
-	if (!tty_hung_up_p(filp))
-		state->count--;
-	sti();
-	info->blocked_open++;
-	while (1) {
-		cli();
-		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    (tty->termios->c_cflag & CBAUD))
-			serial_out(info, UART_MCR,
-				   serial_inp(info, UART_MCR) |
-				   (UART_MCR_DTR | UART_MCR_RTS));
-		sti();
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (info->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
-		    !(info->flags & ASYNC_CLOSING) &&
-		    (do_clocal || (serial_in(info, UART_MSR) &
-				   UART_MSR_DCD)))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
-		       info->line, state->count);
-#endif
-		schedule();
-	}
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp))
-		state->count++;
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
-	       info->line, state->count);
-#endif
-#endif /* DO_THIS_LATER */
-	if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-static int get_async_struct(int line, ser_info_t **ret_info)
-{
-	struct serial_state *sstate;
-
-	sstate = rs_table + line;
-	if (sstate->info) {
-		sstate->count++;
-		*ret_info = (ser_info_t *)sstate->info;
-		return 0;
-	}
-	else {
-		return -ENOMEM;
-	}
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
-{
-	ser_info_t	*info;
-	int 		retval, line;
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	if ((line < 0) || (line >= NR_PORTS))
-		return -ENODEV;
-	retval = get_async_struct(line, &info);
-	if (retval)
-		return retval;
-	if (serial_paranoia_check(info, tty->device, "rs_open"))
-		return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
-	       info->state->count);
-#endif
-	tty->driver_data = info;
-	info->tty = tty;
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval)
-		return retval;
-
-	MOD_INC_USE_COUNT;
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-
-	if ((info->state->count == 1) &&
-	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
-		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-			*tty->termios = info->state->normal_termios;
-		else
-			*tty->termios = info->state->callout_termios;
-		change_speed(info);
-	}
-
-	info->session = current->session;
-	info->pgrp = current->pgrp;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open ttys%d successful...", info->line);
-#endif
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static int inline line_info(char *buf, struct serial_state *state)
-{
-#ifdef notdef
-	struct async_struct *info = state->info, scr_info;
-	char	stat_buf[30], control, status;
-#endif
-	int	ret;
-
-	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
-		      state->line,
-		      (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
-		      state->port, state->irq);
-
-	if (!state->port || (state->type == PORT_UNKNOWN)) {
-		ret += sprintf(buf+ret, "\n");
-		return ret;
-	}
-
-#ifdef notdef
-	/*
-	 * Figure out the current RS-232 lines
-	 */
-	if (!info) {
-		info = &scr_info;	/* This is just for serial_{in,out} */
-
-		info->magic = SERIAL_MAGIC;
-		info->port = state->port;
-		info->flags = state->flags;
-		info->quot = 0;
-		info->tty = 0;
-	}
-	cli();
-	status = serial_in(info, UART_MSR);
-	control = info ? info->MCR : serial_in(info, UART_MCR);
-	sti();
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (control & UART_MCR_RTS)
-		strcat(stat_buf, "|RTS");
-	if (status & UART_MSR_CTS)
-		strcat(stat_buf, "|CTS");
-	if (control & UART_MCR_DTR)
-		strcat(stat_buf, "|DTR");
-	if (status & UART_MSR_DSR)
-		strcat(stat_buf, "|DSR");
-	if (status & UART_MSR_DCD)
-		strcat(stat_buf, "|CD");
-	if (status & UART_MSR_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->quot) {
-		ret += sprintf(buf+ret, " baud:%d",
-			       state->baud_base / info->quot);
-	}
-
-	ret += sprintf(buf+ret, " tx:%d rx:%d",
-		      state->icount.tx, state->icount.rx);
-
-	if (state->icount.frame)
-		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
-
-	if (state->icount.parity)
-		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
-
-	if (state->icount.brk)
-		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
-
-	if (state->icount.overrun)
-		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
-
-	/*
-	 * Last thing is the RS-232 status lines
-	 */
-	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
-#endif
-	return ret;
-}
-
-int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
-		 int *eof, void *data)
-{
-	int i, len = 0;
-	off_t	begin = 0;
-
-	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
-	for (i = 0; i < NR_PORTS && len < 4000; i++) {
-		len += line_info(page + len, &rs_table[i]);
-		if (len+begin > off+count)
-			goto done;
-		if (len+begin < off) {
-			begin += len;
-			len = 0;
-		}
-	}
-	*eof = 1;
-done:
-	if (off >= len+begin)
-		return 0;
-	*start = page + (begin-off);
-	return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static _INLINE_ void show_serial_version(void)
-{
- 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-/*
- * The serial console driver used during boot.  Note that these names
- * clash with those found in "serial.c", so we currently can't support
- * the 16xxx uarts and these at the same time.  I will fix this to become
- * an indirect function call from tty_io.c (or something).
- */
-
-#ifdef CONFIG_SERIAL_CONSOLE
-
-/*
- * Print a string to the serial port trying not to disturb any possible
- * real use of the port...
- */
-static void serial_console_write(struct console *c, const char *s,
-				unsigned count)
-{
-	struct		serial_state	*ser;
-	ser_info_t			*info;
-	unsigned			i;
-	volatile	cbd_t		*bdp, *bdbase;
-	volatile	smc_uart_t	*up;
-	volatile	u_char		*cp;
-
-	ser = rs_table + c->index;
-
-	/* If the port has been initialized for general use, we have
-	 * to use the buffer descriptors allocated there.  Otherwise,
-	 * we simply use the single buffer allocated.
-	 */
-	if ((info = (ser_info_t *)ser->info) != NULL) {
-		bdp = info->tx_cur;
-		bdbase = info->tx_bd_base;
-	}
-	else {
-		/* Pointer to UART in parameter ram.
-		*/
-		up = (smc_uart_t *)&immr->im_dprambase[ser->port];
-
-		/* Get the address of the host memory buffer.
-		 */
-		bdp = bdbase = (cbd_t *)&immr->im_dprambase[up->smc_tbase];
-	}
-
-	/*
-	 * We need to gracefully shut down the transmitter, disable
-	 * interrupts, then send our bytes out.
-	 */
-
-	/*
-	 * Now, do each character.  This is not as bad as it looks
-	 * since this is a holding FIFO and not a transmitting FIFO.
-	 * We could add the complexity of filling the entire transmit
-	 * buffer, but we would just wait longer between accesses......
-	 */
-	for (i = 0; i < count; i++, s++) {
-		/* Wait for transmitter fifo to empty.
-		 * Ready indicates output is ready, and xmt is doing
-		 * that, not that it is ready for us to send.
-		 */
-		while (bdp->cbd_sc & BD_SC_READY);
-		/* Send the character out. */
-		cp = __va(bdp->cbd_bufaddr);
-		*cp = *s;
-
-		bdp->cbd_datlen = 1;
-		bdp->cbd_sc |= BD_SC_READY;
-
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = bdbase;
-		else
-			bdp++;
-
-		/* if a LF, also do CR... */
-		if (*s == 10) {
-			while (bdp->cbd_sc & BD_SC_READY);
-			cp = __va(bdp->cbd_bufaddr);
-			*cp = 13;
-			bdp->cbd_datlen = 1;
-			bdp->cbd_sc |= BD_SC_READY;
-
-			if (bdp->cbd_sc & BD_SC_WRAP) {
-				bdp = bdbase;
-			}
-			else {
-				bdp++;
-			}
-		}
-	}
-
-	/*
-	 * Finally, Wait for transmitter & holding register to empty
-	 *  and restore the IER
-	 */
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	if (info)
-		info->tx_cur = (cbd_t *)bdp;
-}
-
-static kdev_t serial_console_device(struct console *c)
-{
-	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
-}
-
-/*
- *	Register console.
- */
-long __init console_8xx_init(long kmem_start, long kmem_end)
-{
-	register_console(&sercons);
-	return kmem_start;
-}
-
-#endif
-
-/* Default console baud rate as determined by the board information
- * structure.
- */
-static	int	baud_idx;
-
-/*
- * The serial driver boot-time initialization code!
- */
-int __init rs_8xx_init(void)
-{
-	struct serial_state * state;
-	ser_info_t	*info;
-	uint		mem_addr, dp_addr;
-	int		i, j, idx;
-	uint		page, sblock;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	smc_t		*sp;
-	volatile	smc_uart_t	*up;
-	volatile	scc_t		*scp;
-	volatile	scc_uart_t	*sup;
-	volatile	immap_t		*immap;
-	volatile	iop8260_t	*io;
-
-	init_bh(SERIAL_BH, do_serial_bh);
-
-	show_serial_version();
-
-	/* Initialize the tty_driver structure */
-
-	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
-	__clear_user(&serial_driver,sizeof(struct tty_driver));
-	serial_driver.magic = TTY_DRIVER_MAGIC;
-	serial_driver.driver_name = "serial";
-#ifdef CONFIG_DEVFS_FS
-	serial_driver.name = "tts/%d";
-#else
-	serial_driver.name = "ttyS";
-#endif
-	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
-	serial_driver.num = NR_PORTS;
-	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver.subtype = SERIAL_TYPE_NORMAL;
-	serial_driver.init_termios = tty_std_termios;
-	serial_driver.init_termios.c_cflag =
-		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver.flags = TTY_DRIVER_REAL_RAW;
-	serial_driver.refcount = &serial_refcount;
-	serial_driver.table = serial_table;
-	serial_driver.termios = serial_termios;
-	serial_driver.termios_locked = serial_termios_locked;
-
-	serial_driver.open = rs_8xx_open;
-	serial_driver.close = rs_8xx_close;
-	serial_driver.write = rs_8xx_write;
-	serial_driver.put_char = rs_8xx_put_char;
-	serial_driver.write_room = rs_8xx_write_room;
-	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
-	serial_driver.flush_buffer = rs_8xx_flush_buffer;
-	serial_driver.ioctl = rs_8xx_ioctl;
-	serial_driver.throttle = rs_8xx_throttle;
-	serial_driver.unthrottle = rs_8xx_unthrottle;
-	serial_driver.send_xchar = rs_8xx_send_xchar;
-	serial_driver.set_termios = rs_8xx_set_termios;
-	serial_driver.stop = rs_8xx_stop;
-	serial_driver.start = rs_8xx_start;
-	serial_driver.hangup = rs_8xx_hangup;
-	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
-	serial_driver.read_proc = rs_8xx_read_proc;
-
-	/*
-	 * The callout device is just like normal device except for
-	 * major number and the subtype code.
-	 */
-	callout_driver = serial_driver;
-#ifdef CONFIG_DEVFS_FS
-	callout_driver.name = "cua/%d";
-#else
-	callout_driver.name = "cua";
-#endif
-	callout_driver.major = TTYAUX_MAJOR;
-	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-	callout_driver.read_proc = 0;
-	callout_driver.proc_entry = 0;
-
-	if (tty_register_driver(&serial_driver))
-		panic("Couldn't register serial driver\n");
-	if (tty_register_driver(&callout_driver))
-		panic("Couldn't register callout driver\n");
-
-	immap = immr;
-	cp = &immap->im_cpm;
-	io = &immap->im_ioport;
-
-	/* This should have been done long ago by the early boot code,
-	 * but do it again to make sure.
-	 */
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
-
-	/* Geeze, here we go....Picking I/O port bits....Lots of
-	 * choices.  If you don't like mine, pick your own.
-	 * Configure SMCs Tx/Rx.  SMC1 is only on Port D, SMC2 is
-	 * only on Port A.  You either pick 'em, or not.
-	 */
-	io->iop_ppard |= 0x00c00000;
-	io->iop_pdird |= 0x00400000;
-	io->iop_pdird &= ~0x00800000;
-	io->iop_psord &= ~0x00c00000;
-#if USE_SMC2
-	io->iop_ppara |= 0x00c00000;
-	io->iop_pdira |= 0x00400000;
-	io->iop_pdira &= ~0x00800000;
-	io->iop_psora &= ~0x00c00000;
-#endif
-
-	/* Configure SCC2 and SCC3.  Be careful about the fine print.
-	 * Secondary options are only available when you take away
-	 * the primary option.  Unless the pins are used for something
-	 * else, SCC2 and SCC3 are on Port B.
-	 *	Port B,  8 - SCC3 TxD
-	 *	Port B, 12 - SCC2 TxD
-	 *	Port B, 14 - SCC3 RxD
-	 *	Port B, 15 - SCC2 RxD
-	 */
-	io->iop_pparb |= 0x008b0000;
-	io->iop_pdirb |= 0x00880000;
-	io->iop_psorb |= 0x00880000;
-	io->iop_pdirb &= ~0x00030000;
-	io->iop_psorb &= ~0x00030000;
-
-	/* Wire BRG1 to SMC1 and BRG2 to SMC2.
-	*/
-	immap->im_cpmux.cmx_smr = 0;
-
-	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and
-	 * BRG4 to SCC3.
-	 */
-	immap->im_cpmux.cmx_scr &= ~0x00ffff00;
-	immap->im_cpmux.cmx_scr |= 0x00121b00;
-
-	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
-		state->magic = SSTATE_MAGIC;
-		state->line = i;
-		state->type = PORT_UNKNOWN;
-		state->custom_divisor = 0;
-		state->close_delay = 5*HZ/10;
-		state->closing_wait = 30*HZ;
-		state->callout_termios = callout_driver.init_termios;
-		state->normal_termios = serial_driver.init_termios;
-		state->icount.cts = state->icount.dsr =
-			state->icount.rng = state->icount.dcd = 0;
-		state->icount.rx = state->icount.tx = 0;
-		state->icount.frame = state->icount.parity = 0;
-		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
-		       i, state->port,
-		       (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC");
-#ifdef CONFIG_SERIAL_CONSOLE
-		/* If we just printed the message on the console port, and
-		 * we are about to initialize it for general use, we have
-		 * to wait a couple of character times for the CR/NL to
-		 * make it out of the transmit buffer.
-		 */
-		if (i == CONFIG_SERIAL_CONSOLE_PORT)
-			mdelay(2);
-#endif
-		info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
-		if (info) {
-			/*memset(info, 0, sizeof(ser_info_t));*/
-			__clear_user(info,sizeof(ser_info_t));
-			init_waitqueue_head(&info->open_wait);
-			init_waitqueue_head(&info->close_wait);
-			info->magic = SERIAL_MAGIC;
-			info->flags = state->flags;
-			info->tqueue.routine = do_softint;
-			info->tqueue.data = info;
-			info->tqueue_hangup.routine = do_serial_hangup;
-			info->tqueue_hangup.data = info;
-			info->line = i;
-			info->state = state;
-			state->info = (struct async_struct *)info;
-
-			/* We need to allocate a transmit and receive buffer
-			 * descriptors from dual port ram, and a character
-			 * buffer area from host mem.
-			 */
-			dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
-
-			/* Allocate space for FIFOs in the host memory.
-			*/
-			mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
-
-			/* Set the physical address of the host memory
-			 * buffers in the buffer descriptors, and the
-			 * virtual address for us to work with.
-			 */
-			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
-
-			for (j=0; j<(RX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
-				bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
-				mem_addr += RX_BUF_SIZE;
-				bdp++;
-			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
-
-			if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
-				sp = &immap->im_smc[idx];
-				up = (smc_uart_t *)&immap->im_dprambase[state->port];
-				up->smc_rbase = dp_addr;
-			}
-			else {
-				scp = &immap->im_scc[idx - SCC_IDX_BASE];
-				sup = (scc_uart_t *)&immap->im_dprambase[state->port];
-				sup->scc_genscc.scc_rbase = dp_addr;
-			}
-
-			dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
-
-			/* Allocate space for FIFOs in the host memory.
-			*/
-			mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
-
-			/* Set the physical address of the host memory
-			 * buffers in the buffer descriptors, and the
-			 * virtual address for us to work with.
-			 */
-			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
-
-			for (j=0; j<(TX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
-				bdp->cbd_sc = BD_SC_INTRPT;
-				mem_addr += TX_BUF_SIZE;
-				bdp++;
-			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
-
-			if (idx < SCC_NUM_BASE) {
-				up->smc_tbase = dp_addr;
-
-				/* Set up the uart parameters in the
-				 * parameter ram.
-				 */
-				up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-				up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-				/* Set this to 1 for now, so we get single
-				 * character interrupts.  Using idle charater
-				 * time requires some additional tuning.
-				 */
-				up->smc_mrblr = 1;
-				up->smc_maxidl = 0;
-				up->smc_brkcr = 1;
-
-				/* Send the CPM an initialize command.
-				*/
-				if (state->smc_scc_num == 0) {
-					page = CPM_CR_SMC1_PAGE;
-					sblock = CPM_CR_SMC1_SBLOCK;
-				}
-				else {
-					page = CPM_CR_SMC2_PAGE;
-					sblock = CPM_CR_SMC2_SBLOCK;
-				}
-
-				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
-						CPM_CR_INIT_TRX) | CPM_CR_FLG;
-				while (cp->cp_cpcr & CPM_CR_FLG);
-
-				/* Set UART mode, 8 bit, no parity, one stop.
-				 * Enable receive and transmit.
-				 */
-				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
-
-				/* Disable all interrupts and clear all pending
-				 * events.
-				 */
-				sp->smc_smcm = 0;
-				sp->smc_smce = 0xff;
-			}
-			else {
-				sup->scc_genscc.scc_tbase = dp_addr;
-
-				/* Set up the uart parameters in the
-				 * parameter ram.
-				 */
-				sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-				sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-				/* Set this to 1 for now, so we get single
-				 * character interrupts.  Using idle charater
-				 * time requires some additional tuning.
-				 */
-				sup->scc_genscc.scc_mrblr = 1;
-				sup->scc_maxidl = 0;
-				sup->scc_brkcr = 1;
-				sup->scc_parec = 0;
-				sup->scc_frmec = 0;
-				sup->scc_nosec = 0;
-				sup->scc_brkec = 0;
-				sup->scc_uaddr1 = 0;
-				sup->scc_uaddr2 = 0;
-				sup->scc_toseq = 0;
-				sup->scc_char1 = 0x8000;
-				sup->scc_char2 = 0x8000;
-				sup->scc_char3 = 0x8000;
-				sup->scc_char4 = 0x8000;
-				sup->scc_char5 = 0x8000;
-				sup->scc_char6 = 0x8000;
-				sup->scc_char7 = 0x8000;
-				sup->scc_char8 = 0x8000;
-				sup->scc_rccm = 0xc0ff;
-
-				/* Send the CPM an initialize command.
-				*/
-				if (state->smc_scc_num == 2) {
-					page = CPM_CR_SCC2_PAGE;
-					sblock = CPM_CR_SCC2_SBLOCK;
-				}
-				else {
-					page = CPM_CR_SCC3_PAGE;
-					sblock = CPM_CR_SCC3_SBLOCK;
-				}
-
-				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
-						CPM_CR_INIT_TRX) | CPM_CR_FLG;
-				while (cp->cp_cpcr & CPM_CR_FLG);
-
-				/* Set UART mode, 8 bit, no parity, one stop.
-				 * Enable receive and transmit.
-				 */
-				scp->scc_gsmrh = 0;
-				scp->scc_gsmrl =
-					(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
-
-				/* Disable all interrupts and clear all pending
-				 * events.
-				 */
-				scp->scc_sccm = 0;
-				scp->scc_scce = 0xffff;
-				scp->scc_dsr = 0x7e7e;
-				scp->scc_pmsr = 0x3000;
-			}
-
-			/* Install interrupt handler.
-			*/
-			request_irq(state->irq, rs_8xx_interrupt, 0, "uart",
-					info);
-
-			/* Set up the baud rate generator.
-			*/
-			m8260_cpm_setbrg(state->smc_scc_num,
-							baud_table[baud_idx]);
-
-			/* If the port is the console, enable Rx and Tx.
-			*/
-#ifdef CONFIG_SERIAL_CONSOLE
-			if (i == CONFIG_SERIAL_CONSOLE_PORT)
-				sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-#endif
-		}
-	}
-	return 0;
-}
-
-/* This must always be called before the rs_8xx_init() function, otherwise
- * it blows away the port control information.
-*/
-static int __init serial_console_setup(struct console *co, char *options)
-{
-	struct		serial_state *ser;
-	uint		mem_addr, dp_addr, bidx;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8260_t	*cp;
-	volatile	immap_t		*immap;
-	volatile	smc_t		*sp;
-	volatile	smc_uart_t	*up;
-	volatile	iop8260_t	*io;
-	bd_t				*bd;
-
-	bd = (bd_t *)__res;
-
-	for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
-		if (bd->bi_baudrate == baud_table[bidx])
-			break;
-
-	co->cflag = CREAD|CLOCAL|bidx|CS8;
-	baud_idx = bidx;
-
-	ser = rs_table + co->index;
-
-
-	immap = immr;
-	cp = &immap->im_cpm;
-	io = &immap->im_ioport;
-
-	/* This should have been done long ago by the early boot code,
-	 * but do it again to make sure.
-	 */
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
-	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
-
-	/* Right now, assume we are using SMCs.
-	*/
-	sp = &immap->im_smc[ser->smc_scc_num];
-
-	/* When we get here, the CPM has been reset, so we need
-	 * to configure the port.
-	 * We need to allocate a transmit and receive buffer descriptor
-	 * from dual port ram, and a character buffer area from host mem.
-	 */
-	up = (smc_uart_t *)&immap->im_dprambase[ser->port];
-
-	/* Disable transmitter/receiver.
-	*/
-	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-
-	/* Use Port D for SMC1 instead of other functions.
-	*/
-	io->iop_ppard |= 0x00c00000;
-	io->iop_pdird |= 0x00400000;
-	io->iop_pdird &= ~0x00800000;
-	io->iop_psord &= ~0x00c00000;
-
-	/* Allocate space for two buffer descriptors in the DP ram.
-	*/
-	dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2, 8);
-
-	/* Allocate space for two 2 byte FIFOs in the host memory.
-	*/
-	mem_addr = m8260_cpm_hostalloc(4, 1);
-
-	/* Set the physical address of the host memory buffers in
-	 * the buffer descriptors.
-	 */
-	bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
-	bdp->cbd_bufaddr = __pa(mem_addr);
-	(bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
-
-	/* For the receive, set empty and wrap.
-	 * For transmit, set wrap.
-	 */
-	bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
-	(bdp+1)->cbd_sc = BD_SC_WRAP;
-
-	/* Set up the uart parameters in the parameter ram.
-	*/
-	up->smc_rbase = dp_addr;	/* Base of receive buffer desc. */
-	up->smc_tbase = dp_addr+sizeof(cbd_t);	/* Base of xmt buffer desc. */
-	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
-	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
-
-	/* Set this to 1 for now, so we get single character interrupts.
-	*/
-	up->smc_mrblr = 1;		/* receive buffer length */
-	up->smc_maxidl = 0;		/* wait forever for next char */
-
-	/* Send the CPM an initialize command.
-	*/
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
-			CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-
-	/* Set UART mode, 8 bit, no parity, one stop.
-	 * Enable receive and transmit.
-	 */
-	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
-
-	/* Set up the baud rate generator.
-	*/
-	m8260_cpm_setbrg(ser->smc_scc_num, bd->bi_baudrate);
-
-	/* And finally, enable Rx and Tx.
-	*/
-	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
-
-	return 0;
-}
diff -urN linux-2.4.26-pre2/arch/ppc/Makefile linux-2.4.26-pre3/arch/ppc/Makefile
--- linux-2.4.26-pre2/arch/ppc/Makefile	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/Makefile	2004-03-13 07:43:22.000000000 -0800
@@ -72,9 +72,9 @@
 DRIVERS += arch/ppc/8xx_io/8xx_io.o
 endif
 
-ifdef CONFIG_8260
-SUBDIRS += arch/ppc/8260_io
-DRIVERS += arch/ppc/8260_io/8260_io.o
+ifdef CONFIG_CPM2
+SUBDIRS += arch/ppc/cpm2_io
+DRIVERS += arch/ppc/cpm2_io/cpm2_io.o
 endif
 
 ifdef CONFIG_APUS
diff -urN linux-2.4.26-pre2/arch/ppc/boot/simple/embed_config.c linux-2.4.26-pre3/arch/ppc/boot/simple/embed_config.c
--- linux-2.4.26-pre2/arch/ppc/boot/simple/embed_config.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/boot/simple/embed_config.c	2004-03-13 07:43:22.000000000 -0800
@@ -14,7 +14,7 @@
 #endif
 #ifdef CONFIG_8260
 #include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
+#include <asm/immap_cpm2.h>
 #endif
 #ifdef CONFIG_4xx
 #include <asm/io.h>
@@ -394,10 +394,10 @@
 clk_8260(bd_t *bd)
 {
 	uint	scmr, vco_out, clkin;
-	uint	plldf, pllmf, busdf, brgdf, cpmdf;
-	volatile immap_t	*ip;
+	uint	plldf, pllmf, busdf, cpmdf;
+	volatile cpm2_map_t	*ip;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 	scmr = ip->im_clkrst.car_scmr;
 
 	/* The clkin is always bus frequency.
@@ -502,7 +502,6 @@
 embed_config(bd_t **bdp)
 {
 	u_char	*cp, *keyvals;
-	int	i;
 	bd_t	*bd;
 
 	keyvals = (u_char *)*bdp;
@@ -582,7 +581,7 @@
 	*/
 	bd->bi_intfreq = 200000000;
 }
-#endif /* RPX6 for testing */
+#endif /* RPX6 */
 
 #ifdef CONFIG_ADS8260
 void
diff -urN linux-2.4.26-pre2/arch/ppc/boot/simple/m8260_tty.c linux-2.4.26-pre3/arch/ppc/boot/simple/m8260_tty.c
--- linux-2.4.26-pre2/arch/ppc/boot/simple/m8260_tty.c	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/boot/simple/m8260_tty.c	2004-03-13 07:43:22.000000000 -0800
@@ -3,7 +3,8 @@
  */
 #include <linux/types.h>
 #include <asm/mpc8260.h>
-#include <asm/cpm_8260.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
 
 uint	no_print;
 extern char	*params[];
@@ -29,12 +30,12 @@
 	volatile scc_uart_t	*sup;
 #endif
 	volatile cbd_t	*tbdf, *rbdf;
-	volatile immap_t	*ip;
-	volatile iop8260_t	*io;
-	volatile cpm8260_t	*cp;
+	volatile cpm2_map_t	*ip;
+	volatile iop_cpm2_t	*io;
+	volatile cpm_cpm2_t	*cp;
 	uint	dpaddr, memaddr;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 	cp = &ip->im_cpm;
 	io = &ip->im_ioport;
 
@@ -223,10 +224,10 @@
 	volatile char		*buf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 	int	i, nc;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
@@ -255,10 +256,10 @@
 	volatile char		*buf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 	extern bd_t		*board_info;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
 	tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
@@ -298,9 +299,9 @@
 	volatile cbd_t		*rbdf;
 	volatile smc_uart_t	*up;
 	volatile scc_uart_t	*sup;
-	volatile immap_t	*ip;
+	volatile cpm2_map_t	*ip;
 
-	ip = (immap_t *)IMAP_ADDR;
+	ip = (cpm2_map_t *)CPM_MAP_ADDR;
 #ifdef SCC_CONSOLE
 	sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
 	rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
diff -urN linux-2.4.26-pre2/arch/ppc/config.in linux-2.4.26-pre3/arch/ppc/config.in
--- linux-2.4.26-pre2/arch/ppc/config.in	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/config.in	2004-03-13 07:43:22.000000000 -0800
@@ -57,7 +57,16 @@
 
 if [ "$CONFIG_8260" = "y" ]; then
   define_bool CONFIG_SERIAL_CONSOLE y
-  bool 'Support for EST8260' CONFIG_EST8260
+  define_bool CONFIG_CPM2 y
+  bool '  MPC8272 Family Support' CONFIG_8272
+  choice 'Machine Type'	\
+	"ADS8272	CONFIG_ADS8272	\
+	 EST8260	CONFIG_EST8260 \
+	 RPX8260	CONFIG_RPX6"	RPX8260
+fi
+
+if [ "$CONFIG_ADS8272" = "y" ]; then
+  define_bool CONFIG_PQ2ADS y
 fi
 
 if [ "$CONFIG_40x" = "y" ]; then
@@ -572,8 +581,8 @@
 source arch/ppc/8xx_io/Config.in
 fi
 
-if [ "$CONFIG_8260" = "y" ]; then
-source arch/ppc/8260_io/Config.in
+if [ "$CONFIG_CPM2" = "y" ]; then
+source arch/ppc/cpm2_io/Config.in
 fi
 
 source drivers/usb/Config.in
diff -urN linux-2.4.26-pre2/arch/ppc/configs/ads8272_defconfig linux-2.4.26-pre3/arch/ppc/configs/ads8272_defconfig
--- linux-2.4.26-pre2/arch/ppc/configs/ads8272_defconfig	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/configs/ads8272_defconfig	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,629 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_ADVANCED_OPTIONS=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+CONFIG_8272=y
+CONFIG_ADS8272=y
+# CONFIG_EST8260 is not set
+CONFIG_PQ2ADS=y
+# CONFIG_SMP is not set
+CONFIG_EMBEDDEDBOOT=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+# CONFIG_KERNEL_START_BOOL is not set
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+#   IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+#   IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+# CONFIG_IRPORT_SIR is not set
+# CONFIG_DONGLE is not set
+# CONFIG_USB_IRDA is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_OLD is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_IRCC_FIR is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=m
+CONFIG_INPUT_KEYBDEV=m
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+# CONFIG_INPUT_SERIO is not set
+# CONFIG_INPUT_SERPORT is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=m
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+CONFIG_TMPFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_UNIX is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8260 CPM Options
+#
+CONFIG_SCC_CONSOLE=y
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+CONFIG_FCC1_ENET=y
+CONFIG_FCC2_ENET=y
+# CONFIG_FCC3_ENET is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.26-pre2/arch/ppc/configs/est8260_defconfig linux-2.4.26-pre3/arch/ppc/configs/est8260_defconfig
--- linux-2.4.26-pre2/arch/ppc/configs/est8260_defconfig	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/configs/est8260_defconfig	2004-03-13 07:43:22.000000000 -0800
@@ -1,5 +1,5 @@
 #
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
 #
 # CONFIG_UID16 is not set
 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
@@ -10,6 +10,7 @@
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
 
 #
 # Loadable module support
@@ -22,13 +23,17 @@
 CONFIG_PPC=y
 CONFIG_PPC32=y
 CONFIG_6xx=y
-# CONFIG_4xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
 CONFIG_8260=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+# CONFIG_8272 is not set
+# CONFIG_ADS8272 is not set
 CONFIG_EST8260=y
 # CONFIG_SMP is not set
 CONFIG_EMBEDDEDBOOT=y
@@ -37,11 +42,16 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
 # CONFIG_MCA is not set
 # CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -81,6 +91,7 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -126,12 +137,14 @@
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
 
 #
-#  
+#    SCTP Configuration (EXPERIMENTAL)
 #
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 
@@ -280,6 +293,7 @@
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Macintosh device drivers
@@ -310,14 +324,6 @@
 # Joysticks
 #
 # CONFIG_INPUT_GAMEPORT is not set
-
-#
-# Input core support is needed for gameports
-#
-
-#
-# Input core support is needed for joysticks
-#
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_IPMI_PANIC_EVENT is not set
@@ -329,6 +335,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
@@ -342,6 +349,10 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 # CONFIG_DRM is not set
 
 #
@@ -353,6 +364,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -362,6 +374,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -403,6 +416,11 @@
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -411,6 +429,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
@@ -466,13 +485,24 @@
 # CONFIG_USB is not set
 
 #
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # Bluetooth support
 #
 # CONFIG_BLUEZ is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
@@ -480,3 +510,4 @@
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.26-pre2/arch/ppc/configs/rpx8260_defconfig linux-2.4.26-pre3/arch/ppc/configs/rpx8260_defconfig
--- linux-2.4.26-pre2/arch/ppc/configs/rpx8260_defconfig	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/configs/rpx8260_defconfig	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,535 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E500 is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_8260=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_CPM2=y
+# CONFIG_8272 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_EST8260 is not set
+CONFIG_RPX6=y
+# CONFIG_SMP is not set
+CONFIG_EMBEDDEDBOOT=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_STATS is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_GIANFAR is not set
+# CONFIG_GFAR_NAPI is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+
+#
+# Input core support is needed for gameports
+#
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# MPC8260 CPM Options
+#
+# CONFIG_SCC_CONSOLE is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_FCC1_ENET is not set
+# CONFIG_FCC2_ENET is not set
+CONFIG_FCC3_ENET=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/Config.in linux-2.4.26-pre3/arch/ppc/cpm2_io/Config.in
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/Config.in	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/Config.in	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,26 @@
+#
+# MPC8260 Communication options
+#
+mainmenu_option next_comment
+comment 'MPC8260 CPM Options'
+bool 'Enable SCC Console' CONFIG_SCC_CONSOLE
+if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+  bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
+  if [ "$CONFIG_SCC_ENET" = "y" ]; then
+  bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
+    if [ "$CONFIG_SCC1_ENET" != "y" ]; then
+      bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
+    fi
+  fi
+#
+#  CONFIG_FEC_ENET is only used to get netdevices to call our init
+#    function.  Any combination of FCC1,2,3 are supported.
+#
+  bool 'FCC Ethernet' CONFIG_FEC_ENET
+  if [ "$CONFIG_FEC_ENET" = "y" ]; then
+    bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+    bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+    bool 'Ethernet on FCC3' CONFIG_FCC3_ENET
+  fi
+fi
+endmenu
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/Makefile linux-2.4.26-pre3/arch/ppc/cpm2_io/Makefile
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/Makefile	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux CPM2 ppc-specific parts of comm processor
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET		:= cpm2_io.o
+
+obj-y			:= commproc.o uart.o
+
+obj-$(CONFIG_FEC_ENET)	+= fcc_enet.o
+obj-$(CONFIG_SCC_ENET)	+= enet.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/commproc.c linux-2.4.26-pre3/arch/ppc/cpm2_io/commproc.c
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/commproc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/commproc.c	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,179 @@
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *	2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+
+static	uint	dp_alloc_base;	/* Starting offset in DP ram */
+static	uint	dp_alloc_top;	/* Max offset + 1 */
+static	uint	host_buffer;	/* One page of host buffer */
+static	uint	host_end;	/* end + 1 */
+cpm_cpm2_t	*cpmp;		/* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+cpm2_map_t		*cpm2_immr;
+
+void
+cpm2_reset(void)
+{
+	volatile cpm2_map_t	 *imp;
+	volatile cpm_cpm2_t	*commproc;
+	uint			vpgaddr;
+
+	cpm2_immr = imp = (volatile cpm2_map_t *)CPM_MAP_ADDR;
+	commproc = &imp->im_cpm;
+
+	/* Reclaim the DP memory for our use.
+	*/
+	dp_alloc_base = CPM_DATAONLY_BASE;
+	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+
+	/* Set the host page for allocation.
+	*/
+	host_buffer =
+		(uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
+	host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
+
+	vpgaddr = host_buffer;
+
+	/* Tell everyone where the comm processor resides.
+	*/
+	cpmp = (cpm_cpm2_t *)commproc;
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+cpm2_dpalloc(uint size, uint align)
+{
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = dp_alloc_base;
+
+	if ((off = (dp_alloc_base & align_mask)) != 0)
+		dp_alloc_base += (align - off);
+
+	if ((dp_alloc_base + size) >= dp_alloc_top) {
+		dp_alloc_base = savebase;
+		return(CPM_DP_NOSPACE);
+	}
+
+	retloc = dp_alloc_base;
+	dp_alloc_base += size;
+
+	return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+cpm2_hostalloc(uint size, uint align)
+{
+	uint	retloc;
+	uint	align_mask, off;
+	uint	savebase;
+
+	align_mask = align - 1;
+	savebase = host_buffer;
+
+	if ((off = (host_buffer & align_mask)) != 0)
+		host_buffer += (align - off);
+
+	if ((host_buffer + size) >= host_end) {
+		host_buffer = savebase;
+		return(0);
+	}
+
+	retloc = host_buffer;
+	host_buffer += size;
+
+	return(retloc);
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK	(((bd_t *)__res)->bi_brgfreq)
+#define BRG_UART_CLK	(BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+cpm2_setbrg(uint brg, uint rate)
+{
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+cpm2_fastbrg(uint brg, uint rate, int div16)
+{
+	volatile uint	*bp;
+
+	if (brg < 4) {
+		bp = (uint *)&cpm2_immr->im_brgc1;
+	}
+	else {
+		bp = (uint *)&cpm2_immr->im_brgc5;
+		brg -= 4;
+	}
+	bp += brg;
+	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+	if (div16)
+		*bp |= CPM_BRG_DIV16;
+}
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/enet.c linux-2.4.26-pre3/arch/ppc/cpm2_io/enet.c
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/enet.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/enet.c	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,857 @@
+/*
+ * Ethernet driver for Motorola MPC8260.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
+ *	2.3.99 Updates
+ *
+ * I copied this from the 8xx CPM Ethernet driver, so follow the
+ * credits back through that.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations.  It works for the boards I know about
+ * now, and should be easily modified to include others.  Some of the
+ * configuration information is contained in <asm/commproc.h> and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+
+/*
+ *				Theory of Operation
+ *
+ * The MPC8260 CPM performs the Ethernet processing on an SCC.  It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols.  The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers.  The size of the buffers should be a power of two,
+ * since that nicely divides the page.  This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control.  One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag.  The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT	(2*HZ)
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#define CPM_ENET_RX_PAGES	4
+#define CPM_ENET_RX_FRSIZE	2048
+#define CPM_ENET_RX_FRPPG	(PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE		8	/* Must be power of two */
+#define TX_RING_MOD_MASK	7	/*   for this to work */
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+#define PKT_MAXBLR_SIZE		1520
+
+/* The CPM buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses.
+	*/
+	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
+	cbd_t	*tx_bd_base;
+	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
+	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	scc_t	*sccp;
+	struct	net_device_stats stats;
+	uint	tx_free;
+	spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* These will be configurable for the SCC choice.
+*/
+#define CPM_ENET_BLOCK	CPM_CR_SCC1_SBLOCK
+#define CPM_ENET_PAGE	CPM_CR_SCC1_PAGE
+#define PROFF_ENET	PROFF_SCC1
+#define SCC_ENET	0
+#define SIU_INT_ENET	SIU_INT_SCC1
+
+/* These are both board and SCC dependent....
+*/
+#define PD_ENET_RXD	((uint)0x00000001)
+#define PD_ENET_TXD	((uint)0x00000002)
+#define PD_ENET_TENA	((uint)0x00000004)
+#define PC_ENET_RENA	((uint)0x00020000)
+#define PC_ENET_CLSN	((uint)0x00000004)
+#define PC_ENET_TXCLK	((uint)0x00000800)
+#define PC_ENET_RXCLK	((uint)0x00000400)
+#define CMX_CLK_ROUTE	((uint)0x25000000)
+#define CMX_CLK_MASK	((uint)0xff000000)
+
+/* Specific to a board.
+*/
+#define PC_EST8260_ENET_LOOPBACK	((uint)0x80000000)
+#define PC_EST8260_ENET_SQE		((uint)0x40000000)
+#define PC_EST8260_ENET_NOTFD		((uint)0x20000000)
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+	/* I should reset the ring buffers here, but I don't yet know
+	 * a simple way to do that.
+	 */
+	netif_start_queue(dev);
+	return 0;					/* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+
+
+	/* Fill in a Tx ring entry */
+	bdp = cep->cur_tx;
+
+#ifndef final_version
+	if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since the tx queue should be stopped.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags.
+	 */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+	/* If the frame is short, tell CPM to pad it.
+	*/
+	if (skb->len <= ETH_ZLEN)
+		bdp->cbd_sc |= BD_ENET_TX_PAD;
+	else
+		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+	/* Set buffer length and buffer pointer.
+	*/
+	bdp->cbd_datlen = skb->len;
+	bdp->cbd_bufaddr = __pa(skb->data);
+
+	/* Save skb pointer.
+	*/
+	cep->tx_skbuff[cep->skb_cur] = skb;
+
+	cep->stats.tx_bytes += skb->len;
+	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+	spin_lock_irq(&cep->lock);
+
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
+	 */
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+	dev->trans_start = jiffies;
+
+	/* If this was the last BD in the ring, start at the beginning again.
+	*/
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = cep->tx_bd_base;
+	else
+		bdp++;
+
+	if (!--cep->tx_free)
+		netif_stop_queue(dev);
+
+	cep->cur_tx = (cbd_t *)bdp;
+
+	spin_unlock_irq(&cep->lock);
+
+	return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+	printk("%s: transmit timed out.\n", dev->name);
+	cep->stats.tx_errors++;
+#ifndef final_version
+	{
+		int	i;
+		cbd_t	*bdp;
+		printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
+		       cep->cur_tx, cep->tx_free,
+		       cep->cur_rx);
+		bdp = cep->tx_bd_base;
+		printk(" Tx @base %p :\n", bdp);
+		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+		bdp = cep->rx_bd_base;
+		printk(" Rx @base %p :\n", bdp);
+		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+	}
+#endif
+	if (cep->tx_free)
+		netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	volatile struct	scc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	ushort	int_events;
+	int	must_restart;
+
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* Get the interrupt events that caused us to be here.
+	*/
+	int_events = cep->sccp->scc_scce;
+	cep->sccp->scc_scce = int_events;
+	must_restart = 0;
+
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & SCCE_ENET_RXF)
+		scc_enet_rx(dev_id);
+
+	/* Check for a transmit error.  The manual is a little unclear
+	 * about this, so the debug code until I get it figured out.  It
+	 * appears that if TXE is set, then TXB is not set.  However,
+	 * if carrier sense is lost during frame transmission, the TXE
+	 * bit is set, "and continues the buffer transmission normally."
+	 * I don't know if "normally" implies TXB is set when the buffer
+	 * descriptor is closed.....trial and error :-).
+	 */
+
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	*/
+	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+	    spin_lock(&cep->lock);
+	    bdp = cep->dirty_tx;
+	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+		if (cep->tx_free == TX_RING_SIZE)
+		    break;
+
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+			cep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+			cep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+			cep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+			cep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+			cep->stats.tx_carrier_errors++;
+
+
+		/* No heartbeat or Lost carrier are not really bad errors.
+		 * The others require a restart transmit command.
+		 */
+		if (bdp->cbd_sc &
+		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+			must_restart = 1;
+			cep->stats.tx_errors++;
+		}
+
+		cep->stats.tx_packets++;
+
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+			cep->stats.collisions++;
+
+		/* Free the sk buffer associated with this last transmit.
+		*/
+		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+		/* Update pointer to next buffer descriptor to be transmitted.
+		*/
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+			bdp = cep->tx_bd_base;
+		else
+			bdp++;
+
+		/* I don't know if we can be held off from processing these
+		 * interrupts for more than one frame time.  I really hope
+		 * not.  In such a case, we would now want to check the
+		 * currently available BD (cur_tx) and determine if any
+		 * buffers between the dirty_tx and cur_tx have also been
+		 * sent.  We would want to process anything in between that
+		 * does not have BD_ENET_TX_READY set.
+		 */
+
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (!cep->tx_free++) {
+			if (netif_queue_stopped(dev)) {
+				netif_wake_queue(dev);
+			}
+		}
+
+		cep->dirty_tx = (cbd_t *)bdp;
+	    }
+
+	    if (must_restart) {
+		volatile cpm_cpm2_t *cp;
+
+		/* Some transmit errors cause the transmitter to shut
+		 * down.  We now issue a restart transmit.  Since the
+		 * errors close the BD and update the pointers, the restart
+		 * _should_ pick up without having to reset any of our
+		 * pointers either.
+		 */
+
+		cp = cpmp;
+		cp->cp_cpcr =
+		    mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+		    			CPM_CR_RESTART_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	    }
+	    spin_unlock(&cep->lock);
+	}
+
+	/* Check for receive busy, i.e. packets coming but no place to
+	 * put them.
+	 */
+	if (int_events & SCCE_ENET_BSY)
+		cep->stats.rx_dropped++;
+
+	return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+	struct	scc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	struct	sk_buff *skb;
+	ushort	pkt_len;
+
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = cep->cur_rx;
+
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame, both
+	 * the first and last indicators should be set.
+	 */
+	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+			printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+	/* Frame too long or too short.
+	*/
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		cep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		cep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		cep->stats.rx_crc_errors++;
+
+	/* Report late collisions as a frame error.
+	 * On this error, the BD is closed, but we don't know what we
+	 * have in the buffer.  So, just drop this frame on the floor.
+	 */
+	if (bdp->cbd_sc & BD_ENET_RX_CL) {
+		cep->stats.rx_frame_errors++;
+	}
+	else {
+
+		/* Process the incoming frame.
+		*/
+		cep->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		cep->stats.rx_bytes += pkt_len;
+
+		/* This does 16 byte alignment, much more than we need.
+		 * The packet length includes FCS, but we don't want to
+		 * include that when passing upstream as it messes up
+		 * bridging applications.
+		 */
+		skb = dev_alloc_skb(pkt_len-4);
+
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			cep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len-4);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len-4, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
+
+	/* Clear the status flags for this buffer.
+	*/
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+	/* Mark the buffer empty.
+	*/
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry.
+	*/
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = cep->rx_bd_base;
+	else
+		bdp++;
+
+   }
+	cep->cur_rx = (cbd_t *)bdp;
+
+	return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+	/* Don't know what to do yet.
+	*/
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+	struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+	return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct	scc_enet_private *cep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile scc_enet_t *ep;
+	int	i, j;
+	cep = (struct scc_enet_private *)dev->priv;
+
+	/* Get pointer to SCC area in parameter RAM.
+	*/
+	ep = (scc_enet_t *)dev->base_addr;
+
+	if (dev->flags&IFF_PROMISC) {
+
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		cep->sccp->scc_psmr |= SCC_PSMR_PRO;
+	} else {
+
+		cep->sccp->scc_psmr &= ~SCC_PSMR_PRO;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->sen_gaddr1 = 0xffff;
+			ep->sen_gaddr2 = 0xffff;
+			ep->sen_gaddr3 = 0xffff;
+			ep->sen_gaddr4 = 0xffff;
+		}
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->sen_gaddr1 = 0;
+			ep->sen_gaddr2 = 0;
+			ep->sen_gaddr3 = 0;
+			ep->sen_gaddr4 = 0;
+
+			dmi = dev->mc_list;
+
+			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->sen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
+						CPM_ENET_BLOCK, 0,
+						CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				/* this delay is necessary here -- Cort */
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+	}
+}
+
+/* Initialize the CPM Ethernet on SCC.
+ */
+int __init scc_enet_init(void)
+{
+	struct net_device *dev;
+	struct scc_enet_private *cep;
+	int i, j;
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	bd_t		*bd;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	scc_t		*sccp;
+	volatile	scc_enet_t	*ep;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	cp = cpmp;	/* Get pointer to Communication Processor */
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
+	io = &immap->im_ioport;
+
+	bd = (bd_t *)__res;
+
+	/* Allocate some private information.
+	*/
+	cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+	if (cep == NULL)
+		return -ENOMEM;
+
+	__clear_user(cep,sizeof(*cep));
+	spin_lock_init(&cep->lock);
+
+	/* Create an Ethernet device instance.
+	*/
+	dev = init_etherdev(0, 0);
+
+	/* Get pointer to SCC area in parameter RAM.
+	*/
+	ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
+
+	/* And another to the SCC register area.
+	*/
+	sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
+	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
+
+	/* Disable receive and transmit in case someone left it running.
+	*/
+	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* Configure port C and D pins for SCC Ethernet.  This
+	 * won't work for all SCC possibilities....it will be
+	 * board/port specific.
+	 */
+	io->iop_pparc |=
+		(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_pdirc &=
+		~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_psorc &=
+		~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
+	io->iop_psorc |= PC_ENET_CLSN;
+
+	io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
+	io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
+	io->iop_pdird &= ~PD_ENET_RXD;
+	io->iop_psord |= PD_ENET_TXD;
+	io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
+
+	/* Configure Serial Interface clock routing.
+	 * First, clear all SCC bits to zero, then set the ones we want.
+	 */
+	immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
+	immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
+
+	/* Allocate space for the buffer descriptors in the DP ram.
+	 * These are relative offsets in the DP ram address space.
+	 * Initialize base addresses for the buffer descriptors.
+	 */
+	i = cpm2_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->sen_genscc.scc_rbase = i;
+	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	i = cpm2_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->sen_genscc.scc_tbase = i;
+	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+	cep->tx_free = TX_RING_SIZE;
+	cep->cur_rx = cep->rx_bd_base;
+
+	ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	/* Set maximum bytes per receive buffer.
+	 * This appears to be an Ethernet frame size, not the buffer
+	 * fragment size.  It must be a multiple of four.
+	 */
+	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+	/* Set CRC preset and mask.
+	*/
+	ep->sen_cpres = 0xffffffff;
+	ep->sen_cmask = 0xdebb20e3;
+
+	ep->sen_crcec = 0;	/* CRC Error counter */
+	ep->sen_alec = 0;	/* alignment error counter */
+	ep->sen_disfc = 0;	/* discard frame counter */
+
+	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
+	ep->sen_retlim = 15;	/* Retry limit threshold */
+
+	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+	ep->sen_maxd1 = PKT_MAXBLR_SIZE;	/* maximum DMA1 length */
+	ep->sen_maxd2 = PKT_MAXBLR_SIZE;	/* maximum DMA2 length */
+
+	/* Clear hash tables.
+	*/
+	ep->sen_gaddr1 = 0;
+	ep->sen_gaddr2 = 0;
+	ep->sen_gaddr3 = 0;
+	ep->sen_gaddr4 = 0;
+	ep->sen_iaddr1 = 0;
+	ep->sen_iaddr2 = 0;
+	ep->sen_iaddr3 = 0;
+	ep->sen_iaddr4 = 0;
+
+	/* Set Ethernet station address.
+	 *
+	 * This is supplied in the board information structure, so we
+	 * copy that into the controller.
+	 */
+	eap = (unsigned char *)&(ep->sen_paddrh);
+	for (i=5; i>=0; i--)
+		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+	ep->sen_pper = 0;	/* 'cause the book says so */
+	ep->sen_taddrl = 0;	/* temp address (LSB) */
+	ep->sen_taddrm = 0;
+	ep->sen_taddrh = 0;	/* temp address (MSB) */
+
+	/* Now allocate the host memory pages and initialize the
+	 * buffer descriptors.
+	 */
+	bdp = cep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = cep->rx_bd_base;
+	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += CPM_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* Let's re-initialize the channel now.  We have to do it later
+	 * than the manual describes because we have just now finished
+	 * the BD initialization.
+	 */
+	cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	cep->skb_cur = cep->skb_dirty = 0;
+
+	sccp->scc_scce = 0xffff;	/* Clear any pending events */
+
+	/* Enable interrupts for transmit error, complete frame
+	 * received, and any transmit buffer we have also set the
+	 * interrupt flag.
+	 */
+	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+	/* Install our interrupt handler.
+	*/
+	request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+
+	/* Set GSMR_H to enable all normal operating modes.
+	 * Set GSMR_L to enable Ethernet to MC68160.
+	 */
+	sccp->scc_gsmrh = 0;
+	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+	/* Set sync/delimiters.
+	*/
+	sccp->scc_dsr = 0xd555;
+
+	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
+	 * start frame search 22 bit times after RENA.
+	 */
+	sccp->scc_psmr = (SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
+
+	/* It is now OK to enable the Ethernet transmitter.
+	 * Unfortunately, there are board implementation differences here.
+	 */
+	io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
+				PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+	io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
+	io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
+
+	dev->base_addr = (unsigned long)ep;
+	dev->priv = cep;
+
+	/* The CPM Ethernet specific entries in the device structure. */
+	dev->open = scc_enet_open;
+	dev->hard_start_xmit = scc_enet_start_xmit;
+	dev->tx_timeout = scc_enet_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->stop = scc_enet_close;
+	dev->get_stats = scc_enet_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+
+	/* And last, enable the transmit and receive processing.
+	*/
+	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	printk("%s: SCC ENET Version 0.1, ", dev->name);
+	for (i=0; i<5; i++)
+		printk("%02x:", dev->dev_addr[i]);
+	printk("%02x\n", dev->dev_addr[5]);
+
+	return 0;
+}
+
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/fcc_enet.c linux-2.4.26-pre3/arch/ppc/cpm2_io/fcc_enet.c
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/fcc_enet.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/fcc_enet.c	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,2007 @@
+/*
+ * Fast Ethernet Controller (FCC) driver for Motorola MPC8260.
+ * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is a combination of the 8xx fec and
+ * 8260 SCC Ethernet drivers.  This version has some additional
+ * configuration options, which should probably be moved out of
+ * here.  This driver currently works for the EST SBC8260,
+ * SBS Diablo/BCM, Embedded Planet RPX6, TQM8260, and others.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.  Since this is a cache coherent processor and CPM,
+ * I could also preallocate SKB's and use them directly on the interface.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm2.h>
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT	(2*HZ)
+
+#ifdef	CONFIG_USE_MDIO
+/* Forward declarations of some structures to support different PHYs */
+
+typedef struct {
+	uint mii_data;
+	void (*funct)(uint mii_reg, struct net_device *dev);
+} phy_cmd_t;
+
+typedef struct {
+	uint id;
+	char *name;
+
+	const phy_cmd_t *config;
+	const phy_cmd_t *startup;
+	const phy_cmd_t *ack_int;
+	const phy_cmd_t *shutdown;
+} phy_info_t;
+
+/* Register definitions for the PHY. */
+
+#define MII_REG_CR          0  /* Control Register                         */
+#define MII_REG_SR          1  /* Status Register                          */
+#define MII_REG_PHYIR1      2  /* PHY Identification Register 1            */
+#define MII_REG_PHYIR2      3  /* PHY Identification Register 2            */
+#define MII_REG_ANAR        4  /* A-N Advertisement Register               */
+#define MII_REG_ANLPAR      5  /* A-N Link Partner Ability Register        */
+#define MII_REG_ANER        6  /* A-N Expansion Register                   */
+#define MII_REG_ANNPTR      7  /* A-N Next Page Transmit Register          */
+#define MII_REG_ANLPRNPR    8  /* A-N Link Partner Received Next Page Reg. */
+
+/* values for phy_status */
+
+#define PHY_CONF_ANE	0x0001  /* 1 auto-negotiation enabled */
+#define PHY_CONF_LOOP	0x0002  /* 1 loopback mode enabled */
+#define PHY_CONF_SPMASK	0x00f0  /* mask for speed */
+#define PHY_CONF_10HDX	0x0010  /* 10 Mbit half duplex supported */
+#define PHY_CONF_10FDX	0x0020  /* 10 Mbit full duplex supported */
+#define PHY_CONF_100HDX	0x0040  /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX	0x0080  /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK	0x0100  /* 1 up - 0 down */
+#define PHY_STAT_FAULT	0x0200  /* 1 remote fault */
+#define PHY_STAT_ANC	0x0400  /* 1 auto-negotiation complete	*/
+#define PHY_STAT_SPMASK	0xf000  /* mask for speed */
+#define PHY_STAT_10HDX	0x1000  /* 10 Mbit half duplex selected	*/
+#define PHY_STAT_10FDX	0x2000  /* 10 Mbit full duplex selected	*/
+#define PHY_STAT_100HDX	0x4000  /* 100 Mbit half duplex selected */
+#define PHY_STAT_100FDX	0x8000  /* 100 Mbit full duplex selected */
+#endif	/* CONFIG_USE_MDIO */
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#define FCC_ENET_RX_PAGES	16
+#define FCC_ENET_RX_FRSIZE	2048
+#define FCC_ENET_RX_FRPPG	(PAGE_SIZE / FCC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES)
+#define TX_RING_SIZE		16	/* Must be power of two */
+#define TX_RING_MOD_MASK	15	/*   for this to work */
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+
+/* Maximum input DMA size.  Must be a should(?) be a multiple of 4.
+*/
+#define PKT_MAXDMA_SIZE		1520
+
+/* Maximum input buffer size.  Must be a multiple of 32.
+*/
+#define PKT_MAXBLR_SIZE		1536
+
+static int fcc_enet_open(struct net_device *dev);
+static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int fcc_enet_rx(struct net_device *dev);
+static	void fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fcc_enet_close(struct net_device *dev);
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void fcc_restart(struct net_device *dev, int duplex);
+static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
+
+/* These will be configurable for the FCC choice.
+ * Multiple ports can be configured.  There is little choice among the
+ * I/O pins to the PHY, except the clocks.  We will need some board
+ * dependent clock selection.
+ * Why in the hell did I put these inside #ifdef's?  I dunno, maybe to
+ * help show what pins are used for each device.
+ */
+
+/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL		((uint)0x00000001)
+#define PA1_CRS		((uint)0x00000002)
+#define PA1_TXER	((uint)0x00000004)
+#define PA1_TXEN	((uint)0x00000008)
+#define PA1_RXDV	((uint)0x00000010)
+#define PA1_RXER	((uint)0x00000020)
+#define PA1_TXDAT	((uint)0x00003c00)
+#define PA1_RXDAT	((uint)0x0003c000)
+#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+				PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+/* CLK12 is receive, CLK11 is transmit.  These are board specific.
+*/
+#ifdef CONFIG_ADS8272
+#define PC_F1RXCLK	((uint)0x00000400)
+#define PC_F1TXCLK	((uint)0x00000200)
+#define CMX1_CLK_ROUTE	((uint)0x36000000)
+#define CMX1_CLK_MASK	((uint)0xff000000)
+#else
+#define PC_F1RXCLK	((uint)0x00000800)
+#define PC_F1TXCLK	((uint)0x00000400)
+#define CMX1_CLK_ROUTE	((uint)0x3e000000)
+#define CMX1_CLK_MASK	((uint)0xff000000)
+#endif
+
+/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER	((uint)0x00000001)
+#define PB2_RXDV	((uint)0x00000002)
+#define PB2_TXEN	((uint)0x00000004)
+#define PB2_RXER	((uint)0x00000008)
+#define PB2_COL		((uint)0x00000010)
+#define PB2_CRS		((uint)0x00000020)
+#define PB2_TXDAT	((uint)0x000003c0)
+#define PB2_RXDAT	((uint)0x00003c00)
+#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+				PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1	(PB2_TXEN)
+#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+/* CLK13 is receive, CLK14 is transmit.  These are board dependent.
+*/
+#ifdef CONFIG_ADS8272
+#define PC_F2RXCLK	((uint)0x00004000)
+#define PC_F2TXCLK	((uint)0x00008000)
+#define CMX2_CLK_ROUTE	((uint)0x00370000)
+#define CMX2_CLK_MASK	((uint)0x00ff0000)
+#else
+#define PC_F2RXCLK	((uint)0x00001000)
+#define PC_F2TXCLK	((uint)0x00002000)
+#define CMX2_CLK_ROUTE	((uint)0x00250000)
+#define CMX2_CLK_MASK	((uint)0x00ff0000)
+#endif
+
+/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV	((uint)0x00004000)
+#define PB3_RXER	((uint)0x00008000)
+#define PB3_TXER	((uint)0x00010000)
+#define PB3_TXEN	((uint)0x00020000)
+#define PB3_COL		((uint)0x00040000)
+#define PB3_CRS		((uint)0x00080000)
+#define PB3_TXDAT	((uint)0x0f000000)
+#define PB3_RXDAT	((uint)0x00f00000)
+#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+				PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1	(0)
+#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+/* CLK15 is receive, CLK16 is transmit.  These are board dependent.
+*/
+#define PC_F3RXCLK	((uint)0x00004000)
+#define PC_F3TXCLK	((uint)0x00008000)
+#define CMX3_CLK_ROUTE	((uint)0x00003700)
+#define CMX3_CLK_MASK	((uint)0x0000ff00)
+
+/* MII status/control serial interface.
+*/
+#ifdef	CONFIG_TQM8260
+/* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
+#define PC_MDIO		((uint)0x00000002)
+#define PC_MDCK		((uint)0x00000001)
+#elif defined(CONFIG_ADS8272)
+#define PC_MDIO		((uint)0x00002000)
+#define PC_MDCK		((uint)0x00001000)
+#else
+#define PC_MDIO		((uint)0x00000004)
+#define PC_MDCK		((uint)0x00000020)
+#endif
+
+/* A table of information for supporting FCCs.  This does two things.
+ * First, we know how many FCCs we have and they are always externally
+ * numbered from zero.  Second, it holds control register and I/O
+ * information that could be different among board designs.
+ */
+typedef struct fcc_info {
+	uint	fc_fccnum;
+	uint	fc_cpmblock;
+	uint	fc_cpmpage;
+	uint	fc_proff;
+	uint	fc_interrupt;
+	uint	fc_trxclocks;
+	uint	fc_clockroute;
+	uint	fc_clockmask;
+	uint	fc_mdio;
+	uint	fc_mdck;
+} fcc_info_t;
+
+static fcc_info_t fcc_ports[] = {
+#ifdef CONFIG_FCC1_ENET
+	{ 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+		(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# else
+		0x00000004, 0x00000100 },
+# endif
+#endif
+#ifdef CONFIG_FCC2_ENET
+	{ 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+		(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
+		0x00400000, 0x00200000 },
+# else
+		0x00000002, 0x00000080 },
+# endif
+#endif
+#ifdef CONFIG_FCC3_ENET
+	{ 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+		(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
+# if defined(CONFIG_TQM8260) || defined (CONFIG_ADS8272)
+		PC_MDIO, PC_MDCK },
+# else
+		0x00000001, 0x00000040 },
+# endif
+#endif
+};
+
+/* The FCC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fcc_enet_private {
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses.
+	*/
+	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
+	cbd_t	*tx_bd_base;
+	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
+	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	volatile fcc_t	*fccp;
+	volatile fcc_enet_t	*ep;
+	struct	net_device_stats stats;
+	uint	tx_full;
+	spinlock_t lock;
+
+#ifdef	CONFIG_USE_MDIO
+	uint	phy_id;
+	uint	phy_id_done;
+	uint	phy_status;
+	phy_info_t	*phy;
+	struct tq_struct phy_task;
+
+	uint	sequence_done;
+
+	uint	phy_addr;
+#endif	/* CONFIG_USE_MDIO */
+
+	int	link;
+	int	old_link;
+	int	full_duplex;
+
+	fcc_info_t	*fip;
+};
+
+static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+	volatile cpm2_map_t *immap);
+static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev);
+static void init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+	volatile cpm2_map_t *immap);
+static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+	volatile cpm2_map_t *immap);
+
+#ifdef	CONFIG_USE_MDIO
+static int	mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *));
+static uint	mii_send_receive(fcc_info_t *fip, uint cmd);
+
+static void	fcc_stop(struct net_device *dev);
+
+/* Make MII read/write commands for the FCC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | \
+						(VAL & 0xffff))
+#define mk_mii_end	0
+#endif	/* CONFIG_USE_MDIO */
+
+
+static int
+fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+
+	if (!cep->link) {
+		/* Link is down or autonegotiation is in progress. */
+		return 1;
+	}
+
+	/* Fill in a Tx ring entry */
+	bdp = cep->cur_tx;
+
+#ifndef final_version
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since cep->tx_full should be set.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags. */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+	/* If the frame is short, tell CPM to pad it. */
+	if (skb->len <= ETH_ZLEN)
+		bdp->cbd_sc |= BD_ENET_TX_PAD;
+	else
+		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+	/* Set buffer length and buffer pointer. */
+	bdp->cbd_datlen = skb->len;
+	bdp->cbd_bufaddr = __pa(skb->data);
+
+	/* Save skb pointer. */
+	cep->tx_skbuff[cep->skb_cur] = skb;
+
+	cep->stats.tx_bytes += skb->len;
+	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+	spin_lock_irq(&cep->lock);
+
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
+	 */
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+#if 0
+	/* Errata says don't do this. */
+	cep->fccp->fcc_ftodr = 0x8000;
+#endif
+	dev->trans_start = jiffies;
+
+	/* If this was the last BD in the ring, start at the beginning again. */
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = cep->tx_bd_base;
+	else
+		bdp++;
+
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		netif_stop_queue(dev);
+		cep->tx_full = 1;
+	}
+
+	cep->cur_tx = (cbd_t *)bdp;
+
+	spin_unlock_irq(&cep->lock);
+
+	return 0;
+}
+
+
+static void
+fcc_enet_timeout(struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+	printk("%s: transmit timed out.\n", dev->name);
+	cep->stats.tx_errors++;
+#ifndef final_version
+	{
+		int	i;
+		cbd_t	*bdp;
+		printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+		       cep->cur_tx, cep->tx_full ? " (full)" : "",
+		       cep->cur_rx);
+		bdp = cep->tx_bd_base;
+		printk(" Tx @base %p :\n", bdp);
+		for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+		bdp = cep->rx_bd_base;
+		printk(" Rx @base %p :\n", bdp);
+		for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+			printk("%04x %04x %08x\n",
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+	}
+#endif
+	if (!cep->tx_full)
+		netif_wake_queue(dev);
+}
+
+/* The interrupt handler. */
+static void
+fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	volatile struct	fcc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	ushort	int_events;
+	int	must_restart;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+	/* Get the interrupt events that caused us to be here.
+	*/
+	int_events = cep->fccp->fcc_fcce;
+	cep->fccp->fcc_fcce = int_events;
+	must_restart = 0;
+
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & FCC_ENET_RXF)
+		fcc_enet_rx(dev_id);
+
+	/* Check for a transmit error.  The manual is a little unclear
+	 * about this, so the debug code until I get it figured out.  It
+	 * appears that if TXE is set, then TXB is not set.  However,
+	 * if carrier sense is lost during frame transmission, the TXE
+	 * bit is set, "and continues the buffer transmission normally."
+	 * I don't know if "normally" implies TXB is set when the buffer
+	 * descriptor is closed.....trial and error :-).
+	 */
+
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	*/
+	if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) {
+	    spin_lock(&cep->lock);
+	    bdp = cep->dirty_tx;
+	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+		if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+		    break;
+
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+			cep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+			cep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+			cep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+			cep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+			cep->stats.tx_carrier_errors++;
+
+
+		/* No heartbeat or Lost carrier are not really bad errors.
+		 * The others require a restart transmit command.
+		 */
+		if (bdp->cbd_sc &
+		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+			must_restart = 1;
+			cep->stats.tx_errors++;
+		}
+
+		cep->stats.tx_packets++;
+
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+			cep->stats.collisions++;
+
+		/* Free the sk buffer associated with this last transmit. */
+		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+		/* Update pointer to next buffer descriptor to be transmitted. */
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+			bdp = cep->tx_bd_base;
+		else
+			bdp++;
+
+		/* I don't know if we can be held off from processing these
+		 * interrupts for more than one frame time.  I really hope
+		 * not.  In such a case, we would now want to check the
+		 * currently available BD (cur_tx) and determine if any
+		 * buffers between the dirty_tx and cur_tx have also been
+		 * sent.  We would want to process anything in between that
+		 * does not have BD_ENET_TX_READY set.
+		 */
+
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (cep->tx_full) {
+			cep->tx_full = 0;
+			if (netif_queue_stopped(dev)) {
+				netif_wake_queue(dev);
+			}
+		}
+
+		cep->dirty_tx = (cbd_t *)bdp;
+	    }
+
+	    if (must_restart) {
+		volatile cpm_cpm2_t *cp;
+
+		/* Some transmit errors cause the transmitter to shut
+		 * down.  We now issue a restart transmit.  Since the
+		 * errors close the BD and update the pointers, the restart
+		 * _should_ pick up without having to reset any of our
+		 * pointers either.  Also, To workaround 8260 device erratum 
+		 * CPM37, we must disable and then re-enable the transmitter
+		 * following a Late Collision, Underrun, or Retry Limit error.
+		 */
+		cep->fccp->fcc_gfmr &= ~FCC_GFMR_ENT;
+		udelay(10); /* wait a few microseconds just on principle */
+		cep->fccp->fcc_gfmr |=  FCC_GFMR_ENT;
+
+		cp = cpmp;
+		cp->cp_cpcr =
+		    mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock,
+		    		0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	    }
+	    spin_unlock(&cep->lock);
+	}
+
+	/* Check for receive busy, i.e. packets coming but no place to
+	 * put them.
+	 */
+	if (int_events & FCC_ENET_BSY) {
+		cep->stats.rx_dropped++;
+	}
+	return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fcc_enet_rx(struct net_device *dev)
+{
+	struct	fcc_enet_private *cep;
+	volatile cbd_t	*bdp;
+	struct	sk_buff *skb;
+	ushort	pkt_len;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = cep->cur_rx;
+
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame, both
+	 * the first and last indicators should be set.
+	 */
+	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+			printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+	/* Frame too long or too short. */
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		cep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		cep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CL)	/* Late Collision */
+		cep->stats.rx_frame_errors++;
+
+	if (!(bdp->cbd_sc &
+	      (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR
+	       | BD_ENET_RX_OV | BD_ENET_RX_CL)))
+	{
+		/* Process the incoming frame. */
+		cep->stats.rx_packets++;
+
+		/* Remove the FCS from the packet length. */
+		pkt_len = bdp->cbd_datlen - 4;
+		cep->stats.rx_bytes += pkt_len;
+
+		/* This does 16 byte alignment, much more than we need. */
+		skb = dev_alloc_skb(pkt_len);
+
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			cep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
+
+	/* Clear the status flags for this buffer. */
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+	/* Mark the buffer empty. */
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry. */
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = cep->rx_bd_base;
+	else
+		bdp++;
+
+   }
+	cep->cur_rx = (cbd_t *)bdp;
+
+	return 0;
+}
+
+static int
+fcc_enet_close(struct net_device *dev)
+{
+	/* Don't know what to do yet. */
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev)
+{
+	struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
+
+	return &cep->stats;
+}
+
+#ifdef	CONFIG_USE_MDIO
+
+/* NOTE: Most of the following comes from the FEC driver for 860. The
+ * overall structure of MII code has been retained (as it's proved stable
+ * and well-tested), but actual transfer requests are processed "at once"
+ * instead of being queued (there's no interrupt-driven MII transfer
+ * mechanism, one has to toggle the data/clock bits manually).
+ */
+static int
+mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+{
+	struct fcc_enet_private *fep;
+	int		retval, tmp;
+
+	/* Add PHY address to register command. */
+	fep = dev->priv;
+	regval |= fep->phy_addr << 23;
+
+	retval = 0;
+
+	tmp = mii_send_receive(fep->fip, regval);
+	if (func)
+		func(tmp, dev);
+
+	return retval;
+}
+
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
+{
+	int k;
+
+	if(!c)
+		return;
+
+	for(k = 0; (c+k)->mii_data != mk_mii_end; k++)
+		mii_queue(dev, (c+k)->mii_data, (c+k)->funct);
+}
+
+static void mii_parse_sr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+
+	if (mii_reg & 0x0004)
+		s |= PHY_STAT_LINK;
+	if (mii_reg & 0x0010)
+		s |= PHY_STAT_FAULT;
+	if (mii_reg & 0x0020)
+		s |= PHY_STAT_ANC;
+
+	fep->phy_status = s;
+	fep->link = (s & PHY_STAT_LINK) ? 1 : 0;
+}
+
+static void mii_parse_cr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+
+	if (mii_reg & 0x1000)
+		s |= PHY_CONF_ANE;
+	if (mii_reg & 0x4000)
+		s |= PHY_CONF_LOOP;
+
+	fep->phy_status = s;
+}
+
+static void mii_parse_anar(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_CONF_SPMASK);
+
+	if (mii_reg & 0x0020)
+		s |= PHY_CONF_10HDX;
+	if (mii_reg & 0x0040)
+		s |= PHY_CONF_10FDX;
+	if (mii_reg & 0x0080)
+		s |= PHY_CONF_100HDX;
+	if (mii_reg & 0x00100)
+		s |= PHY_CONF_100FDX;
+
+	fep->phy_status = s;
+}
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT970 is used by many boards				     */
+
+#ifdef CONFIG_FCC_LXT970
+
+#define MII_LXT970_MIRROR    16  /* Mirror register           */
+#define MII_LXT970_IER       17  /* Interrupt Enable Register */
+#define MII_LXT970_ISR       18  /* Interrupt Status Register */
+#define MII_LXT970_CONFIG    19  /* Configuration Register    */
+#define MII_LXT970_CSR       20  /* Chip Status Register      */
+
+static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	if (mii_reg & 0x0800) {
+		if (mii_reg & 0x1000)
+			s |= PHY_STAT_100FDX;
+		else
+			s |= PHY_STAT_100HDX;
+	} else {
+		if (mii_reg & 0x1000)
+			s |= PHY_STAT_10FDX;
+		else
+			s |= PHY_STAT_10HDX;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt970 = {
+	0x07810000,
+	"LXT970",
+
+	(const phy_cmd_t []) {  /* config */
+#if 0
+//		{ mk_mii_write(MII_REG_ANAR, 0x0021), NULL },
+
+		/* Set default operation of 100-TX....for some reason
+		 * some of these bits are set on power up, which is wrong.
+		 */
+		{ mk_mii_write(MII_LXT970_CONFIG, 0), NULL },
+#endif
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+		/* read SR and ISR to acknowledge */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_LXT970_ISR), NULL },
+
+		/* find out the current status */
+
+		{ mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+/* ------------------------------------------------------------------------- */
+/* The Level one LXT971 is used on some of my custom boards                  */
+
+#ifdef CONFIG_FCC_LXT971
+
+/* register definitions for the 971 */
+
+#define MII_LXT971_PCR       16  /* Port Control Register     */
+#define MII_LXT971_SR2       17  /* Status Register 2         */
+#define MII_LXT971_IER       18  /* Interrupt Enable Register */
+#define MII_LXT971_ISR       19  /* Interrupt Status Register */
+#define MII_LXT971_LCR       20  /* LED Control Register      */
+#define MII_LXT971_TCR       30  /* Transmit Control Register */
+
+/*
+ * I had some nice ideas of running the MDIO faster...
+ * The 971 should support 8MHz and I tried it, but things acted really
+ * weird, so 2.5 MHz ought to be enough for anyone...
+ */
+
+static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	if (mii_reg & 0x4000) {
+		if (mii_reg & 0x0200)
+			s |= PHY_STAT_100FDX;
+		else
+			s |= PHY_STAT_100HDX;
+	} else {
+		if (mii_reg & 0x0200)
+			s |= PHY_STAT_10FDX;
+		else
+			s |= PHY_STAT_10HDX;
+	}
+	if (mii_reg & 0x0008)
+		s |= PHY_STAT_FAULT;
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_lxt971 = {
+	0x0001378e,
+	"LXT971",
+
+	(const phy_cmd_t []) {  /* config */
+//		{ mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10  Mbps, HD */
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+
+		/* Somehow does the 971 tell me that the link is down
+		 * the first read after power-up.
+		 * read here to get a valid value in ack_int */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+		/* find out the current status */
+
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
+
+		/* we only need to read ISR to acknowledge */
+
+		{ mk_mii_read(MII_LXT971_ISR), NULL },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+#endif /* CONFIG_FEC_LXT970 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Quality Semiconductor QS6612 is used on the RPX CLLF                  */
+
+#ifdef CONFIG_FCC_QS6612
+
+/* register definitions */
+
+#define MII_QS6612_MCR       17  /* Mode Control Register      */
+#define MII_QS6612_FTR       27  /* Factory Test Register      */
+#define MII_QS6612_MCO       28  /* Misc. Control Register     */
+#define MII_QS6612_ISR       29  /* Interrupt Source Register  */
+#define MII_QS6612_IMR       30  /* Interrupt Mask Register    */
+#define MII_QS6612_PCR       31  /* 100BaseTx PHY Control Reg. */
+
+static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	switch((mii_reg >> 2) & 7) {
+	case 1: s |= PHY_STAT_10HDX;  break;
+	case 2: s |= PHY_STAT_100HDX; break;
+	case 5: s |= PHY_STAT_10FDX;  break;
+	case 6: s |= PHY_STAT_100FDX; break;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_qs6612 = {
+	0x00181440,
+	"QS6612",
+
+	(const phy_cmd_t []) {  /* config */
+//	{ mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10  Mbps */
+
+		/* The PHY powers up isolated on the RPX,
+		 * so send a command to allow operation.
+		 */
+
+		{ mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL },
+
+		/* parse cr and anar to get some info */
+
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+
+		/* we need to read ISR, SR and ANER to acknowledge */
+
+		{ mk_mii_read(MII_QS6612_ISR), NULL },
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_REG_ANER), NULL },
+
+		/* read pcr to get info */
+
+		{ mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+
+#endif /* CONFIG_FEC_QS6612 */
+
+
+/* ------------------------------------------------------------------------- */
+/* The Davicom DM9131 is used on the HYMOD board			     */
+
+#ifdef CONFIG_FCC_DM9131
+
+/* register definitions */
+
+#define MII_DM9131_ACR		16	/* Aux. Config Register		*/
+#define MII_DM9131_ACSR		17	/* Aux. Config/Status Register	*/
+#define MII_DM9131_10TCSR	18	/* 10BaseT Config/Status Reg.	*/
+#define MII_DM9131_INTR		21	/* Interrupt Register		*/
+#define MII_DM9131_RECR		22	/* Receive Error Counter Reg.	*/
+#define MII_DM9131_DISCR	23	/* Disconnect Counter Register	*/
+
+static void mii_parse_dm9131_acsr(uint mii_reg, struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	s &= ~(PHY_STAT_SPMASK);
+
+	switch ((mii_reg >> 12) & 0xf) {
+	case 1: s |= PHY_STAT_10HDX;  break;
+	case 2: s |= PHY_STAT_10FDX;  break;
+	case 4: s |= PHY_STAT_100HDX; break;
+	case 8: s |= PHY_STAT_100FDX; break;
+	}
+
+	fep->phy_status = s;
+}
+
+static phy_info_t phy_info_dm9131 = {
+	0x00181b80,
+	"DM9131",
+
+	(const phy_cmd_t []) {  /* config */
+		/* parse cr and anar to get some info */
+		{ mk_mii_read(MII_REG_CR), mii_parse_cr },
+		{ mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* startup - enable interrupts */
+		{ mk_mii_write(MII_DM9131_INTR, 0x0002), NULL },
+		{ mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) { /* ack_int */
+
+		/* we need to read INTR, SR and ANER to acknowledge */
+
+		{ mk_mii_read(MII_DM9131_INTR), NULL },
+		{ mk_mii_read(MII_REG_SR), mii_parse_sr },
+		{ mk_mii_read(MII_REG_ANER), NULL },
+
+		/* read acsr to get info */
+
+		{ mk_mii_read(MII_DM9131_ACSR), mii_parse_dm9131_acsr },
+		{ mk_mii_end, }
+	},
+	(const phy_cmd_t []) {  /* shutdown - disable interrupts */
+		{ mk_mii_write(MII_DM9131_INTR, 0x0f00), NULL },
+		{ mk_mii_end, }
+	},
+};
+
+
+#endif /* CONFIG_FEC_DM9131 */
+
+
+static phy_info_t *phy_info[] = {
+
+#ifdef CONFIG_FCC_LXT970
+	&phy_info_lxt970,
+#endif /* CONFIG_FEC_LXT970 */
+
+#ifdef CONFIG_FCC_LXT971
+	&phy_info_lxt971,
+#endif /* CONFIG_FEC_LXT971 */
+
+#ifdef CONFIG_FCC_QS6612
+	&phy_info_qs6612,
+#endif /* CONFIG_FEC_QS6612 */
+
+#ifdef CONFIG_FCC_DM9131
+	&phy_info_dm9131,
+#endif /* CONFIG_FEC_DM9131 */
+
+	NULL
+};
+
+static void mii_display_status(struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	if (!fep->link && !fep->old_link) {
+		/* Link is still down - don't print anything */
+		return;
+	}
+
+	printk("%s: status: ", dev->name);
+
+	if (!fep->link) {
+		printk("link down");
+	} else {
+		printk("link up");
+
+		switch(s & PHY_STAT_SPMASK) {
+		case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break;
+		case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break;
+		case PHY_STAT_10FDX:  printk(", 10 Mbps Full Duplex");  break;
+		case PHY_STAT_10HDX:  printk(", 10 Mbps Half Duplex");  break;
+		default:
+			printk(", Unknown speed/duplex");
+		}
+
+		if (s & PHY_STAT_ANC)
+			printk(", auto-negotiation complete");
+	}
+
+	if (s & PHY_STAT_FAULT)
+		printk(", remote fault");
+
+	printk(".\n");
+}
+
+static void mii_display_config(struct net_device *dev)
+{
+	volatile struct fcc_enet_private *fep = dev->priv;
+	uint s = fep->phy_status;
+
+	printk("%s: config: auto-negotiation ", dev->name);
+
+	if (s & PHY_CONF_ANE)
+		printk("on");
+	else
+		printk("off");
+
+	if (s & PHY_CONF_100FDX)
+		printk(", 100FDX");
+	if (s & PHY_CONF_100HDX)
+		printk(", 100HDX");
+	if (s & PHY_CONF_10FDX)
+		printk(", 10FDX");
+	if (s & PHY_CONF_10HDX)
+		printk(", 10HDX");
+	if (!(s & PHY_CONF_SPMASK))
+		printk(", No speed/duplex selected?");
+
+	if (s & PHY_CONF_LOOP)
+		printk(", loopback enabled");
+
+	printk(".\n");
+
+	fep->sequence_done = 1;
+}
+
+static void mii_relink(struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+	int duplex;
+
+	fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+	mii_display_status(dev);
+	fep->old_link = fep->link;
+
+	if (fep->link) {
+		duplex = 0;
+		if (fep->phy_status
+		    & (PHY_STAT_100FDX | PHY_STAT_10FDX))
+			duplex = 1;
+		fcc_restart(dev, duplex);
+	} else {
+		fcc_stop(dev);
+	}
+}
+
+static void mii_queue_relink(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+	fep->phy_task.routine = (void *)mii_relink;
+	fep->phy_task.data = dev;
+	schedule_task(&fep->phy_task);
+}
+
+static void mii_queue_config(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+	fep->phy_task.routine = (void *)mii_display_config;
+	fep->phy_task.data = dev;
+	schedule_task(&fep->phy_task);
+}
+
+
+
+phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
+			       { mk_mii_end, } };
+phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
+			       { mk_mii_end, } };
+
+
+/* Read remainder of PHY ID.
+*/
+static void
+mii_discover_phy3(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep;
+	int	i;
+
+	fep = dev->priv;
+	fep->phy_id |= (mii_reg & 0xffff);
+
+	for(i = 0; phy_info[i]; i++)
+		if(phy_info[i]->id == (fep->phy_id >> 4))
+			break;
+
+	if(!phy_info[i])
+		panic("%s: PHY id 0x%08x is not supported!\n",
+		      dev->name, fep->phy_id);
+
+	fep->phy = phy_info[i];
+
+	printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
+		dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
+}
+
+/* Scan all of the MII PHY addresses looking for someone to respond
+ * with a valid ID.  This usually happens quickly.
+ */
+static void
+mii_discover_phy(uint mii_reg, struct net_device *dev)
+{
+	struct fcc_enet_private *fep;
+	uint	phytype;
+
+	fep = dev->priv;
+
+	if ((phytype = (mii_reg & 0xfff)) != 0xfff) {
+
+		/* Got first part of ID, now get remainder. */
+		fep->phy_id = phytype << 16;
+		mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3);
+	} else {
+		fep->phy_addr++;
+		if (fep->phy_addr < 32) {
+			mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+							mii_discover_phy);
+		} else {
+			printk("fec: No PHY device found.\n");
+		}
+	}
+}
+
+/* This interrupt occurs when the PHY detects a link change. */
+static void
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	net_device *dev = dev_id;
+	struct fcc_enet_private *fep = dev->priv;
+
+	mii_do_cmd(dev, fep->phy->ack_int);
+	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
+}
+
+#endif	/* CONFIG_USE_MDIO */
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+	struct	fcc_enet_private *cep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile fcc_enet_t *ep;
+	int	i, j;
+
+	cep = (struct fcc_enet_private *)dev->priv;
+
+return;
+	/* Get pointer to FCC area in parameter RAM.
+	*/
+	ep = (fcc_enet_t *)dev->base_addr;
+
+	if (dev->flags&IFF_PROMISC) {
+
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO;
+	} else {
+
+		cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->fen_gaddrh = 0xffffffff;
+			ep->fen_gaddrl = 0xffffffff;
+		}
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->fen_gaddrh = 0;
+			ep->fen_gaddrl = 0;
+
+			dmi = dev->mc_list;
+
+			for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->fen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage,
+						cep->fip->fc_cpmblock, 0x0c,
+						CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+	}
+}
+
+
+/* Set the individual MAC address.
+ */
+int fcc_enet_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr= (struct sockaddr *) p;
+	struct fcc_enet_private *cep;
+	volatile fcc_enet_t *ep;
+	unsigned char *eap;
+	int i;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	ep = cep->ep;
+	
+        if (netif_running(dev))
+                return -EBUSY;
+
+        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	
+	eap = (unsigned char *) &(ep->fen_paddrh);
+	for (i=5; i>=0; i--)
+		*eap++ = addr->sa_data[i];
+
+        return 0;
+}
+
+
+/* Initialize the CPM Ethernet on FCC.
+ */
+int __init fec_enet_init(void)
+{
+	struct net_device *dev;
+	struct fcc_enet_private *cep;
+	fcc_info_t	*fip;
+	int	i, np;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
+	io = &immap->im_ioport;
+
+	np = sizeof(fcc_ports) / sizeof(fcc_info_t);
+	fip = fcc_ports;
+
+	while (np-- > 0) {
+
+		/* Allocate some private information.
+		*/
+		cep = (struct fcc_enet_private *)
+					kmalloc(sizeof(*cep), GFP_KERNEL);
+		if (cep == NULL)
+			return -ENOMEM;
+
+		__clear_user(cep,sizeof(*cep));
+		spin_lock_init(&cep->lock);
+		cep->fip = fip;
+
+		/* Create an Ethernet device instance.
+		*/
+		dev = init_etherdev(0, 0);
+		dev->priv = cep;
+
+		init_fcc_shutdown(fip, cep, immap);
+		init_fcc_ioports(fip, io, immap);
+		init_fcc_param(fip, dev, immap);
+
+		dev->base_addr = (unsigned long)(cep->ep);
+
+		/* The CPM Ethernet specific entries in the device
+		 * structure.
+		 */
+		dev->open = fcc_enet_open;
+		dev->hard_start_xmit = fcc_enet_start_xmit;
+		dev->tx_timeout = fcc_enet_timeout;
+		dev->watchdog_timeo = TX_TIMEOUT;
+		dev->stop = fcc_enet_close;
+		dev->get_stats = fcc_enet_get_stats;
+		dev->set_multicast_list = set_multicast_list;
+		dev->set_mac_address = fcc_enet_set_mac_address;
+
+		init_fcc_startup(fip, dev);
+
+		printk("%s: FCC ENET Version 0.3, ", dev->name);
+		for (i=0; i<5; i++)
+			printk("%02x:", dev->dev_addr[i]);
+		printk("%02x\n", dev->dev_addr[5]);
+
+#ifdef	CONFIG_USE_MDIO
+		/* Queue up command to detect the PHY and initialize the
+	 	* remainder of the interface.
+	 	*/
+		cep->phy_addr = 0;
+		mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+#endif	/* CONFIG_USE_MDIO */
+
+		fip++;
+	}
+
+	return 0;
+}
+
+/* Make sure the device is shut down during initialization.
+*/
+static void __init
+init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep,
+						volatile cpm2_map_t *immap)
+{
+	volatile	fcc_enet_t	*ep;
+	volatile	fcc_t		*fccp;
+
+	/* Get pointer to FCC area in parameter RAM.
+	*/
+	ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]);
+
+	/* And another to the FCC register area.
+	*/
+	fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]);
+	cep->fccp = fccp;		/* Keep the pointers handy */
+	cep->ep = ep;
+
+	/* Disable receive and transmit in case someone left it running.
+	*/
+	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+
+/* Initialize the I/O pins for the FCC Ethernet.
+*/
+static void __init
+init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
+						volatile cpm2_map_t *immap)
+{
+
+	/* FCC1 pins are on port A/C.  FCC2/3 are port B/C.
+	*/
+	if (fip->fc_proff == PROFF_FCC1) {
+		/* Configure port A and C pins for FCC1 Ethernet.
+		 */
+		io->iop_pdira &= ~PA1_DIRA0;
+		io->iop_pdira |= PA1_DIRA1;
+		io->iop_psora &= ~PA1_PSORA0;
+		io->iop_psora |= PA1_PSORA1;
+		io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
+	}
+	if (fip->fc_proff == PROFF_FCC2) {
+		/* Configure port B and C pins for FCC Ethernet.
+		 */
+		io->iop_pdirb &= ~PB2_DIRB0;
+		io->iop_pdirb |= PB2_DIRB1;
+		io->iop_psorb &= ~PB2_PSORB0;
+		io->iop_psorb |= PB2_PSORB1;
+		io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
+	}
+	if (fip->fc_proff == PROFF_FCC3) {
+		/* Configure port B and C pins for FCC Ethernet.
+		 */
+		io->iop_pdirb &= ~PB3_DIRB0;
+		io->iop_pdirb |= PB3_DIRB1;
+		io->iop_psorb &= ~PB3_PSORB0;
+		io->iop_psorb |= PB3_PSORB1;
+		io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
+	}
+
+	/* Port C has clocks......
+	*/
+	io->iop_psorc &= ~(fip->fc_trxclocks);
+	io->iop_pdirc &= ~(fip->fc_trxclocks);
+	io->iop_pparc |= fip->fc_trxclocks;
+
+#ifdef	CONFIG_USE_MDIO
+	/* ....and the MII serial clock/data.
+	*/
+	io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck);
+	io->iop_podrc &= ~(fip->fc_mdio | fip->fc_mdck);
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+	io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck);
+#endif	/* CONFIG_USE_MDIO */
+
+	/* Configure Serial Interface clock routing.
+	 * First, clear all FCC bits to zero,
+	 * then set the ones we want.
+	 */
+	immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask);
+	immap->im_cpmux.cmx_fcr |= fip->fc_clockroute;
+}
+
+static void __init
+init_fcc_param(fcc_info_t *fip, struct net_device *dev,
+						volatile cpm2_map_t *immap)
+{
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	bd_t		*bd;
+	int		i, j;
+	struct		fcc_enet_private *cep;
+	volatile	fcc_enet_t	*ep;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	ep = cep->ep;
+	cp = cpmp;
+
+	bd = (bd_t *)__res;
+
+	/* Zero the whole thing.....I must have missed some individually.
+	 * It works when I do this.
+	 */
+	memset((char *)ep, 0, sizeof(fcc_enet_t));
+
+	/* Allocate space for the buffer descriptors in the DP ram.
+	 * These are relative offsets in the DP ram address space.
+	 * Initialize base addresses for the buffer descriptors.
+	 */
+#if 0
+	/* I really want to do this, but for some reason it doesn't
+	 * work with the data cache enabled, so I allocate from the
+	 * main memory instead.
+	 */
+	i = cpm2_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_rbase = (uint)&immap->im_dprambase[i];
+	cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+	i = cpm2_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_tbase = (uint)&immap->im_dprambase[i];
+	cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+#else
+	cep->rx_bd_base = (cbd_t *)cpm2_hostalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base);
+	cep->tx_bd_base = (cbd_t *)cpm2_hostalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
+	ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base);
+#endif
+
+	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+	cep->cur_rx = cep->rx_bd_base;
+
+	ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+	ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+
+	/* Set maximum bytes per receive buffer.
+	 * It must be a multiple of 32.
+	 */
+	ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+
+	/* Allocate space in the reserved FCC area of DPRAM for the
+	 * internal buffers.  No one uses this space (yet), so we
+	 * can do this.  Later, we will add resource management for
+	 * this area.
+	 */
+	mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128);
+	ep->fen_genfcc.fcc_riptr = mem_addr;
+	ep->fen_genfcc.fcc_tiptr = mem_addr+32;
+	ep->fen_padptr = mem_addr+64;
+	memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32);
+
+	ep->fen_genfcc.fcc_rbptr = 0;
+	ep->fen_genfcc.fcc_tbptr = 0;
+	ep->fen_genfcc.fcc_rcrc = 0;
+	ep->fen_genfcc.fcc_tcrc = 0;
+	ep->fen_genfcc.fcc_res1 = 0;
+	ep->fen_genfcc.fcc_res2 = 0;
+
+	ep->fen_camptr = 0;	/* CAM isn't used in this driver */
+
+	/* Set CRC preset and mask.
+	*/
+	ep->fen_cmask = 0xdebb20e3;
+	ep->fen_cpres = 0xffffffff;
+
+	ep->fen_crcec = 0;	/* CRC Error counter */
+	ep->fen_alec = 0;	/* alignment error counter */
+	ep->fen_disfc = 0;	/* discard frame counter */
+	ep->fen_retlim = 15;	/* Retry limit threshold */
+	ep->fen_pper = 0;	/* Normal persistence */
+
+	/* Clear hash filter tables.
+	*/
+	ep->fen_gaddrh = 0;
+	ep->fen_gaddrl = 0;
+	ep->fen_iaddrh = 0;
+	ep->fen_iaddrl = 0;
+
+	/* Clear the Out-of-sequence TxBD.
+	*/
+	ep->fen_tfcstat = 0;
+	ep->fen_tfclen = 0;
+	ep->fen_tfcptr = 0;
+
+	ep->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+	ep->fen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+	/* Set Ethernet station address.
+	 *
+	 * This is supplied in the board information structure, so we
+	 * copy that into the controller.
+	 * So, far we have only been given one Ethernet address. We make
+	 * it unique by toggling selected bits in the upper byte of the
+	 * non-static part of the address (for the second and third ports,
+	 * the first port uses the address supplied as is).
+	 */
+	eap = (unsigned char *)&(ep->fen_paddrh);
+	for (i=5; i>=0; i--) {
+
+/* 
+ * The EP8260 only uses FCC3, so we can safely give it the real
+ * MAC address.
+ */
+#ifndef CONFIG_RPX6
+		if (i == 3 && fip->fc_fccnum != 0) {
+			dev->dev_addr[i] = bd->bi_enetaddr[i];
+			dev->dev_addr[i] ^= (1 << (7 - fip->fc_fccnum));
+			*eap++ = dev->dev_addr[i];
+		}
+		else {
+			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+		}
+#else
+		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+#endif
+	}
+
+	ep->fen_taddrh = 0;
+	ep->fen_taddrm = 0;
+	ep->fen_taddrl = 0;
+
+	ep->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length */
+	ep->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length */
+
+	/* Clear stat counters, in case we ever enable RMON.
+	*/
+	ep->fen_octc = 0;
+	ep->fen_colc = 0;
+	ep->fen_broc = 0;
+	ep->fen_mulc = 0;
+	ep->fen_uspc = 0;
+	ep->fen_frgc = 0;
+	ep->fen_ospc = 0;
+	ep->fen_jbrc = 0;
+	ep->fen_p64c = 0;
+	ep->fen_p65c = 0;
+	ep->fen_p128c = 0;
+	ep->fen_p256c = 0;
+	ep->fen_p512c = 0;
+	ep->fen_p1024c = 0;
+
+	ep->fen_rfthr = 0;	/* Suggested by manual */
+	ep->fen_rfcnt = 0;
+	ep->fen_cftype = 0;
+
+	/* Now allocate the host memory pages and initialize the
+	 * buffer descriptors.
+	 */
+	bdp = cep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		bdp->cbd_sc = 0;
+		bdp->cbd_datlen = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	bdp = cep->rx_bd_base;
+	for (i=0; i<FCC_ENET_RX_PAGES; i++) {
+
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<FCC_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+			bdp->cbd_datlen = 0;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += FCC_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* Let's re-initialize the channel now.  We have to do it later
+	 * than the manual describes because we have just now finished
+	 * the BD initialization.
+	 */
+	cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	cep->skb_cur = cep->skb_dirty = 0;
+}
+
+/* Let 'er rip.
+*/
+static void __init
+init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private *cep;
+
+	cep = (struct fcc_enet_private *)(dev->priv);
+	fccp = cep->fccp;
+
+	fccp->fcc_fcce = 0xffff;	/* Clear any pending events */
+
+	/* Enable interrupts for transmit error, complete frame
+	 * received, and any transmit buffer we have also set the
+	 * interrupt flag.
+	 */
+	fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
+	/* Install our interrupt handler.
+	*/
+	if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
+				dev) < 0)
+		printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
+
+#ifdef	CONFIG_USE_MDIO
+	if (request_8xxirq(PHY_INTERRUPT, mii_link_interrupt, 0,
+							"mii", dev) < 0)
+		printk("Can't get MII IRQ %d\n", fip->fc_interrupt);
+#endif	/* CONFIG_USE_MDIO */
+
+	/* Set GFMR to enable Ethernet operating mode.
+	 */
+	fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET);
+
+	/* Set sync/delimiters.
+	*/
+	fccp->fcc_fdsr = 0xd555;
+
+	/* Set protocol specific processing mode for Ethernet.
+	 * This has to be adjusted for Full Duplex operation after we can
+	 * determine how to detect that.
+	 */
+	fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
+
+#ifdef CONFIG_PQ2ADS
+	/* Enable the PHY.
+	*/
+        *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
+        *(volatile uint *)(BCSR_ADDR + 4) |=  BCSR1_FETH_RST;
+#endif
+
+#if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)
+	/* start in full duplex mode, and negotiate speed
+	 */
+	fcc_restart (dev, 1);
+#else
+	/* start in half duplex mode
+	 */
+	fcc_restart (dev, 0);
+#endif
+}
+
+#ifdef	CONFIG_USE_MDIO
+/* MII command/status interface.
+ * I'm not going to describe all of the details.  You can find the
+ * protocol definition in many other places, including the data sheet
+ * of most PHY parts.
+ * I wonder what "they" were thinking (maybe weren't) when they leave
+ * the I2C in the CPM but I have to toggle these bits......
+ */
+
+#define FCC_PDATC_MDIO(bit)					\
+	if (bit)						\
+		io->iop_pdatc |= fip->fc_mdio;			\
+	else							\
+		io->iop_pdatc &= ~fip->fc_mdio;
+
+#define FCC_PDATC_MDC(bit)					\
+	if (bit)						\
+		io->iop_pdatc |= fip->fc_mdck;			\
+	else							\
+		io->iop_pdatc &= ~fip->fc_mdck;
+
+static uint
+mii_send_receive(fcc_info_t *fip, uint cmd)
+{
+	uint		retval;
+	int		read_op, i, off;
+	volatile	cpm2_map_t		*immap;
+	volatile	iop_cpm2_t	*io;
+
+	immap = (cpm2_map_t *)CPM_MAP_ADDR;
+	io = &immap->im_ioport;
+
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+
+	read_op = ((cmd & 0xf0000000) == 0x60000000);
+
+	/* Write preamble
+	 */
+	for (i = 0; i < 32; i++)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO(1);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	/* Write data
+	 */
+	for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO((cmd >> off) & 0x00000001);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	retval = cmd;
+
+	if (read_op)
+	{
+		retval >>= 16;
+
+		FCC_PDATC_MDC(0);
+		io->iop_pdirc &= ~fip->fc_mdio;
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+		FCC_PDATC_MDC(0);
+		udelay(1);
+
+		for (i = 0, off = 15; i < 16; i++, off--)
+		{
+			FCC_PDATC_MDC(1);
+			retval <<= 1;
+			if (io->iop_pdatc & fip->fc_mdio)
+				retval++;
+			udelay(1);
+			FCC_PDATC_MDC(0);
+			udelay(1);
+		}
+	}
+
+	io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+
+	for (i = 0; i < 32; i++)
+	{
+		FCC_PDATC_MDC(0);
+		FCC_PDATC_MDIO(1);
+		udelay(1);
+		FCC_PDATC_MDC(1);
+		udelay(1);
+	}
+
+	return retval;
+}
+
+static void
+fcc_stop(struct net_device *dev)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private	*fcp;
+
+	fcp = (struct fcc_enet_private *)(dev->priv);
+	fccp = fcp->fccp;
+
+	/* Disable transmit/receive */
+	fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+}
+#endif	/* CONFIG_USE_MDIO */
+	
+static void
+fcc_restart(struct net_device *dev, int duplex)
+{
+	volatile fcc_t	*fccp;
+	struct fcc_enet_private	*fcp;
+
+	fcp = (struct fcc_enet_private *)(dev->priv);
+	fccp = fcp->fccp;
+
+	if (duplex)
+		fccp->fcc_fpsmr |= FCC_PSMR_FDE;
+	else
+		fccp->fcc_fpsmr &= ~FCC_PSMR_FDE;
+
+	/* Enable transmit/receive */
+	fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
+}
+
+static int
+fcc_enet_open(struct net_device *dev)
+{
+	struct fcc_enet_private *fep = dev->priv;
+
+#ifdef	CONFIG_USE_MDIO
+	fep->sequence_done = 0;
+	fep->link = 0;
+
+	if (fep->phy) {
+		mii_do_cmd(dev, fep->phy->ack_int);
+		mii_do_cmd(dev, fep->phy->config);
+		mii_do_cmd(dev, phy_cmd_config);  /* display configuration */
+		while(!fep->sequence_done)
+			schedule();
+
+		mii_do_cmd(dev, fep->phy->startup);
+		netif_start_queue(dev);
+		return 0;		/* Success */
+	}
+	return -ENODEV;		/* No PHY we understand */
+#else
+	fep->link = 1;
+	netif_start_queue(dev);
+	return 0;					/* Always succeed */
+#endif	/* CONFIG_USE_MDIO */
+}
+
diff -urN linux-2.4.26-pre2/arch/ppc/cpm2_io/uart.c linux-2.4.26-pre3/arch/ppc/cpm2_io/uart.c
--- linux-2.4.26-pre2/arch/ppc/cpm2_io/uart.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/cpm2_io/uart.c	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,3160 @@
+/*
+ *  UART driver for MPC8260 CPM SCC or SMC
+ *  Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *  Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
+ *	2.3.99 updates
+ *
+ * I used the 8xx uart.c driver as the framework for this driver.
+ * The original code was written for the EST8260 board.  I tried to make
+ * it generic, but there may be some assumptions in the structures that
+ * have to be fixed later.
+ *
+ * The 8xx and 8260 are similar, but not identical.  Over time we
+ * could probably merge these two drivers.
+ * To save porting time, I did not bother to change any object names
+ * that are not accessed outside of this file.
+ * It still needs lots of work........When it was easy, I included code
+ * to support the SCCs.
+ * Only the SCCs support modem control, so that is not complete either.
+ *
+ * This module exports the following rs232 io functions:
+ *
+ *	int rs_8xx_init(void);
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+
+/* SCC Console configuration.  Not quite finished.  The SCC_CONSOLE
+ * should be the number of the SCC to use, but only SCC1 will
+ * work at this time.
+ */
+#ifdef CONFIG_SCC_CONSOLE
+#define SCC_CONSOLE 1
+#endif
+
+/* this defines the index into rs_table for the port to use
+*/
+#ifndef CONFIG_SERIAL_CONSOLE_PORT
+#define CONFIG_SERIAL_CONSOLE_PORT	0
+#endif
+#endif
+#define CONFIG_SERIAL_CONSOLE_PORT	0
+
+#define TX_WAKEUP	ASYNC_SHARE_IRQ
+
+static char *serial_name = "CPM UART driver";
+static char *serial_version = "0.01";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+static int serial_console_setup(struct console *co, char *options);
+
+static void serial_console_write(struct console *c, const char *s,
+		                                unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
+/*
+ * Serial driver configuration section.  Here are the various options:
+ */
+#define SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+#define _INLINE_ inline
+
+#define DBG_CNT(s)
+
+/* We overload some of the items in the data structure to meet our
+ * needs.  For example, the port address is the CPM parameter ram
+ * offset for the SCC or SMC.  The maximum number of ports is 4 SCCs and
+ * 2 SMCs.  The "hub6" field is used to indicate the channel number, with
+ * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
+ * Since these ports are so versatile, I don't yet have a strategy for
+ * their management.  For example, SCC1 is used for Ethernet.  Right
+ * now, just don't put them in the table.  Of course, right now I just
+ * want the SMC to work as a uart :-)..
+ * The "type" field is currently set to 0, for PORT_UNKNOWN.  It is
+ * not currently used.  I should probably use it to indicate the port
+ * type of CMS or SCC.
+ * The SMCs do not support any modem control signals.
+ */
+#define smc_scc_num	hub6
+
+/* The choice of serial port to use for KGDB.  If the system has
+ * two ports, you can use one for console and one for KGDB (which
+ * doesn't make sense to me, but people asked for it).
+ */
+#ifdef CONFIG_KGDB_TTYS1
+#define KGDB_SER_IDX 1		/* SCC2/SMC2 */
+#else
+#define KGDB_SER_IDX 0		/* SCC1/SMC1 */
+#endif
+
+#ifndef SCC_CONSOLE
+
+/* SMC2 is sometimes used for low performance TDM interfaces.  Define
+ * this as 1 if you want SMC2 as a serial port UART managed by this driver.
+ * Define this as 0 if you wish to use SMC2 for something else.
+ */
+#define USE_SMC2 1
+
+/* Define SCC to ttySx mapping.
+*/
+#define SCC_NUM_BASE	(USE_SMC2 + 1)	/* SCC base tty "number" */
+
+/* Define which SCC is the first one to use for a serial port.  These
+ * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
+ * for Ethernet, and the first available SCC for serial UART is SCC2.
+ * NOTE:  IF YOU CHANGE THIS, you have to change the PROFF_xxx and
+ * interrupt vectors in the table below to match.
+ */
+#define SCC_IDX_BASE	1	/* table index */
+
+static struct serial_state rs_table[] = {
+	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
+	{ 0,     0, PROFF_SMC1, SIU_INT_SMC1,   0,    0 },    /* SMC1 ttyS0 */
+#if USE_SMC2
+	{ 0,     0, PROFF_SMC2, SIU_INT_SMC2,   0,    1 },    /* SMC2 ttyS1 */
+#endif
+#ifndef CONFIG_SCC1_ENET
+	{ 0,     0, PROFF_SCC1, SIU_INT_SCC1,   0, SCC_NUM_BASE},    /* SCC1 ttyS2 */
+#endif
+#ifndef CONFIG_SCC2_ENET
+	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE + 1},    /* SCC2 ttyS3 */
+#endif
+};
+
+#else /* SCC_CONSOLE */
+#define SCC_NUM_BASE	0	/* SCC base tty "number" */
+#define SCC_IDX_BASE	0	/* table index */
+static struct serial_state rs_table[] = {
+	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
+	{ 0,     0, PROFF_SCC1, SIU_INT_SCC1,   0, SCC_NUM_BASE},    /* SCC1 ttyS2 */
+	{ 0,     0, PROFF_SCC2, SIU_INT_SCC2,   0, SCC_NUM_BASE + 1},    /* SCC2 ttyS3 */
+};
+#endif /* SCC_CONSOLE */
+
+#define PORT_NUM(P)	(((P) < (SCC_NUM_BASE)) ? (P) : (P)-(SCC_NUM_BASE))
+
+#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+/* The number of buffer descriptors and their sizes.
+*/
+#define RX_NUM_FIFO	4
+#define RX_BUF_SIZE	32
+#define TX_NUM_FIFO	4
+#define TX_BUF_SIZE	32
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/* The async_struct in serial.h does not really give us what we
+ * need, so define our own here.
+ */
+typedef struct serial_info {
+	int			magic;
+	int			flags;
+	struct serial_state	*state;
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			timeout;
+	int			line;
+	int			x_char;	/* xon/xoff character */
+	int			close_delay;
+	unsigned short		closing_wait;
+	unsigned short		closing_wait2;
+	unsigned long		event;
+	unsigned long		last_active;
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	struct tq_struct	tqueue;
+	struct tq_struct	tqueue_hangup;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+
+	/* CPM Buffer Descriptor pointers.
+	*/
+	cbd_t			*rx_bd_base;
+	cbd_t			*rx_cur;
+	cbd_t			*tx_bd_base;
+	cbd_t			*tx_cur;
+} ser_info_t;
+
+static struct console sercons = {
+        name:           "ttyS",
+        write:          serial_console_write,
+        device:         serial_console_device,
+        setup:          serial_console_setup,
+        flags:          CON_PRINTBUFFER,
+        index:          CONFIG_SERIAL_CONSOLE_PORT,
+};
+
+
+static void change_speed(ser_info_t *info);
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static inline int serial_paranoia_check(ser_info_t *info,
+					kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null async_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts,
+ * indexed by the termio value.  The generic CPM functions are responsible
+ * for setting and assigning baud rate generators for us.
+ */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_stop(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	idx;
+	unsigned long flags;
+	volatile scc_t	*sccp;
+	volatile smc_t	*smcp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+
+	save_flags(flags); cli();
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		smcp->smc_smcm &= ~SMCM_TX;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm &= ~UART_SCCM_TX;
+	}
+	restore_flags(flags);
+}
+
+static void rs_8xx_start(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	idx;
+	unsigned long flags;
+	volatile scc_t	*sccp;
+	volatile smc_t	*smcp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+
+	save_flags(flags); cli();
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		smcp->smc_smcm |= SMCM_TX;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm |= UART_SCCM_TX;
+	}
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(ser_info_t *info,
+				  int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch, *cp;
+	/*int	ignored = 0;*/
+	int	i;
+	ushort	status;
+	struct	async_icount *icount;
+	volatile cbd_t	*bdp;
+
+	icount = &info->state->icount;
+
+	/* Just loop through the closed BDs and copy the characters into
+	 * the buffer.
+	 */
+	bdp = info->rx_cur;
+	for (;;) {
+		if (bdp->cbd_sc & BD_SC_EMPTY)	/* If this one is empty */
+			break;			/*   we are all done */
+
+		/* The read status mask tell us what we should do with
+		 * incoming characters, especially if errors occur.
+		 * One special case is the use of BD_SC_EMPTY.  If
+		 * this is not set, we are supposed to be ignoring
+		 * inputs.  In this case, just mark the buffer empty and
+		 * continue.
+		if (!(info->read_status_mask & BD_SC_EMPTY)) {
+			bdp->cbd_sc |= BD_SC_EMPTY;
+			bdp->cbd_sc &=
+				~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+			if (bdp->cbd_sc & BD_SC_WRAP)
+				bdp = info->rx_bd_base;
+			else
+				bdp++;
+			continue;
+		}
+		 */
+
+		/* Get the number of characters and the buffer pointer.
+		*/
+		i = bdp->cbd_datlen;
+		cp = (unsigned char *)__va(bdp->cbd_bufaddr);
+		status = bdp->cbd_sc;
+#ifdef CONFIG_KGDB
+		if (info->state->smc_scc_num == KGDB_SER_IDX &&
+				(*cp == 0x03 || *cp == '$')) {
+			breakpoint();
+			return;
+		}
+#endif
+
+		/* Check to see if there is room in the tty buffer for
+		 * the characters in our BD buffer.  If not, we exit
+		 * now, leaving the BD with the characters.  We'll pick
+		 * them up again on the next receive interrupt (which could
+		 * be a timeout).
+		 */
+		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
+			break;
+
+		while (i-- > 0) {
+			ch = *cp++;
+			*tty->flip.char_buf_ptr = ch;
+			icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+			printk("DR%02x:%02x...", ch, *status);
+#endif
+			*tty->flip.flag_buf_ptr = 0;
+			if (status & (BD_SC_BR | BD_SC_FR |
+				       BD_SC_PR | BD_SC_OV)) {
+				/*
+				 * For statistics only
+				 */
+				if (status & BD_SC_BR)
+					icount->brk++;
+				else if (status & BD_SC_PR)
+					icount->parity++;
+				else if (status & BD_SC_FR)
+					icount->frame++;
+				if (status & BD_SC_OV)
+					icount->overrun++;
+
+				/*
+				 * Now check to see if character should be
+				 * ignored, and mask off conditions which
+				 * should be ignored.
+				if (status & info->ignore_status_mask) {
+					if (++ignored > 100)
+						break;
+					continue;
+				}
+				 */
+				status &= info->read_status_mask;
+
+				if (status & (BD_SC_BR)) {
+#ifdef SERIAL_DEBUG_INTR
+					printk("handling break....");
+#endif
+					*tty->flip.flag_buf_ptr = TTY_BREAK;
+					if (info->flags & ASYNC_SAK)
+						do_SAK(tty);
+				} else if (status & BD_SC_PR)
+					*tty->flip.flag_buf_ptr = TTY_PARITY;
+				else if (status & BD_SC_FR)
+					*tty->flip.flag_buf_ptr = TTY_FRAME;
+				if (status & BD_SC_OV) {
+					/*
+					 * Overrun is special, since it's
+					 * reported immediately, and doesn't
+					 * affect the current character
+					 */
+					if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+						tty->flip.count++;
+						tty->flip.flag_buf_ptr++;
+						tty->flip.char_buf_ptr++;
+						*tty->flip.flag_buf_ptr =
+								TTY_OVERRUN;
+					}
+				}
+			}
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies,
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
+			
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				break;
+
+			tty->flip.flag_buf_ptr++;
+			tty->flip.char_buf_ptr++;
+			tty->flip.count++;
+		}
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	ignore_char:
+#endif
+
+		/* This BD is ready to be used again.  Clear status.
+		 * Get next BD.
+		 */
+		bdp->cbd_sc |= BD_SC_EMPTY;
+		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = info->rx_bd_base;
+		else
+			bdp++;
+	}
+
+	info->rx_cur = (cbd_t *)bdp;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+
+	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
+	/* Check to see if there is room in the tty buffer for
+	 * the break.  If not, we exit now, losing the break.  FIXME
+	 */
+	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
+		return;
+	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
+	*(tty->flip.char_buf_ptr++) = 0;
+	tty->flip.count++;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
+{
+
+	if (info->flags & TX_WAKEUP) {
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+	}
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+}
+
+#ifdef notdef
+	/* I need to do this for the SCCs, so it is left as a reminder.
+	*/
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+	int	status;
+	struct	async_icount *icount;
+
+	status = serial_in(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+			if ((info->flags & ASYNC_HARDPPS_CD) &&
+			    (status & UART_MSR_DCD))
+				hardpps();
+#endif
+		}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&info->open_wait);
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("scheduling hangup...");
+#endif
+			MOD_INC_USE_COUNT;
+			if (schedule_task(&info->tqueue_hangup) == 0)
+				MOD_DEC_USE_COUNT;
+		}
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+			}
+		}
+	}
+}
+#endif
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	u_char	events;
+	int	idx;
+	ser_info_t *info;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	info = (ser_info_t *)dev_id;
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+		events = smcp->smc_smce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
+		if (events & SMCM_RX)
+			receive_chars(info, regs);
+		if (events & SMCM_TX)
+			transmit_chars(info, regs);
+		smcp->smc_smce = events;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
+		if (events & SCCM_RX)
+			receive_chars(info, regs);
+		if (events & SCCM_TX)
+			transmit_chars(info, regs);
+		sccp->scc_scce = events;
+	}
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_single(%d, %x)...",
+					info->state->smc_scc_num, events);
+#endif
+#ifdef modem_control
+	check_modem_status(info);
+#endif
+	info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+	ser_info_t	*info = (ser_info_t *) private_;
+	struct tty_struct	*tty;
+
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred.  The path of
+ * hangup processing is:
+ *
+ * 	serial interrupt routine -> (scheduler tqueue) ->
+ * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ *
+ */
+static void do_serial_hangup(void *private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+
+	tty = info->tty;
+	if (tty)
+		tty_hangup(tty);
+	MOD_DEC_USE_COUNT;
+}
+
+/*static void rs_8xx_timer(void)
+{
+	printk("rs_8xx_timer\n");
+}*/
+
+
+static int startup(ser_info_t *info)
+{
+	unsigned long flags;
+	int	retval=0;
+	int	idx;
+	struct serial_state *state= info->state;
+	volatile smc_t		*smcp;
+	volatile scc_t		*sccp;
+	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*scup;
+
+
+	save_flags(flags); cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		goto errout;
+	}
+
+#ifdef maybe
+	if (!state->port || !state->type) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		goto errout;
+	}
+#endif
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+
+#ifdef modem_control
+	info->MCR = 0;
+	if (info->tty->termios->c_cflag & CBAUD)
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+#endif
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info);
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Enable interrupts and I/O.
+		*/
+		smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+		smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+
+		/* We can tune the buffer length and idle characters
+		 * to take advantage of the entire incoming buffer size.
+		 * If mrblr is something other than 1, maxidl has to be
+		 * non-zero or we never get an interrupt.  The maxidl
+		 * is the number of character times we wait after reception
+		 * of the last character before we decide no more characters
+		 * are coming.
+		 */
+		up = (smc_uart_t *)&cpm2_immr->im_dprambase[state->port];
+#if 0
+		up->smc_mrblr = 1;	/* receive buffer length */
+		up->smc_maxidl = 0;	/* wait forever for next char */
+#else
+		up->smc_mrblr = RX_BUF_SIZE;
+		up->smc_maxidl = RX_BUF_SIZE;
+#endif
+		up->smc_brkcr = 1;	/* number of break chars */
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		scup = (scc_uart_t *)&cpm2_immr->im_dprambase[state->port];
+#if 0
+		scup->scc_genscc.scc_mrblr = 1;	/* receive buffer length */
+		scup->scc_maxidl = 0;	/* wait forever for next char */
+#else
+		scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+		scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+		sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+		sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	}
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(ser_info_t * info)
+{
+	unsigned long	flags;
+	struct serial_state *state;
+	int		idx;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d (irq %d)....", info->line,
+	       state->irq);
+#endif
+
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Disable interrupts and I/O.
+		*/
+		smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+#ifdef CONFIG_SERIAL_CONSOLE
+		/* We can't disable the transmitter if this is the
+		 * system console.
+		 */
+		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+#endif
+			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+#ifdef CONFIG_SERIAL_CONSOLE
+		if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+			sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+	}
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(ser_info_t *info)
+{
+	int	baud_rate;
+	unsigned cflag, cval, scval, prev_mode;
+	int	i, bits, sbits, idx;
+	unsigned long	flags;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+
+	/* Character length programmed into the mode register is the
+	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+	 * 1 or 2 stop bits, minus 1.
+	 * The value 'bits' counts this for us.
+	 */
+	cval = 0;
+	scval = 0;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	      case CS5: bits = 5; break;
+	      case CS6: bits = 6; break;
+	      case CS7: bits = 7; break;
+	      case CS8: bits = 8; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      default:  bits = 8; break;
+	}
+	sbits = bits - 5;
+
+	if (cflag & CSTOPB) {
+		cval |= SMCMR_SL;	/* Two stops */
+		scval |= SCU_PSMR_SL;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		cval |= SMCMR_PEN;
+		scval |= SCU_PSMR_PEN;
+		bits++;
+	}
+	if (!(cflag & PARODD)) {
+		cval |= SMCMR_PM_EVEN;
+		scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
+	}
+
+	/* Determine divisor based on baud rate */
+	i = cflag & CBAUD;
+	if (i >= (sizeof(baud_table)/sizeof(int)))
+		baud_rate = 9600;
+	else
+		baud_rate = baud_table[i];
+
+	info->timeout = (TX_BUF_SIZE*HZ*bits);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+#ifdef modem_control
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (info->flags & ASYNC_HARDPPS_CD)
+		info->IER |= UART_IER_MSI;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+	} else
+		info->flags &= ~ASYNC_CTS_FLOW;
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	serial_out(info, UART_IER, info->IER);
+#endif
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= BD_SC_FR | BD_SC_PR;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= BD_SC_BR;
+
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= BD_SC_BR;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= BD_SC_OV;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->read_status_mask &= ~BD_SC_EMPTY;
+	save_flags(flags); cli();
+
+	/* Start bit has not been added (so don't, because we would just
+	 * subtract it later), and we need to add one for the number of
+	 * stops bits (there is always at least one).
+	 */
+	bits++;
+	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		smcp = &cpm2_immr->im_smc[idx];
+
+		/* Set the mode register.  We want to keep a copy of the
+		 * enables, because we want to put them back if they were
+		 * present.
+		 */
+		prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN);
+		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART
+			| prev_mode;
+	}
+	else {
+		sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+		sccp->scc_psmr = (sbits << 12) | scval;
+	}
+
+	cpm2_setbrg(info->state->smc_scc_num, baud_rate);
+
+	restore_flags(flags);
+}
+
+static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	volatile cbd_t	*bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+		return;
+
+	if (!tty)
+		return;
+
+	bdp = info->tx_cur;
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	*((char *)__va(bdp->cbd_bufaddr)) = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
+
+	/* Get next BD.
+	*/
+	if (bdp->cbd_sc & BD_SC_WRAP)
+		bdp = info->tx_bd_base;
+	else
+		bdp++;
+
+	info->tx_cur = (cbd_t *)bdp;
+
+}
+
+static int rs_8xx_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	volatile cbd_t *bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write"))
+		return 0;
+
+	if (!tty)
+		return 0;
+
+	bdp = info->tx_cur;
+
+	while (1) {
+		c = MIN(count, TX_BUF_SIZE);
+
+		if (c <= 0)
+			break;
+
+		if (bdp->cbd_sc & BD_SC_READY) {
+			info->flags |= TX_WAKEUP;
+			break;
+		}
+
+		if (from_user) {
+			if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+		} else {
+			memcpy(__va(bdp->cbd_bufaddr), buf, c);
+		}
+
+		bdp->cbd_datlen = c;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		buf += c;
+		count -= c;
+		ret += c;
+
+		/* Get next BD.
+		*/
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = info->tx_bd_base;
+		else
+			bdp++;
+		info->tx_cur = (cbd_t *)bdp;
+	}
+	return ret;
+}
+
+static int rs_8xx_write_room(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int	ret;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+		return 0;
+
+	if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
+		info->flags &= ~TX_WAKEUP;
+		ret = TX_BUF_SIZE;
+	}
+	else {
+		info->flags |= TX_WAKEUP;
+		ret = 0;
+	}
+	return ret;
+}
+
+/* I could track this with transmit counters....maybe later.
+*/
+static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+		return 0;
+	return 0;
+}
+
+static void rs_8xx_flush_buffer(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+		return;
+
+	/* There is nothing to "flush", whatever we gave the CPM
+	 * is on its way out.
+	 */
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+	info->flags &= ~TX_WAKEUP;
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
+{
+	volatile cbd_t	*bdp;
+
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+		return;
+
+	bdp = info->tx_cur;
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	*((char *)__va(bdp->cbd_bufaddr)) = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
+
+	/* Get next BD.
+	*/
+	if (bdp->cbd_sc & BD_SC_WRAP)
+		bdp = info->tx_bd_base;
+	else
+		bdp++;
+
+	info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_throttle(struct tty_struct * tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("throttle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+		return;
+
+	if (I_IXOFF(tty))
+		rs_8xx_send_xchar(tty, STOP_CHAR(tty));
+
+#ifdef modem_control
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR &= ~UART_MCR_RTS;
+
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+}
+
+static void rs_8xx_unthrottle(struct tty_struct * tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			rs_8xx_send_xchar(tty, START_CHAR(tty));
+	}
+#ifdef modem_control
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR |= UART_MCR_RTS;
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+#ifdef maybe
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned char status;
+	unsigned int result;
+
+	cli();
+	status = serial_in(info, UART_LSR);
+	sti();
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+	return put_user(result,value);
+}
+#endif
+
+static int get_modem_info(ser_info_t *info, unsigned int *value)
+{
+	unsigned int result = 0;
+#ifdef modem_control
+	unsigned char control, status;
+
+	control = info->MCR;
+	cli();
+	status = serial_in(info, UART_MSR);
+	sti();
+	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
+		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
+		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
+		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
+#endif
+	return put_user(result,value);
+}
+
+static int set_modem_info(ser_info_t *info, unsigned int cmd,
+			  unsigned int *value)
+{
+	int error;
+	unsigned int arg;
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+#ifdef modem_control
+	switch (cmd) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS)
+			info->MCR |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR |= UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR |= UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			info->MCR &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR &= ~UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR &= ~UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMSET:
+		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+					    UART_MCR_OUT1 |
+					    UART_MCR_OUT2 |
+#endif
+					    UART_MCR_DTR))
+			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+		break;
+	default:
+		return -EINVAL;
+	}
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+#endif
+	return 0;
+}
+
+/* Sending a break is a two step process on the SMC/SCC.  It is accomplished
+ * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
+ * command.  We take advantage of the begin/end functions to make this
+ * happen.
+ */
+static void begin_break(ser_info_t *info)
+{
+	volatile cpm_cpm2_t *cp;
+	uint	page, sblock;
+	ushort	num;
+
+	cp = cpmp;
+
+	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		if (num == 0) {
+			page = CPM_CR_SMC1_PAGE;
+			sblock = CPM_CR_SMC1_SBLOCK;
+		}
+		else {
+			page = CPM_CR_SMC2_PAGE;
+			sblock = CPM_CR_SMC2_SBLOCK;
+		}
+	}
+	else {
+		num -= SCC_NUM_BASE;
+		switch (num) {
+		case 0:
+			page = CPM_CR_SCC1_PAGE;
+			sblock = CPM_CR_SCC1_SBLOCK;
+			break;
+		case 1:
+			page = CPM_CR_SCC2_PAGE;
+			sblock = CPM_CR_SCC2_SBLOCK;
+			break;
+		case 2:
+			page = CPM_CR_SCC3_PAGE;
+			sblock = CPM_CR_SCC3_SBLOCK;
+			break;
+		case 3:
+			page = CPM_CR_SCC4_PAGE;
+			sblock = CPM_CR_SCC4_SBLOCK;
+			break;
+		default: return;
+		}
+	}
+	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+static void end_break(ser_info_t *info)
+{
+	volatile cpm_cpm2_t *cp;
+	uint	page, sblock;
+	ushort	num;
+
+	cp = cpmp;
+
+	if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+		if (num == 0) {
+			page = CPM_CR_SMC1_PAGE;
+			sblock = CPM_CR_SMC1_SBLOCK;
+		}
+		else {
+			page = CPM_CR_SMC2_PAGE;
+			sblock = CPM_CR_SMC2_SBLOCK;
+		}
+	}
+	else {
+		num -= SCC_NUM_BASE;
+		switch (num) {
+		case 0:
+			page = CPM_CR_SCC1_PAGE;
+			sblock = CPM_CR_SCC1_SBLOCK;
+			break;
+		case 1:
+			page = CPM_CR_SCC2_PAGE;
+			sblock = CPM_CR_SCC2_SBLOCK;
+			break;
+		case 2:
+			page = CPM_CR_SCC3_PAGE;
+			sblock = CPM_CR_SCC3_SBLOCK;
+			break;
+		case 3:
+			page = CPM_CR_SCC4_PAGE;
+			sblock = CPM_CR_SCC4_SBLOCK;
+			break;
+		default: return;
+		}
+	}
+	cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break(ser_info_t *info, int duration)
+{
+	current->state = TASK_INTERRUPTIBLE;
+#ifdef SERIAL_DEBUG_SEND_BREAK
+	printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
+#endif
+	begin_break(info);
+	schedule_timeout(duration);
+	end_break(info);
+#ifdef SERIAL_DEBUG_SEND_BREAK
+	printk("done jiffies=%lu\n", jiffies);
+#endif
+}
+
+
+static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	int retval;
+	struct async_icount cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;	/* user space */
+
+	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+		case TCSBRK:	/* SVID version: non-zero arg --> no break */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			if (!arg) {
+				send_break(info, HZ/4);	/* 1/4 second */
+				if (signal_pending(current))
+					return -EINTR;
+			}
+			return 0;
+		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			if (signal_pending(current))
+				return -EINTR;
+			return 0;
+		case TIOCSBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			begin_break(info);
+			return 0;
+		case TIOCCBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			end_break(info);
+			return 0;
+		case TIOCGSOFTCAR:
+			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
+		case TIOCSSOFTCAR:
+			error = get_user(arg, (unsigned int *) arg);
+			if (error)
+				return error;
+			tty->termios->c_cflag =
+				((tty->termios->c_cflag & ~CLOCAL) |
+				 (arg ? CLOCAL : 0));
+			return 0;
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+#ifdef maybe
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+#endif
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		 case TIOCMIWAIT:
+#ifdef modem_control
+			cli();
+			/* note the counters on entry */
+			cprev = info->state->icount;
+			sti();
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				cli();
+				cnow = info->state->icount; /* atomic copy */
+				sti();
+				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
+				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+#else
+			return 0;
+#endif
+
+		/*
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			cli();
+			cnow = info->state->icount;
+			sti();
+			p_cuser = (struct serial_icounter_struct *) arg;
+			error = put_user(cnow.cts, &p_cuser->cts);
+			if (error) return error;
+			error = put_user(cnow.dsr, &p_cuser->dsr);
+			if (error) return error;
+			error = put_user(cnow.rng, &p_cuser->rng);
+			if (error) return error;
+			error = put_user(cnow.dcd, &p_cuser->dcd);
+			if (error) return error;
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+/* FIX UP modem control here someday......
+*/
+static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+	if (   (tty->termios->c_cflag == old_termios->c_cflag)
+	    && (   RELEVANT_IFLAG(tty->termios->c_iflag)
+		== RELEVANT_IFLAG(old_termios->c_iflag)))
+	  return;
+
+	change_speed(info);
+
+#ifdef modem_control
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (tty->termios->c_cflag & CBAUD)) {
+		info->MCR |= UART_MCR_DTR;
+		if (!tty->hw_stopped ||
+		    !(tty->termios->c_cflag & CRTSCTS)) {
+			info->MCR |= UART_MCR_RTS;
+		}
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_8xx_start(tty);
+	}
+#endif
+
+#if 0
+	/*
+	 * No need to wake up processes in open wait, since they
+	 * sample the CLOCAL flag once, and don't recheck it.
+	 * XXX  It's not clear whether the current behavior is correct
+	 * or not.  Hence, this may change.....
+	 */
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct serial_state *state;
+	unsigned long	flags;
+	int		idx;
+	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
+
+	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+		return;
+
+	state = info->state;
+
+	save_flags(flags); cli();
+
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+	if ((tty->count == 1) && (state->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	if (--state->count < 0) {
+		printk("rs_close: bad serial port count for ttys%d: %d\n",
+		       info->line, state->count);
+		state->count = 0;
+	}
+	if (state->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->state->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->state->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->read_status_mask &= ~BD_SC_EMPTY;
+	if (info->flags & ASYNC_INITIALIZED) {
+		if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+			smcp = &cpm2_immr->im_smc[idx];
+			smcp->smc_smcm &= ~SMCM_RX;
+			smcp->smc_smcmr &= ~SMCMR_REN;
+		}
+		else {
+			sccp = &cpm2_immr->im_scc[idx - SCC_IDX_BASE];
+			sccp->scc_sccm &= ~UART_SCCM_RX;
+			sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
+		}
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		rs_8xx_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	/*int lsr;*/
+	volatile cbd_t *bdp;
+
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+#ifdef maybe
+	if (info->state->type == PORT_UNKNOWN)
+		return;
+#endif
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 *
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = 1;
+	if (timeout)
+		char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+
+	/* We go through the loop at least once because we can't tell
+	 * exactly when the last character exits the shifter.  There can
+	 * be at least two characters waiting to be sent after the buffers
+	 * are empty.
+	 */
+	do {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		current->state = TASK_INTERRUPTIBLE;
+/*		current->counter = 0;	 make us low-priority */
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+		bdp = info->tx_cur;
+	} while (bdp->cbd_sc & BD_SC_READY);
+	current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_8xx_hangup(struct tty_struct *tty)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct serial_state *state = info->state;
+
+	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+		return;
+
+	state = info->state;
+
+	rs_8xx_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	state->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   ser_info_t *info)
+{
+#ifdef DO_THIS_LATER
+	DECLARE_WAITQUEUE(wait, current);
+#endif
+	struct serial_state *state = info->state;
+	int		retval;
+	int		do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		if (info->flags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 * If this is an SMC port, we don't have modem control to wait
+	 * for, so just get out here.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR)) ||
+	    (info->state->smc_scc_num < SCC_NUM_BASE)) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (state->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, state->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+#ifdef DO_THIS_LATER
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       state->line, state->count);
+#endif
+	cli();
+	if (!tty_hung_up_p(filp))
+		state->count--;
+	sti();
+	info->blocked_open++;
+	while (1) {
+		cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (tty->termios->c_cflag & CBAUD))
+			serial_out(info, UART_MCR,
+				   serial_inp(info, UART_MCR) |
+				   (UART_MCR_DTR | UART_MCR_RTS));
+		sti();
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (serial_in(info, UART_MSR) &
+				   UART_MSR_DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, state->count);
+#endif
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		state->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, state->count);
+#endif
+#endif /* DO_THIS_LATER */
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+static int get_async_struct(int line, ser_info_t **ret_info)
+{
+	struct serial_state *sstate;
+
+	sstate = rs_table + line;
+	if (sstate->info) {
+		sstate->count++;
+		*ret_info = (ser_info_t *)sstate->info;
+		return 0;
+	}
+	else {
+		return -ENOMEM;
+	}
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
+{
+	ser_info_t	*info;
+	int 		retval, line;
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= NR_PORTS))
+		return -ENODEV;
+	retval = get_async_struct(line, &info);
+	if (retval)
+		return retval;
+	if (serial_paranoia_check(info, tty->device, "rs_open"))
+		return -ENODEV;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	       info->state->count);
+#endif
+	tty->driver_data = info;
+	info->tty = tty;
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval)
+		return retval;
+
+	MOD_INC_USE_COUNT;
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+	if ((info->state->count == 1) &&
+	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->state->normal_termios;
+		else
+			*tty->termios = info->state->callout_termios;
+		change_speed(info);
+	}
+
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open ttys%d successful...", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static int inline line_info(char *buf, struct serial_state *state)
+{
+#ifdef notdef
+	struct async_struct *info = state->info, scr_info;
+	char	stat_buf[30], control, status;
+#endif
+	int	ret;
+
+	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+		      state->line,
+		      (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+		      (unsigned int)(state->port), state->irq);
+
+	if (!state->port || (state->type == PORT_UNKNOWN)) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+#ifdef notdef
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	if (!info) {
+		info = &scr_info;	/* This is just for serial_{in,out} */
+
+		info->magic = SERIAL_MAGIC;
+		info->port = state->port;
+		info->flags = state->flags;
+		info->quot = 0;
+		info->tty = 0;
+	}
+	cli();
+	status = serial_in(info, UART_MSR);
+	control = info ? info->MCR : serial_in(info, UART_MCR);
+	sti();
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (control & UART_MCR_RTS)
+		strcat(stat_buf, "|RTS");
+	if (status & UART_MSR_CTS)
+		strcat(stat_buf, "|CTS");
+	if (control & UART_MCR_DTR)
+		strcat(stat_buf, "|DTR");
+	if (status & UART_MSR_DSR)
+		strcat(stat_buf, "|DSR");
+	if (status & UART_MSR_DCD)
+		strcat(stat_buf, "|CD");
+	if (status & UART_MSR_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->quot) {
+		ret += sprintf(buf+ret, " baud:%d",
+			       state->baud_base / info->quot);
+	}
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      state->icount.tx, state->icount.rx);
+
+	if (state->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+
+	if (state->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+
+	if (state->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
+
+	if (state->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+#endif
+	return ret;
+}
+
+int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+		len += line_info(page + len, &rs_table[i]);
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_serial_version(void)
+{
+ 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+}
+
+
+/*
+ * The serial console driver used during boot.  Note that these names
+ * clash with those found in "serial.c", so we currently can't support
+ * the 16xxx uarts and these at the same time.  I will fix this to become
+ * an indirect function call from tty_io.c (or something).
+ */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * Print a string to the serial port trying not to disturb any possible
+ * real use of the port...
+ * These funcitons work equally well for SCC, even though they are
+ * designed for SMC.  Our only interests are the transmit/receive
+ * buffers, which are identically mapped for either the SCC or SMC.
+ */
+static void my_console_write(int idx, const char *s,
+				unsigned count)
+{
+	struct		serial_state	*ser;
+	ser_info_t			*info;
+	unsigned			i;
+	volatile	cbd_t		*bdp, *bdbase;
+	volatile	smc_uart_t	*up;
+	volatile	u_char		*cp;
+
+	ser = rs_table + idx;
+
+	/* If the port has been initialized for general use, we have
+	 * to use the buffer descriptors allocated there.  Otherwise,
+	 * we simply use the single buffer allocated.
+	 */
+	if ((info = (ser_info_t *)ser->info) != NULL) {
+		bdp = info->tx_cur;
+		bdbase = info->tx_bd_base;
+	}
+	else {
+		/* Pointer to UART in parameter ram.
+		*/
+		up = (smc_uart_t *)&cpm2_immr->im_dprambase[ser->port];
+
+		/* Get the address of the host memory buffer.
+		 */
+		bdp = bdbase = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_tbase];
+	}
+
+	/*
+	 * We need to gracefully shut down the transmitter, disable
+	 * interrupts, then send our bytes out.
+	 */
+
+	/*
+	 * Now, do each character.  This is not as bad as it looks
+	 * since this is a holding FIFO and not a transmitting FIFO.
+	 * We could add the complexity of filling the entire transmit
+	 * buffer, but we would just wait longer between accesses......
+	 */
+	for (i = 0; i < count; i++, s++) {
+		/* Wait for transmitter fifo to empty.
+		 * Ready indicates output is ready, and xmt is doing
+		 * that, not that it is ready for us to send.
+		 */
+		while (bdp->cbd_sc & BD_SC_READY);
+
+		/* Send the character out.
+		 * If the buffer address is in the CPM DPRAM, don't
+		 * convert it.
+		 */
+		if ((uint)(bdp->cbd_bufaddr) > (uint)CPM_MAP_ADDR)
+			cp = (u_char *)(bdp->cbd_bufaddr);
+		else
+			cp = __va(bdp->cbd_bufaddr);
+		*cp = *s;
+
+		bdp->cbd_datlen = 1;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = bdbase;
+		else
+			bdp++;
+
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while (bdp->cbd_sc & BD_SC_READY);
+			cp = __va(bdp->cbd_bufaddr);
+			*cp = 13;
+			bdp->cbd_datlen = 1;
+			bdp->cbd_sc |= BD_SC_READY;
+
+			if (bdp->cbd_sc & BD_SC_WRAP) {
+				bdp = bdbase;
+			}
+			else {
+				bdp++;
+			}
+		}
+	}
+
+	/*
+	 * Finally, Wait for transmitter & holding register to empty
+	 *  and restore the IER
+	 */
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	if (info)
+		info->tx_cur = (cbd_t *)bdp;
+}
+
+static void serial_console_write(struct console *c, const char *s,
+				unsigned count)
+{
+#if defined(CONFIG_KGDB_CONSOLE) && !defined(CONFIG_USE_SERIAL2_KGDB)
+	/* Try to let stub handle output. Returns true if it did. */ 
+	if (kgdb_output_string(s, count))
+		return;
+#endif
+	my_console_write(c->index, s, count);
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_write(const char *s, unsigned count)
+{
+	my_console_write(KGDB_SER_IDX, s, count);
+	return(count);
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void
+putDebugChar(char ch)
+{
+	my_console_write(KGDB_SER_IDX, &ch, 1);
+}
+#endif
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
+/*
+ * Receive character from the serial port.  This only works well
+ * before the port is initialize for real use.
+ */
+static int my_console_wait_key(int idx, int xmon, char *obuf)
+{
+	struct serial_state		*ser;
+	u_char				c, *cp;
+	ser_info_t			*info;
+	volatile	cbd_t		*bdp;
+	volatile	smc_uart_t	*up;
+	int				i;
+
+	ser = rs_table + idx;
+
+	/* Pointer to UART in parameter ram.
+	*/
+	up = (smc_uart_t *)&cpm2_immr->im_dprambase[ser->port];
+
+	/* Get the address of the host memory buffer.
+	 * If the port has been initialized for general use, we must
+	 * use information from the port structure.
+	 */
+	if ((info = (ser_info_t *)ser->info))
+		bdp = info->rx_cur;
+	else
+		bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_rbase];
+
+	/*
+	 * We need to gracefully shut down the receiver, disable
+	 * interrupts, then read the input.
+	 * XMON just wants a poll.  If no character, return -1, else
+	 * return the character.
+	 */
+	if (!xmon) {
+		while (bdp->cbd_sc & BD_SC_EMPTY);
+	}
+	else {
+		if (bdp->cbd_sc & BD_SC_EMPTY)
+			return -1;
+	}
+
+	/* If the buffer address is in the CPM DPRAM, don't
+	 * convert it.
+	 */
+	if ((uint)(bdp->cbd_bufaddr) > (uint)CPM_MAP_ADDR)
+		cp = (u_char *)(bdp->cbd_bufaddr);
+	else
+		cp = __va(bdp->cbd_bufaddr);
+
+	if (obuf) {
+		i = c = bdp->cbd_datlen;
+		while (i-- > 0)
+			*obuf++ = *cp++;
+	}
+	else {
+		c = *cp;
+	}
+	bdp->cbd_sc |= BD_SC_EMPTY;
+
+	if (info) {
+		if (bdp->cbd_sc & BD_SC_WRAP) {
+			bdp = info->rx_bd_base;
+		}
+		else {
+			bdp++;
+		}
+		info->rx_cur = (cbd_t *)bdp;
+	}
+
+	return((int)c);
+}
+#endif
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_read_poll(void)
+{
+	return(my_console_wait_key(KGDB_SER_IDX, 1, NULL));
+}
+
+int
+xmon_8xx_read_char(void)
+{
+	return(my_console_wait_key(KGDB_SER_IDX, 0, NULL));
+}
+#endif
+
+#ifdef CONFIG_KGDB
+static char kgdb_buf[RX_BUF_SIZE], *kgdp;
+static int kgdb_chars;
+
+char
+getDebugChar(void)
+{
+	if (kgdb_chars <= 0) {
+		kgdb_chars = my_console_wait_key(KGDB_SER_IDX, 0, kgdb_buf);
+		kgdp = kgdb_buf;
+	}
+	kgdb_chars--;
+
+	return(*kgdp++);
+}
+
+void kgdb_interruptible(int yes)
+{
+	volatile smc_t	*smcp;
+
+	smcp = &cpm2_immr->im_smc[KGDB_SER_IDX];
+
+	if (yes == 1)
+		smcp->smc_smcm |= SMCM_RX;
+	else
+		smcp->smc_smcm &= ~SMCM_RX;
+}
+
+void kgdb_map_scc(void)
+{
+	ushort		serbase;
+	uint		mem_addr;
+	volatile	cbd_t		*bdp;
+	volatile	smc_uart_t	*up;
+
+	/* The serial port has already been initialized before
+	 * we get here.  We have to assign some pointers needed by
+	 * the kernel, and grab a memory location in the CPM that will
+	 * work until the driver is really initialized.
+	 */
+	cpm2_immr = (cpm2_map_t *)CPM_MAP_ADDR;
+
+	/* Right now, assume we are using SMCs.
+	*/
+#ifdef USE_KGDB_SMC2
+	*(ushort *)(&cpm2_immr->im_dprambase[PROFF_SMC2_BASE]) = serbase = PROFF_SMC2;
+#else
+	*(ushort *)(&cpm2_immr->im_dprambase[PROFF_SMC1_BASE]) = serbase = PROFF_SMC1;
+#endif
+	up = (smc_uart_t *)&cpm2_immr->im_dprambase[serbase];
+
+	/* Allocate space for an input FIFO, plus a few bytes for output.
+	 * Allocate bytes to maintain word alignment.
+	 */
+	mem_addr = (uint)(&cpm2_immr->im_dprambase[0x1000]);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_rbase];
+	bdp->cbd_bufaddr = mem_addr;
+
+	bdp = (cbd_t *)&cpm2_immr->im_dprambase[up->smc_tbase];
+	bdp->cbd_bufaddr = mem_addr+RX_BUF_SIZE;
+
+	up->smc_mrblr = RX_BUF_SIZE;		/* receive buffer length */
+	up->smc_maxidl = RX_BUF_SIZE;
+}
+#endif
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Register console.
+ */
+long __init console_8xx_init(long kmem_start, long kmem_end)
+{
+	register_console(&sercons);
+	return kmem_start;
+}
+
+#endif
+
+/* Default console baud rate as determined by the board information
+ * structure.
+ */
+static	int	baud_idx;
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+int __init rs_8xx_init(void)
+{
+	struct serial_state * state;
+	ser_info_t	*info;
+	uint		mem_addr, dp_addr;
+	int		i, j, idx;
+	uint		page, sblock;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	smc_t		*sp;
+	volatile	smc_uart_t	*up;
+	volatile	scc_t		*scp;
+	volatile	scc_uart_t	*sup;
+	volatile	cpm2_map_t	*immap;
+	volatile	iop_cpm2_t	*io;
+
+	init_bh(SERIAL_BH, do_serial_bh);
+
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+
+	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
+	__clear_user(&serial_driver,sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "serial";
+#ifdef CONFIG_DEVFS_FS
+	serial_driver.name = "tts/%d";
+#else
+	serial_driver.name = "ttyS";
+#endif
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = NR_PORTS;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = rs_8xx_open;
+	serial_driver.close = rs_8xx_close;
+	serial_driver.write = rs_8xx_write;
+	serial_driver.put_char = rs_8xx_put_char;
+	serial_driver.write_room = rs_8xx_write_room;
+	serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
+	serial_driver.flush_buffer = rs_8xx_flush_buffer;
+	serial_driver.ioctl = rs_8xx_ioctl;
+	serial_driver.throttle = rs_8xx_throttle;
+	serial_driver.unthrottle = rs_8xx_unthrottle;
+	serial_driver.send_xchar = rs_8xx_send_xchar;
+	serial_driver.set_termios = rs_8xx_set_termios;
+	serial_driver.stop = rs_8xx_stop;
+	serial_driver.start = rs_8xx_start;
+	serial_driver.hangup = rs_8xx_hangup;
+	serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
+	serial_driver.read_proc = rs_8xx_read_proc;
+
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
+	callout_driver.name = "cua/%d";
+#else
+	callout_driver.name = "cua";
+#endif
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+
+	immap = cpm2_immr;
+	cp = &immap->im_cpm;
+	io = &immap->im_ioport;
+
+	/* This should have been done long ago by the early boot code,
+	 * but do it again to make sure.
+	 */
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+	/* Geeze, here we go....Picking I/O port bits....Lots of
+	 * choices.  If you don't like mine, pick your own.
+	 * Configure SMCs Tx/Rx.  SMC1 is only on Port D, SMC2 is
+	 * only on Port A.  You either pick 'em, or not.
+	 */
+#ifndef SCC_CONSOLE
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+#if USE_SMC2
+	io->iop_ppara |= 0x00c00000;
+	io->iop_pdira |= 0x00400000;
+	io->iop_pdira &= ~0x00800000;
+	io->iop_psora &= ~0x00c00000;
+#endif
+
+	/* Configure SCC2 and SCC3.  Be careful about the fine print.
+	 * Secondary options are only available when you take away
+	 * the primary option.  Unless the pins are used for something
+	 * else, SCC2 and SCC3 are on Port B.
+	 *	Port B,  8 - SCC3 TxD
+	 *	Port B, 12 - SCC2 TxD
+	 *	Port B, 14 - SCC3 RxD
+	 *	Port B, 15 - SCC2 RxD
+	 */
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+
+	/* Wire BRG1 to SMC1 and BRG2 to SMC2.
+	*/
+	immap->im_cpmux.cmx_smr = 0;
+
+	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and
+	 * BRG4 to SCC3.
+	 */
+	immap->im_cpmux.cmx_scr &= ~0x00ffff00;
+	immap->im_cpmux.cmx_scr |= 0x00121b00;
+#else
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+
+	/* Use Port D for SCC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+	/* Connect SCC1, SCC2, SCC3 to NMSI.  Connect BRG1 to SCC1,
+	 * BRG2 to SCC2, BRG3 to SCC3.
+	 */
+	immap->im_cpmux.cmx_scr &= ~0xffffff00;
+	immap->im_cpmux.cmx_scr |= 0x00091200;
+#endif
+
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		state->magic = SSTATE_MAGIC;
+		state->line = i;
+		state->type = PORT_UNKNOWN;
+		state->custom_divisor = 0;
+		state->close_delay = 5*HZ/10;
+		state->closing_wait = 30*HZ;
+		state->callout_termios = callout_driver.init_termios;
+		state->normal_termios = serial_driver.init_termios;
+		state->icount.cts = state->icount.dsr =
+			state->icount.rng = state->icount.dcd = 0;
+		state->icount.rx = state->icount.tx = 0;
+		state->icount.frame = state->icount.parity = 0;
+		state->icount.overrun = state->icount.brk = 0;
+ 		printk (KERN_INFO "ttyS%d on %s%d at 0x%04x, BRG%d\n",
+ 			i,
+ 			(state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+ 			PORT_NUM(state->smc_scc_num) + 1,
+ 			(unsigned int)(state->port),
+ 			state->smc_scc_num + 1);
+#ifdef CONFIG_SERIAL_CONSOLE
+		/* If we just printed the message on the console port, and
+		 * we are about to initialize it for general use, we have
+		 * to wait a couple of character times for the CR/NL to
+		 * make it out of the transmit buffer.
+		 */
+		if (i == CONFIG_SERIAL_CONSOLE_PORT)
+			mdelay(300);
+#endif
+		info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
+		if (info) {
+			/*memset(info, 0, sizeof(ser_info_t));*/
+			__clear_user(info,sizeof(ser_info_t));
+			init_waitqueue_head(&info->open_wait);
+			init_waitqueue_head(&info->close_wait);
+			info->magic = SERIAL_MAGIC;
+			info->flags = state->flags;
+			info->tqueue.routine = do_softint;
+			info->tqueue.data = info;
+			info->tqueue_hangup.routine = do_serial_hangup;
+			info->tqueue_hangup.data = info;
+			info->line = i;
+			info->state = state;
+			state->info = (struct async_struct *)info;
+
+			/* We need to allocate a transmit and receive buffer
+			 * descriptors from dual port ram, and a character
+			 * buffer area from host mem.
+			 */
+			dp_addr = cpm2_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO, 8);
+
+			/* Allocate space for FIFOs in the host memory.
+			*/
+			mem_addr = cpm2_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE, 1);
+
+			/* Set the physical address of the host memory
+			 * buffers in the buffer descriptors, and the
+			 * virtual address for us to work with.
+			 */
+			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
+
+			for (j=0; j<(RX_NUM_FIFO-1); j++) {
+				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+				mem_addr += RX_BUF_SIZE;
+				bdp++;
+			}
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+			if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+				sp = &immap->im_smc[idx];
+				up = (smc_uart_t *)&immap->im_dprambase[state->port];
+				up->smc_rbase = dp_addr;
+			}
+			else {
+				scp = &immap->im_scc[idx - SCC_IDX_BASE];
+				sup = (scc_uart_t *)&immap->im_dprambase[state->port];
+				scp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+				sup->scc_genscc.scc_rbase = dp_addr;
+			}
+
+			dp_addr = cpm2_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO, 8);
+
+			/* Allocate space for FIFOs in the host memory.
+			*/
+			mem_addr = cpm2_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE, 1);
+
+			/* Set the physical address of the host memory
+			 * buffers in the buffer descriptors, and the
+			 * virtual address for us to work with.
+			 */
+			bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
+
+			for (j=0; j<(TX_NUM_FIFO-1); j++) {
+				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_sc = BD_SC_INTRPT;
+				mem_addr += TX_BUF_SIZE;
+				bdp++;
+			}
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
+
+			if (idx < SCC_NUM_BASE) {
+				up->smc_tbase = dp_addr;
+
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				up->smc_mrblr = 1;
+				up->smc_maxidl = 0;
+				up->smc_brkcr = 1;
+
+				/* Send the CPM an initialize command.
+				*/
+				if (state->smc_scc_num == 0) {
+					page = CPM_CR_SMC1_PAGE;
+					sblock = CPM_CR_SMC1_SBLOCK;
+				}
+				else {
+					page = CPM_CR_SMC2_PAGE;
+					sblock = CPM_CR_SMC2_SBLOCK;
+				}
+
+				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+						CPM_CR_INIT_TRX) | CPM_CR_FLG;
+				while (cp->cp_cpcr & CPM_CR_FLG);
+
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				sp->smc_smcm = 0;
+				sp->smc_smce = 0xff;
+			}
+			else {
+				sup->scc_genscc.scc_tbase = dp_addr;
+
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				sup->scc_genscc.scc_mrblr = 1;
+				sup->scc_maxidl = 0;
+				sup->scc_brkcr = 1;
+				sup->scc_parec = 0;
+				sup->scc_frmec = 0;
+				sup->scc_nosec = 0;
+				sup->scc_brkec = 0;
+				sup->scc_uaddr1 = 0;
+				sup->scc_uaddr2 = 0;
+				sup->scc_toseq = 0;
+				sup->scc_char1 = 0x8000;
+				sup->scc_char2 = 0x8000;
+				sup->scc_char3 = 0x8000;
+				sup->scc_char4 = 0x8000;
+				sup->scc_char5 = 0x8000;
+				sup->scc_char6 = 0x8000;
+				sup->scc_char7 = 0x8000;
+				sup->scc_char8 = 0x8000;
+				sup->scc_rccm = 0xc0ff;
+
+				/* Send the CPM an initialize command.
+				*/
+#ifdef SCC_CONSOLE
+				switch (state->smc_scc_num) {
+				case 0:
+					page = CPM_CR_SCC1_PAGE;
+					sblock = CPM_CR_SCC1_SBLOCK;
+					break;
+				case 1:
+					page = CPM_CR_SCC2_PAGE;
+					sblock = CPM_CR_SCC2_SBLOCK;
+					break;
+				case 2:
+					page = CPM_CR_SCC3_PAGE;
+					sblock = CPM_CR_SCC3_SBLOCK;
+					break;
+				}
+#else
+				if (state->smc_scc_num == 2) {
+					page = CPM_CR_SCC2_PAGE;
+					sblock = CPM_CR_SCC2_SBLOCK;
+				}
+				else {
+					page = CPM_CR_SCC3_PAGE;
+					sblock = CPM_CR_SCC3_SBLOCK;
+				}
+#endif
+
+				cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+						CPM_CR_INIT_TRX) | CPM_CR_FLG;
+				while (cp->cp_cpcr & CPM_CR_FLG);
+
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				scp->scc_gsmrh = 0;
+				scp->scc_gsmrl =
+					(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				scp->scc_sccm = 0;
+				scp->scc_scce = 0xffff;
+				scp->scc_dsr = 0x7e7e;
+				scp->scc_psmr = 0x3000;
+			}
+
+			/* Install interrupt handler.
+			*/
+			request_irq(state->irq, rs_8xx_interrupt, 0, "uart",
+					info);
+
+			/* Set up the baud rate generator.
+			*/
+			cpm2_setbrg(state->smc_scc_num,
+							baud_table[baud_idx]);
+
+			/* If the port is the console, enable Rx and Tx.
+			*/
+#ifdef CONFIG_SERIAL_CONSOLE
+			if (i == CONFIG_SERIAL_CONSOLE_PORT) {
+				if (idx < SCC_NUM_BASE)
+					sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+				else
+					scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+			}
+#endif
+		}
+	}
+	return 0;
+}
+
+/* This must always be called before the rs_8xx_init() function, otherwise
+ * it blows away the port control information.
+*/
+static int __init serial_console_setup(struct console *co, char *options)
+{
+	struct		serial_state *ser;
+	uint		mem_addr, dp_addr, bidx;
+	volatile	cbd_t		*bdp;
+	volatile	cpm_cpm2_t	*cp;
+	volatile	cpm2_map_t	*immap;
+#ifndef SCC_CONSOLE
+	volatile	smc_t		*sp;
+	volatile	smc_uart_t	*up;
+#endif
+	volatile	scc_t		*scp;
+	volatile	scc_uart_t	*sup;
+	volatile	iop_cpm2_t	*io;
+	bd_t				*bd;
+
+	bd = (bd_t *)__res;
+
+	for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
+		if (bd->bi_baudrate == baud_table[bidx])
+			break;
+
+	co->cflag = CREAD|CLOCAL|bidx|CS8;
+	baud_idx = bidx;
+
+	ser = rs_table + co->index;
+
+	immap = cpm2_immr;
+	cp = &immap->im_cpm;
+	io = &immap->im_ioport;
+
+#ifdef SCC_CONSOLE
+	scp = (scc_t *)&(immap->im_scc[SCC_CONSOLE-1]);
+	sup = (scc_uart_t *)&immap->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
+	scp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+	scp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+	/* Use Port D for SCC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+#else
+	/* This should have been done long ago by the early boot code,
+	 * but do it again to make sure.
+	 */
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+	*(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+	/* Right now, assume we are using SMCs.
+	*/
+	sp = &immap->im_smc[ser->smc_scc_num];
+
+	/* When we get here, the CPM has been reset, so we need
+	 * to configure the port.
+	 * We need to allocate a transmit and receive buffer descriptor
+	 * from dual port ram, and a character buffer area from host mem.
+	 */
+	up = (smc_uart_t *)&immap->im_dprambase[ser->port];
+
+	/* Disable transmitter/receiver.
+	*/
+	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+	/* Use Port D for SMC1 instead of other functions.
+	*/
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+#endif
+
+	/* Allocate space for two buffer descriptors in the DP ram.
+	*/
+	dp_addr = cpm2_dpalloc(sizeof(cbd_t) * 2, 8);
+
+	/* Allocate space for two 2 byte FIFOs in the host memory.
+	*/
+	mem_addr = cpm2_hostalloc(4, 1);
+
+	/* Set the physical address of the host memory buffers in
+	 * the buffer descriptors.
+	 */
+	bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+	bdp->cbd_bufaddr = __pa(mem_addr);
+	(bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+
+	/* For the receive, set empty and wrap.
+	 * For transmit, set wrap.
+	 */
+	bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+	(bdp+1)->cbd_sc = BD_SC_WRAP;
+
+	/* Set up the uart parameters in the parameter ram.
+	*/
+#ifdef SCC_CONSOLE
+	sup->scc_genscc.scc_rbase = dp_addr;
+	sup->scc_genscc.scc_tbase = dp_addr + sizeof(cbd_t);
+
+	/* Set up the uart parameters in the
+	 * parameter ram.
+	 */
+	sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	sup->scc_genscc.scc_mrblr = 1;
+	sup->scc_maxidl = 0;
+	sup->scc_brkcr = 1;
+	sup->scc_parec = 0;
+	sup->scc_frmec = 0;
+	sup->scc_nosec = 0;
+	sup->scc_brkec = 0;
+	sup->scc_uaddr1 = 0;
+	sup->scc_uaddr2 = 0;
+	sup->scc_toseq = 0;
+	sup->scc_char1 = 0x8000;
+	sup->scc_char2 = 0x8000;
+	sup->scc_char3 = 0x8000;
+	sup->scc_char4 = 0x8000;
+	sup->scc_char5 = 0x8000;
+	sup->scc_char6 = 0x8000;
+	sup->scc_char7 = 0x8000;
+	sup->scc_char8 = 0x8000;
+	sup->scc_rccm = 0xc0ff;
+
+	/* Send the CPM an initialize command.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	scp->scc_gsmrh = 0;
+	scp->scc_gsmrl = 
+		(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+	/* Disable all interrupts and clear all pending
+	 * events.
+	 */
+	scp->scc_sccm = 0;
+	scp->scc_scce = 0xffff;
+	scp->scc_dsr = 0x7e7e;
+	scp->scc_psmr = 0x3000;
+
+	/* Wire BRG1 to SCC1.  The serial init will take care of
+	 * others.
+	 */
+	immap->im_cpmux.cmx_scr = 0;
+
+	/* Set up the baud rate generator.
+	*/
+	cpm2_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+	scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#else
+	up->smc_rbase = dp_addr;	/* Base of receive buffer desc. */
+	up->smc_tbase = dp_addr+sizeof(cbd_t);	/* Base of xmt buffer desc. */
+	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+
+	/* Set this to 1 for now, so we get single character interrupts.
+	*/
+	up->smc_mrblr = 1;		/* receive buffer length */
+	up->smc_maxidl = 0;		/* wait forever for next char */
+
+	/* Send the CPM an initialize command.
+	*/
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+			CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+
+	/* Set up the baud rate generator.
+	*/
+	cpm2_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+	/* And finally, enable Rx and Tx.
+	*/
+	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+
+	return 0;
+}
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/Makefile linux-2.4.26-pre3/arch/ppc/kernel/Makefile
--- linux-2.4.26-pre2/arch/ppc/kernel/Makefile	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/kernel/Makefile	2004-03-13 07:43:22.000000000 -0800
@@ -85,7 +85,7 @@
 obj-$(CONFIG_SANDPOINT)		+= i8259.o open_pic.o mpc10x_common.o \
 					pci_auto.o indirect_pci.o todc_time.o
 obj-$(CONFIG_SPRUCE)		+= indirect_pci.o pci_auto.o todc_time.o
-obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
+obj-$(CONFIG_8260)		+= m8260_setup.o cpm2_pic.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/cpm2_pic.c linux-2.4.26-pre3/arch/ppc/kernel/cpm2_pic.c
--- linux-2.4.26-pre2/arch/ppc/kernel/cpm2_pic.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/kernel/cpm2_pic.c	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,128 @@
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include "cpm2_pic.h"
+
+/* The CPM2 internal interrupt controller.  It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static	u_char	irq_to_siureg[] = {
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static	u_char	irq_to_siubit[] = {
+	31, 16, 17, 18, 19, 20, 21, 22,
+	23, 24, 25, 26, 27, 28, 29, 30,
+	29, 30, 16, 17, 18, 19, 20, 21,
+	22, 23, 24, 25, 26, 27, 28, 31,
+	 0,  1,  2,  3,  4,  5,  6,  7,
+	 8,  9, 10, 11, 12, 13, 14, 15,
+	15, 14, 13, 12, 11, 10,  9,  8,
+	 7,  6,  5,  4,  3,  2,  1,  0
+};
+
+static void cpm2_mask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_unmask_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void cpm2_mask_and_ack(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr, *sipnr;
+
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
+
+	simr = &(cpm2_immr->im_intctl.ic_simrh);
+	sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
+	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+	simr[word] = ppc_cached_irq_mask[word];
+	sipnr[word] = 1 << (31 - bit);
+}
+
+static void cpm2_end_irq(unsigned int irq_nr)
+{
+	int	bit, word;
+	volatile uint	*simr;
+
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+
+		bit = irq_to_siubit[irq_nr];
+		word = irq_to_siureg[irq_nr];
+
+		simr = &(cpm2_immr->im_intctl.ic_simrh);
+		ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+		simr[word] = ppc_cached_irq_mask[word];
+	}
+}
+
+struct hw_interrupt_type cpm2_pic = {
+	" CPM2 SIU  ",
+	NULL,
+	NULL,
+	cpm2_unmask_irq,
+	cpm2_mask_irq,
+	cpm2_mask_and_ack,
+	cpm2_end_irq,
+	0
+};
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int
+cpm2_get_irq(struct pt_regs *regs)
+{
+	int irq;
+        unsigned long bits;
+
+        /* For CPM2, read the SIVEC register and shift the bits down
+         * to get the irq number.         */
+        bits = cpm2_immr->im_intctl.ic_sivec;
+        irq = bits >> 26;
+
+	if (irq == 0)	/* 0 --> no irq is pending */
+		irq = -1;
+
+	return irq;
+}
+
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/cpm2_pic.h linux-2.4.26-pre3/arch/ppc/kernel/cpm2_pic.h
--- linux-2.4.26-pre2/arch/ppc/kernel/cpm2_pic.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/kernel/cpm2_pic.h	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,13 @@
+#ifndef _PPC_KERNEL_CPM2_H
+#define _PPC_KERNEL_CPM2_H
+
+#include <linux/irq.h>
+
+extern struct hw_interrupt_type cpm2_pic;
+
+void cpm2_pic_init(void);
+void cpm2_do_IRQ(struct pt_regs *regs,
+                 int            cpu);
+int cpm2_get_irq(struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_CPM2_H */
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/m8260_setup.c linux-2.4.26-pre3/arch/ppc/kernel/m8260_setup.c
--- linux-2.4.26-pre2/arch/ppc/kernel/m8260_setup.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/kernel/m8260_setup.c	2004-03-13 07:43:22.000000000 -0800
@@ -40,12 +40,12 @@
 #include <asm/pgtable.h>
 #include <asm/ide.h>
 #include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
+#include <asm/immap_cpm2.h>
 #include <asm/machdep.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 
-#include "ppc8260_pic.h"
+#include "cpm2_pic.h"
 
 static int m8260_set_rtc_time(unsigned long time);
 static unsigned long m8260_get_rtc_time(void);
@@ -53,14 +53,14 @@
 
 unsigned char __res[sizeof(bd_t)];
 
-extern void m8260_cpm_reset(void);
+extern void cpm2_reset(void);
 
 static void __init
 m8260_setup_arch(void)
 {
 	/* Reset the Communication Processor Module.
 	*/
-	m8260_cpm_reset();
+	cpm2_reset();
 }
 
 static void
@@ -172,18 +172,18 @@
 	void cpm_interrupt_init(void);
 
 #if 0
-        ppc8260_pic.irq_offset = 0;
+        cpm2_pic.irq_offset = 0;
 #endif
         for ( i = 0 ; i < NR_SIU_INTS ; i++ )
-                irq_desc[i].handler = &ppc8260_pic;
+                irq_desc[i].handler = &cpm2_pic;
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
 	 */
-	immr->im_intctl.ic_sicr = 0;
-	immr->im_intctl.ic_siprr = 0x05309770;
-	immr->im_intctl.ic_scprrh = 0x05309770;
-	immr->im_intctl.ic_scprrl = 0x05309770;
+	cpm2_immr->im_intctl.ic_sicr = 0;
+	cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+	cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+	cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
 
 }
 
@@ -242,7 +242,7 @@
 	ppc_md.show_percpuinfo		= m8260_show_percpuinfo;
 	ppc_md.irq_cannonicalize	= NULL;
 	ppc_md.init_IRQ			= m8260_init_IRQ;
-	ppc_md.get_irq			= m8260_get_irq;
+	ppc_md.get_irq			= cpm2_get_irq;
 	ppc_md.init			= NULL;
 
 	ppc_md.restart			= m8260_restart;
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/ppc8260_pic.c linux-2.4.26-pre3/arch/ppc/kernel/ppc8260_pic.c
--- linux-2.4.26-pre2/arch/ppc/kernel/ppc8260_pic.c	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/kernel/ppc8260_pic.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,128 +0,0 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <asm/irq.h>
-#include <asm/immap_8260.h>
-#include <asm/mpc8260.h>
-#include "ppc8260_pic.h"
-
-/* The 8260 internal interrupt controller.  It is usually
- * the only interrupt controller.
- * There are two 32-bit registers (high/low) for up to 64
- * possible interrupts.
- *
- * Now, the fun starts.....Interrupt Numbers DO NOT MAP
- * in a simple arithmetic fashion to mask or pending registers.
- * That is, interrupt 4 does not map to bit position 4.
- * We create two tables, indexed by vector number, to indicate
- * which register to use and which bit in the register to use.
- */
-static	u_char	irq_to_siureg[] = {
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1,
-	0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static	u_char	irq_to_siubit[] = {
-	31, 16, 17, 18, 19, 20, 21, 22,
-	23, 24, 25, 26, 27, 28, 29, 30,
-	29, 30, 16, 17, 18, 19, 20, 21,
-	22, 23, 24, 25, 26, 27, 28, 31,
-	 0,  1,  2,  3,  4,  5,  6,  7,
-	 8,  9, 10, 11, 12, 13, 14, 15,
-	15, 14, 13, 12, 11, 10,  9,  8,
-	 7,  6,  5,  4,  3,  2,  1,  0
-};
-
-static void m8260_mask_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-}
-
-static void m8260_unmask_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-}
-
-static void m8260_mask_and_ack(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr, *sipnr;
-
-	bit = irq_to_siubit[irq_nr];
-	word = irq_to_siureg[irq_nr];
-
-	simr = &(immr->im_intctl.ic_simrh);
-	sipnr = &(immr->im_intctl.ic_sipnrh);
-	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
-	simr[word] = ppc_cached_irq_mask[word];
-	sipnr[word] = 1 << (31 - bit);
-}
-
-static void m8260_end_irq(unsigned int irq_nr)
-{
-	int	bit, word;
-	volatile uint	*simr;
-
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-
-		bit = irq_to_siubit[irq_nr];
-		word = irq_to_siureg[irq_nr];
-
-		simr = &(immr->im_intctl.ic_simrh);
-		ppc_cached_irq_mask[word] |= (1 << (31 - bit));
-		simr[word] = ppc_cached_irq_mask[word];
-	}
-}
-
-struct hw_interrupt_type ppc8260_pic = {
-	" 8260 SIU  ",
-	NULL,
-	NULL,
-	m8260_unmask_irq,
-	m8260_mask_irq,
-	m8260_mask_and_ack,
-	m8260_end_irq,
-	0
-};
-
-/* Return an interrupt vector or -1 if no interrupt is pending. */
-int
-m8260_get_irq(struct pt_regs *regs)
-{
-	int irq;
-        unsigned long bits;
-
-        /* For MPC8260, read the SIVEC register and shift the bits down
-         * to get the irq number.         */
-        bits = immr->im_intctl.ic_sivec;
-        irq = bits >> 26;
-
-	if (irq == 0)	/* 0 --> no irq is pending */
-		irq = -1;
-
-	return irq;
-}
-
diff -urN linux-2.4.26-pre2/arch/ppc/kernel/ppc8260_pic.h linux-2.4.26-pre3/arch/ppc/kernel/ppc8260_pic.h
--- linux-2.4.26-pre2/arch/ppc/kernel/ppc8260_pic.h	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/kernel/ppc8260_pic.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,13 +0,0 @@
-#ifndef _PPC_KERNEL_PPC8260_H
-#define _PPC_KERNEL_PPC8260_H
-
-#include <linux/irq.h>
-
-extern struct hw_interrupt_type ppc8260_pic;
-
-void m8260_pic_init(void);
-void m8260_do_IRQ(struct pt_regs *regs,
-                 int            cpu);
-int m8260_get_irq(struct pt_regs *regs);
-
-#endif /* _PPC_KERNEL_PPC8260_H */
diff -urN linux-2.4.26-pre2/arch/ppc/platforms/est8260.h linux-2.4.26-pre3/arch/ppc/platforms/est8260.h
--- linux-2.4.26-pre2/arch/ppc/platforms/est8260.h	2003-06-13 07:51:31.000000000 -0700
+++ linux-2.4.26-pre3/arch/ppc/platforms/est8260.h	2004-03-13 07:43:22.000000000 -0800
@@ -4,7 +4,7 @@
  * the configuration SCMR and the Power-On-Reset word.
  */
 
-#define IMAP_ADDR	((uint)0xf0000000)
+#define CPM_MAP_ADDR	((uint)0xf0000000)
 
 
 /* A Board Information structure that is given to a program when
diff -urN linux-2.4.26-pre2/arch/ppc/platforms/pq2ads.h linux-2.4.26-pre3/arch/ppc/platforms/pq2ads.h
--- linux-2.4.26-pre2/arch/ppc/platforms/pq2ads.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/platforms/pq2ads.h	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,89 @@
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MPC8260ADS/MPC8266ADS-PCI boards.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@mvista.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_ADS8260_DEFS
+#define __MACH_ADS8260_DEFS
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define BCSR_ADDR		((uint)0xf4500000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+ * only on word boundaries.
+ * Not all are used (yet), or are interesting to us (yet).
+ */
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_LED0		((uint)0x02000000)	/* 0 == on */
+#define BCSR0_LED1		((uint)0x01000000)	/* 0 == on */
+#define BCSR1_FETHIEN		((uint)0x08000000)	/* 0 == enable */
+#define BCSR1_FETH_RST		((uint)0x04000000)	/* 0 == reset */
+#define BCSR1_RS232_EN1		((uint)0x02000000)	/* 0 == enable */
+#define BCSR1_RS232_EN2		((uint)0x01000000)	/* 0 == enable */
+
+#define PHY_INTERRUPT	SIU_INT_IRQ7
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PCI_INT_STAT_REG	0xF8200000
+#define PCI_INT_MASK_REG	0xF8200004
+#define PIRQA			(NR_SIU_INTS + 0)
+#define PIRQB			(NR_SIU_INTS + 1)
+#define PIRQC			(NR_SIU_INTS + 2)
+#define PIRQD			(NR_SIU_INTS + 3)
+
+/*
+ * PCI memory map definitions for MPC8266ADS-PCI.
+ *
+ * processor view
+ *	local address		PCI address		target
+ *	0x80000000-0x9FFFFFFF	0x80000000-0x9FFFFFFF	PCI mem with prefetch
+ *	0xA0000000-0xBFFFFFFF	0xA0000000-0xBFFFFFFF	PCI mem w/o prefetch
+ *	0xF4000000-0xF7FFFFFF	0x00000000-0x03FFFFFF	PCI IO
+ *
+ * PCI master view
+ *	local address		PCI address		target
+ *	0x00000000-0x1FFFFFFF	0x00000000-0x1FFFFFFF	MPC8266 local memory
+ */
+
+/* window for a PCI master to access MPC8266 memory */
+#define PCI_SLV_MEM_LOCAL	0x00000000	/* Local base */
+#define PCI_SLV_MEM_BUS		0x00000000	/* PCI base */
+
+/* window for the processor to access PCI memory with prefetching */
+#define PCI_MSTR_MEM_LOCAL	0x80000000	/* Local base */
+#define PCI_MSTR_MEM_BUS	0x80000000	/* PCI base   */
+#define PCI_MSTR_MEM_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI memory without prefetching */
+#define PCI_MSTR_MEMIO_LOCAL	0xA0000000	/* Local base */
+#define PCI_MSTR_MEMIO_BUS	0xA0000000	/* PCI base   */
+#define PCI_MSTR_MEMIO_SIZE	0x20000000	/* 512MB */
+
+/* window for the processor to access PCI I/O */
+#define PCI_MSTR_IO_LOCAL	0xF4000000	/* Local base */
+#define PCI_MSTR_IO_BUS         0x00000000	/* PCI base   */
+#define PCI_MSTR_IO_SIZE        0x04000000	/* 64MB */
+
+#define _IO_BASE		PCI_MSTR_IO_LOCAL
+#define _ISA_MEM_BASE		PCI_MSTR_MEMIO_LOCAL
+#define PCI_DRAM_OFFSET		PCI_SLV_MEM_BUS
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_ADS8260_DEFS */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.26-pre2/arch/ppc/platforms/rpx8260.h linux-2.4.26-pre3/arch/ppc/platforms/rpx8260.h
--- linux-2.4.26-pre2/arch/ppc/platforms/rpx8260.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/arch/ppc/platforms/rpx8260.h	2004-03-13 07:43:22.000000000 -0800
@@ -0,0 +1,73 @@
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Embedded Planet RPX6 (or RPX Super) MPC8260 board.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Copyright (c) 2001 Dan Malek (dan@embeddededge.com)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPXSUPER_DEFS
+#define __MACH_RPXSUPER_DEFS
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_nvsize;	/* NVRAM size in bytes (can be 0) */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define CPM_MAP_ADDR		((uint)0xf0000000)
+#define RPX_CSR_ADDR		((uint)0xfa000000)
+#define RPX_CSR_SIZE		((uint)(512 * 1024))
+#define RPX_NVRTC_ADDR		((uint)0xfa080000)
+#define RPX_NVRTC_SIZE		((uint)(512 * 1024))
+
+/* The RPX6 has 16, byte wide control/status registers.
+ * Not all are used (yet).
+ */
+extern volatile u_char *rpx6_csr_addr;
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ID_MASK		((u_char)0xf0)		/* Read only */
+#define BCSR0_SWITCH_MASK	((u_char)0x0f)		/* Read only */
+#define BCSR1_XCVR_SMC1		((u_char)0x80)
+#define BCSR1_XCVR_SMC2		((u_char)0x40)
+#define BCSR2_FLASH_WENABLE	((u_char)0x20)
+#define BCSR2_NVRAM_ENABLE	((u_char)0x10)
+#define BCSR2_ALT_IRQ2		((u_char)0x08)
+#define BCSR2_ALT_IRQ3		((u_char)0x04)
+#define BCSR2_PRST		((u_char)0x02)		/* Force reset */
+#define BCSR2_ENPRST		((u_char)0x01)		/* Enable POR */
+#define BCSR3_MODCLK_MASK	((u_char)0xe0)
+#define BCSR3_ENCLKHDR		((u_char)0x10)
+#define BCSR3_LED5		((u_char)0x04)		/* 0 == on */
+#define BCSR3_LED6		((u_char)0x02)		/* 0 == on */
+#define BCSR3_LED7		((u_char)0x01)		/* 0 == on */
+#define BCSR4_EN_PHY		((u_char)0x80)		/* Enable PHY */
+#define BCSR4_EN_MII		((u_char)0x40)		/* Enable PHY */
+#define BCSR4_MII_READ		((u_char)0x04)
+#define BCSR4_MII_MDC		((u_char)0x02)
+#define BCSR4_MII_MDIO		((u_char)0x02)
+#define BCSR13_FETH_IRQMASK	((u_char)0xf0)
+#define BCSR15_FETH_IRQ		((u_char)0x20)
+
+#endif
+#endif /* __KERNEL__ */
diff -urN linux-2.4.26-pre2/crypto/arc4.c linux-2.4.26-pre3/crypto/arc4.c
--- linux-2.4.26-pre2/crypto/arc4.c	2004-03-13 07:43:20.000000000 -0800
+++ linux-2.4.26-pre3/crypto/arc4.c	2004-03-13 07:43:22.000000000 -0800
@@ -59,10 +59,11 @@
 	u8 *const S = ctx->S;
 	u8 x = ctx->x;
 	u8 y = ctx->y;
+	u8 a, b;
 
-	u8 a = S[x];
+	a = S[x];
 	y = (y + a) & 0xff;
-	u8 b = S[y];
+	b = S[y];
 	S[x] = b;
 	S[y] = a;
 	x = (x + 1) & 0xff;
diff -urN linux-2.4.26-pre2/drivers/char/agp/agpgart_be.c linux-2.4.26-pre3/drivers/char/agp/agpgart_be.c
--- linux-2.4.26-pre2/drivers/char/agp/agpgart_be.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/char/agp/agpgart_be.c	2004-03-13 07:43:22.000000000 -0800
@@ -6181,12 +6181,6 @@
 		"SiS",
 		"650",
 		sis_generic_setup },
-	{ PCI_DEVICE_ID_SI_651,
-		PCI_VENDOR_ID_SI,
-		SIS_GENERIC,
-		"SiS",
-		"651",
-		sis_generic_setup },
 	{ PCI_DEVICE_ID_SI_645,
 		PCI_VENDOR_ID_SI,
 		SIS_GENERIC,
diff -urN linux-2.4.26-pre2/drivers/char/tty_io.c linux-2.4.26-pre3/drivers/char/tty_io.c
--- linux-2.4.26-pre2/drivers/char/tty_io.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/char/tty_io.c	2004-03-13 07:43:22.000000000 -0800
@@ -2249,7 +2249,7 @@
 	au1x00_serial_console_init();
 #endif
 #ifdef CONFIG_SERIAL_CONSOLE
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+#if (defined(CONFIG_8xx) || defined(CONFIG_CPM2))
 	console_8xx_init();
 #elif defined(CONFIG_MAC_SERIAL) && defined(CONFIG_SERIAL)
 	if (_machine == _MACH_Pmac)
@@ -2435,7 +2435,7 @@
 #ifdef CONFIG_SPECIALIX
 	specialix_init();
 #endif
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+#if (defined(CONFIG_8xx) || defined(CONFIG_CPM2))
 	rs_8xx_init();
 #endif /* CONFIG_8xx */
 	pty_init();
diff -urN linux-2.4.26-pre2/drivers/md/lvm-snap.c linux-2.4.26-pre3/drivers/md/lvm-snap.c
--- linux-2.4.26-pre2/drivers/md/lvm-snap.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/md/lvm-snap.c	2004-03-13 07:43:22.000000000 -0800
@@ -554,17 +554,15 @@
 
 int lvm_snapshot_alloc(lv_t * lv_snap)
 {
-	int ret, max_sectors;
+	int ret;
 
 	/* allocate kiovec to do chunk io */
 	ret = alloc_kiovec(1, &lv_snap->lv_iobuf);
 	if (ret)
 		goto out;
 
-	max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT - 9);
-
-	ret =
-	    lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
+	ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf,
+					     KIO_MAX_SECTORS);
 	if (ret)
 		goto out_free_kiovec;
 
diff -urN linux-2.4.26-pre2/drivers/net/tg3.c linux-2.4.26-pre3/drivers/net/tg3.c
--- linux-2.4.26-pre2/drivers/net/tg3.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/drivers/net/tg3.c	2004-03-13 07:43:22.000000000 -0800
@@ -55,8 +55,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.8"
-#define DRV_MODULE_RELDATE	"February 23, 2004"
+#define DRV_MODULE_VERSION	"2.9"
+#define DRV_MODULE_RELDATE	"March 8, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -214,6 +214,21 @@
 	}
 }
 
+static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
+{
+	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&tp->indirect_lock, flags);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
+		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
+		spin_unlock_irqrestore(&tp->indirect_lock, flags);
+	} else {
+		unsigned long dest = tp->regs + off;
+		writel(val, dest);
+		readl(dest);    /* always flush PCI write */
+	}
+}
 
 static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
 {
@@ -238,6 +253,7 @@
 #define tw32_tx_mbox(reg, val)  _tw32_tx_mbox(tp, reg, val)
 
 #define tw32(reg,val)		tg3_write_indirect_reg32(tp,(reg),(val))
+#define tw32_f(reg,val)		_tw32_flush(tp,(reg),(val))
 #define tw16(reg,val)		writew(((val) & 0xffff), tp->regs + (reg))
 #define tw8(reg,val)		writeb(((val) & 0xff), tp->regs + (reg))
 #define tr32(reg)		readl(tp->regs + (reg))
@@ -324,18 +340,15 @@
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
 	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
-		tw32(TG3PCI_CLOCK_CTRL,
+		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl | (CLOCK_CTRL_ALTCLK));
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	}
-	tw32(TG3PCI_CLOCK_CTRL, clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl);
 	udelay(40);
 }
 
@@ -347,9 +360,8 @@
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -361,8 +373,7 @@
 		      MI_COM_REG_ADDR_MASK);
 	frame_val |= (MI_COM_CMD_READ | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -383,8 +394,7 @@
 	}
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -397,9 +407,8 @@
 	int loops, ret;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE,
+		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		tr32(MAC_MI_MODE);
 		udelay(40);
 	}
 
@@ -410,8 +419,7 @@
 	frame_val |= (val & MI_COM_DATA_MASK);
 	frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
 	
-	tw32(MAC_MI_COM, frame_val);
-	tr32(MAC_MI_COM);
+	tw32_f(MAC_MI_COM, frame_val);
 
 	loops = PHY_BUSY_LOOPS;
 	while (loops-- > 0) {
@@ -429,8 +437,7 @@
 		ret = 0;
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
@@ -713,45 +720,41 @@
 	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		} else {
 			if (tp_peer != tp &&
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT2));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE0 |
 			      GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OE2 |
 			      GRC_LCLCTRL_GPIO_OUTPUT0 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	} else {
@@ -761,27 +764,24 @@
 			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
 				return;
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 
-			tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
+			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 			     (GRC_LCLCTRL_GPIO_OE1 |
 			      GRC_LCLCTRL_GPIO_OUTPUT1));
-			tr32(GRC_LOCAL_CTRL);
 			udelay(100);
 		}
 	}
 }
 
-static int tg3_setup_phy(struct tg3 *);
+static int tg3_setup_phy(struct tg3 *, int);
 
 static int tg3_set_power_state(struct tg3 *tp, int state)
 {
@@ -807,8 +807,7 @@
 		pci_write_config_word(tp->pdev,
 				      pm + PCI_PM_CTRL,
 				      power_control);
-		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-		tr32(GRC_LOCAL_CTRL);
+		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 		udelay(100);
 
 		return 0;
@@ -849,7 +848,7 @@
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
-		tg3_setup_phy(tp);
+		tg3_setup_phy(tp, 0);
 	}
 
 	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
@@ -875,12 +874,10 @@
 		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
 			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
 
-		tw32(MAC_MODE, mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, mac_mode);
 		udelay(100);
 
-		tw32(MAC_RX_MODE, RX_MODE_ENABLE);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
 		udelay(10);
 	}
 
@@ -893,10 +890,9 @@
 		base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
 			     CLOCK_CTRL_TXCLK_DISABLE);
 
-		tw32(TG3PCI_CLOCK_CTRL, base_val |
+		tw32_f(TG3PCI_CLOCK_CTRL, base_val |
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
-		tr32(TG3PCI_CLOCK_CTRL);
 		udelay(40);
 	} else {
 		u32 newbits1, newbits2;
@@ -915,12 +911,10 @@
 			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
 		}
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
 		udelay(40);
 
-		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
-		tr32(TG3PCI_CLOCK_CTRL);
+		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
 		udelay(40);
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
@@ -935,8 +929,8 @@
 				newbits3 = CLOCK_CTRL_44MHZ_CORE;
 			}
 
-			tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3);
-			tr32(TG3PCI_CLOCK_CTRL);
+			tw32_f(TG3PCI_CLOCK_CTRL,
+					 tp->pci_clock_ctrl | newbits3);
 			udelay(40);
 		}
 	}
@@ -1050,7 +1044,7 @@
 	};
 }
 
-static int tg3_phy_copper_begin(struct tg3 *tp, int wait_for_link)
+static int tg3_phy_copper_begin(struct tg3 *tp)
 {
 	u32 new_adv;
 	int i;
@@ -1168,7 +1162,7 @@
 		tg3_readphy(tp, MII_BMCR, &orig_bmcr);
 		if (bmcr != orig_bmcr) {
 			tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
-			for (i = 0; i < 15000; i++) {
+			for (i = 0; i < 1500; i++) {
 				u32 tmp;
 
 				udelay(10);
@@ -1187,27 +1181,6 @@
 			     BMCR_ANENABLE | BMCR_ANRESTART);
 	}
 
-	if (wait_for_link) {
-		tp->link_config.active_speed = SPEED_INVALID;
-		tp->link_config.active_duplex = DUPLEX_INVALID;
-		for (i = 0; i < 300000; i++) {
-			u32 tmp;
-
-			udelay(10);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			tg3_readphy(tp, MII_BMSR, &tmp);
-			if (!(tmp & BMSR_LSTATUS))
-				continue;
-
-			tg3_readphy(tp, MII_TG3_AUX_STAT, &tmp);
-			tg3_aux_stat_to_speed_duplex(tp, tmp,
-						     &tp->link_config.active_speed,
-						     &tp->link_config.active_duplex);
-		}
-		if (tp->link_config.active_speed == SPEED_INVALID)
-			return -EINVAL;
-	}
-
 	return 0;
 }
 
@@ -1238,7 +1211,7 @@
 	return err;
 }
 
-static int tg3_setup_copper_phy(struct tg3 *tp)
+static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
 	u32 bmsr, dummy;
@@ -1248,17 +1221,15 @@
 
 	tw32(MAC_EVENT, 0);
 
-	tw32(MAC_STATUS,
+	tw32_f(MAC_STATUS,
 	     (MAC_STATUS_SYNC_CHANGED |
 	      MAC_STATUS_CFG_CHANGED |
 	      MAC_STATUS_MI_COMPLETION |
 	      MAC_STATUS_LNKSTATE_CHANGED));
-	tr32(MAC_STATUS);
 	udelay(40);
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
@@ -1273,8 +1244,10 @@
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		if (!(bmsr & BMSR_LSTATUS))
-			tg3_phy_reset(tp, 1);
+			force_reset = 1;
 	}
+	if (force_reset)
+		tg3_phy_reset(tp, 1);
 
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1410,7 +1383,7 @@
 	if (current_link_up == 0) {
 		u32 tmp;
 
-		tg3_phy_copper_begin(tp, 0);
+		tg3_phy_copper_begin(tp);
 
 		tg3_readphy(tp, MII_BMSR, &tmp);
 		tg3_readphy(tp, MII_BMSR, &tmp);
@@ -1450,24 +1423,19 @@
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
 	    tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
 		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
-		tw32(MAC_MI_MODE, tp->mi_mode);
-		tr32(MAC_MI_MODE);
+		tw32_f(MAC_MI_MODE, tp->mi_mode);
 		udelay(40);
 	}
 
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags &
-	    (TG3_FLAG_USE_LINKCHG_REG |
-	     TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
 		/* Polled via timer. */
-		tw32(MAC_EVENT, 0);
+		tw32_f(MAC_EVENT, 0);
 	} else {
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	}
-	tr32(MAC_EVENT);
 	udelay(40);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
@@ -1476,10 +1444,9 @@
 	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
 	     (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
 		udelay(120);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		tg3_write_mem(tp,
 			      NIC_SRAM_FIRMWARE_MBOX,
@@ -1641,8 +1608,7 @@
 		ap->txconfig = 0;
 		tw32(MAC_TX_AUTO_NEG, 0);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ret = ANEG_TIMER_ENAB;
@@ -1667,8 +1633,7 @@
 		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ABILITY_DETECT;
@@ -1684,8 +1649,7 @@
 		ap->txconfig |= ANEG_CFG_ACK;
 		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_ACK_DETECT;
@@ -1771,8 +1735,7 @@
 	case ANEG_STATE_IDLE_DETECT_INIT:
 		ap->link_time = ap->cur_time;
 		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32(MAC_MODE, tp->mac_mode);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode);
 		udelay(40);
 
 		ap->state = ANEG_STATE_IDLE_DETECT;
@@ -1813,7 +1776,7 @@
 	return ret;
 }
 
-static int tg3_setup_fiber_phy(struct tg3 *tp)
+static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 {
 	u32 orig_pause_cfg;
 	u16 orig_active_speed;
@@ -1829,8 +1792,7 @@
 
 	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
 	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	/* Reset when initting first time or we have a link. */
@@ -1878,10 +1840,9 @@
 
 	/* Enable link change interrupt unless serdes polling.  */
 	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	else
-		tw32(MAC_EVENT, 0);
-	tr32(MAC_EVENT);
+		tw32_f(MAC_EVENT, 0);
 	udelay(40);
 
 	current_link_up = 0;
@@ -1899,12 +1860,10 @@
 			tw32(MAC_TX_AUTO_NEG, 0);
 
 			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-			tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
 			udelay(40);
 
-			tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
 			udelay(40);
 
 			aninfo.state = ANEG_STATE_UNKNOWN;
@@ -1920,8 +1879,7 @@
 			}
 
 			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 
 			if (status == ANEG_DONE &&
@@ -1945,10 +1903,9 @@
 			}
 			for (i = 0; i < 60; i++) {
 				udelay(20);
-				tw32(MAC_STATUS,
+				tw32_f(MAC_STATUS,
 				     (MAC_STATUS_SYNC_CHANGED |
 				      MAC_STATUS_CFG_CHANGED));
-				tr32(MAC_STATUS);
 				udelay(40);
 				if ((tr32(MAC_STATUS) &
 				     (MAC_STATUS_SYNC_CHANGED |
@@ -1966,8 +1923,7 @@
 	}
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->hw_status->status =
@@ -1976,10 +1932,9 @@
 
 	for (i = 0; i < 100; i++) {
 		udelay(20);
-		tw32(MAC_STATUS,
+		tw32_f(MAC_STATUS,
 		     (MAC_STATUS_SYNC_CHANGED |
 		      MAC_STATUS_CFG_CHANGED));
-		tr32(MAC_STATUS);
 		udelay(40);
 		if ((tr32(MAC_STATUS) &
 		     (MAC_STATUS_SYNC_CHANGED |
@@ -2015,12 +1970,10 @@
 	}
 
 	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		tr32(MAC_MODE);
+		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
 		udelay(40);
 		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32(MAC_MODE, tp->mac_mode);
-			tr32(MAC_MODE);
+			tw32_f(MAC_MODE, tp->mac_mode);
 			udelay(40);
 		}
 	}
@@ -2028,14 +1981,14 @@
 	return 0;
 }
 
-static int tg3_setup_phy(struct tg3 *tp)
+static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 {
 	int err;
 
 	if (tp->phy_id == PHY_ID_SERDES) {
-		err = tg3_setup_fiber_phy(tp);
+		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
-		err = tg3_setup_copper_phy(tp);
+		err = tg3_setup_copper_phy(tp, force_reset);
 	}
 
 	if (tp->link_config.active_speed == SPEED_1000 &&
@@ -2398,7 +2351,7 @@
 		if (sblk->status & SD_STATUS_LINK_CHG) {
 			sblk->status = SD_STATUS_UPDATED |
 				(sblk->status & ~SD_STATUS_LINK_CHG);
-			tg3_setup_phy(tp);
+			tg3_setup_phy(tp, 0);
 		}
 	}
 
@@ -3348,8 +3301,7 @@
 
 	val = tr32(ofs);
 	val &= ~enable_bit;
-	tw32(ofs, val);
-	tr32(ofs);
+	tw32_f(ofs, val);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3376,8 +3328,7 @@
 	tg3_disable_ints(tp);
 
 	tp->rx_mode &= ~RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
@@ -3398,13 +3349,11 @@
 		goto out;
 
 	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
 	tp->tx_mode &= ~TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 
 	for (i = 0; i < MAX_WAIT_CNT; i++) {
 		udelay(100);
@@ -3730,8 +3679,7 @@
 		}
 
 		tw32(offset + CPU_STATE, 0xffffffff);
-		tw32(offset + CPU_MODE,  CPU_MODE_HALT);
-		tr32(offset + CPU_MODE);
+		tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
 		udelay(10);
 	} else {
 		for (i = 0; i < 10000; i++) {
@@ -3854,20 +3802,14 @@
 
 	/* Now startup only the RX cpu. */
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
+	tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
 			break;
 		tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 		tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
-		tw32(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
-
-		/* Flush posted writes. */
-		tr32(RX_CPU_BASE + CPU_PC);
-
+		tw32_f(RX_CPU_BASE + CPU_PC,    TG3_FW_TEXT_ADDR);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -3878,10 +3820,7 @@
 		return -ENODEV;
 	}
 	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
-	tw32(RX_CPU_BASE + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(RX_CPU_BASE + CPU_MODE);
+	tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 
 	return 0;
 }
@@ -4439,20 +4378,14 @@
 
 	/* Now startup the cpu. */
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_PC,    info.text_base);
+	tw32_f(cpu_base + CPU_PC,    info.text_base);
 
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_PC);
 	for (i = 0; i < 5; i++) {
 		if (tr32(cpu_base + CPU_PC) == info.text_base)
 			break;
 		tw32(cpu_base + CPU_STATE, 0xffffffff);
 		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
-		tw32(cpu_base + CPU_PC,    info.text_base);
-
-		/* Flush posted writes. */
-		tr32(cpu_base + CPU_PC);
-
+		tw32_f(cpu_base + CPU_PC,    info.text_base);
 		udelay(1000);
 	}
 	if (i >= 5) {
@@ -4463,11 +4396,7 @@
 		return -ENODEV;
 	}
 	tw32(cpu_base + CPU_STATE, 0xffffffff);
-	tw32(cpu_base + CPU_MODE,  0x00000000);
-
-	/* Flush posted writes. */
-	tr32(cpu_base + CPU_MODE);
-
+	tw32_f(cpu_base + CPU_MODE,  0x00000000);
 	return 0;
 }
 
@@ -4514,9 +4443,6 @@
 	struct tg3 *tp = dev->priv;
 	struct sockaddr *addr = p;
 
-	if (netif_running(dev))
-		return -EBUSY;
-
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	spin_lock_irq(&tp->lock);
@@ -4576,10 +4502,9 @@
 		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 	if (tp->phy_id == PHY_ID_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-		tw32(MAC_MODE, tp->mac_mode);
+		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
-		tw32(MAC_MODE, 0);
-	tr32(MAC_MODE);
+		tw32_f(MAC_MODE, 0);
 	udelay(40);
 
 	/* Wait for firmware initialization to complete. */
@@ -4609,8 +4534,7 @@
 	 * other revision.
 	 */
 	tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
-	tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
-	tr32(TG3PCI_CLOCK_CTRL);
+	tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
 	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
@@ -4954,24 +4878,21 @@
 
 	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
 		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
-	tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
-	tr32(MAC_MODE);
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
 	udelay(40);
 
 	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
 		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
 				       GRC_LCLCTRL_GPIO_OUTPUT1);
-	tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-	tr32(GRC_LOCAL_CTRL);
+	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
 	tr32(MAILBOX_INTERRUPT_0);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-		tw32(DMAC_MODE, DMAC_MODE_ENABLE);
-		tr32(DMAC_MODE);
+		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
 	}
 
@@ -4984,8 +4905,7 @@
 	    (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 &&
 	    !(tp->tg3_flags2 & TG3_FLG2_IS_5788))
 		val |= WDMAC_MODE_RX_ACCEL;
-	tw32(WDMAC_MODE, val);
-	tr32(WDMAC_MODE);
+	tw32_f(WDMAC_MODE, val);
 	udelay(40);
 
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
@@ -5003,8 +4923,7 @@
 		tw32(TG3PCI_X_CAPS, val);
 	}
 
-	tw32(RDMAC_MODE, rdmac_mode);
-	tr32(RDMAC_MODE);
+	tw32_f(RDMAC_MODE, rdmac_mode);
 	udelay(40);
 
 	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
@@ -5033,13 +4952,11 @@
 #endif
 
 	tp->tx_mode = TX_MODE_ENABLE;
-	tw32(MAC_TX_MODE, tp->tx_mode);
-	tr32(MAC_TX_MODE);
+	tw32_f(MAC_TX_MODE, tp->tx_mode);
 	udelay(100);
 
 	tp->rx_mode = RX_MODE_ENABLE;
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->link_config.phy_is_low_power) {
@@ -5050,19 +4967,16 @@
 	}
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	tw32(MAC_LED_CTRL, 0);
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 	if (tp->phy_id == PHY_ID_SERDES) {
-		tw32(MAC_RX_MODE, RX_MODE_RESET);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
-	tw32(MAC_RX_MODE, tp->rx_mode);
-	tr32(MAC_RX_MODE);
+	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
@@ -5071,10 +4985,9 @@
 	/* Prevent chip from dropping frames when flow control
 	 * is enabled.
 	 */
-	tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
-	tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
+	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
-	err = tg3_setup_phy(tp);
+	err = tg3_setup_phy(tp, 1);
 	if (err)
 		return err;
 
@@ -5256,7 +5169,7 @@
 				phy_event = 1;
 
 			if (phy_event)
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 		} else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) {
 			u32 mac_stat = tr32(MAC_STATUS);
 			int need_setup = 0;
@@ -5270,15 +5183,13 @@
 				need_setup = 1;
 			}
 			if (need_setup) {
-				tw32(MAC_MODE,
+				tw32_f(MAC_MODE,
 				     (tp->mac_mode &
 				      ~MAC_MODE_PORT_MODE_MASK));
-				tr32(MAC_MODE);
 				udelay(40);
-				tw32(MAC_MODE, tp->mac_mode);
-				tr32(MAC_MODE);
+				tw32_f(MAC_MODE, tp->mac_mode);
 				udelay(40);
-				tg3_setup_phy(tp);
+				tg3_setup_phy(tp, 0);
 			}
 		}
 
@@ -5831,8 +5742,7 @@
 
 	if (rx_mode != tp->rx_mode) {
 		tp->rx_mode = rx_mode;
-		tw32(MAC_RX_MODE, rx_mode);
-		tr32(MAC_RX_MODE);
+		tw32_f(MAC_RX_MODE, rx_mode);
 		udelay(10);
 	}
 }
@@ -5958,7 +5868,7 @@
 	struct tg3 *tp = dev->priv;
   
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-					tp->link_config.phy_is_low_power)
+	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
 	spin_lock_irq(&tp->lock);
@@ -5974,7 +5884,7 @@
 		tp->link_config.duplex = cmd->duplex;
   	}
   
-	tg3_setup_phy(tp);
+	tg3_setup_phy(tp, 1);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
   
@@ -6299,7 +6209,7 @@
 	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
 		return;
 
-	tw32(GRC_EEPROM_ADDR,
+	tw32_f(GRC_EEPROM_ADDR,
 	     (EEPROM_ADDR_FSM_RESET |
 	      (EEPROM_DEFAULT_CLOCK_PERIOD <<
 	       EEPROM_ADDR_CLKPERD_SHIFT)));
@@ -6309,9 +6219,8 @@
 		udelay(10);
 
 	/* Enable seeprom accesses. */
-	tw32(GRC_LOCAL_CTRL,
+	tw32_f(GRC_LOCAL_CTRL,
 	     tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
-	tr32(GRC_LOCAL_CTRL);
 	udelay(100);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
@@ -6940,8 +6849,7 @@
 		tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
 
 	/* Initialize MAC MI mode, polling disabled. */
-	tw32(MAC_MI_MODE, tp->mi_mode);
-	tr32(MAC_MI_MODE);
+	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(40);
 
 	/* Initialize data/descriptor byte/word swapping. */
@@ -7217,14 +7125,12 @@
 	if (to_device) {
 		test_desc.cqid_sqid = (13 << 8) | 2;
 
-		tw32(RDMAC_MODE, RDMAC_MODE_ENABLE);
-		tr32(RDMAC_MODE);
+		tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
 		udelay(40);
 	} else {
 		test_desc.cqid_sqid = (16 << 8) | 7;
 
-		tw32(WDMAC_MODE, WDMAC_MODE_ENABLE);
-		tr32(WDMAC_MODE);
+		tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
 		udelay(40);
 	}
 	test_desc.flags = 0x00000005;
diff -urN linux-2.4.26-pre2/drivers/sound/sb_audio.c linux-2.4.26-pre3/drivers/sound/sb_audio.c
--- linux-2.4.26-pre2/drivers/sound/sb_audio.c	2002-02-25 11:38:06.000000000 -0800
+++ linux-2.4.26-pre3/drivers/sound/sb_audio.c	2004-03-13 07:43:23.000000000 -0800
@@ -879,7 +879,7 @@
 			c -= locallen; p += locallen;
 		}
 		/* used = ( samples * 16 bits size ) */
-		*used = len << 1;
+		*used =  max_in  > ( max_out << 1) ? (max_out << 1) : max_in;
 		/* returned = ( samples * 8 bits size ) */
 		*returned = len;
 	}
diff -urN linux-2.4.26-pre2/drivers/video/sis/300vtbl.h linux-2.4.26-pre3/drivers/video/sis/300vtbl.h
--- linux-2.4.26-pre2/drivers/video/sis/300vtbl.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/300vtbl.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -52,20 +49,7 @@
  *
  */
 
-typedef struct _SiS300_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS300_StStruct;
-
-static const SiS300_StStruct  SiS300_SModeIDTable[] =
+static const SiS_StStruct  SiS300_SModeIDTable[] =
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
@@ -89,206 +73,168 @@
 	{0xff,     0,   0,   0,   0,   0,   0,   0, 0}
 };
 
-typedef struct _SiS300_ExtStruct
+static const SiS_ExtStruct  SiS300_EModeIDTable[] =
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS300_ExtStruct;
-
-static const SiS300_ExtStruct  SiS300_EModeIDTable[] =
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x2f,0x021b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
-	{0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
-	{0x32,0x2a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x3d,0x067d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x40,0x921c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
-	{0x41,0x921d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x50,0x921b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
-	{0x51,0xb21b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
-	{0x52,0x921b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
-	{0x56,0x921d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
-	{0x57,0xb21d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
-	{0x58,0x921d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
-	{0x59,0x921b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
-	{0x5c,0x921f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
-	{0x5d,0x021d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
- 	{0x5e,0x021f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x66,0x06ff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6b,0x07ff,0x08,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
-	{0x77,0x0a3f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
-	{0x78,0x0eff,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
-	{0x20,0x0a1b,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
-	{0x21,0x0a3d,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x22,0x0a7f,0x05,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x23,0x0a1b,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
-	{0x24,0x0a3d,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x25,0x0a7f,0x0c,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x29,0x0e1b,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
-	{0x2a,0x0e3d,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x2b,0x0e7f,0x0c,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x39,0x2a1b,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
-	{0x3b,0x2a3d,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3e,0x2a7f,0x0d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3f,0x2a1b,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
-	{0x42,0x2a3d,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x45,0x2a7f,0x0d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x48,0x223b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
-	{0x4b,0x227d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4e,0x22ff,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4f,0x921f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
-	{0x53,0x921f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
-	{0x54,0xb21f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
-	{0x55,0x2e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
-	{0x5a,0x2e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5b,0x2eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
-	{0x67,0x2e3b,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x2e7d,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x2eff,0x0e,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
-	{0xff,0x0000,0x00,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS300_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;  /* Index in SiS300_CRT1Table */
-	UCHAR  Ext_CRTVCLK;   /* Index in VCLK array */
-	UCHAR  Ext_CRT2CRTC;  /* Index in LCD Paneltype arrays (&3f) */
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS300_Ext2Struct;
+	{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) */
+	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
+};
 
-static const SiS300_Ext2Struct  SiS300_RefIndex[] =
+static const SiS_Ext2Struct  SiS300_RefIndex[] =
 { 
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0}, /* 00 */
-	{0x0467,0x0e,0x44,0x05,0x6a, 800, 600, 0}, /* 01 */
-	{0x0067,0x0f,0x07,0x48,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
-	{0x0067,0x10,0x06,0x8b,0x6a, 800, 600, 0}, /* 03 */
-	{0x0147,0x11,0x08,0x00,0x6a, 800, 600, 0}, /* 04 */
-	{0x0147,0x12,0x0c,0x00,0x6a, 800, 600, 0}, /* 05 */
-	{0x0047,0x11,0x4e,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
-	{0x0047,0x11,0x13,0x00,0x6a, 800, 600, 0}, /* 07 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 08 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0}, /* 09 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0}, /* 0a */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0}, /* 0b */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0}, /* 0c */
-	{0xc047,0x0a,0x08,0x00,0x2e, 640, 480, 0}, /* 0d */
-	{0xc047,0x0b,0x0a,0x00,0x2e, 640, 480, 0}, /* 0e */
-	{0xc047,0x0c,0x10,0x00,0x2e, 640, 480, 0}, /* 0f */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
-	{0xc04f,0x31,0x01,0x06,0x31, 720, 480, 0}, /* 11 */
-	{0x004f,0x32,0x03,0x06,0x32, 720, 576, 0}, /* 12 */
-	{0x0187,0x15,0x05,0x00,0x37,1024, 768, 0}, /* 13 */
-        {0xc877,0x16,0x09,0x06,0x37,1024, 768, 0}, /* 14 */
-	{0xc067,0x17,0x0b,0x49,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
-	{0x0267,0x18,0x0d,0x00,0x37,1024, 768, 0}, /* 16 */
-	{0x0047,0x19,0x11,0x8c,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
-	{0x0047,0x1a,0x52,0x00,0x37,1024, 768, 0}, /* 18 */
-	{0x0007,0x1b,0x16,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
-	{0x0387,0x1c,0x4d,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
-	{0x0077,0x1d,0x14,0x07,0x3a,1280,1024, 0}, /* 1b */
-	{0x0047,0x1e,0x17,0x00,0x3a,1280,1024, 0}, /* 1c */
-	{0x0007,0x1f,0x98,0x00,0x3a,1280,1024, 0}, /* 1d */
-	{0x0007,0x20,0x59,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
-	{0x0007,0x21,0x5a,0x00,0x3c,1600,1200, 0}, /* 1f */
-	{0x0007,0x22,0x1b,0x00,0x3c,1600,1200, 0}, /* 20 */
-	{0x0007,0x23,0x1d,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
-	{0x0007,0x24,0x1e,0x00,0x3c,1600,1200, 0}, /* 22 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0}, /* 24 */
-	{0x0077,0x02,0x04,0x05,0x51, 400, 300, 0}, /* 25 */
-	{0xc877,0x03,0x09,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
-	{0x8207,0x25,0x1f,0x00,0x68,1920,1440, 0}, /* 27 */
-	{0x0007,0x26,0x20,0x00,0x6c,2048,1536, 0}, /* 28 */
-	{0x0067,0x27,0x14,0x08,0x6e,1280, 960, 0}, /* 29 - TW: 1280x960-60 */
-	{0x0027,0x45,0x3c,0x08,0x6e,1280, 960, 0}, /* 2a - TW: 1280x960-85 */
-	{0xc077,0x33,0x09,0x06,0x20,1024, 600, 0}, /* 2b */
-	{0xc077,0x34,0x0b,0x06,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
-	{0x0057,0x35,0x27,0x08,0x70, 800, 480, 0}, /* 2d */
-	{0x0047,0x36,0x37,0x08,0x70, 800, 480, 0}, /* 2e */
-	{0x0047,0x37,0x08,0x08,0x70, 800, 480, 0}, /* 2f */
-	{0x0057,0x38,0x09,0x09,0x71,1024, 576, 0}, /* 30 */
-	{0x0047,0x39,0x38,0x09,0x71,1024, 576, 0}, /* 31 */
-	{0x0047,0x3a,0x11,0x09,0x71,1024, 576, 0}, /* 32 */
-	{0x0057,0x3b,0x39,0x0a,0x75,1280, 720, 0}, /* 33 */
-	{0x0047,0x3c,0x3a,0x0a,0x75,1280, 720, 0}, /* 34 */
-	{0x0007,0x3d,0x3b,0x0a,0x75,1280, 720, 0}, /* 35 */
-	{0x0047,0x3e,0x34,0x06,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
-	{0x0047,0x44,0x3a,0x06,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
-	{0x00c7,0x3f,0x28,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
-	{0xc067,0x40,0x3d,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
-	{0x00c7,0x41,0x28,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
-	{0xc047,0x42,0x28,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
-	{0x0067,0x43,0x3e,0x0c,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
-	{0x0077,0x46,0x3f,0x08,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
-	{0x004f,0x47,0x03,0x06,0x5f, 768, 576, 0}, /* 3e 768x576 */
-	{0x0027,0x48,0x13,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
-	{0xffff,   0,   0,   0,   0,   0,   0, 0}
-};
-
-typedef struct _SiS_VBModeIDTableStruct
-{
-	UCHAR  ModeID;
-	UCHAR  VB_TVDelayIndex;
-	UCHAR  VB_TVFlickerIndex;
-	UCHAR  VB_TVPhaseIndex;
-	UCHAR  VB_TVYFilterIndex;
-	UCHAR  VB_LCDDelayIndex;
-	UCHAR  _VB_LCDHIndex;
-	UCHAR  _VB_LCDVIndex;
-}SiS_VBModeIDTableStruct;
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
+	{0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
+	{0x0067,0x0f,0x07,0x48,0x00,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
+	{0x0067,0x10,0x06,0x8b,0x00,0x6a, 800, 600, 0}, /* 03 */
+	{0x0147,0x11,0x08,0x00,0x00,0x6a, 800, 600, 0}, /* 04 */
+	{0x0147,0x12,0x0c,0x00,0x00,0x6a, 800, 600, 0}, /* 05 */
+	{0x0047,0x11,0x4e,0x00,0x00,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
+	{0x0047,0x11,0x13,0x00,0x00,0x6a, 800, 600, 0}, /* 07 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
+	{0xc047,0x09,0x05,0x00,0x00,0x2e, 640, 480, 0}, /* 0c */
+	{0xc047,0x0a,0x08,0x00,0x00,0x2e, 640, 480, 0}, /* 0d */
+	{0xc047,0x0b,0x0a,0x00,0x00,0x2e, 640, 480, 0}, /* 0e */
+	{0xc047,0x0c,0x10,0x00,0x00,0x2e, 640, 480, 0}, /* 0f */
+	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
+	{0xc04f,0x31,0x01,0x06,0x00,0x31, 720, 480, 0}, /* 11 */
+	{0x004f,0x32,0x03,0x06,0x00,0x32, 720, 576, 0}, /* 12 */
+	{0x0187,0x15,0x05,0x00,0x00,0x37,1024, 768, 0}, /* 13 */
+        {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
+	{0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
+	{0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
+	{0x0047,0x19,0x11,0x8c,0x00,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
+	{0x0047,0x1a,0x52,0x00,0x00,0x37,1024, 768, 0}, /* 18 */
+	{0x0007,0x1b,0x16,0x00,0x00,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
+	{0x0387,0x1c,0x4d,0x00,0x00,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
+	{0x0077,0x1d,0x14,0x07,0x00,0x3a,1280,1024, 0}, /* 1b */
+	{0x0047,0x1e,0x17,0x00,0x00,0x3a,1280,1024, 0}, /* 1c */
+	{0x0007,0x1f,0x98,0x00,0x00,0x3a,1280,1024, 0}, /* 1d */
+	{0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
+	{0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
+	{0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
+	{0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
+	{0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
+	{0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
+	{0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
+	{0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
+	{0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
+	{0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
+	{0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
+	{0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
+	{0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */	/* VCLK 0x09 */
+	{0x0057,0x35,0x27,0x08,0x00,0x70, 800, 480, 0}, /* 2d */
+	{0x0047,0x36,0x37,0x08,0x00,0x70, 800, 480, 0}, /* 2e */
+	{0x0047,0x37,0x08,0x08,0x00,0x70, 800, 480, 0}, /* 2f */
+	{0x0057,0x38,0x09,0x09,0x00,0x71,1024, 576, 0}, /* 30 */
+	{0x0047,0x39,0x38,0x09,0x00,0x71,1024, 576, 0}, /* 31 */
+	{0x0047,0x3a,0x11,0x09,0x00,0x71,1024, 576, 0}, /* 32 */
+	{0x0057,0x3b,0x39,0x0a,0x00,0x75,1280, 720, 0}, /* 33 */
+	{0x0047,0x3c,0x3a,0x0a,0x00,0x75,1280, 720, 0}, /* 34 */
+	{0x0007,0x3d,0x3b,0x0a,0x00,0x75,1280, 720, 0}, /* 35 */
+	{0x0047,0x3e,0x34,0x06,0x00,0x29,1152, 864, 0}, /* 36 1152x864-75Hz */
+	{0x0047,0x44,0x3a,0x06,0x00,0x29,1152, 864, 0}, /* 37 1152x864-85Hz */
+	{0x00c7,0x3f,0x28,0x00,0x00,0x39, 848, 480, 0}, /* 38 848x480-38Hzi */
+	{0xc067,0x40,0x3d,0x0b,0x0b,0x39, 848, 480, 0}, /* 39 848x480-60Hz  */
+	{0x00c7,0x41,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3a 856x480-38Hzi */
+	{0xc047,0x42,0x28,0x00,0x00,0x3f, 856, 480, 0}, /* 3b 856x480-60Hz  */
+	{0x0067,0x43,0x3e,0x0c,0x0b,0x48,1360, 768, 0}, /* 3c 1360x768-60Hz */
+	{0x0077,0x46,0x3f,0x08,0x00,0x55,1280, 768, 0}, /* 3d 1280x768-60Hz */
+	{0x004f,0x47,0x03,0x06,0x00,0x5f, 768, 576, 0}, /* 3e 768x576 */
+	{0x0027,0x48,0x13,0x08,0x08,0x67,1360,1024, 0}, /* 3f 1360x1024-59Hz (BARCO1366 only) */
+	{0xffff,   0,   0,   0,   0,   0,   0,   0, 0}
+};
 
-static const SiS_VBModeIDTableStruct  SiS300_VBModeIDTable[] =
+static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
 {
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
 	{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -355,12 +301,7 @@
 	{0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
 };
 
-typedef struct _SiS300_CRT1TableStruct
-{
-	UCHAR CR[17];
-} SiS300_CRT1TableStruct;
-
-static const SiS300_CRT1TableStruct  SiS300_CRT1Table[] =
+static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
 {
 #if 1
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
@@ -625,13 +566,7 @@
    0x00}}   /* 0x48 */
 };
 
-typedef struct _SiS300_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS300_MCLKDataStruct;
-
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_630[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_630[] =
 {
 	{ 0x5a,0x64,0x80, 66},
 	{ 0xb3,0x45,0x80, 83},
@@ -643,7 +578,7 @@
 	{ 0x37,0x61,0x80,100}
 };
 
-static const SiS300_MCLKDataStruct  SiS300_MCLKData_300[] =
+static const SiS_MCLKDataStruct  SiS300_MCLKData_300[] =
 {
 	{ 0x68,0x43,0x80,125},
 	{ 0x68,0x43,0x80,125},
@@ -655,13 +590,7 @@
 	{ 0x37,0x61,0x80,100}
 };
 
-typedef struct _SiS300_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS300_VCLKDataStruct;
-
-static const SiS300_VCLKDataStruct  SiS300_VCLKData[] =
+static SiS_VCLKDataStruct SiS300_VCLKData[] =
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -736,14 +665,7 @@
 	{ 0x37,0x61,100}, /* 0x43 */  /* 1280x960 LCD */
 	{ 0xe3,0x9a,106}, /* 0x44 */  /* 1360x1024 - special for Barco iQ R300 */
 	{ 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
-	{ 0xff,0x00,  0}
-};
-
-static const UCHAR  SiS300_ScreenOffset[] =
-{
-	0x14,0x19,0x20,0x28,0x32,0x40,0x50,
-        0x64,0x78,0x80,0x2d,0x35,0x48,0x35,
-	0x55,0x30,0xff
+	{    0,   0,  0}  /* 0x46 custom (will be filled out) */
 };
 
 #ifndef LINUX_XF86
@@ -789,12 +711,7 @@
 static UCHAR SiS300_CR49[2];
 #endif
 
-typedef struct _SiS300_PanelDelayTblStruct
-{
-	UCHAR timer[2];
-} SiS300_PanelDelayTblStruct;
-
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -815,7 +732,7 @@
 };
 
 #if 0
-static const SiS300_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
+static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
 {
 	{{0x05,0xaa}},
 	{{0x05,0x14}},
@@ -840,28 +757,18 @@
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LCDDataStruct
+static const SiS_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
 {
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LCDDataStruct;
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1024x768Data[] =
-{
-	{   66,  31, 992, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{  176,  75, 900, 510,1320, 816},
-	{   66,  31, 992, 510,1320, 816},
-	{   27,  16,1024, 650,1350, 832},
+	{   62,  25, 800, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{   32,  15, 930, 546,1344, 806},
+	{  104,  45, 945, 496,1344, 806},
+	{   62,  25, 800, 546,1344, 806},
+	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
 {
 	{   12,   5, 896, 512,1344, 806},
 	{   12,   5, 896, 510,1344, 806},
@@ -878,30 +785,19 @@
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
+static const SiS_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
 {
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS300_LCDDataStruct  SiS300_StLCD1280x1024Data[] =
-{
-	{    4,   1, 880, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
 	{  176,  45, 900, 510,1650,1088},
-	{    4,   1, 880, 510,1650,1088},
+	{   22,   5, 800, 510,1650,1088},
 	{   13,   5,1024, 675,1560,1152},
 	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -913,74 +809,18 @@
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS300_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1024x768[] =
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-static const SiS300_LCDDataStruct  SiS300_NoScaleData1280x1024[] =  /* TW: Fake */
-{
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 800, 449, 800, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 900, 449, 900, 449},
-	{    1,   1, 800, 525, 800, 525},
-	{    1,   1,1056, 628,1056, 628},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS300_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS300_Part2PortTblStruct;
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
 { /* VESA Timing */
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
- {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_1[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
 {  /* Non-VESA */
  {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
@@ -991,38 +831,23 @@
  {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
-{
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
+{	
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_2[] =
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
 {
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_2[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{	/* TW: Temporary data, invalid */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
-{	/* TW: Temporary data, invalid */
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1400x1050_3[] =
-{	/* TW: Temporary data, invalid */
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
+{
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
-static const SiS300_Part2PortTblStruct SiS300_CRT2Part2_1600x1200_3[] =
-{	/* TW: Temporary data, invalid */
+static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+{
   {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
@@ -1030,15 +855,7 @@
 /* LVDS/Chrontel -------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS300_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS300_LVDSDataStruct;
-
-static const SiS300_LVDSDataStruct  SiS300_CHTVUPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVUPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1048,7 +865,7 @@
 	{ 936, 836, 936, 836}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1058,7 +875,7 @@
 	{ 960, 750, 960, 750}
 };
 
-static const SiS300_LVDSDataStruct  SiS300_CHTVSOPALData[] =
+static const SiS_LVDSDataStruct  SiS300_CHTVSOPALData[] =
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1068,13 +885,8 @@
 	{ 944, 625, 944, 625}
 };
 
-typedef struct _SiS300_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS300_LVDSDesStruct;
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_1[] =
 {
 	{ 1059, 626 },   /* 2.08 */
 	{ 1059, 624 },
@@ -1098,7 +910,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_1[] =
 {
 	{   0,   0 },  /* 2.08 */
 	{   0,   0 },
@@ -1122,7 +934,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_1[] =
 {
 	{ 1059, 626 },  /* 2.08 */
 	{ 1059, 624 },
@@ -1146,7 +958,7 @@
 #endif
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_1[] =
 {
 	{   8, 436},
 	{   8, 440},
@@ -1159,7 +971,7 @@
 	{1343, 794}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1[] =	/* 1280x1024 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1172,7 +984,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1185,7 +997,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_1[] =	/* Clevo Trumpion 1024x768 */
 {
 	{1343, 798},
 	{1343, 794},
@@ -1198,7 +1010,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1211,7 +1023,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1224,7 +1036,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1237,7 +1049,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_1[] =
 {
 	{1059, 626},
 	{1059, 624},
@@ -1250,7 +1062,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_1[] =
 {
 	{1343,   0},
 	{1343,   0},
@@ -1263,7 +1075,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1276,7 +1088,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1289,7 +1101,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1302,7 +1114,7 @@
 	{   0,   0}     /* 1280x960 - not applicable */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_1[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_1[] =
 {
 	{1343, 798},
 	{1343, 794},
@@ -1315,7 +1127,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType00_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType00_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1328,7 +1140,7 @@
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType01_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType01_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1341,7 +1153,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType02_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType02_2[] =
 {
 	{976, 527},
 	{976, 502},
@@ -1354,7 +1166,7 @@
 	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType03_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType03_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1367,7 +1179,7 @@
 	{1152, 597}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1380,7 +1192,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType05_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType05_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1393,7 +1205,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType06_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType06_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1406,7 +1218,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType07_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType07_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1419,7 +1231,7 @@
 	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType08_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType08_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1432,7 +1244,7 @@
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType09_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType09_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1445,7 +1257,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0a_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0a_2[] =
 {
  	{976, 527},
  	{976, 502},
@@ -1458,7 +1270,7 @@
  	{  0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0b_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0b_2[] =
 {
  	{ 1152, 700},
  	{ 1152, 675},
@@ -1471,7 +1283,7 @@
  	{    0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0c_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0c_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1484,7 +1296,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0d_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0d_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1497,7 +1309,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0e_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0e_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1510,7 +1322,7 @@
  	{   0,   0}
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType0f_2[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType0f_2[] =
 {
  	{1152, 622},
  	{1152, 597},
@@ -1523,8 +1335,36 @@
  	{   0,   0}
 };
 
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_1[]=
+{
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 805},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0}
+};
+
+static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_2[] =
+{
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
+
 /* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1a[] =	/* 1280x1024 (1366x1024) */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1537,7 +1377,7 @@
 	{   0,   0}   /* 1360x1024          */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2a[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2a[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1551,7 +1391,7 @@
 };
 
 /* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
+static const SiS_LVDSDesStruct  SiS300_PanelType04_1b[] =	/* 1024x768 */
 {
 	{1330, 798},  /* 320x200 */
 	{1330, 794},
@@ -1562,7 +1402,7 @@
 	{   0, 805}   /* 1024x768 / 512x384 */
 };
 
-static const SiS300_LVDSDesStruct  SiS300_PanelType04_2b[] =
+static const SiS_LVDSDesStruct  SiS300_PanelType04_2b[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -1575,12 +1415,7 @@
 
 /* CRT1 CRTC for slave modes */
 
-typedef struct _SiS300_LVDSCRT1DataStruct
-{
-UCHAR CR[15];
-} SiS300_LVDSCRT1DataStruct;
-
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
 {
 	{{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1602,7 +1437,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
 {
 	{{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
 	  0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
@@ -1624,7 +1459,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
 { 
 	{{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1649,7 +1484,7 @@
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
@@ -1698,7 +1533,7 @@
 #endif
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
 {
 	{{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
@@ -1723,7 +1558,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
 {
 	{{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
 	  0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
@@ -1748,7 +1583,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
 {
 	{{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
@@ -1770,7 +1605,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
 {
 	{{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
 	  0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
@@ -1792,7 +1627,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1817,7 +1652,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1842,7 +1677,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
 {
 	{{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
@@ -1867,7 +1702,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
 {
 	{{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
 	  0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
@@ -1892,7 +1727,64 @@
 	  0x01}}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
 {
 	{{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
 	  0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1914,7 +1806,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
 {
 	{{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
 	  0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1936,7 +1828,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1958,7 +1850,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1980,7 +1872,7 @@
 	  0x01 }}
 };
 
-static const SiS300_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
 {
 	{{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
 	  0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2002,12 +1894,7 @@
 	  0x01 }}
 };
 
-typedef struct _SiS300_CHTVRegDataStruct
-{
-	UCHAR Reg[16];
-} SiS300_CHTVRegDataStruct;
-
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
 {
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2017,7 +1904,7 @@
 	{{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
 {
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2027,7 +1914,7 @@
 	{{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2038,7 +1925,7 @@
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -2049,7 +1936,7 @@
 
 };
 
-static const SiS300_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
 {
 	{{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
 	{{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
diff -urN linux-2.4.26-pre2/drivers/video/sis/310vtbl.h linux-2.4.26-pre3/drivers/video/sis/310vtbl.h
--- linux-2.4.26-pre2/drivers/video/sis/310vtbl.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/310vtbl.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -52,20 +49,7 @@
  *
  */
 
-typedef struct _SiS310_StStruct
-{
-	UCHAR St_ModeID;
-	USHORT St_ModeFlag;
-	UCHAR St_StTableIndex;
-	UCHAR St_CRT2CRTC;
-	UCHAR St_ResInfo;
-	UCHAR VB_StTVFlickerIndex;
-	UCHAR VB_StTVEdgeIndex;
-	UCHAR VB_StTVYFilterIndex;
-	UCHAR St_PDC;
-} SiS310_StStruct;
-
-static const SiS310_StStruct SiS310_SModeIDTable[]=
+static const SiS_StStruct SiS310_SModeIDTable[]=
 {
 	{0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
 	{0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
@@ -89,207 +73,184 @@
 	{0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
 };
 
-typedef struct _SiS310_ExtStruct
+static const SiS_ExtStruct  SiS310_EModeIDTable[]=
 {
-	UCHAR  Ext_ModeID;
-	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
-	USHORT Ext_VESAID;
-	UCHAR  Ext_RESINFO;
-	UCHAR  VB_ExtTVFlickerIndex;
-	UCHAR  VB_ExtTVEdgeIndex;
-	UCHAR  VB_ExtTVYFilterIndex;
-	UCHAR  VB_ExtTVYFilterIndexROM661;
-	UCHAR  REFindex;
-} SiS310_ExtStruct;
-
-static const SiS310_ExtStruct  SiS310_EModeIDTable[]=
-{
-	{0x6a,0x2212,0x04,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
-	{0x2e,0x0a1b,0x03,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x03,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
-	{0x30,0x2a1b,0x04,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
-        {0x31,0x0a1b,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
-	{0x32,0x0a1b,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
-	{0x33,0x0a1d,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
-	{0x34,0x2a1d,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
-	{0x35,0x0a1f,0x0a,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
-	{0x36,0x2a1f,0x0a,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
-	{0x37,0x0212,0x05,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
-	{0x38,0x0a1b,0x05,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x06,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x07,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x07,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x00,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
-	{0x41,0x9a1d,0x00,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
-	{0x43,0x0a1c,0x03,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
-	{0x44,0x0a1d,0x03,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
-	{0x46,0x2a1c,0x04,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
-	{0x47,0x2a1d,0x04,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
-	{0x49,0x0a3c,0x05,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
-	{0x4a,0x0a3d,0x05,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x06,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x06,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x00,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
-	{0x51,0xba1b,0x01,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
-  	{0x52,0xba1b,0x02,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
-	{0x56,0x9a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
-	{0x57,0xba1d,0x01,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
- 	{0x58,0xba1d,0x02,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
-	{0x59,0x9a1b,0x00,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
-	{0x5a,0x021b,0x00,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x00,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x02,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x03,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
-	{0x5e,0x0a1f,0x03,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
-	{0x62,0x0a3f,0x03,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
-	{0x63,0x2a3f,0x04,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
-	{0x64,0x0a7f,0x05,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
-	{0x65,0x0eff,0x06,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x07,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
-	{0x68,0x067b,0x08,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x08,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x08,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x09,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
-	{0x70,0x2a1b,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
-	{0x71,0x0a1b,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
-	{0x74,0x0a1d,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
-	{0x76,0x2a1f,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
-	{0x77,0x0a1f,0x05,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x06,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
-	{0x7a,0x2a1d,0x04,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x06,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
-	{0x25,0x0eff,0x06,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0c,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
-	{0x29,0x0e1b,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
-	{0x2a,0x0e3d,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x2b,0x0e7f,0x0d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x39,0x2a1b,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
-	{0x3b,0x2a3d,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3e,0x2a7f,0x0b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3f,0x2a1b,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
-	{0x42,0x2a3d,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x45,0x2a7f,0x0b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x48,0x2a1b,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
-	{0x4b,0x2a3d,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4e,0x2a7f,0x0e,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4f,0x9a1f,0x00,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
-	{0x53,0x9a1f,0x00,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
-	{0x54,0xba1f,0x01,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
-	{0x5f,0x2a1b,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x8 */
-	{0x60,0x2a1d,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x16 */
-	{0x61,0x2a1f,0x0f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576x32 */
-	{0xff,0x0000,0x00,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
-};
-
-typedef struct _SiS310_Ext2Struct
-{
-	USHORT Ext_InfoFlag;
-	UCHAR  Ext_CRT1CRTC;
-	UCHAR  Ext_CRTVCLK;
-	UCHAR  Ext_CRT2CRTC;
-	UCHAR  ModeID;
-	USHORT XRes;
-	USHORT YRes;
-	UCHAR  Ext_PDC;
-} SiS310_Ext2Struct;
-
-static const SiS310_Ext2Struct SiS310_RefIndex[]=
-{
-	{0x085f,0x0d,0x03,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
-	{0x0067,0x0e,0x04,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
-	{0x0067,0x0f,0x08,0x48,0x6a, 800, 600, 0x40}, /* 0x2 */
-	{0x0067,0x10,0x07,0x8b,0x6a, 800, 600, 0x40}, /* 0x3 */
-	{0x0047,0x11,0x0a,0x00,0x6a, 800, 600, 0x40}, /* 0x4 */
-	{0x0047,0x12,0x0d,0x00,0x6a, 800, 600, 0x40}, /* 0x5 */
-	{0x0047,0x13,0x13,0x00,0x6a, 800, 600, 0x20}, /* 0x6 */
-	{0x0107,0x14,0x1c,0x00,0x6a, 800, 600, 0x20}, /* 0x7 */
-	{0xc85f,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
-	{0xc067,0x06,0x02,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
-	{0xc067,0x07,0x02,0x47,0x2e, 640, 480, 0x40}, /* 0xa */
-	{0xc067,0x08,0x03,0x8a,0x2e, 640, 480, 0x40}, /* 0xb */
-	{0xc047,0x09,0x05,0x00,0x2e, 640, 480, 0x40}, /* 0xc */
-	{0xc047,0x0a,0x09,0x00,0x2e, 640, 480, 0x40}, /* 0xd */
-	{0xc047,0x0b,0x0e,0x00,0x2e, 640, 480, 0x40}, /* 0xe */
-	{0xc047,0x0c,0x15,0x00,0x2e, 640, 480, 0x40}, /* 0xf */
-	{0x487f,0x04,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-	{0xc04f,0x3c,0x01,0x06,0x31, 720, 480, 0x30}, /* 0x11 */
-	{0x004f,0x3d,0x03,0x06,0x32, 720, 576, 0x30}, /* 0x12 */
-	{0x0087,0x15,0x06,0x00,0x37,1024, 768, 0x30}, /* 0x13 */
-	{0xc877,0x16,0x0b,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
-	{0xc067,0x17,0x0f,0x49,0x37,1024, 768, 0x20}, /* 0x15 */
-	{0x0067,0x18,0x11,0x00,0x37,1024, 768, 0x20}, /* 0x16 */
-	{0x0047,0x19,0x16,0x8c,0x37,1024, 768, 0x20}, /* 0x17 */
-	{0x0107,0x1a,0x1b,0x00,0x37,1024, 768, 0x10}, /* 0x18 */
-	{0x0107,0x1b,0x1f,0x00,0x37,1024, 768, 0x10}, /* 0x19 */
-	{0x0087,0x1c,0x11,0x00,0x3a,1280,1024, 0x30}, /* 0x1a */
-	{0x0137,0x1d,0x19,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
-	{0x0107,0x1e,0x1e,0x00,0x3a,1280,1024, 0x00}, /* 0x1c */
-	{0x0207,0x1f,0x20,0x00,0x3a,1280,1024, 0x00}, /* 0x1d */
-	{0x0227,0x20,0x21,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
-	{0x0407,0x21,0x22,0x00,0x3c,1600,1200, 0x00}, /* 0x1f */
-	{0x0407,0x22,0x23,0x00,0x3c,1600,1200, 0x00}, /* 0x20 */
-	{0x0407,0x23,0x25,0x00,0x3c,1600,1200, 0x00}, /* 0x21 */
-	{0x0007,0x24,0x26,0x00,0x3c,1600,1200, 0x00}, /* 0x22 */
-	{0x0007,0x25,0x2c,0x00,0x3c,1600,1200, 0x00}, /* 0x23 */
-	{0x0007,0x26,0x34,0x00,0x3c,1600,1200, 0x00}, /* 0x24 */
-	{0x407f,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
-	{0xc07f,0x01,0x00,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
-	{0x007f,0x02,0x04,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
-	{0xc077,0x03,0x0b,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
-	{0x8007,0x27,0x27,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
-	{0x4007,0x28,0x29,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
-	{0x4007,0x29,0x2e,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
-	{0x4007,0x2a,0x30,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
-	{0x4007,0x2b,0x35,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
-	{0x4005,0x2c,0x39,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
-	{0x4007,0x2d,0x2b,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
-	{0x4007,0x2e,0x31,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
-	{0x4007,0x2f,0x33,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
-	{0x4007,0x30,0x37,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
-	{0x4005,0x31,0x38,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-	{0x0057,0x32,0x40,0x08,0x70, 800, 480, 0x30}, /* 0x34 */
-	{0x0047,0x33,0x07,0x08,0x70, 800, 480, 0x30}, /* 0x35 */
-	{0x0047,0x34,0x0a,0x08,0x70, 800, 480, 0x30}, /* 0x36 */
-	{0x0057,0x35,0x0b,0x09,0x71,1024, 576, 0x30}, /* 0x37 */
-	{0x0047,0x36,0x11,0x09,0x71,1024, 576, 0x30}, /* 0x38 */
-	{0x0047,0x37,0x16,0x09,0x71,1024, 576, 0x30}, /* 0x39 */
-	{0x0117,0x38,0x19,0x0a,0x75,1280, 720, 0x30}, /* 0x3a */
-	{0x0107,0x39,0x1e,0x0a,0x75,1280, 720, 0x30}, /* 0x3b */
-	{0x0207,0x3a,0x20,0x0a,0x75,1280, 720, 0x30}, /* 0x3c */
-	{0x0127,0x3b,0x19,0x08,0x7c,1280, 960, 0x30}, /* 0x3d */
-	{0x0227,0x4c,0x59,0x08,0x7c,1280, 960, 0x20}, /* 0x3e */
-	{0xc07f,0x4e,0x00,0x06,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
-        {0x0077,0x42,0x5b,0x08,0x23,1280, 768, 0x30}, /* 0x40 */    /* TW: 0x5b was 0x12 */
-	{0x0127,0x43,0x4d,0x08,0x26,1400,1050, 0x30}, /* 0x41 */
-	{0x0207,0x4b,0x5a,0x08,0x26,1400,1050, 0x30}, /* 0x42 Non-BIOS, new */
-	{0x0107,0x44,0x19,0x00,0x29,1152, 864, 0x30}, /* 0x43 Non-BIOS, new */
-	{0x0107,0x4a,0x1e,0x00,0x29,1152, 864, 0x30}, /* 0x44 Non-BIOS, new */
-	{0x0087,0x45,0x57,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi - Non-BIOS, new */
-	{0xc067,0x46,0x55,0x0b,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz  - Non-BIOS, new */
-	{0x0087,0x47,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi - Non-BIOS, new */
-	{0xc047,0x48,0x57,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz  - Non-BIOS, new */
-	{0x0067,0x49,0x58,0x0c,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz - Non-BIOS, new */
-	{0x004f,0x4d,0x03,0x06,0x5f, 768, 576, 0x30}, /* 0x4a 768x576 */
-	{0xffff,0x00,0x00,0x00,0x00,   0,   0, 0}
+	{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}
+};
+
+static const SiS_Ext2Struct SiS310_RefIndex[]=
+{
+	{0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
+	{0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
+	{0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
+	{0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
+	{0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
+	{0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
+	{0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
+	{0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
+	{0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
+	{0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
+	{0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
+	{0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
+	{0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
+	{0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
+	{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 */
+	{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 */
+	{0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
+	{0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
+	{0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
+	{0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
+	{0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
+	{0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
+	{0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
+	{0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
+	{0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
+	{0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
+	{0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
+	{0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
+	{0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
+	{0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
+	{0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
+	{0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
+	{0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
+	{0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
+	{0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
+	{0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
+	{0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
+	{0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
+	{0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
+	{0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
+	{0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
+	{0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
+	{0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
+	{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 */
+	{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 */
+	{0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
+	{0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
+	{0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
+        {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   */
+	{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}
 };
 
-typedef struct _SiS310_CRT1TableStruct
-{
- 	UCHAR CR[17];
-} SiS310_CRT1TableStruct;
-
-static const SiS310_CRT1TableStruct SiS310_CRT1Table[]=
+static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
 {
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
    0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
@@ -310,7 +271,7 @@
  {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
    0x00}}, /* 0x5 */
-#endif   
+#endif
  {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
    0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
    0x00}},
@@ -329,16 +290,16 @@
    0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
    0x00}}, /* 0x8 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
-   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0x9 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
    0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
    0x61}}, /* 0xa */
  {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
-   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* TW: Corrected VBE */
+   0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
    0x61}}, /* 0xb */
  {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
-   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* TW: Corrected VDE, VBE */
+   0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
    0x00}}, /* 0xc */
  {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
    0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
@@ -466,7 +427,7 @@
  {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
    0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
    0x01}}, /* 0x36 */
- {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* TW: 95 was 15 - illegal HBE! */
+ {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
    0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
    0x01}}, /* 0x37 */
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
@@ -498,7 +459,7 @@
  {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
    0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
    0x00}}, /* 0x3f */
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,   /* TW: The following from 650/LVDS BIOS */
+ {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
    0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
    0x01}},  /* 0x40 */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
@@ -510,31 +471,31 @@
  {{0xe6,0xae,0xae,0x8a,0xbd,0x90,0x3d,0x10,
    0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x00,0x03,
    0x00}},  /* 0x43 */
- {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* New, 1152x864-75, not in BIOS */
+ {{0xc3,0x8f,0x8f,0x87,0x9b,0x0b,0x82,0xef, /* 1152x864-75 */
    0x60,0x83,0x5f,0x5f,0x83,0x10,0x00,0x07,
    0x01}},  /* 0x44 */
- {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* New, 848x480-38i, not in BIOS */
+ {{0x86,0x69,0x69,0x8A,0x74,0x06,0x8C,0x15, /* 848x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x45 */
- {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* New, 848x480-60, not in BIOS */
+ {{0x83,0x69,0x69,0x87,0x6f,0x1d,0x03,0x3E, /* 848x480-60 */
    0xE5,0x8d,0xDF,0xe4,0x04,0x00,0x00,0x06,
    0x00}},  /* 0x46 */
- {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* New, 856x480-38i, not in BIOS */
+ {{0x86,0x6A,0x6A,0x8A,0x74,0x06,0x8C,0x15, /* 856x480-38i */
    0x4F,0x83,0xEF,0xEF,0x8D,0x30,0x00,0x02,
    0x00}},  /* 0x47 */
- {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* New, 856x480-60, not in BIOS */
+ {{0x81,0x6A,0x6A,0x85,0x70,0x00,0x0F,0x3E, /* 856x480-60 */
    0xEB,0x8E,0xDF,0xDF,0x10,0x00,0x00,0x02,
    0x00}},  /* 0x48 */
- {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* New, 1360x768-60, not in BIOS */
+ {{0xdd,0xa9,0xa9,0x81,0xb4,0x97,0x26,0xfd, /* 1360x768-60 */
    0x01,0x8d,0xff,0x00,0x27,0x10,0x00,0x03,
    0x01}},  /* 0x49 */
- {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* New, 1152x864-84, not in any BIOS   */
+ {{0xd9,0x8f,0x8f,0x9d,0xba,0x0a,0x8a,0xff, /* 1152x864-84  */
    0x60,0x8b,0x5f,0x5f,0x8b,0x10,0x00,0x03,
    0x01}},  /* 0x4a */
- {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* New, 1400x1050-75, not in any BIOS  */
+ {{0xea,0xae,0xae,0x8e,0xba,0x82,0x40,0x10, /* 1400x1050-75  */
    0x1b,0x87,0x19,0x1a,0x41,0x0f,0x00,0x03,
    0x00}},  /* 0x4b */
- {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* New, 1280x960-85, not in any BIOS */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
    0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
    0x01}},  /* 0x4c */
  {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
@@ -542,16 +503,16 @@
    0x01}},  /* 0x4d */
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}   /* 0x4e */
+   0x00}},  /* 0x4e */
+ {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
+   0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
+   0x21}},  /* 0x4f */
+ {{0x15,0xd1,0xd1,0x99,0xe2,0x19,0x3d,0x10, /* 1680x1050-60 */
+   0x1a,0x8d,0x19,0x19,0x3e,0x2f,0x01,0x0c,
+   0x20}}   /* 0x50 */
 };
 
-typedef struct _SiS310_MCLKDataStruct
-{
-	UCHAR SR28,SR29,SR2A;
-	USHORT CLOCK;
-} SiS310_MCLKDataStruct;
-
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_315[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
 {
 	{ 0x3b,0x22,0x01,143},
 	{ 0x5c,0x23,0x01,166},
@@ -563,7 +524,7 @@
 	{ 0x5c,0x23,0x01,166}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
 {
 	{ 0x5a,0x64,0x82, 66},
 	{ 0xb3,0x45,0x82, 83},
@@ -575,7 +536,7 @@
 	{ 0x37,0x22,0x82,133}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
 {
 	{ 0x5c,0x23,0x01,166},
 	{ 0x5c,0x23,0x01,166},
@@ -587,7 +548,7 @@
 	{ 0x79,0x06,0x01,250}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_0_660[] =  /* TODO */
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
 {
 	{ 0x5c,0x23,0x82,166},
 	{ 0x5c,0x23,0x82,166},
@@ -599,7 +560,19 @@
 	{ 0x37,0x21,0x82,200}
 };
 
-static const SiS310_MCLKDataStruct SiS310_MCLKData_1[] =
+static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+{
+	{ 0x37,0x22,0x82,133},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x7c,0x08,0x82,200},
+	{ 0x29,0x21,0x82,150},
+	{ 0x5c,0x23,0x82,166},
+	{ 0x65,0x23,0x82,183},
+	{ 0x37,0x21,0x82,200}
+};
+
+static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
 {
         { 0x29,0x21,0x82,150},
 	{ 0x5c,0x23,0x82,166},
@@ -611,13 +584,7 @@
 	{ 0x37,0x22,0x82,133}
 };
 
-typedef struct _SiS310_VCLKDataStruct
-{
-	UCHAR SR2B,SR2C;
-	USHORT CLOCK;
-} SiS310_VCLKDataStruct;
-
-static const SiS310_VCLKDataStruct SiS310_VCLKData[]=
+static SiS_VCLKDataStruct SiS310_VCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -630,7 +597,7 @@
 	{ 0x53,0xe2, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x5a,0x64, 65}, /* 0x0b */  /* TW: was 6c c3 - WRONG */
+	{ 0x5a,0x64, 65}, /* 0x0b */  /* was 6c c3 - WRONG */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -644,7 +611,7 @@
 	{ 0x62,0x44, 94}, /* 0x16 */
 	{ 0x2b,0x41,104}, /* 0x17 */
 	{ 0x3a,0x23,105}, /* 0x18 */
-	{ 0x70,0x44,108}, /* 0x19 */ 
+	{ 0x70,0x44,108}, /* 0x19 */
 	{ 0x3c,0x23,109}, /* 0x1a */
 	{ 0x5e,0x43,113}, /* 0x1b */
 	{ 0xbc,0x44,116}, /* 0x1c */
@@ -677,49 +644,51 @@
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x60,0x36, 30}, /* 0x41 */  /* Chrontel */
-	{ 0x40,0x4a, 28}, /* 0x42 */  /* Chrontel */
-	{ 0x9f,0x46, 44}, /* 0x43 */  /* Chrontel */
+	{ 0x60,0x36, 30}, /* 0x41 Chrontel */
+	{ 0x40,0x4a, 28}, /* 0x42 Chrontel */
+	{ 0x9f,0x46, 44}, /* 0x43 Chrontel */
 	{ 0x97,0x2c, 26}, /* 0x44 */
-	{ 0x44,0xe4, 25}, /* 0x45 */  /* Chrontel */
-	{ 0x7e,0x32, 47}, /* 0x46 */  /* Chrontel */
-	{ 0x8a,0x24, 31}, /* 0x47 */  /* Chrontel */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* Chrontel */
+	{ 0x44,0xe4, 25}, /* 0x45 Chrontel */
+	{ 0x7e,0x32, 47}, /* 0x46 Chrontel */
+	{ 0x8a,0x24, 31}, /* 0x47 Chrontel */
+	{ 0x97,0x2c, 26}, /* 0x48 Chrontel */
 	{ 0xce,0x3c, 39}, /* 0x49 */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* Chrontel */
+	{ 0x52,0x4a, 36}, /* 0x4a Chrontel */
 	{ 0x34,0x61, 95}, /* 0x4b */
 	{ 0x78,0x27,108}, /* 0x4c - was 102 */
-	{ 0x66,0x43,123}, /* 0x4d */  /* Modes 0x26-0x28 (1400x1050) */
+	{ 0x66,0x43,123}, /* 0x4d Modes 0x26-0x28 (1400x1050) */
 	{ 0x41,0x4e, 21}, /* 0x4e */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* Chrontel */
+	{ 0xa1,0x4a, 29}, /* 0x4f Chrontel */
 	{ 0x19,0x42, 42}, /* 0x50 */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* Chrontel */
+	{ 0x54,0x46, 58}, /* 0x51 Chrontel */
 	{ 0x25,0x42, 61}, /* 0x52 */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* Chrontel */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* Chrontel */
-	{ 0x62,0xc6, 34}, /* 0x55 - added for 848x480-60 (not in any BIOS) */
-	{ 0x6a,0xc6, 37}, /* 0x56 - added for 848x480-75 (not in any BIOS)    - TEMP */
-	{ 0xbf,0xc8, 35}, /* 0x57 - added for 856x480-38i,60 (not in any BIOS) */
-	{ 0x30,0x23, 88}, /* 0x58 - added for 1360x768-62 (is 60Hz!) (not in any BIOS) */
-	{ 0x52,0x07,149}, /* 0x59 - added for 1280x960-85 (Not in any BIOS) */
-	{ 0x56,0x07,156}, /* 0x5a - added for 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b - added for 1280x768 LCD */
-};
-
-typedef struct _SiS310_VBVCLKDataStruct
-{
-	UCHAR Part4_A,Part4_B;
-	USHORT CLOCK;
-} SiS310_VBVCLKDataStruct;
+	{ 0x44,0x44, 66}, /* 0x53 Chrontel */
+	{ 0x3a,0x62, 70}, /* 0x54 Chrontel */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60 */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
+	{ 0x52,0x07,149}, /* 0x59 1280x960-85 */
+	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
+   	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800  */
+	{ 0x70,0x0a,147}, /* 0x5d 1680x1050 */
+	{ 0x70,0x24,162}, /* 0x5e 1600x1200 */
+	{ 0x5a,0x64, 65}, /* 0x5f 1280x720 - temp */
+	{ 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) */
+};
 
-static const SiS310_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -732,7 +701,7 @@
 	{ 0x53,0x47, 50}, /* 0x08 */
 	{ 0x74,0x67, 52}, /* 0x09 */
 	{ 0x6d,0x66, 56}, /* 0x0a */
-	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301 bios: 35,62  */
+	{ 0x35,0x62, 65}, /* 0x0b */  /* Was 0x5a,0x64 - 650/LVDS+301: 35,62  */
 	{ 0x46,0x44, 67}, /* 0x0c */
 	{ 0xb1,0x46, 68}, /* 0x0d */
 	{ 0xd3,0x4a, 72}, /* 0x0e */
@@ -785,47 +754,48 @@
 	{ 0xea,0x08,340}, /* 0x37 */
 	{ 0xe8,0x07,376}, /* 0x38 */
 	{ 0xde,0x06,389}, /* 0x39 */
-	{ 0x52,0x2a, 54}, /* 0x3a */  /* 301 TV */
-	{ 0x52,0x6a, 27}, /* 0x3b */  /* 301 TV */
-	{ 0x62,0x24, 70}, /* 0x3c */  /* 301 TV */
-	{ 0x62,0x64, 70}, /* 0x3d */  /* 301 TV */
-	{ 0xa8,0x4c, 30}, /* 0x3e */  /* 301 TV */
-	{ 0x20,0x26, 33}, /* 0x3f */  /* 301 TV */
+	{ 0x52,0x2a, 54}, /* 0x3a 301 TV - start */
+	{ 0x52,0x6a, 27}, /* 0x3b 301 TV */
+	{ 0x62,0x24, 70}, /* 0x3c 301 TV */
+	{ 0x62,0x64, 70}, /* 0x3d 301 TV */
+	{ 0xa8,0x4c, 30}, /* 0x3e 301 TV */
+	{ 0x20,0x26, 33}, /* 0x3f 301 TV */
 	{ 0x31,0xc2, 39}, /* 0x40 */
-	{ 0x2e,0x48, 25}, /* 0x41 */  /* Replacement for LCD on 315 for index 0 */
-	{ 0x24,0x46, 25}, /* 0x42 */  /* Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
-	{ 0x26,0x64, 28}, /* 0x43 */  /* Replacement for LCD on 315 for index 1 */
-	{ 0x37,0x64, 40}, /* 0x44 */  /* Replacement for LCD on 315 for index 4 */
-	{ 0xa1,0x42,108}, /* 0x45 */  /* 1280x960 LCD */
-	{ 0x37,0x61,100}, /* 0x46 */  /* 1280x960 LCD */
+	{ 0x2e,0x48, 25}, /* 0x41 Replacement for LCD on 315 for index 0 */
+	{ 0x24,0x46, 25}, /* 0x42 Replacement for LCD on 315 for modes 0x01, 0x03, 0x0f, 0x10, 0x12 */
+	{ 0x26,0x64, 28}, /* 0x43 Replacement for LCD on 315 for index 1 */
+	{ 0x37,0x64, 40}, /* 0x44 Replacement for LCD on 315 for index 4 */
+	{ 0xa1,0x42,108}, /* 0x45 1280x960 LCD */
+	{ 0x37,0x61,100}, /* 0x46 1280x960 LCD */
 	{ 0x78,0x27,108}, /* 0x47 */
-	{ 0x97,0x2c, 26}, /* 0x48 */  /* UNUSED - Entries from here new, not in any BIOS */
-	{ 0xce,0x3c, 39}, /* 0x49 */  /* UNUSED */
-	{ 0x52,0x4a, 36}, /* 0x4a */  /* UNUSED */
-	{ 0x34,0x61, 95}, /* 0x4b */  /* UNUSED */
-	{ 0x78,0x27,108}, /* 0x4c */  /* UNUSED */
-	{ 0x66,0x43,123}, /* 0x4d */  /* 1400x1050-60 */
-	{ 0x41,0x4e, 21}, /* 0x4e */  /* UNUSED */
-	{ 0xa1,0x4a, 29}, /* 0x4f */  /* UNUSED */
-	{ 0x19,0x42, 42}, /* 0x50 */  /* UNUSED */
-	{ 0x54,0x46, 58}, /* 0x51 */  /* UNUSED */
-	{ 0x25,0x42, 61}, /* 0x52 */  /* UNUSED */
-	{ 0x44,0x44, 66}, /* 0x53 */  /* UNUSED */
-	{ 0x3a,0x62, 70}, /* 0x54 */  /* UNUSED */
-	{ 0x62,0xc6, 34}, /* 0x55 */  /* 848x480-60 */
-	{ 0x6a,0xc6, 37}, /* 0x56 */  /* 848x480-75 - TEMP, UNUSED */
-	{ 0xbf,0xc8, 35}, /* 0x57 */  /* 856x480-38i,60  */
-	{ 0x30,0x23, 88}, /* 0x58 */  /* 1360x768-62 (is 60Hz!) TEMP, UNUSED */
-	{ 0x52,0x07,149}, /* 0x59 */  /* 1280x960-85  */
-	{ 0x56,0x07,156}, /* 0x5a */  /* 1400x1050-75 */
-   	{ 0x70,0x29, 81}  /* 0x5b */  /* 1280x768 LCD */
-};
-
-static const UCHAR SiS310_ScreenOffset[] =
-{
-        0x14,0x19,0x20,0x28,0x32,0x40,0x50,0x64,
-	0x78,0x80,0x2d,0x35,0x57,0x48,0x55,0x30,
-	0xff
+	{ 0x97,0x2c, 26}, /* 0x48 UNUSED */
+	{ 0xce,0x3c, 39}, /* 0x49 UNUSED */
+	{ 0x52,0x4a, 36}, /* 0x4a UNUSED */
+	{ 0x34,0x61, 95}, /* 0x4b UNUSED */
+	{ 0x78,0x27,108}, /* 0x4c UNUSED */
+	{ 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
+	{ 0x41,0x4e, 21}, /* 0x4e UNUSED */
+	{ 0xa1,0x4a, 29}, /* 0x4f UNUSED */
+	{ 0x19,0x42, 42}, /* 0x50 UNUSED */
+	{ 0x54,0x46, 58}, /* 0x51 UNUSED */
+	{ 0x25,0x42, 61}, /* 0x52 UNUSED */
+	{ 0x44,0x44, 66}, /* 0x53 UNUSED */
+	{ 0x3a,0x62, 70}, /* 0x54 UNUSED */
+	{ 0x62,0xc6, 34}, /* 0x55 848x480-60 */
+	{ 0x6a,0xc6, 37}, /* 0x56 848x480-75 - TEMP, UNUSED */
+	{ 0xbf,0xc8, 35}, /* 0x57 856x480-38i,60  */
+	{ 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
+	{ 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? */
+	{ 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) */
 };
 
 static const DRAM4Type SiS310_SR15[8] = {
@@ -873,12 +843,7 @@
 static const USHORT SiS310_YCSenseData2    = 0x016b;
 #endif
 
-typedef struct _SiS310_PanelDelayTblStruct
-{
- 	UCHAR timer[2];
-} SiS310_PanelDelayTblStruct;
-
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
 {
         {{0x10,0x40}},
 	{{0x10,0x40}},
@@ -898,7 +863,7 @@
 	{{0x10,0x40}}
 };
 
-static const SiS310_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
 {
 	{{0x28,0xc8}},
 	{{0x28,0xc8}},
@@ -922,28 +887,18 @@
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LCDDataStruct
-{
-	USHORT RVBHCMAX;
-	USHORT RVBHCFACT;
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LCDDataStruct;
-
-static const SiS310_LCDDataStruct  SiS310_StLCD1024x768Data[]=
+static const SiS_LCDDataStruct  SiS310_St2LCD1024x768Data[] =
 {
 	{   62,  25, 800, 546,1344, 806},
 	{   32,  15, 930, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
+        {   62,  25, 800, 546,1344, 806},
 	{  104,  45, 945, 496,1344, 806},
 	{   62,  25, 800, 546,1344, 806},
 	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =   
+static const SiS_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =
 {
 	{   42,  25,1536, 419,1344, 806},
 	{   48,  25,1536, 369,1344, 806},
@@ -951,28 +906,10 @@
 	{   48,  25,1536, 369,1344, 806},
 	{   12,   5, 896, 500,1344, 806},
 	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{   12,   5, 896, 500,1344, 806},
-	{   42,  25,1024, 625,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-	 
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1024x768Data[] =  
-{
-	{   62,  25, 800, 546,1344, 806},
-	{   32,  15, 930, 546,1344, 806},
-        {   62,  25, 800, 546,1344, 806},    
-	{  104,  45, 945, 496,1344, 806},
-	{   62,  25, 800, 546,1344, 806},
-	{   31,  18,1008, 624,1344, 806},
 	{    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS310_LCDDataStruct  SiS310_StLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
 {
 	{   22,   5, 800, 510,1650,1088},
 	{   22,   5, 800, 510,1650,1088},
@@ -984,7 +921,7 @@
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
+static const SiS_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
 {
 	{  211,  60,1024, 501,1688,1066},
 	{  211,  60,1024, 508,1688,1066},
@@ -993,53 +930,10 @@
 	{  211,  60,1024, 500,1688,1066},
 	{  211,  75,1024, 625,1688,1066},
 	{  211, 120,1280, 798,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1800,1000,1688,1066}  /* 1280x960 - does not work, use panel scaler instead */
-};
-
-static const SiS310_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
-{
-	{   22,   5, 800, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{  176,  45, 900, 510,1650,1088},
-	{   22,   5, 800, 510,1650,1088},
-	{   13,   5,1024, 675,1560,1152},
-	{   16,   9,1266, 804,1688,1072},
 	{    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1024x768[] =  
-{
-        {    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},  /* 640x400 - does not work */
-	{    1,   1,1344, 806,1344, 806},  /* 640x480 - does not work */
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806},
-	{    1,   1,1344, 806,1344, 806}
-};
-
-static const SiS310_LCDDataStruct  SiS310_NoScaleData1280x1024[] =
-{
-        {    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066},
-	{    1,   1,1688,1066,1688,1066}
-};
-
-typedef struct _SiS310_Part2PortTblStruct
-{
- 	UCHAR CR[12];
-} SiS310_Part2PortTblStruct;
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
 {
  {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
@@ -1047,646 +941,37 @@
  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
  {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
  {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
+ {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6e,0x48,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x2c,0x12,0x38,0x55,0x2f,0xc1,0x35,0xb1,0x47,0xe9,0x71,0x33}},
- {{0x2d,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xc1,0x49,0x33}},
- {{0x29,0x12,0xb5,0xd2,0xac,0xe9,0x35,0xd9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},  /* others  */
-/* 0x36,0x13,0x02,0x25,0xff,0x03,0x45,0x09,0x07,0xf9,0x00,0x24        my      */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
+/* *** LCDA *** */
 
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1024x768_3[] =
-{
-#if 1   /* Data from 650/301LVx 1.10.6s and others */
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x24,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0xf9,0x45,0x09,0x07,0xf9,0x09,0x24}}
+#if 0
+static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
+{ /* Clevo, 651+301C */
+	{1200, 450, 2048,1250},
+	{1200, 400, 2048,1250},
+	{1280, 450, 2048,1250},
+	{1280, 400, 2048,1250},
+	{1200, 530, 2048,1250},
+	{1360, 650, 2048,1250},
+	{1584, 818, 2048,1250},
+	{1688,1066, 2048,1250},
+	{1688,1066, 2048,1250},
+#if 0
+	{2048,1250, 2048,1250}   /* this should be correct */
 #endif
-#if 0    /* Data from my 301LV */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},   /* TEST */
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}},
- {{0x36,0x13,0x02,0x25,0xff,0x21,0x45,0x09,0x07,0x88,0x09,0x24}}
+#if 1
+	{2160,1250, 2048,1250}   /* ? */
 #endif
 };
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_1[] =
-{ /* Acer; BIOS data invalid, last row taken from _3 */
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x02,0x25,0xFF,0x03,0x45,0x09,0x07,0xF9,0x00,0x24}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_2[] =
-{ /* Acer */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-/*   1     2    4    5    6   1c   1d   1f   20   21   23   25   */
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1280x1024_3[] =
-{ /* Acer */
- {{0x31,0x1B,0xC4,0xDA,0xB0,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x34,0x1B,0x9F,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3E,0x1B,0xCF,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_1[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_2[] =
-{
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x2b,0x12,0xd9,0xe5,0xd5,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x22,0x12,0xc0,0xcc,0xbc,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x33,0x13,0x01,0x0d,0xfd,0x2c,0x23,0x98,0x27,0x3e,0x08,0x42}},
- {{0x3f,0x1b,0x3d,0x49,0x39,0x54,0x23,0xc0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1b,0x91,0x9d,0x8d,0x8c,0x23,0xf8,0x27,0x9e,0x68,0x42}},
- {{0x43,0x24,0x11,0x1d,0x0d,0xcc,0x23,0x38,0x37,0xde,0xa8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1400x1050_3[] =
-{
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}},
- {{0x43,0x24,0x21,0x29,0x19,0xea,0x23,0x0a,0x07,0x32,0xc6,0x32}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_1[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_2[] =
-{
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x32,0x1B,0x2C,0x52,0x20,0x80,0x20,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x3A,0x1B,0x54,0x7A,0x48,0x80,0x24,0x52,0x30,0xA3,0x3A,0x02}},
- {{0x36,0x1B,0x90,0xB6,0x84,0xA8,0x24,0x7A,0x30,0xCB,0x62,0x02}},
- {{0x3A,0x1C,0xE4,0x0A,0xD8,0xE0,0x24,0xB2,0x30,0x03,0x9A,0x02}},
- {{0x4A,0x24,0x64,0x8A,0x58,0x20,0x34,0xF2,0x30,0x43,0xDA,0x52}},
- {{0x47,0x24,0x71,0x97,0x65,0x3E,0x34,0x10,0x40,0x61,0xF8,0x02}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-static const SiS310_Part2PortTblStruct SiS310_CRT2Part2_1600x1200_3[] =
-{
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}},
- {{0x4C,0x24,0xC8,0xE1,0xAF,0x70,0x34,0x0A,0x07,0xFC,0x2A,0x53}}
-};
-
-/* CRT1 CRTC for LCDA */
-
-typedef struct _SiS310_LCDACRT1DataStruct
-{
- 	UCHAR CR[17];
-}SiS310_LCDACRT1DataStruct;
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x59,0x84,0x04,0x3e,
-   0xE2,0x89,0xdf,0xdf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x6D,0x18,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x06,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x31,0x1c,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x3b,0x06,0x7c,0xf0,
-   0x5A,0x81,0x57,0x57,0x7D,0x00,0x00,0x01,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x49,0x94,0x24,0xF5,
-   0x02,0x89,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2[]=
-{
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x4f,0x4f,0x0f,0x6e,0x1f,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x06,
-   0x01}},
- {{0xa3,0x63,0x63,0x98,0x78,0x19,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x89,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11024x768_2_H[]=
-{
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x4a,0x81,0x8f,0xdb,0xda,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xbb,
-   0x31,0x88,0x5d,0xc2,0xc1,0x20,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x0f,0x46,0x97,0x24,0xb3,
-   0x72,0x89,0xdf,0x03,0x02,0x30,0x00,0x01,
-   0x01 }},
- {{0x71,0x31,0x31,0x98,0x46,0x17,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x02,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x4c,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1[]=
-{ /* Acer */
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x04,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x18,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_1_H[]=
-{  /* Acer */
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x05,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x31,0x1c,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x86,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11280x1024_2_H[]=
-{  /* Illegal data in BIOS (Acer, Compaq) */
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x27,0x27,0x93,0x39,0x81,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x4f,0x31,0x31,0x93,0x3e,0x86,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x01,
-   0x01 }},
- {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1[]=
-{
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0xee,0x1f,
-   0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x83,0x63,0x63,0x87,0x68,0x16,0x66,0xf0,
-   0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x06,
-   0x01}},
- {{0x9f,0x7f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x02,
-   0x01}},
- {{0xbf,0x9f,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
-   0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xb3,0x01,0x28,0x10,
-   0x1a,0x80,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_1_H[]=
-{
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-    0x93,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-    0x92,0x86,0x8f,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-    0x60,0x84,0x5d,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x47,0x27,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-    0xe2,0x86,0xdf,0xdf,0xef,0x10,0x00,0x05,
-    0x00}},
-  {{0x51,0x31,0x31,0x95,0x36,0x04,0x66,0xf0,
-    0x5a,0x8e,0x57,0x57,0x67,0x20,0x00,0x01,
-    0x01}},
-  {{0x5f,0x3f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
-    0x02,0x86,0xff,0xff,0x0f,0x10,0x00,0x01,
-    0x01}},
-  {{0x6f,0x4f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-    0x02,0x86,0xff,0xff,0x0f,0x09,0x00,0x05,
-    0x01}},
-  {{0x76,0x56,0x56,0x9a,0x5b,0x89,0x28,0x10,
-    0x1c,0x80,0x19,0x19,0x29,0x0b,0x00,0x05,
-    0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2[]=
-{
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x63,0x63,0x92,0x96,0x04,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x07,
-   0x01}},
- {{0xce,0x7f,0x7f,0x92,0xa4,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xb4,0x02,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x03,
-   0x01}},
- {{0xce,0xae,0xae,0x92,0xbc,0x0a,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11400x1050_2_H[]=
-{
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x27,0x8a,0x64,0x92,0x28,0x9e,
-   0x03,0x87,0xdf,0xdf,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0x9c,0x31,0x31,0x80,0x64,0x92,0x28,0xd4,
-   0x3f,0x83,0x57,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x3f,0x92,0x64,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0xff,0x29,0x21,0x00,0x06,
-   0x01}},
- {{0x7e,0x4f,0x4f,0x82,0x64,0x12,0x28,0x5a,
-   0x13,0x87,0xff,0xff,0x29,0x29,0x00,0x06,
-   0x01}},
- {{0x76,0x56,0x56,0x9a,0x64,0x92,0x28,0x10,
-   0x20,0x84,0x19,0x19,0x29,0x0f,0x00,0x05,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1[]=
-{
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x8F,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x4F,0x87,0x51,0x09,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x63,0x9B,0x65,0x1D,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x06,
-   0x01}},
- {{0xB3,0x7F,0x7F,0x97,0x81,0x99,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x02,
-   0x01}},
- {{0xD3,0x9F,0x9F,0x97,0xA1,0x19,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x07,
-   0x01}},
- {{0xE2,0xAE,0xAE,0x86,0xB0,0x88,0x4A,0x10,
-   0x1A,0x8E,0x19,0x19,0x4B,0x2F,0x00,0x03,
-   0x00}},
- {{0xFB,0xC7,0xC7,0x9F,0xC9,0x81,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x07,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_1_H[]=
-{
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0xC0,0x1F,
-   0x90,0x84,0x8F,0x8F,0xC1,0x30,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x8E,0x1F,
-   0x5E,0x82,0x5D,0x5D,0x87,0x10,0x00,0x01,
-   0x00}},
- {{0x69,0x27,0x27,0x8D,0x30,0x88,0x10,0x3E,
-   0xE0,0x84,0xDF,0xDF,0x11,0x00,0x00,0x01,
-   0x00}},
- {{0x73,0x31,0x31,0x97,0x3A,0x92,0x88,0xF0,
-   0x58,0x8C,0x57,0x57,0x89,0x20,0x00,0x01,
-   0x01}},
- {{0x81,0x3F,0x3F,0x85,0x48,0x00,0x30,0xF5,
-   0x00,0x84,0xFF,0xFF,0x31,0x10,0x00,0x06,
-   0x01}},
- {{0x91,0x4F,0x4F,0x95,0x58,0x10,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x06,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x6C,0x84,0xE0,0x10,
-   0xB0,0x84,0xAF,0xAF,0xE1,0x2F,0x00,0x02,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2[]=
-{
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x4F,0x4F,0x8D,0xA3,0x1B,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x01,0x04,
-   0x00}},
- {{0x09,0x63,0x63,0x8D,0xAD,0x05,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x7F,0x7F,0x8D,0xBB,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x01,0x00,
-   0x01}},
- {{0x09,0x9F,0x9F,0x8D,0xCB,0x03,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x01,0x04,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0x09,0xC7,0xC7,0x8D,0xDF,0x17,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x01,0x04,
-   0x00}}
-};
-
-static const SiS310_LCDACRT1DataStruct  SiS310_LCDACRT11600x1200_2_H[]=
-{
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x37,0x8B,0x8F,0x8F,0xE1,0x21,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x1E,0x82,0x5D,0x5D,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xE1,0x27,0x27,0x85,0x7B,0x93,0xE0,0x9E,
-   0x5F,0x83,0xDF,0xDF,0xE1,0x01,0x00,0x03,
-   0x00}},
- {{0xD7,0x31,0x31,0x9B,0x7B,0x13,0xE0,0xD4,
-   0x9B,0x8F,0x57,0x57,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xC9,0x3F,0x3F,0x8D,0x7B,0x13,0xE0,0xD4,
-   0xEF,0x83,0xFF,0xFF,0xE1,0x21,0x00,0x03,
-   0x01}},
- {{0xB9,0x4F,0x4F,0x9D,0x7B,0x93,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xFF,0xE1,0x29,0x00,0x02,
-   0x01}},
- {{0xD4,0x9F,0x9F,0x98,0xA8,0x00,0x30,0x5A,
-   0x00,0x84,0xFF,0xFF,0x31,0x09,0x00,0x03,
-   0x01}},
- {{0xA5,0x63,0x63,0x89,0x7B,0x93,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xAF,0xE1,0x0F,0x00,0x02,
-   0x00}}
-};
-
+#endif
 
 /**************************************************************/
 /* LVDS, CHRONTEL ------------------------------------------- */
 /**************************************************************/
 
-typedef struct _SiS310_LVDSDataStruct
-{
-	USHORT VGAHT;
-	USHORT VGAVT;
-	USHORT LCDHT;
-	USHORT LCDVT;
-} SiS310_LVDSDataStruct;
-
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1697,7 +982,7 @@
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALData[]= 
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1708,7 +993,7 @@
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALMData[]=  
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALMData[]=
 {
 	{ 840, 600, 840, 600},
 	{ 840, 600, 840, 600},
@@ -1719,7 +1004,7 @@
         {1160, 945,1160, 945}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALMData[]=
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALMData[]=
 {
 	{ 840, 525, 840, 525},
 	{ 840, 525, 840, 525},
@@ -1730,7 +1015,7 @@
         {1160, 840,1160, 840}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVUPALNData[]=  
+static const SiS_LVDSDataStruct  SiS310_CHTVUPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1741,7 +1026,7 @@
 	{1400,1000,1400,1000}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVOPALNData[]= 
+static const SiS_LVDSDataStruct  SiS310_CHTVOPALNData[]=
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1752,7 +1037,7 @@
         {1400, 875,1400, 875}
 };
 
-static const SiS310_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* TW: (super overscan - no effect on 7019) */
+static const SiS_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* (super overscan - no effect on 7019) */
 {
 	{1008, 625,1008, 625},
 	{1008, 625,1008, 625},
@@ -1763,13 +1048,8 @@
         {1400, 875,1400, 875}       	
 };
 
-typedef struct _SiS310_LVDSDesStruct
-{
-	USHORT LCDHDES;
-	USHORT LCDVDES;
-} SiS310_LVDSDesStruct;
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
+static const SiS_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1782,7 +1062,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1795,7 +1075,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
+static const SiS_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1810,7 +1090,7 @@
 };
 
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType03_1[]=
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1823,7 +1103,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType04_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1836,7 +1116,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType05_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1849,7 +1129,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType06_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1862,7 +1142,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_1[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType07_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1875,7 +1155,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1890,7 +1170,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1905,7 +1185,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
 {
 	{ 0, 0},
 	{ 0, 0},
@@ -1920,7 +1200,7 @@
 	{ 0, 0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1932,7 +1212,7 @@
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
 {
 	{ 0, 524},
 	{ 0, 524},
@@ -1944,7 +1224,7 @@
 	{ 0, 524}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_1[]=
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1957,7 +1237,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1970,7 +1250,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_1[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_1[]=
 {
 	{1343, 798},
 	{1343, 794},
@@ -1983,7 +1263,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType00_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType00_2[]=
 {
 	{980, 528},
 	{980, 503},
@@ -1996,7 +1276,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType01_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType01_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2009,7 +1289,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType02_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType02_2[]=
 {
 	{1368, 754},
 	{1368, 729},
@@ -2024,7 +1304,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType03_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType03_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2035,7 +1315,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType04_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType04_2[]=
 {
 	{ 0,   0},
 	{ 0,   0},
@@ -2048,7 +1328,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType05_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType05_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2061,7 +1341,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType06_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType06_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2074,7 +1354,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType07_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType07_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2087,7 +1367,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
+static const SiS_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
 {
 	{1308, 741},
 	{1308, 716},
@@ -2102,7 +1382,7 @@
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
+static const SiS_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
 {
 	{1083, 622},
 	{1083, 597},
@@ -2115,7 +1395,7 @@
 	{   0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
 {
 	{1568, 920},
 	{1568, 895},
@@ -2141,7 +1421,7 @@
 #endif
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2154,7 +1434,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
+static const SiS_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
 {
 	{1152, 622},
 	{1152, 597},
@@ -2167,7 +1447,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0d_2[]=  
+static const SiS_LVDSDesStruct  SiS310_PanelType0d_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2180,7 +1460,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0e_2[]= 
+static const SiS_LVDSDesStruct  SiS310_PanelType0e_2[]=
 {
 	{1152, 622},
 	{1152, 597},
@@ -2193,7 +1473,7 @@
 	{ 0,   0}
 };
 
-static const SiS310_LVDSDesStruct  SiS310_PanelType0f_2[] = 
+static const SiS_LVDSDesStruct  SiS310_PanelType0f_2[] =
 {
 	{1152, 622},
 	{1152, 597},
@@ -2206,14 +1486,37 @@
 	{ 0,   0}
 };
 
-/* CRT1 CRTC for SlaveModes and LCDA */
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_1[]=
+{
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 8,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0,   0},
+	{ 0, 806},
+	{ 0,   0}
+};
 
-typedef struct _SiS310_LVDSCRT1DataStruct
+static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_2[] =
 {
- 	UCHAR CR[15];
-} SiS310_LVDSCRT1DataStruct;
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0},
+	{ 0 , 0}
+};
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
+/* CRT1 CRTC for SlaveModes and LCDA */
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
 {
  {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2235,7 +1538,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
 {
  {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -2257,7 +1560,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
 {
  {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
@@ -2279,7 +1582,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
 {
  {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
    0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
@@ -2301,7 +1604,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
 {
  {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2326,7 +1629,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
 {
  {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
    0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
@@ -2351,7 +1654,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
 {
  {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
@@ -2376,7 +1679,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
 {
  {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
    0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
@@ -2401,7 +1704,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
 {
  {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
@@ -2429,7 +1732,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =
 {
  {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
    0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
@@ -2454,7 +1757,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =
 {
  {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
@@ -2482,7 +1785,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
    0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
@@ -2507,7 +1810,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
 {
   {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
     0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2567,7 +1870,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] =
 {
  {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
    0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
@@ -2627,7 +1930,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =
 {
  {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
@@ -2687,7 +1990,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =
 {
  {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
    0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
@@ -2747,7 +2050,7 @@
 #endif   
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
 {
  {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
@@ -2813,7 +2116,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
 {
  {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
    0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
@@ -2879,7 +2182,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
 {
  {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
@@ -2945,7 +2248,7 @@
 #endif
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] = 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] =
 {
  {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
    0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
@@ -3011,9 +2314,66 @@
 #endif
 };
 
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1[] =
+{
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
+   0x00}},
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
+   0x00}},
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
+   0x01}},
+ {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
+   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
+   0x01}},
+ {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
+   0x01}}
+};
+
+static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1_H[] =
+{
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
+   0x00}},
+ {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}},
+ {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
+   0x01}},
+ {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
+   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
+   0x01}}
+};
+
+
 /* CRT1 CRTC for Chrontel TV slave modes */
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =  
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =
 { 
  {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -3038,7 +2398,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
 {
  {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -3063,7 +2423,7 @@
    0x01 }}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =    
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =
 { 
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3088,7 +2448,7 @@
    0x01}}
 };
 
-static const SiS310_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
+static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
 {
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -3113,12 +2473,8 @@
    0x01 }}
 };
 
-typedef struct _SiS310_CHTVRegDataStruct
-{
- 	UCHAR Reg[16];
-} SiS310_CHTVRegDataStruct;
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
 {
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3138,7 +2494,7 @@
       for PAL-M and PAL-N all above is corrected.
     */
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
 {
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3149,7 +2505,7 @@
  {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3160,7 +2516,7 @@
  {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3171,7 +2527,7 @@
  {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
 {
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3187,7 +2543,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
 {
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -3203,7 +2559,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -3219,7 +2575,7 @@
 #endif
 };
 
-static const SiS310_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
diff -urN linux-2.4.26-pre2/drivers/video/sis/init.c linux-2.4.26-pre3/drivers/video/sis/init.c
--- linux-2.4.26-pre2/drivers/video/sis/init.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/init.c	2004-03-13 07:43:23.000000000 -0800
@@ -34,13 +34,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -78,7 +75,6 @@
 
 #if defined(ALLOC_PRAGMA)
 #pragma alloc_text(PAGE,SiSSetMode)
-#pragma alloc_text(PAGE,SiSInit)
 #endif
 
 /*********************************************/
@@ -108,17 +104,20 @@
    SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
    SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
    SiS_Pr->SiS_HiTVSt2Timing  = SiS_HiTVSt2Timing;
-   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
+
    SiS_Pr->SiS_HiTVExtTiming  = SiS_HiTVExtTiming;
    SiS_Pr->SiS_HiTVGroup3Data = SiS_HiTVGroup3Data;
    SiS_Pr->SiS_HiTVGroup3Simu = SiS_HiTVGroup3Simu;
+#if 0
+   SiS_Pr->SiS_HiTVTextTiming = SiS_HiTVTextTiming;
    SiS_Pr->SiS_HiTVGroup3Text = SiS_HiTVGroup3Text;
+#endif
 
    SiS_Pr->SiS_StPALData   = SiS_StPALData;
    SiS_Pr->SiS_ExtPALData  = SiS_ExtPALData;
    SiS_Pr->SiS_StNTSCData  = SiS_StNTSCData;
    SiS_Pr->SiS_ExtNTSCData = SiS_ExtNTSCData;
-/* SiS_Pr->SiS_St1HiTVData = SiS_St1HiTVData;  */
+   SiS_Pr->SiS_St1HiTVData = SiS_StHiTVData; 
    SiS_Pr->SiS_St2HiTVData = SiS_St2HiTVData;
    SiS_Pr->SiS_ExtHiTVData = SiS_ExtHiTVData;
    SiS_Pr->SiS_St525iData  = SiS_StNTSCData;
@@ -131,16 +130,17 @@
    SiS_Pr->pSiS_OutputSelect = &SiS_OutputSelect;
    SiS_Pr->pSiS_SoftSetting  = &SiS_SoftSetting;
 
+   SiS_Pr->SiS_LCD1280x720Data      = SiS_LCD1280x720Data;
+   SiS_Pr->SiS_StLCD1280x768_2Data  = SiS_StLCD1280x768_2Data;
+   SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
+   SiS_Pr->SiS_LCD1280x768_3Data    = SiS_LCD1280x768_3Data;
+   SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
    SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
-   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
-   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
+   SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
+   SiS_Pr->SiS_LCD1680x1050Data     = SiS_LCD1680x1050Data;
    SiS_Pr->SiS_StLCD1600x1200Data   = SiS_StLCD1600x1200Data;
-   SiS_Pr->SiS_NoScaleData1400x1050 = SiS_NoScaleData1400x1050;
-   SiS_Pr->SiS_NoScaleData1600x1200 = SiS_NoScaleData1600x1200;
-   SiS_Pr->SiS_ExtLCD1280x768Data   = SiS_ExtLCD1280x768Data;
-   SiS_Pr->SiS_StLCD1280x768Data    = SiS_StLCD1280x768Data;
-   SiS_Pr->SiS_NoScaleData1280x768  = SiS_NoScaleData1280x768;
+   SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
 
    SiS_Pr->SiS_LVDS320x480Data_1   = SiS_LVDS320x480Data_1;
@@ -169,41 +169,12 @@
    SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
    SiS_Pr->SiS_LVDS640x480Data_2   = SiS_LVDS640x480Data_2;
 
-   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
-   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
-   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
    SiS_Pr->SiS_LVDS848x480Data_1   = SiS_LVDS848x480Data_1;
    SiS_Pr->SiS_LVDS848x480Data_2   = SiS_LVDS848x480Data_2;
-
-   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
-   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
-
-   SiS_Pr->SiS_LCDA1024x768Data_1  = SiS_LCDA1024x768Data_1;
-   SiS_Pr->SiS_LCDA1024x768Data_2  = SiS_LCDA1024x768Data_2;
-   SiS_Pr->SiS_LCDA1280x1024Data_1 = SiS_LCDA1280x1024Data_1;
-   SiS_Pr->SiS_LCDA1280x1024Data_2 = SiS_LCDA1280x1024Data_2;
-   SiS_Pr->SiS_LCDA1400x1050Data_1 = SiS_LCDA1400x1050Data_1;
-   SiS_Pr->SiS_LCDA1400x1050Data_2 = SiS_LCDA1400x1050Data_2;
-   SiS_Pr->SiS_LCDA1600x1200Data_1 = SiS_LCDA1600x1200Data_1;
-   SiS_Pr->SiS_LCDA1600x1200Data_2 = SiS_LCDA1600x1200Data_2;
-
-   SiS_Pr->LVDS1024x768Des_1  = SiS_PanelType1076_1;
-   SiS_Pr->LVDS1280x1024Des_1 = SiS_PanelType1210_1;
-   SiS_Pr->LVDS1400x1050Des_1 = SiS_PanelType1296_1;
-   SiS_Pr->LVDS1600x1200Des_1 = SiS_PanelType1600_1;
-   SiS_Pr->LVDS1024x768Des_2  = SiS_PanelType1076_2;
-   SiS_Pr->LVDS1280x1024Des_2 = SiS_PanelType1210_2;
-   SiS_Pr->LVDS1400x1050Des_2 = SiS_PanelType1296_2;
-   SiS_Pr->LVDS1600x1200Des_2 = SiS_PanelType1600_2;
-
-   SiS_Pr->SiS_PanelTypeNS_1 = SiS_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = SiS_PanelTypeNS_2;
-
-   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
 
    SiS_Pr->SiS_LVDSCRT11280x768_1    = SiS_LVDSCRT11280x768_1;
    SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
@@ -218,14 +189,23 @@
    SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
    SiS_Pr->SiS_LVDSCRT11152x768_2_H  = SiS_LVDSCRT11152x768_2_H;
    SiS_Pr->SiS_LVDSCRT1320x480_1     = SiS_LVDSCRT1320x480_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS_LVDSCRT1XXXxXXX_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
    SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
    SiS_Pr->SiS_LVDSCRT1640x480_2     = SiS_LVDSCRT1640x480_2;
    SiS_Pr->SiS_LVDSCRT1640x480_2_H   = SiS_LVDSCRT1640x480_2_H;
    SiS_Pr->SiS_LVDSCRT1640x480_3     = SiS_LVDSCRT1640x480_3;
    SiS_Pr->SiS_LVDSCRT1640x480_3_H   = SiS_LVDSCRT1640x480_3_H;
+
+   SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
+   SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
+
+   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
+   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
+   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
+   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
+
+   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
+   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
 }
 
 #ifdef SIS300
@@ -262,19 +242,18 @@
    SiS_StandTable[0x1c].CRTC[4] = 0x54;
    SiS_StandTable[0x1c].CRTC[5] = 0x80;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS300_SModeIDTable;
-   SiS_Pr->SiS_VBModeIDTable = (SiS_VBModeStruct *)SiS300_VBModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS300_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS300_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS300_CRT1Table;
+   SiS_Pr->SiS_SModeIDTable  = SiS300_SModeIDTable;
+   SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
+   SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
+   SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
    if(HwInfo->jChipType == SIS_300) {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_300; /* 300 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_300; /* 300 */
    } else {
-      SiS_Pr->SiS_MCLKData_0    = (SiS_MCLKDataStruct *)SiS300_MCLKData_630; /* 630, 730 */
+      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_630; /* 630, 730 */
    }
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS300_VCLKData;
+   SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS300_ScreenOffset;
 
    SiS_Pr->SiS_SR15  = SiS300_SR15;
 
@@ -303,97 +282,102 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS300_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS300_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS300_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS300_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS300_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS300_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS300_NoScaleData1280x1024;
+   SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
 
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTbl;
-#if 0
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS300_PanelDelayTblLVDS;
-#endif
-
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData; 			   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVUPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS300_CHTVOPALData;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS300_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS300_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS300_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS300_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS300_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS300_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS300_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS300_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS300_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS300_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS300_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS300_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS300_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS300_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS300_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS300_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS300_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS300_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS300_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS300_PanelType0f_2;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS300_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS300_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS300_ExtLCD1280x1024Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
+   SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
+   SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
+   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS_CHTVUNTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALMData = SiS_CHTVONTSCData;    /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVUPALNData = SiS300_CHTVUPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
 
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1a;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2a;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
    }
    if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-      SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS300_PanelType04_1b;
-      SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS300_PanelType04_2b;
+      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
+      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
    }
 
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS300_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL  = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL = (SiS_LVDSCRT1DataStruct *)SiS300_CHTVCRT1SOPAL;
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS300_CHTVReg_SOPAL;
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS300_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS300_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS300_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS300_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS300_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS300_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS300_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS300_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS300_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS300_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS300_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS300_LVDSCRT1XXXxXXX_1_H;
+
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS300_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS300_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS300_CHTVCRT1SOPAL;
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS300_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS300_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS300_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS300_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS300_CHTVReg_UNTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS300_CHTVReg_ONTSC;  /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS300_CHTVReg_UPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS300_CHTVReg_OPAL;   /* not supported on 300 series */
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS300_CHTVReg_SOPAL;
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS300_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS300_CHTVVCLKONTSC;
    SiS_Pr->SiS_CHTVVCLKUPAL  = SiS300_CHTVVCLKUPAL;
@@ -403,40 +387,6 @@
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS300_CHTVVCLKUPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKOPALN = SiS300_CHTVVCLKOPAL;   /* not supported on 300 series */
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS300_CHTVVCLKSOPAL;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS300_CRT2Part2_1600x1200_3;
-
-   /* LCDResInfo will on 300 series be translated to 315 series definitions */
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1600x1200 = 255;  		   /* Something illegal */
-   SiS_Pr->SiS_Panel1400x1050 = 255;
-   SiS_Pr->SiS_Panel640x480_2 = 255;
-   SiS_Pr->SiS_Panel640x480_3 = 255;
-   SiS_Pr->SiS_Panel1152x864  = 255;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;     /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;     /* Lowest value LVDS */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;    /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = Panel_Barco1366;
 }
 #endif
 
@@ -474,23 +424,24 @@
    SiS_StandTable[0x1c].CRTC[4] = 0x55;
    SiS_StandTable[0x1c].CRTC[5] = 0x81;
 
-   SiS_Pr->SiS_SModeIDTable  = (SiS_StStruct *)SiS310_SModeIDTable;
-   SiS_Pr->SiS_EModeIDTable  = (SiS_ExtStruct *)SiS310_EModeIDTable;
+   SiS_Pr->SiS_SModeIDTable  = SiS310_SModeIDTable;
+   SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS310_RefIndex;
-   SiS_Pr->SiS_CRT1Table     = (SiS_CRT1TableStruct *)SiS310_CRT1Table;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_660;  /* 661/741/760 */
+   SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
+   if(HwInfo->jChipType >= SIS_760) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
+   } else if(HwInfo->jChipType >= SIS_661) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
    } else if(HwInfo->jChipType == SIS_330) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_330;  /* 330 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
    } else if(HwInfo->jChipType > SIS_315PRO) {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_650;  /* 550, 650, 740 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
    } else {
-      SiS_Pr->SiS_MCLKData_0 = (SiS_MCLKDataStruct *)SiS310_MCLKData_0_315;  /* 315 */
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
    }
-   SiS_Pr->SiS_MCLKData_1    = (SiS_MCLKDataStruct *)SiS310_MCLKData_1;
-   SiS_Pr->SiS_VCLKData      = (SiS_VCLKDataStruct *)SiS310_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS310_VBVCLKData;
-   SiS_Pr->SiS_ScreenOffset  = SiS310_ScreenOffset;
+   SiS_Pr->SiS_MCLKData_1    = SiS310_MCLKData_1;
+   SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
 
    SiS_Pr->SiS_SR15  = SiS310_SR15;
 
@@ -519,124 +470,96 @@
    SiS_Pr->pSiS_YCSenseData2    = &SiS310_YCSenseData2;
 #endif
 
-   SiS_Pr->SiS_StLCD1024x768Data    = (SiS_LCDDataStruct *)SiS310_StLCD1024x768Data;
-   SiS_Pr->SiS_ExtLCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_ExtLCD1024x768Data;
-   SiS_Pr->SiS_St2LCD1024x768Data   = (SiS_LCDDataStruct *)SiS310_St2LCD1024x768Data;
-   SiS_Pr->SiS_StLCD1280x1024Data   = (SiS_LCDDataStruct *)SiS310_StLCD1280x1024Data;
-   SiS_Pr->SiS_ExtLCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_ExtLCD1280x1024Data;
-   SiS_Pr->SiS_St2LCD1280x1024Data  = (SiS_LCDDataStruct *)SiS310_St2LCD1280x1024Data;
-   SiS_Pr->SiS_NoScaleData1024x768  = (SiS_LCDDataStruct *)SiS310_NoScaleData1024x768;
-   SiS_Pr->SiS_NoScaleData1280x1024 = (SiS_LCDDataStruct *)SiS310_NoScaleData1280x1024;
-
-   SiS_Pr->SiS_PanelDelayTbl     = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTbl;
-   SiS_Pr->SiS_PanelDelayTblLVDS = (SiS_PanelDelayTblStruct *)SiS310_PanelDelayTblLVDS;
-
-   SiS_Pr->SiS_CHTVUPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVUPALData;
-   SiS_Pr->SiS_CHTVOPALData  = (SiS_LVDSDataStruct *)SiS310_CHTVOPALData;
-   SiS_Pr->SiS_CHTVUPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALMData;
-   SiS_Pr->SiS_CHTVOPALMData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALMData;
-   SiS_Pr->SiS_CHTVUPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVUPALNData;
-   SiS_Pr->SiS_CHTVOPALNData = (SiS_LVDSDataStruct *)SiS310_CHTVOPALNData;
-   SiS_Pr->SiS_CHTVSOPALData = (SiS_LVDSDataStruct *)SiS310_CHTVSOPALData;
-
-   SiS_Pr->SiS_PanelType00_1 = (SiS_LVDSDesStruct *)SiS310_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = (SiS_LVDSDesStruct *)SiS310_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = (SiS_LVDSDesStruct *)SiS310_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = (SiS_LVDSDesStruct *)SiS310_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = (SiS_LVDSDesStruct *)SiS310_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = (SiS_LVDSDesStruct *)SiS310_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = (SiS_LVDSDesStruct *)SiS310_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = (SiS_LVDSDesStruct *)SiS310_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = (SiS_LVDSDesStruct *)SiS310_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = (SiS_LVDSDesStruct *)SiS310_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = (SiS_LVDSDesStruct *)SiS310_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = (SiS_LVDSDesStruct *)SiS310_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = (SiS_LVDSDesStruct *)SiS310_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = (SiS_LVDSDesStruct *)SiS310_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = (SiS_LVDSDesStruct *)SiS310_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = (SiS_LVDSDesStruct *)SiS310_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = (SiS_LVDSDesStruct *)SiS310_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = (SiS_LVDSDesStruct *)SiS310_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = (SiS_LVDSDesStruct *)SiS310_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = (SiS_LVDSDesStruct *)SiS310_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = (SiS_LVDSDesStruct *)SiS310_PanelType0f_2;
-
-   SiS_Pr->SiS_CRT2Part2_1024x768_1  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_1;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_1;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_1 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_1;
-   SiS_Pr->SiS_CRT2Part2_1024x768_2  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_2;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_2;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_2 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_2;
-   SiS_Pr->SiS_CRT2Part2_1024x768_3  = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1280x1024_3;
-   SiS_Pr->SiS_CRT2Part2_1400x1050_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1400x1050_3;
-   SiS_Pr->SiS_CRT2Part2_1600x1200_3 = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_1600x1200_3;
-
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_1_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11400x1050_2_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = (SiS_LVDSCRT1DataStruct *)SiS310_LVDSCRT11600x1200_2_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL          = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL         = (SiS_LVDSCRT1DataStruct *)SiS310_CHTVCRT1OPAL;
-
-   SiS_Pr->SiS_CHTVReg_UNTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UNTSC;
-   SiS_Pr->SiS_CHTVReg_ONTSC = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_ONTSC;
-   SiS_Pr->SiS_CHTVReg_UPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPAL;
-   SiS_Pr->SiS_CHTVReg_OPAL  = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-   SiS_Pr->SiS_CHTVReg_UPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALM;
-   SiS_Pr->SiS_CHTVReg_OPALM = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALM;
-   SiS_Pr->SiS_CHTVReg_UPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_UPALN;
-   SiS_Pr->SiS_CHTVReg_OPALN = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPALN;
-   SiS_Pr->SiS_CHTVReg_SOPAL = (SiS_CHTVRegDataStruct *)SiS310_CHTVReg_OPAL;
-
-   SiS_Pr->SiS_LCDACRT11024x768_1    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1;
-   SiS_Pr->SiS_LCDACRT11280x1024_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1;
-   SiS_Pr->SiS_LCDACRT11400x1050_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1;
-   SiS_Pr->SiS_LCDACRT11600x1200_1   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1;
-   SiS_Pr->SiS_LCDACRT11024x768_1_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_1_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_1_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_1_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_1_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_1_H;
-   SiS_Pr->SiS_LCDACRT11024x768_2    = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2;
-   SiS_Pr->SiS_LCDACRT11280x1024_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2;
-   SiS_Pr->SiS_LCDACRT11400x1050_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2;
-   SiS_Pr->SiS_LCDACRT11600x1200_2   = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2;
-   SiS_Pr->SiS_LCDACRT11024x768_2_H  = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11024x768_2_H;
-   SiS_Pr->SiS_LCDACRT11280x1024_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11280x1024_2_H;
-   SiS_Pr->SiS_LCDACRT11400x1050_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11400x1050_2_H;
-   SiS_Pr->SiS_LCDACRT11600x1200_2_H = (SiS_LCDACRT1DataStruct *)SiS310_LCDACRT11600x1200_2_H;
+   SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
+   SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
+
+   SiS_Pr->SiS_St2LCD1024x768Data   = SiS310_St2LCD1024x768Data;
+   SiS_Pr->SiS_ExtLCD1024x768Data   = SiS310_ExtLCD1024x768Data;
+   SiS_Pr->SiS_St2LCD1280x1024Data  = SiS310_St2LCD1280x1024Data;
+   SiS_Pr->SiS_ExtLCD1280x1024Data  = SiS310_ExtLCD1280x1024Data;
+
+   SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
+
+   SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
+   SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
+   SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
+   SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
+   SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
+   SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
+   SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
+   SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
+   SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
+   SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
+   SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
+   SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
+   SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
+   SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
+   SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
+   SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
+   SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
+   SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
+   SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
+   SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
+   SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
+   SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
+   SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
+   SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
+   SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
+   SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
+   SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
+   SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
+   SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
+   SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
+   SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
+   SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
+   SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
+   SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
+
+   SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
+   SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
+   SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
+   SiS_Pr->SiS_CHTVOPALMData = SiS310_CHTVOPALMData;
+   SiS_Pr->SiS_CHTVUPALNData = SiS310_CHTVUPALNData;
+   SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
+   SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
+
+   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS310_LVDSCRT1800x600_1;
+   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS310_LVDSCRT11024x768_1;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS310_LVDSCRT11280x1024_1;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1   = SiS310_LVDSCRT11400x1050_1;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1   = SiS310_LVDSCRT11600x1200_1;
+   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS310_LVDSCRT1800x600_1_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS310_LVDSCRT11024x768_1_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
+   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS310_LVDSCRT1800x600_2;
+   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS310_LVDSCRT11024x768_2;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS310_LVDSCRT11280x1024_2;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2   = SiS310_LVDSCRT11400x1050_2;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2   = SiS310_LVDSCRT11600x1200_2;
+   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS310_LVDSCRT1800x600_2_H;
+   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS310_LVDSCRT11024x768_2_H;
+   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
+   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
+   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS310_LVDSCRT1XXXxXXX_1;
+   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS310_LVDSCRT1XXXxXXX_1_H;
+   SiS_Pr->SiS_CHTVCRT1UNTSC         = SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC         = SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL          = SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL          = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL         = SiS310_CHTVCRT1OPAL;
+
+   SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
+   SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
+   SiS_Pr->SiS_CHTVReg_UPAL  = SiS310_CHTVReg_UPAL;
+   SiS_Pr->SiS_CHTVReg_OPAL  = SiS310_CHTVReg_OPAL;
+   SiS_Pr->SiS_CHTVReg_UPALM = SiS310_CHTVReg_UPALM;
+   SiS_Pr->SiS_CHTVReg_OPALM = SiS310_CHTVReg_OPALM;
+   SiS_Pr->SiS_CHTVReg_UPALN = SiS310_CHTVReg_UPALN;
+   SiS_Pr->SiS_CHTVReg_OPALN = SiS310_CHTVReg_OPALN;
+   SiS_Pr->SiS_CHTVReg_SOPAL = SiS310_CHTVReg_OPAL;
 
    SiS_Pr->SiS_CHTVVCLKUNTSC = SiS310_CHTVVCLKUNTSC;
    SiS_Pr->SiS_CHTVVCLKONTSC = SiS310_CHTVVCLKONTSC;
@@ -645,28 +568,8 @@
    SiS_Pr->SiS_CHTVVCLKUPALM = SiS310_CHTVVCLKUPALM;
    SiS_Pr->SiS_CHTVVCLKOPALM = SiS310_CHTVVCLKOPALM;
    SiS_Pr->SiS_CHTVVCLKUPALN = SiS310_CHTVVCLKUPALN;
-   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;   
+   SiS_Pr->SiS_CHTVVCLKOPALN = SiS310_CHTVVCLKOPALN;
    SiS_Pr->SiS_CHTVVCLKSOPAL = SiS310_CHTVVCLKOPAL;
-
-   SiS_Pr->SiS_Panel320x480   = Panel_320x480;
-   SiS_Pr->SiS_Panel640x480   = Panel_640x480;
-   SiS_Pr->SiS_Panel800x600   = Panel_800x600;
-   SiS_Pr->SiS_Panel1024x768  = Panel_1024x768;
-   SiS_Pr->SiS_Panel1280x1024 = Panel_1280x1024;
-   SiS_Pr->SiS_Panel1280x960  = Panel_1280x960;
-   SiS_Pr->SiS_Panel1600x1200 = Panel_1600x1200;
-   SiS_Pr->SiS_Panel1400x1050 = Panel_1400x1050;
-   SiS_Pr->SiS_Panel1152x768  = Panel_1152x768;
-   SiS_Pr->SiS_Panel1152x864  = Panel_1152x864;
-   SiS_Pr->SiS_Panel1280x768  = Panel_1280x768;
-   SiS_Pr->SiS_Panel1024x600  = Panel_1024x600;
-   SiS_Pr->SiS_Panel640x480_2 = Panel_640x480_2;
-   SiS_Pr->SiS_Panel640x480_3 = Panel_640x480_3;
-   SiS_Pr->SiS_PanelMax       = Panel_320x480;    /* highest value */
-   SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
-   SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
-   SiS_Pr->SiS_PanelCustom    = Panel_Custom;
-   SiS_Pr->SiS_PanelBarco1366 = 255;
 }
 #endif
 
@@ -707,7 +610,8 @@
 /*********************************************/
 
 USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN)
+SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+              int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
 {
    USHORT ModeIndex = 0;
 
@@ -775,10 +679,23 @@
 	  }
 	  break;
      case 1280:
-          if(VDisplay == 1024)        ModeIndex = ModeIndex_1280x1024[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
+          if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	  else if(VDisplay == 800) {
+	     if(VGAEngine == SIS_315_VGA) {
+	        if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 800)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1280x800[Depth];
+	        }
+	     }
+	  } else if(VDisplay == 720) {
+	     if((VBFlags & CRT1_LCDA) && (LCDwidth == 1280) && (LCDheight == 720)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     } else if(!(VBFlags & CRT1_LCDA)) {
+	        ModeIndex = ModeIndex_1280x720[Depth];
+	     }
+	  } else if(!(VBFlags & CRT1_LCDA)) {
              if(VDisplay == 960)      ModeIndex = ModeIndex_1280x960[Depth];
-	     else if(VDisplay == 720) ModeIndex = ModeIndex_1280x720[Depth];
 	     else if(VDisplay == 768) {
 	        if(VGAEngine == SIS_300_VGA) {
 	           ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -798,12 +715,25 @@
           break;
      case 1400:
           if(VGAEngine == SIS_315_VGA) {
-	     if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+	     if(VDisplay == 1050) {
+	        if((VBFlags & CRT1_LCDA) &&
+	           (((LCDwidth == 1400) && (LCDheight == 1050)) ||
+		    ((LCDwidth == 1600) && (LCDheight == 1200)))) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        } else if(!(VBFlags & CRT1_LCDA)) {
+	           ModeIndex = ModeIndex_1400x1050[Depth];
+	        }
+	     }
 	  }
           break;
      case 1600:
           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
           break;
+     case 1680:
+          if(VGAEngine == SIS_315_VGA) {
+             if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+	  }
+          break;
      case 1920:
           if(!(VBFlags & CRT1_LCDA)) {
              if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
@@ -848,14 +778,18 @@
              break;
      	case 400:
 	     if(CustomT != CUT_PANEL848) {
-          	if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+          	   if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+		}
 	     }
              break;
 	case 512:
 	     if(CustomT != CUT_PANEL848) {
-		if(VDisplay == 384) {
+	        if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
 		   if(LCDwidth != 1024 || LCDheight != 600) {
-		      ModeIndex = ModeIndex_512x384[Depth];
+		      if(VDisplay == 384) {
+		         ModeIndex = ModeIndex_512x384[Depth];
+		      }
 		   }
 		}
 	     }
@@ -895,6 +829,9 @@
 	        if((VDisplay == 768) && (LCDheight == 768)) {
 		   ModeIndex = ModeIndex_310_1280x768[Depth];
 		}
+		if((VDisplay == 800) && (LCDheight == 800)) {
+		   ModeIndex = ModeIndex_310_1280x768[Depth];
+		}
 	     }
 	     break;
 	case 1360:
@@ -946,7 +883,7 @@
 	case 1280:
 	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 	     else if(VDisplay == 768) {
-		if((LCDheight == 768) ||
+		if((LCDheight == 768) || (LCDwidth == 1680) ||
 		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
 		   if(VGAEngine == SIS_300_VGA) {
 		      ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -959,20 +896,41 @@
 		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
 		   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)))) {
+		      ModeIndex = ModeIndex_1280x800[Depth];
+		   }
+		} else if(VDisplay == 720) {
+		   if((LCDheight == 720) || (LCDwidth == 1680) ||
+		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		      ModeIndex = ModeIndex_1280x720[Depth];
+		   }
+		}
 	     }
 	     break;
 	case 1400:
 	     if(VGAEngine == SIS_315_VGA) {
 	        if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-		   if(LCDheight != 1200) {
-	              if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+		   if((LCDwidth == 1400) || (LCDwidth == 1600) || (LCDwidth == 1680)) {
+		      ModeIndex = ModeIndex_1400x1050[Depth];
 		   }
 		}
 	     }
 	     break;
 	case 1600:
-	     if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
-	        if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+		}
+	     }
+	     break;
+	case 1680:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VBFlags & (VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
+	           if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		}
 	     }
 	     break;
       }
@@ -1021,8 +979,8 @@
              if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
              break;
       	case 512:
-	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR525P | TV_YPBPR750P))) ||
-	         (VBFlags & TV_HIVISION) 					     ||
+	     if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
+	         (VBFlags & TV_HIVISION) 					      ||
 	         ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
 	        if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
 	     }
@@ -1032,19 +990,21 @@
 	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 	     break;
 	case 720:
-	     if(!(VBFlags & TV_HIVISION)) {
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
                 if(VDisplay == 480) {
 		   if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM)))
                       ModeIndex = ModeIndex_720x480[Depth];
                 } else if(VDisplay == 576) {
-		   if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))
+		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
                       ModeIndex = ModeIndex_720x576[Depth];
                 }
 	     }
              break;
 	case 768:
-	     if(!(VBFlags & TV_HIVISION)) {
-	        if((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) {
+	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
+	        if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+		    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
           	   if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 		}
              }
@@ -1052,7 +1012,7 @@
 	case 800:
 	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
 	     else if(VDisplay == 480) {
-	        if(VBFlags & TV_HIVISION) {
+	        if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 		   ModeIndex = ModeIndex_800x480[Depth];
 		}
 	     }
@@ -1063,15 +1023,22 @@
 		   ModeIndex = ModeIndex_1024x768[Depth];
 		}
 	     } else if(VDisplay == 576) {
-	        if(VBFlags & TV_HIVISION) {
+	        if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
 		   ModeIndex = ModeIndex_1024x576[Depth];
 		}
 	     }
 	     break;
 	case 1280:
-	     if(VBFlags & TV_HIVISION) {
-	        if(VDisplay == 720)       ModeIndex = ModeIndex_1280x720[Depth];
-		else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
+	     if(VDisplay == 720) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
+	           ModeIndex = ModeIndex_1280x720[Depth];
+		}
+	     } else if(VDisplay == 1024) {
+	        if((VBFlags & TV_HIVISION) ||
+		   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+	           ModeIndex = ModeIndex_1280x1024[Depth];
+		}
 	     }
 	     break;
       }
@@ -1138,6 +1105,7 @@
 		   }
 		} else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 		else if(VDisplay == 720)    ModeIndex = ModeIndex_1280x720[Depth];
+		else if(VDisplay == 800)    ModeIndex = ModeIndex_1280x800[Depth];
 		else if(VDisplay == 960)    ModeIndex = ModeIndex_1280x960[Depth];
 		break;
         case 1360:
@@ -1155,6 +1123,13 @@
 		   }
 		}
 		break;
+	case 1680:
+		if(VGAEngine == SIS_315_VGA) {
+		   if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
+	              if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+		   }
+		}
+		break;
    }
 
    return ModeIndex;
@@ -1252,13 +1227,13 @@
 void
 SiS_DisplayOn(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x00);
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 }
 
 void
 SiS_DisplayOff(SiS_Private *SiS_Pr)
 {
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x01,0xDF,0x20);
+   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 }
 
 
@@ -1301,6 +1276,15 @@
 {
    unsigned char cr5f, temp1, temp2;
 
+   /* 661 and newer: NEVER write non-zero to SR11[7:4] */
+   /* (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;
+      SiS_Pr->SiS_MyCR63 = 0x53;
+   }
+
    /* You should use the macros, not these flags directly */
 
    SiS_Pr->SiS_SysFlags = 0;
@@ -1338,6 +1322,10 @@
 	 }
       }
    }
+   if(HwInfo->jChipType == SIS_760) {
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
+      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760UMA;
+   }
 }
 
 /*********************************************/
@@ -1410,18 +1398,19 @@
 
    SiS_Pr->SiS_ChrontelInit = 0;
 
+   /* Check for SiS30x first */
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+   if((temp == 1) || (temp == 2)) return;
+
    switch(HwInfo->jChipType) {
 #ifdef SIS300
    case SIS_540:
    case SIS_630:
    case SIS_730:
-        /* Check for SiS30x first */
-        temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-	if((temp == 1) || (temp == 2)) return;
       	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 5)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+      	if((temp >= 2) && (temp <= 5)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)   		SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
       	if((temp == 4) || (temp == 5)) {
 		/* Save power status (and error check) - UNUSED */
 		SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
@@ -1436,8 +1425,8 @@
    case SIS_330:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
       	temp = (temp & 0x0E) >> 1;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
         break;
    case SIS_661:
    case SIS_741:
@@ -1445,9 +1434,9 @@
    case SIS_760:
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       	temp = (temp & 0xe0) >> 5;
-      	if((temp >= 2) && (temp <= 3)) SiS_Pr->SiS_IF_DEF_LVDS = 1;
-      	if(temp == 3)  SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-	if(temp == 4)  SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
+      	if((temp >= 2) && (temp <= 3)) 	SiS_Pr->SiS_IF_DEF_LVDS = 1;
+      	if(temp == 3)  			SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+	if(temp == 4)  			SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
         break;
 #endif
    default:
@@ -1475,44 +1464,72 @@
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
+BOOLEAN
+SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romversoffs, romvmaj = 1, romvmin = 0;
+
+   if(HwInfo->jChipType >= SIS_661) {
+      romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
+      if(romversoffs) {
+	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
+	    romvmaj = ROMAddr[romversoffs] - '0';
+	    romvmin = ((ROMAddr[romversoffs+2] -'0') * 10) + (ROMAddr[romversoffs+3] - '0');
+	 }
+      }
+      if((romvmaj != 0) || (romvmin >= 92)) {
+	 return TRUE;
+      }
+   } else if(IS_SIS650740) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
+   }
+   return FALSE;
+}
+
 static void
 SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT romptr = 0;
+
+   SiS_Pr->SiS_UseROM = FALSE;
+   SiS_Pr->SiS_ROMNew = FALSE;
 
    if((ROMAddr) && (HwInfo->UseROM)) {
-      if((ROMAddr[0x00] != 0x55) || (ROMAddr[0x01] != 0xAA)) {
-         SiS_Pr->SiS_UseROM = FALSE;
-      } else if(HwInfo->jChipType == SIS_300) {
-        /* 300: We check if the code starts below 0x220 by
-	 * checking the jmp instruction at the beginning
-	 * of the BIOS image.
-	 */
-	 if((ROMAddr[3] == 0xe9) &&
-	    ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
+      if(HwInfo->jChipType == SIS_300) {
+         /* 300: We check if the code starts below 0x220 by
+	  * checking the jmp instruction at the beginning
+	  * of the BIOS image.
+	  */
+	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
 	    SiS_Pr->SiS_UseROM = TRUE;
-	 else
-	    SiS_Pr->SiS_UseROM = FALSE;
       } else if(HwInfo->jChipType < SIS_315H) {
-#if 0
-        /* Rest of 300 series: We don't use the ROM image if
-	 * the BIOS version < 2.0.0 as such old BIOSes don't
-	 * have the needed data at the expected locations.
-	 */
-         if(ROMAddr[0x06] < '2')  SiS_Pr->SiS_UseROM = FALSE;
-	 else                     SiS_Pr->SiS_UseROM = TRUE;
-#else
-	/* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
-	 * the others do as well
-	 */
+	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
+	  * the others do as well
+	  */
 	 SiS_Pr->SiS_UseROM = TRUE;
-#endif
       } else {
          /* 315/330 series stick to the standard */
 	 SiS_Pr->SiS_UseROM = TRUE;
+	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+	    /* Find out about LCD data table entry size */
+	    if((romptr = SISGETROMW(0x0102))) {
+	       if(ROMAddr[romptr + (32 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 32;
+	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 34;
+	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)
+	          SiS_Pr->SiS661LCD2TableSize = 36;
+	    }
+	 }
       }
-   } else SiS_Pr->SiS_UseROM = FALSE;
-
+   }
 }
 
 /*********************************************/
@@ -1597,7 +1614,8 @@
 
   SiS_Pr->SiS_VBType = 0;
 
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) return;
+  if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+     return;
 
   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
 
@@ -1608,7 +1626,6 @@
   if(flag >= 2) {
      SiS_Pr->SiS_VBType = VB_SIS302B;
   } else if(flag == 1) {
-     SiS_Pr->SiS_VBType = VB_SIS301;
      if(rev >= 0xC0) {
        	SiS_Pr->SiS_VBType = VB_SIS301C;
      } else if(rev >= 0xB0) {
@@ -1616,20 +1633,17 @@
 	/* Check if 30xB DH version (no LCD support, use Panel Link instead) */
     	nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
         if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+     } else {
+        SiS_Pr->SiS_VBType = VB_SIS301;
      }
   }
   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
-     if(rev >= 0xD0) {
-	SiS_Pr->SiS_VBType &= ~(VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_NoLCD);
-	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_SIS301LV;
-	}
+     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 if(rev >= 0xD0) {
+	SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
   }
 }
@@ -1685,12 +1699,24 @@
 
   case SIS_661:
   case SIS_741:
-  case SIS_660:
-  case SIS_760:
         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
@@ -1758,7 +1784,10 @@
    if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
      data = *SiS_Pr->pSiS_SoftSetting & 0x03;
    } else {
-     if(HwInfo->jChipType >= SIS_661) {
+     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;
      } else if(IS_SIS550650740) {
         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
@@ -1932,6 +1961,43 @@
 }
 
 /*********************************************/
+/*            HELPER: ENABLE CRT1            */
+/*********************************************/
+
+static void
+SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+      if(IS_SIS650) {
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+      } else if(IS_SIS661741660760) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+	 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+	 if(!SiS_Pr->SiS_ROMNew) {
+	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+	 }
+      }
+   }
+}
+
+static void
+SiS_HandleCRT1(SiS_Private *SiS_Pr)
+{
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+#if 0
+  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+     }
+  }
+#endif
+}
+
+/*********************************************/
 /*           HELPER: GetColorDepth           */
 /*********************************************/
 
@@ -1965,28 +2031,22 @@
 SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT temp,colordepth,infoflag;
+  USHORT xres, temp, colordepth, infoflag;
 
   if(SiS_Pr->UseCustomMode) {
      infoflag = SiS_Pr->CInfoFlag;
-     temp = SiS_Pr->CHDisplay / 16;
+     xres = SiS_Pr->CHDisplay;
   } else {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-     temp = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeOffset;
-     temp = SiS_Pr->SiS_ScreenOffset[temp];
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
 
+  temp = xres / 16;
   if(infoflag & InterlaceMode) temp <<= 1;
-
   temp *= colordepth;
-
-  if( ( ((ModeNo >= 0x26) && (ModeNo <= 0x28)) ||
-        ModeNo == 0x3f ||
-	ModeNo == 0x42 ||
-	ModeNo == 0x45 ) ||
-      (SiS_Pr->UseCustomMode && (SiS_Pr->CHDisplay % 16)) ) {
+  if(xres % 16) {
      colordepth >>= 1;
      temp += colordepth;
   }
@@ -2091,9 +2151,15 @@
      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);                     /* Set CRTC(3d4) */
   }
-  if( ( (HwInfo->jChipType == SIS_630) ||
-        (HwInfo->jChipType == SIS_730) )  &&
-      (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetupCR5x(SiS_Pr, HwInfo);
+     for(i = 0x13; i <= 0x14; i++) {
+        CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+     }
+  } else if( ( (HwInfo->jChipType == SIS_630) ||
+               (HwInfo->jChipType == SIS_730) )  &&
+             (HwInfo->jChipRevision >= 0x30) ) {       	   /* for 630S0 */
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
            SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
@@ -2194,7 +2260,7 @@
 /*********************************************/
 
 static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 {
   USHORT i;
 
@@ -2204,6 +2270,11 @@
 
   if(HwInfo->jChipType >= SIS_315H) {
      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+     if(ModeNo <= 0x13) {
+        if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+	}
+     }
   }
 }
 
@@ -2267,45 +2338,6 @@
 /*                  CRTC/2                   */
 /*********************************************/
 
-#ifdef SIS315H
-static void
-SiS_GetLCDACRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
-		   USHORT *DisplayType)
- {
-  USHORT modeflag = 0;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     *ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  *ResIndex &= 0x3F;
-
-  *DisplayType = SiS_Pr->SiS_LCDResInfo;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 32;
-  if(modeflag & HalfDCLK)                 *DisplayType += 16;
-
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        *DisplayType = 100;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        *DisplayType = 104;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) *DisplayType += 2;
-        if(modeflag & HalfDCLK)                 *DisplayType += 1;
-     }
-  }
-
-}
-#endif
-
 static void
 SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex,
@@ -2313,10 +2345,6 @@
 {
   UCHAR  index;
   USHORT temp,i,j,modeflag;
-#ifdef SIS315H
-  USHORT ResIndex,DisplayType;
-  const SiS_LCDACRT1DataStruct *LCDACRT1Ptr = NULL;
-#endif
 
   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);		/* unlock cr0-7 */
 
@@ -2324,7 +2352,7 @@
 
      modeflag = SiS_Pr->CModeFlag;
 
-     for(i=0,j=0;i<=07;i++,j++) {
+     for(i=0,j=0;i<=7;i++,j++) {
         SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
      }
      for(j=0x10;i<=10;i++,j++) {
@@ -2342,7 +2370,7 @@
 
      temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
      if(modeflag & DoubleScanMode) temp |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
   } else {
 
@@ -2352,87 +2380,28 @@
         modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      }
 
-     if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-
-#ifdef SIS315H
-
-        SiS_GetLCDACRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, &ResIndex, &DisplayType);
-
-        switch(DisplayType) {
-        case Panel_1024x768      : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        case Panel_1280x1024     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1;    break;
-        case Panel_1400x1050     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1;    break;
-        case Panel_1600x1200     : LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1;    break;
-        case Panel_1024x768  + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1_H;   break;
-        case Panel_1280x1024 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_1_H;  break;
-        case Panel_1400x1050 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_1_H;  break;
-        case Panel_1600x1200 + 16: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_1_H;  break;
-        case Panel_1024x768  + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2;     break;
-        case Panel_1280x1024 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case Panel_1400x1050 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2;    break;
-        case Panel_1600x1200 + 32: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2;    break;
-        case Panel_1024x768  + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_2_H;   break;
-        case Panel_1280x1024 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case Panel_1400x1050 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11400x1050_2_H;  break;
-        case Panel_1600x1200 + 48: LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11600x1200_2_H;  break;
-        case 100:	  	   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1;         break;
-        case 101:		   LCDACRT1Ptr = Compaq1280x1024_LCDACRT1_1_H;       break;
-        case 102:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2;    break;
-        case 103:		   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11280x1024_2_H;  break;
-        case 104:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1;           break;
-        case 105:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_1_H;         break;
-        case 106:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2;           break;
-        case 107:		   LCDACRT1Ptr = Clevo1024x768_LCDACRT1_2_H;         break;
-        default:                   LCDACRT1Ptr = SiS_Pr->SiS_LCDACRT11024x768_1;     break;
-        }
-
-        for(i=0, j=0; i<=0x07; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x10, j=8; i<=0x12; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x15, j=11; i<=0x16; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
-        for(i=0x0A, j=13; i<=0x0C; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,i,(LCDACRT1Ptr+ResIndex)->CR[j]);
-        }
+     index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 
-        temp = (LCDACRT1Ptr+ResIndex)->CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
-        temp = ((LCDACRT1Ptr+ResIndex)->CR[16] & 0x01) << 5;
-        if(modeflag & DoubleScanMode) temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
-
-#endif
-
-     } else {
-
-        index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-        for(i=0,j=0;i<=07;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x10;i<=10;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x15;i<=12;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
-        for(j=0x0A;i<=15;i++,j++) {
-          SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-        }
+     for(i=0,j=0;i<=7;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x10;i<=10;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x15;i<=12;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
+     for(j=0x0A;i<=15;i++,j++) {
+        SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
+     }
 
-        temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
+     temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
 
-        temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
-        if(modeflag & DoubleScanMode)  temp |= 0x80;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0xDF,temp);
+     temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
+     if(modeflag & DoubleScanMode)  temp |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
 
-     }
   }
 
   if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
@@ -2470,7 +2439,7 @@
 
    DisplayUnit <<= 5;
    temp = (DisplayUnit & 0xff00) >> 8;
-   if (DisplayUnit & 0xff) temp++;
+   if(DisplayUnit & 0xff) temp++;
    temp++;
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
 }
@@ -2905,7 +2874,8 @@
 {
   USHORT modeflag;
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);  /* disable auto-threshold */
+  /* disable auto-threshold */
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -2913,30 +2883,19 @@
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(HwInfo->jChipType >= SIS_661) {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-     if(ModeNo > 0x13) {
+  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+  if(ModeNo > 0x13) {
+     if(HwInfo->jChipType >= SIS_661) {
         if(!(modeflag & HalfDCLK)) {
 	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-	   if(ModeNo != 0x38) {
-	      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-	   }
+	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
 	}
-     }
-  } else {
-     if(ModeNo > 0x13) {
-        if( (!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+     } else {
+        if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
            SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-        } else {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-        }
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+	}
      }
   }
 }
@@ -2951,33 +2910,29 @@
                  USHORT ModeNo, USHORT RefreshRateTableIndex,
                  USHORT ModeIdIndex)
 {
-  USHORT data, data2=0;
-  USHORT VCLK, index=0;
+  USHORT data=0, VCLK=0, index=0;
 
-  if(ModeNo <= 0x13) VCLK = 0;
-  else {
+  if(ModeNo > 0x13) {
      if(SiS_Pr->UseCustomMode) {
         VCLK = SiS_Pr->CSRClock;
      } else {
         index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
-	               RefreshRateTableIndex,HwInfo);
+	                      RefreshRateTableIndex,HwInfo);
         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
      }
   }
 
-  if(HwInfo->jChipType < SIS_315H) {		/* 300 series */
+  if(HwInfo->jChipType < SIS_315H) {
 
-     data2 = 0x00;
-     if(VCLK > 150) data2 |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data2);
+     if(VCLK > 150) data |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
 
-     data2 = 0x00;
-     if(VCLK >= 150) data2 |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data2);
+     data = 0x00;
+     if(VCLK >= 150) data |= 0x08;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
 
-  } else { 					/* 315 series */
+  } else {
 
-     data = 0;
      if(VCLK >= 166) data |= 0x0c;
      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
 
@@ -2986,23 +2941,31 @@
      }
   }
 
-  data2 = 0x03;
-  if((VCLK >= 135) && (VCLK < 160))      data2 = 0x02;
-  else if((VCLK >= 160) && (VCLK < 260)) data2 = 0x01;
-  else if(VCLK >= 260)                   data2 = 0x00;
+  /* DAC speed */
+  if(HwInfo->jChipType >= SIS_661) {
 
-  if(HwInfo->jChipType == SIS_540) {
-     if((VCLK == 203) || (VCLK < 234)) data2 = 0x02;
-  }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
 
-  if(HwInfo->jChipType < SIS_315H) {
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data2);  	/* DAC speed */
   } else {
-     if(HwInfo->jChipType > SIS_315PRO) {
-        /* This "if" is done in 330 and 650/LVDS/301LV BIOSes; Not in 315 BIOS */
-        if(ModeNo > 0x13) data2 &= 0xfc;
+
+     data = 0x03;
+     if((VCLK >= 135) && (VCLK < 160))      data = 0x02;
+     else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
+     else if(VCLK >= 260)                   data = 0x00;
+
+     if(HwInfo->jChipType == SIS_540) {
+        if((VCLK == 203) || (VCLK < 234))   data = 0x02;
+     }
+
+     if(HwInfo->jChipType < SIS_315H) {
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+     } else {
+        if(HwInfo->jChipType > SIS_315PRO) {
+           if(ModeNo > 0x13) data &= 0xfc;
+        }
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data2);  	/* DAC speed */
+
   }
 }
 
@@ -3010,75 +2973,51 @@
 SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
 {
-  USHORT data,data2;
-  USHORT infoflag=0,modeflag;
+  USHORT data,infoflag=0,modeflag;
   USHORT resindex,xres;
 #ifdef SIS315H
-  USHORT data3;
+  USHORT data2,data3;
   ULONG  longdata;
-#if 0
-  resinfo = 0;
-#endif
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
 #endif
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
      infoflag = SiS_Pr->CInfoFlag;
+     xres = SiS_Pr->CHDisplay;
   } else {
+     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
      if(ModeNo > 0x13) {
     	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
     	infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-#ifdef SIS315H
-#if 0
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-#endif
-#endif
+	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
      } else {
     	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
      }
   }
 
   /* Disable DPMS */
   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
 
-  if(ModeNo > 0x13) data = infoflag;
-  else data = 0;
-
-  data2 = 0;
+  data = 0;
   if(ModeNo > 0x13) {
      if(SiS_Pr->SiS_ModeType > 0x02) {
-        data2 |= 0x02;
-        data2 |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
-     }
-  }
-
-#ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "Debug: Mode infoflag = %x, Chiptype %d\n",
-  	data, HwInfo->jChipType);
-#endif
-
-  if(data & InterlaceMode) data2 |= 0x20;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data2);
-
-  if(SiS_Pr->UseCustomMode) {
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-     if(ModeNo <= 0x13) {
-      	xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-     } else {
-      	xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+        data |= 0x02;
+        data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
      }
+     if(infoflag & InterlaceMode) data |= 0x20;
   }
+  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
 
   if(HwInfo->jChipType != SIS_300) {
-     data = 0x0000;
+     data = 0;
      if(infoflag & InterlaceMode) {
-        if(xres <= 800) data = 0x0020;
+        if(xres <= 800)       data = 0x0020;
         else if(xres <= 1024) data = 0x0035;
-        else data = 0x0048;
+        else                  data = 0x0048;
      }
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0x00FF));
+     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
   }
 
@@ -3086,18 +3025,12 @@
      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
   }
 
+  data = 0;
+  if(modeflag & LineCompareOff) data = 0x08;
   if(HwInfo->jChipType == SIS_300) {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xF7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
   } else {
-     if(modeflag & LineCompareOff) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,0x08);
-     } else {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0F,0xB7);
-     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(ModeNo > 0x13) {
   	   SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
@@ -3105,9 +3038,13 @@
      }
   }
 
+  if(HwInfo->jChipType >= SIS_661) {
+     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+  }
+
 #ifdef SIS315H
-  /* 315 BIOS sets SR17 at this point */
   if(HwInfo->jChipType == SIS_315PRO) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
      data = SiS_Pr->SiS_SR15[2][data];
      if(SiS_Pr->SiS_ModeType == ModeText) {
@@ -3126,12 +3063,18 @@
 	}
      }
      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-  }
 
-  /* 330 BIOS sets SR17 at this point */
-  if(HwInfo->jChipType == SIS_330) {
+  } else if( (HwInfo->jChipType == SIS_330) ||
+             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760UMA))) {
+
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-     data = SiS_Pr->SiS_SR15[2][data];
+     if(HwInfo->jChipType == SIS_330) {
+        data = SiS_Pr->SiS_SR15[2][data];
+     } else {
+        if(SiS_Pr->SiS_ROMNew) 	    data = ROMAddr[0xf6];
+        else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+	else                        data = 0xba;
+     }
      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
         data &= 0xc7;
      } else {
@@ -3144,31 +3087,38 @@
 	}
 
 	data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
-	if(!data3) data3++;
-
-	data2 *= data3;
+	if(data3) data2 *= data3;
 
 	longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
 
 	data2 = longdata / data2;
 
-	if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
-           if(data2 >= 0x19c)      data = 0xba;
-	   else if(data2 >= 0x140) data = 0x7a;
-	   else if(data2 >= 0x101) data = 0x3a;
-	   else if(data2 >= 0xf5)  data = 0x32;
-	   else if(data2 >= 0xe2)  data = 0x2a;
-	   else if(data2 >= 0xc4)  data = 0x22;
-	   else if(data2 >= 0xac)  data = 0x1a;
-	   else if(data2 >= 0x9e)  data = 0x12;
-	   else if(data2 >= 0x8e)  data = 0x0a;
+	if(HwInfo->jChipType == SIS_330) {
+	   if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+              if     (data2 >= 0x19c) data = 0xba;
+	      else if(data2 >= 0x140) data = 0x7a;
+	      else if(data2 >= 0x101) data = 0x3a;
+	      else if(data2 >= 0xf5)  data = 0x32;
+	      else if(data2 >= 0xe2)  data = 0x2a;
+	      else if(data2 >= 0xc4)  data = 0x22;
+	      else if(data2 >= 0xac)  data = 0x1a;
+	      else if(data2 >= 0x9e)  data = 0x12;
+	      else if(data2 >= 0x8e)  data = 0x0a;
+	      else                    data = 0x02;
+	   } else {
+	      if(data2 >= 0x127)      data = 0xba;
+	      else                    data = 0x7a;
+	   }
+	} else {
+	   if     (data2 >= 0x190) data = 0xba;
+	   else if(data2 >= 0xff)  data = 0x7a;
+	   else if(data2 >= 0xd3)  data = 0x3a;
+	   else if(data2 >= 0xa9)  data = 0x1a;
+	   else if(data2 >= 0x93)  data = 0x0a;
 	   else                    data = 0x02;
-	 } else {
-	   if(data2 >= 0x127)      data = 0xba;
-	   else                    data = 0x7a;
-	 }
-      }
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
   }
 #endif
 
@@ -3190,46 +3140,6 @@
      } else {
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
      }
-#if 0   /* What is SR0E[D5:6]? */
-     if(HwInfo->jChipType >= SIS_661) {
-        data = 0;
-        if((ModeNo == 6) || ((ModeNo >= 0x0e) && (ModeNo <= 0x13))) {
-	   data |= 0x20;
-	}
-	if(SiS_Pr->SiS_ModeType != ModeVGA) {
-	   if(SiS_Pr->UseCustomMode) {
-              if((xres >= 640) && (SiS_Pr->CVDisplay >= 480)) {
-	         data |= 0x40;
-	      }
-	      if((xres > 1280) && (SiS_Pr->CVDisplay > 1024)) {
-	         data |= 0x60;
-	      }
-	   }
-	} else if(ModeNo > 0x13) {   /* These are in the CRT1 table, and set by CRT1CRTC */
-	   if(resinfo >= SIS_RI_640x480) {
-	      if(resinfo <= SIS_RI_2048x1536) {
-	         data |= 0x40;
-		 if(resinfo > SIS_RI_1280x1024) {
-		    data |= 0x60;
-		    if(resinfo != SIS_RI_1600x1200) {
-		       data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data += 0x60;
-		       SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e);
-		       data = 0;
-		    }
-		 }
-	      }
-	      if(resinfo == SIS_RI_1152x864) {
-		 data = 0x40;
-	      }
-	      if(resinfo == SIS_RI_1400x1050) { /* TW */
-		 data = 0x60;
-	      }
-	   }
-	}
-	SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0e,data);
-     }
-#endif
   }
 #endif
 }
@@ -3404,7 +3314,7 @@
   SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
   SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
-  SiS_ClearExt1Regs(SiS_Pr,HwInfo);
+  SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
   SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
 
   SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -3469,22 +3379,31 @@
   }
 }
 
+
+
 /*********************************************/
-/*            HELPER: ENABLE CRT1            */
+/*         HELPER: RESET VIDEO BRIDGE        */
 /*********************************************/
 
 static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x63,0xbf);
-#if 0
-  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
-        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x63,0x40);
-     }
-  }
-#endif
+   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+   USHORT temp;
+
+   if(SiS_Pr->SiS_UseROM) {
+      if(HwInfo->jChipType < SIS_330) {
+         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+	 if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      } else if(HwInfo->jChipType >= SIS_661) {
+         temp = ROMAddr[0x7e];
+         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80];
+         if(HwInfo->jChipType >= SIS_660)                  temp |= 0x40;
+         else if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
+         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
+      }
+   }
 }
 
 /*********************************************/
@@ -3573,13 +3492,12 @@
 SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
 #endif
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
-   unsigned char backupreg=0, tempr1, tempr2;
+   unsigned char backupreg=0;
 #ifndef LINUX_XF86
    USHORT  KeepLockReg;
+   ULONG   temp;
 
    SiS_Pr->UseCustomMode = FALSE;
    SiS_Pr->CRT1UsesCustomMode = FALSE;
@@ -3590,37 +3508,26 @@
    }
 
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
 
-#ifdef LINUX_XF86
+#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
    else
 #endif
          SiS_Pr->SiS_VGAINFO = 0x11;
 
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
-   if(!SiS_Pr->UseCustomMode) {
-      ModeNo = ((ModeNo & 0x80) << 8) | (ModeNo & 0x7f);
-   }
+   SiS_Pr->SiS_flag_clearbuffer = 0;
 
-#ifdef LINUX_XF86
-   /* We never clear the buffer in X */
-   ModeNo |= 0x8000;
+   if(!SiS_Pr->UseCustomMode) {
+#ifndef LINUX_XF86
+      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
 #endif
-
-   if(ModeNo & 0x8000) {
-     	ModeNo &= 0x7fff;
-     	SiS_Pr->SiS_flag_clearbuffer = 0;
-   } else {
-     	SiS_Pr->SiS_flag_clearbuffer = 1;
+      ModeNo &= 0x7f;
    }
 
 #ifndef LINUX_XF86
@@ -3642,23 +3549,9 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	 if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+         SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3679,27 +3572,7 @@
 #endif
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    if(SiS_Pr->UseCustomMode) {
@@ -3743,7 +3616,7 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -3753,14 +3626,6 @@
 
 	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
 
-	 tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	 tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00);
-	 if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7;
-	 else			      tempr2 |= 0x08;
-	 if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB;
-	 else			      tempr2 |= 0x04;
-	 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2);
-
 	 if((IS_SIS650) && (SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0xfc)) {
 	    if((ModeNo == 0x03) || (ModeNo == 0x10)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
@@ -3768,7 +3633,7 @@
             }
 	 }
 
-	 if(tempr1 & SetCRT2ToLCD) {
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
 	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	 }
       } else if((HwInfo->jChipType == SIS_630) ||
@@ -3840,12 +3705,10 @@
 SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
 {
-   ULONG   temp;
    USHORT  ModeIdIndex;
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
    SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
    UShort  ModeNo   = 0;
-   unsigned char tempr1, tempr2, backupreg=0;
+   unsigned char backupreg=0;
    SISPtr  pSiS     = SISPTR(pScrn);
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
@@ -3877,17 +3740,15 @@
    }
 
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
-
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
    /* Save mode info so we can set it from within SetMode for CRT1 */
@@ -3947,23 +3808,9 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         SiS_UnLockCRT2(SiS_Pr,HwInfo);
-         if(ROMAddr && SiS_Pr->SiS_UseROM) {
-	    if(HwInfo->jChipType < SIS_330) {
-               temp = ROMAddr[VB310Data_1_2_Offset];
-	       temp |= 0x40;
-               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-            }
-	    if(HwInfo->jChipType > SIS_330) {
-	       temp = ROMAddr[0x7e];
-	       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x7b) >= 100) temp |= 0x40;
-	       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-	    }
-	 }
+	 SiS_ResetVB(SiS_Pr, HwInfo);
 	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
-
 	 SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -4005,7 +3852,7 @@
 
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if(HwInfo->jChipType >= SIS_315H) {
-         if(HwInfo->jChipType < SIS_661) {
+         if(!SiS_Pr->SiS_ROMNew) {
 	    if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
 	       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
 	    } else {
@@ -4015,15 +3862,7 @@
 
 	 SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
 
-	 tempr1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-	 tempr2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00);
-	 if(tempr1 & SetCRT2ToAVIDEO) tempr2 &= 0xF7;
-	 else			      tempr2 |= 0x08;
-	 if(tempr1 & SetCRT2ToSVIDEO) tempr2 &= 0xFB;
-	 else			      tempr2 |= 0x04;
-	 SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,tempr2);
-
-	 if(tempr1 & SetCRT2ToLCD) {
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
 	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	 }
       } else if((HwInfo->jChipType == SIS_630) ||
@@ -4081,17 +3920,15 @@
    }
 
    SiSInitPtr(SiS_Pr, HwInfo);
-
    SiSRegInit(SiS_Pr, BaseAddr);
-
    SiS_GetSysFlags(SiS_Pr, HwInfo);
-
+#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-
+#else
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#endif
    SiSInitPCIetc(SiS_Pr, HwInfo);
-
    SiSSetLVDSetc(SiS_Pr, HwInfo);
-
    SiSDetermineROMUsage(SiS_Pr, HwInfo);
 
    /* We don't clear the buffer under X */
@@ -4127,27 +3964,7 @@
    SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
 
    if(HwInfo->jChipType >= SIS_315H) {
-#if 0
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x08)  {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(ModeNo != 0x10)  SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         } else if((IS_SIS651) && (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-            SiS_Pr->SiS_SetFlag |= SetDOSMode;
-         }
-      }
-#endif
-
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(IS_SIS650) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	 } else if(IS_SIS661741660760) {
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-	    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-	 }
-      }
+      SiS_SetupCR5x(SiS_Pr, HwInfo);
    }
 
    /* Set mode on CRT1 */
@@ -4316,12 +4133,188 @@
 }
 #endif
 
+#ifndef GETBITSTR
+#define BITMASK(h,l)    	(((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
+#define GENMASK(mask)   	BITMASK(1?mask,0?mask)
+#define GETBITS(var,mask)   	(((var) & GENMASK(mask)) >> (0?mask))
+#define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
+#endif
+
+static void
+SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+{
+   SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;		/* CR0 */
+   SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;			/* CR1 */
+   SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;			/* CR2 */
+   SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;	/* CR3 */
+   SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;			/* CR4 */
+   SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |	/* CR5 */
+       			    (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+
+   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal - 2) & 0xFF;			/* CR6 */
+   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal - 2) & 0x100) >> 8)		/* CR7 */
+ 	 		  | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
+	 		  | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
+	 	  	  | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+			  | 0x10
+	 		  | (((SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
+	 		  | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
+	 		  | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+
+   SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* CR9 */
+
+   if(depth != 8) {
+      if(SiS_Pr->CHDisplay >= 1600)      SiS_Pr->CCRT1CRTC[16] |= 0x60;		/* SRE */
+      else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
+   }
+
+#if 0
+   if (mode->VScan >= 32)
+	regp->CRTC[9] |= 0x1F;
+   else if (mode->VScan > 1)
+	regp->CRTC[9] |= mode->VScan - 1;
+#endif
+
+   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart     ) & 0xFF;			/* CR10 */
+   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;		/* CR11 */
+   SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;			/* CR12 */
+   SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;			/* CR15 */
+   SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;			/* CR16 */
+
+   SiS_Pr->CCRT1CRTC[13] =							/* SRA */
+                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
+                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
+                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+                        GETBITSTR((SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
+                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
+                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
+
+   SiS_Pr->CCRT1CRTC[14] =							/* SRB */
+                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
+                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
+                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
+
+
+   SiS_Pr->CCRT1CRTC[15] =							/* SRC */
+                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+}
+
+void
+SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+{
+   USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
+   int i,j;
+
+   /* 1:1 data: use data set by setcrt1crtc() */
+   if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+   if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+   } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   if(modeflag & HalfDCLK) VGAHDE >>= 1;
+
+   SiS_Pr->CHDisplay = VGAHDE;
+   SiS_Pr->CHBlankStart = VGAHDE;
+
+   SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
+   SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
+
+   tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+   tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelXRes;
+   }
+   tempbx += tempax;
+   if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+   SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
+
+   tempax = VGAHDE;
+   tempbx = SiS_Pr->CHTotal;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempbx = SiS_Pr->PanelXRes;
+      if(modeflag & HalfDCLK) tempbx >>= 1;
+      tempax += ((tempbx - tempax) >> 1);
+   }
+
+   tempax += SiS_Pr->PanelHRS;
+   SiS_Pr->CHSyncStart = tempax;
+   tempax += SiS_Pr->PanelHRE;
+   SiS_Pr->CHSyncEnd = tempax;
+
+   tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax = SiS_Pr->PanelYRes;
+   }
+   SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
+
+   tempax = SiS_Pr->SiS_VGAVDE;
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      tempax += (SiS_Pr->PanelYRes - tempax) >> 1;
+   }
+   tempax += SiS_Pr->PanelVRS;
+   SiS_Pr->CVSyncStart = tempax;
+   tempax += SiS_Pr->PanelVRE;
+   SiS_Pr->CVSyncEnd = tempax;
+
+   SiS_CalcCRRegisters(SiS_Pr, 8);
+   SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i=0,j=0;i<=7;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x10;i<=10;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x15;i<=12;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+   for(j=0x0A;i<=15;i++,j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
+   }
+
+   tempax = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1F,tempax);
+
+   tempax = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) tempax |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
+
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
+       	SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+	SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+	SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+	SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+	SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+	SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+   	SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+	SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+	SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+	SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+}
 
 /* ================ XFREE86 ================= */
 
 /* Helper functions */
 
 #ifdef LINUX_XF86
+
 USHORT
 SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
 {
@@ -4402,73 +4395,16 @@
 
    pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
 
-   pSiS->SiS_Pr->CCRT1CRTC[0]  =  ((pSiS->SiS_Pr->CHTotal >> 3) - 5) & 0xff;
-   pSiS->SiS_Pr->CCRT1CRTC[1]  =  (pSiS->SiS_Pr->CHDisplay >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[2]  =  (pSiS->SiS_Pr->CHBlankStart >> 3) - 1;
-   pSiS->SiS_Pr->CCRT1CRTC[3]  =  (((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
-   pSiS->SiS_Pr->CCRT1CRTC[4]  =  (pSiS->SiS_Pr->CHSyncStart >> 3) + 3;
-   pSiS->SiS_Pr->CCRT1CRTC[5]  =  ((((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |
-       				  (((pSiS->SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
-
-   pSiS->SiS_Pr->CCRT1CRTC[6]  =  (pSiS->SiS_Pr->CVTotal - 2) & 0xFF;
-   pSiS->SiS_Pr->CCRT1CRTC[7]  =  (((pSiS->SiS_Pr->CVTotal - 2) & 0x100) >> 8)
- 	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x100) >> 6)
-	 			| (((pSiS->SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
-	 			| 0x10
-	 			| (((pSiS->SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
-	 			| (((pSiS->SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
-	 			| ((pSiS->SiS_Pr->CVSyncStart & 0x200) >> 2);
-
-   pSiS->SiS_Pr->CCRT1CRTC[16] = ((((pSiS->SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5); 	/* cr9 */
-
-#if 0
-   if (mode->VScan >= 32)
-	regp->CRTC[9] |= 0x1F;
-   else if (mode->VScan > 1)
-	regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
-   pSiS->SiS_Pr->CCRT1CRTC[8] =  (pSiS->SiS_Pr->CVSyncStart     ) & 0xFF;		/* cr10 */
-   pSiS->SiS_Pr->CCRT1CRTC[9] =  ((pSiS->SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;	/* cr11 */
-   pSiS->SiS_Pr->CCRT1CRTC[10] = (pSiS->SiS_Pr->CVDisplay    - 1) & 0xFF;		/* cr12 */
-   pSiS->SiS_Pr->CCRT1CRTC[11] = (pSiS->SiS_Pr->CVBlankStart - 1) & 0xFF;		/* cr15 */
-   pSiS->SiS_Pr->CCRT1CRTC[12] = (pSiS->SiS_Pr->CVBlankEnd   - 1) & 0xFF;		/* cr16 */
-
-   pSiS->SiS_Pr->CCRT1CRTC[13] =
-                        GETBITSTR((pSiS->SiS_Pr->CVTotal     -2), 10:10, 0:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
-                        GETBITSTR((pSiS->SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
-
-   pSiS->SiS_Pr->CCRT1CRTC[14] =
-                        GETBITSTR((pSiS->SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
-
-
-   pSiS->SiS_Pr->CCRT1CRTC[15] =
-                        GETBITSTR((pSiS->SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-                        GETBITSTR((pSiS->SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+   SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
 
    switch(depth) {
-   case 8:
-      	pSiS->SiS_Pr->CModeFlag |= 0x223b;
-	break;
-   case 16:
-      	pSiS->SiS_Pr->CModeFlag |= 0x227d;
-	break;
-   case 32:
-      	pSiS->SiS_Pr->CModeFlag |= 0x22ff;
-	break;		
-   default: 
-   	return 0;	
-   }	
-   
-   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) 
+   case 8:  pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
+   case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
+   case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
+   default: return 0;
+   }
+
+   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
       pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
 
    if((pSiS->SiS_Pr->CVDisplay >= 1024)	||
@@ -4492,33 +4428,23 @@
 
    pSiS->SiS_Pr->UseCustomMode = TRUE;
 #ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n", 
+   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
    	pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
    xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
    	pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
    xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[0],
-	pSiS->SiS_Pr->CCRT1CRTC[1],
-	pSiS->SiS_Pr->CCRT1CRTC[2],
-	pSiS->SiS_Pr->CCRT1CRTC[3],
-	pSiS->SiS_Pr->CCRT1CRTC[4],
-	pSiS->SiS_Pr->CCRT1CRTC[5],
-	pSiS->SiS_Pr->CCRT1CRTC[6],
-	pSiS->SiS_Pr->CCRT1CRTC[7]);
+   	pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
+	pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
+	pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
+	pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
    xf86DrvMsg(0, X_INFO, "  0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-   	pSiS->SiS_Pr->CCRT1CRTC[8],
-	pSiS->SiS_Pr->CCRT1CRTC[9],
-	pSiS->SiS_Pr->CCRT1CRTC[10],
-	pSiS->SiS_Pr->CCRT1CRTC[11],
-	pSiS->SiS_Pr->CCRT1CRTC[12],
-	pSiS->SiS_Pr->CCRT1CRTC[13],
-	pSiS->SiS_Pr->CCRT1CRTC[14],
-	pSiS->SiS_Pr->CCRT1CRTC[15]);
+   	pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
+	pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
+	pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
+	pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
    xf86DrvMsg(0, X_INFO, "  0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
    xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
-   	pSiS->SiS_Pr->CSR2B,
-	pSiS->SiS_Pr->CSR2C,
-	pSiS->SiS_Pr->CSRClock);
+   	pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
 #endif
    return 1;
 }
@@ -4635,7 +4561,7 @@
       /* Horizontal display enable end */
       HDE = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0x0C) << 6);
-      E = HDE + 1;
+      E = HDE + 1;  /* 0x80 0x64 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
 	/* inSISIDXREG(SISCR, 0x04, cr_data); */
@@ -4643,7 +4569,7 @@
       /* Horizontal retrace (=sync) start */
       HRS = (cr_data & 0xff) |
             ((unsigned short) (sr_data & 0xC0) << 2);
-      F = HRS - E - 3;
+      F = HRS - E - 3;  /* 0x06 0x06 */
 
       cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
 	/* inSISIDXREG(SISCR, 0x02, cr_data); */
@@ -4673,7 +4599,7 @@
       B = (temp > 0) ? temp : (temp + 256);
 
       temp = HRE - ((E + F + 3) & 63);
-      C = (temp > 0) ? temp : (temp + 64);
+      C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
 
       D = B - F - C;
 
@@ -5205,7 +5131,7 @@
        return 0;
 #endif
     }
-    
+
     if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
 
     RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
diff -urN linux-2.4.26-pre2/drivers/video/sis/init.h linux-2.4.26-pre3/drivers/video/sis/init.h
--- linux-2.4.26-pre2/drivers/video/sis/init.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/init.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -111,9 +108,11 @@
 const USHORT  ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
 const USHORT  ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
 const USHORT  ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
+const USHORT  ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
 const USHORT  ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
 const USHORT  ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
 const USHORT  ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
+const USHORT  ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
 const USHORT  ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
 const USHORT  ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
 const USHORT  ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
@@ -253,7 +252,9 @@
 	{ 1024, 600, 8,16},   /* 0x19 */
 	{ 1152, 768, 8,16},   /* 0x1a */
 	{  768, 576, 8,16},   /* 0x1b */
-	{ 1360,1024, 8,16}    /* 0x1c */
+	{ 1360,1024, 8,16},   /* 0x1c */
+	{ 1280, 800, 8,16},   /* 0x1d */
+	{ 1680,1050, 8,16}    /* 0x1e */
 };
 
 static SiS_StandTableStruct SiS_StandTable[]=
@@ -758,6 +759,7 @@
 	0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
 };
 
+#if 0
 static const UCHAR SiS_HiTVTextTiming[] = {
         0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
 	0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
@@ -768,6 +770,7 @@
         0x60,0x80,0x14,0x90,0x8c,0x60,0x04,0x96,
 	0x72,0x5c,0x11,0x00,0xfc,0xff,0x32,0x00
 };
+#endif
 
 static const UCHAR SiS_HiTVGroup3Data[] = {
         0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
@@ -791,6 +794,7 @@
 	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
 };
 
+#if 0
 static const UCHAR SiS_HiTVGroup3Text[] = {
         0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
 	0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
@@ -801,6 +805,7 @@
 	0x01,0x05,0x03,0x7e,0x65,0x31,0x14,0x75,
 	0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
 };
+#endif
 
 static const UCHAR SiS_NTSCPhase[]    = {0x21,0xed,0xba,0x08};
 static const UCHAR SiS_PALPhase[]     = {0x2a,0x05,0xe3,0x00};
@@ -814,7 +819,7 @@
 static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0};
 static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e};
 
-static const SiS_TVDataStruct  SiS_StPALData[]=
+static const SiS_TVDataStruct  SiS_StPALData[] =
 {
  {    1,   1, 864, 525,1270, 400, 100,   0, 760,0xf4,0xff,0x1c,0x22},
  {    1,   1, 864, 525,1270, 350, 100,   0, 760,0xf4,0xff,0x1c,0x22},
@@ -838,7 +843,7 @@
  {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20}   /* 1024x768 (for NTSC equ) */
 };
 
-static const SiS_TVDataStruct  SiS_StNTSCData[]=
+static const SiS_TVDataStruct  SiS_StNTSCData[] =
 {
  {    1,   1, 858, 525,1270, 400,  50,   0, 760,0xf1,0x04,0x1f,0x18},
  {    1,   1, 858, 525,1270, 350,  50,   0, 640,0xf1,0x04,0x1f,0x18},
@@ -847,7 +852,7 @@
  {    1,   1, 858, 525,1270, 480,   0,   0, 760,0xf1,0x04,0x1f,0x18}
 };
 
-static const SiS_TVDataStruct  SiS_ExtNTSCData[]=
+static const SiS_TVDataStruct  SiS_ExtNTSCData[] =
 {
  {  143,  65, 858, 443,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
  {   88,  35, 858, 393,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},
@@ -855,39 +860,49 @@
  {  143,  70, 924, 393,1270, 440,  92,   0,  92,0xf4,0x0b,0x1c,0x0a},
  {  143,  76, 836, 523,1270, 440, 224,   0,   0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
  {  143, 120,1056, 643,1270, 440,   0, 128,   0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
- {  143,  76, 836, 523,1270, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
 /*{   2,   1, 858, 503,1270, 480,   0, 128,   0,0xee,0x0c,0x22,0x08},*/  /* 720x480  (old, from 650) */
- {    1,   1,1100, 811,1412, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
+ {  143,  76, 836, 523,1270, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
 /*{  65,  64,1056, 791,1270, 480, 638,   0,   0,0xEE,0x0C,0x22,0x08} */  /* 1024x768 (525i) */
+ {    1,   1,1100, 811,1412, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
  {   65,  64,1056, 791,1270, 480, 455,   0,   0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
 };
 
-static const SiS_TVDataStruct  SiS_St2HiTVData[]=
+static const SiS_TVDataStruct  SiS_StHiTVData[] =  /* Slave + TVSimu */
+{
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00}
+};
+
+static const SiS_TVDataStruct  SiS_St2HiTVData[] = /* Slave */
 {
  {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x37c,0x233,0x2b2,0x2bc, 	  0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x3e8,0x233,0x311,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
  {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_ExtHiTVData[]=
+static const SiS_TVDataStruct  SiS_ExtHiTVData[] =
 {
  {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    3,   1, 0x348,0x1e3,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
  {    5,   1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00},  /* 640x480   */
  {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x600   */
  {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
  {    5,   4, 0x627,0x464,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00},  /* 1280x1024 */
- {    4,   1, 0x41a,0x233,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x480   */
+ {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x480   */
  {    5,   2, 0x578,0x293,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x576  */
  {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00}   /* 1280x720  */
 };
 
-static const SiS_TVDataStruct  SiS_St525pData[]=
+static const SiS_TVDataStruct  SiS_St525pData[] =
 {
  {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
@@ -896,7 +911,7 @@
  {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_St750pData[]=
+static const SiS_TVDataStruct  SiS_St750pData[] =
 {
  {    1,   1, 0x672,0x2ee,0x500,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
  {    1,   1, 0x672,0x2ee,0x500,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
@@ -905,8 +920,21 @@
  {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
 };
 
-static const SiS_TVDataStruct  SiS_Ext750pData[]=
+static const SiS_TVDataStruct  SiS_Ext750pData[] =
 {
+#if 1
+ {  143,  65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   88,  35, 0x35a,0x189,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
+ {   18,   5, 0x339,0x1ae,0x500,0x2d0,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
+ {  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  */
+ {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480  */
+ {   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 */
+#endif
+#if 0
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {   24,   7, 0x3a7,0x1a4,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
  {    3,   1, 0x3a7,0x1d6,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},
@@ -915,63 +943,105 @@
  {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
  {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
  {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
+#if 0
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* TEST (0.93) */
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   17,   6, 0x339,0x203,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00},
+ {   85,  46, 0x3f4,0x27b,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480   */
+ {   17,  16, 0x55f,0x323,0x460,0x2a8,0x2b6,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600   */
+ {  136,  35, 0x339,0x181,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480   */
+ {  187,  74, 0x39d,0x203,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
+ {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,    50, 0x00,0x00,0x00,0x00}   /* 1280x720  */
+#endif
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+static const SiS_LCDDataStruct  SiS_LCD1280x720Data[] =  
 {
-	{    9,   2, 800, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    4,   1, 900, 500,1800,1000},
-	{    9,   2, 800, 500,1800,1000},
-	{   30,  11,1056, 625,1800,1000},
-	{    5,   3,1350, 800,1800,1000},
-	{    1,   1,1576,1050,1576,1050},
-	{    1,   1,1800,1000,1800,1000}
-};
-
-/* 1280x768 panel data from Fujitsu 7911 (VL-17WDX8).
- * Other 1280x768 panels (with clock != 81000, HTxVT != 1688x802)
- * will be treated as custom panels.
+	{  14,    5,  864,  432, 1344,  806 }, /* 640x400 */
+	{  16,    5,  864,  378, 1344,  806 },
+	{  14,    5,  864,  432, 1344,  806 },
+	{  16,    5,  864,  378, 1344,  806 },
+	{  24,   11,  924,  523, 1344,  806 }, /* 640x480 */
+	{   7,    5, 1152,  664, 1344,  806 }, /* 800x600 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1344,  806, 1344,  806 }  /* 1280x720 */
+};
+
+/* About 1280x768: For TMDS, Panel_1280x768 will only be set if
+ * the panel is a Fujitsu 7911 (VL-17WDX8) (with clock 81, 1688x802)
+ * Other TMDS panels of this resolution will be treated as custom.
+ * For LVDS, we know two types. Data follows:
  */
 
-static const SiS_LCDDataStruct  SiS_StLCD1280x768Data[] =
+static const SiS_LCDDataStruct  SiS_StLCD1280x768_2Data[] =
 {
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_ExtLCD1280x768Data[] =
-{
-	{ 211,  100, 2100,  408, 1688,  802 }, /* These values are *wrong* */
-	{ 211,   64, 1536,  358, 1688,  802 }, /* (which is why they aren't used yet) */
-	{ 211,  100, 2100,  408, 1688,  802 },
-	{ 211,   64, 1536,  358, 1688,  802 },
-	{ 211,   48,  840,  488, 1688,  802 },
-	{ 211,   72, 1008,  609, 1688,  802 },
-	{ 211,  128, 1400,  776, 1688,  802 },
-	{ 211,  205, 1680, 1041, 1688,  802 },
-	{ 1,      1, 1688,  802, 1688,  802 }  /* That's the only one that is correct */
-};
-
-static const SiS_LCDDataStruct  SiS_NoScaleData1280x768[] =
-{
-        { 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802},
-	{ 1, 1, 1688,  802, 1688,  802}
+	{  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
+	{  32,    9,  858,  372, 1408,  806 },
+	{  64,   21,  858,  434, 1408,  806 },
+	{  32,    9,  858,  372, 1408,  806 },
+	{ 143,   68, 1024,  527, 1408,  806 }, /* 640x480 */
+	{  64,   51, 1364,  663, 1408,  806 }, /* 800x600 */
+	{  88,   81, 1296,  806, 1408,  806 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }  /* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_ExtLCD1280x768_2Data[] =
+{
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  64,   25, 1056,  422, 1408,  806 }, /*, 664 */
+	{ 128,   39,  884,  396, 1408,  806 }, /*, 640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /*, 664 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /*, 768 */
+	{  88,   81, 1296,  806, 1408,  806 },
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x768_3Data[] =
+{
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  64,   25, 1056,  422, 1664,  798 },			/* 640x400 */
+	{ 128,   39,  884,  396, 1408,  806 }, /* ,640 */
+	{  32,   15, 1056,  513, 1408,  806 }, /* ,664 */	/* 640x480 */
+	{ 176,  125, 1280,  640, 1408,  806 }, /* ,768 */	/* 800x600 */
+	{  64,   61, 1342,  806, 1408,  806 },			/* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  806, 1408,  806 }			/* 1280x768 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x800Data[] =
+{
+	{ 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{ 128,   51, 1122,  412, 1408,  816 },
+	{ 128,   49, 1232,  361, 1408,  816 },
+	{   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
+	{  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
+	{  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
+	{   0,    0,    0,    0,    0,    0 },
+	{   1,    1, 1408,  816, 1408,  816 }  /* 1280x800 */
+};
+
+static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+{
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    4,   1,  900,  500, 1800, 1000 },
+	{    9,   2,  800,  500, 1800, 1000 },
+	{   30,  11, 1056,  625, 1800, 1000 },
+	{    5,   3, 1350,  800, 1800, 1000 },
+	{    1,   1, 1576, 1050, 1576, 1050 },
+	{    1,   1, 1800, 1000, 1800, 1000 }
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1400x1050Data[] =
@@ -989,28 +1059,32 @@
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
 {
-	{ 211,  100, 2100,  408, 1688, 1066 },
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 */
 	{ 211,   64, 1536,  358, 1688, 1066 },
 	{ 211,  100, 2100,  408, 1688, 1066 },
 	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 },
-	{ 211,   72, 1008,  609, 1688, 1066 },
+	{ 211,   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 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData1400x1050[] =
+static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
 {
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 },
-	{ 1, 1, 1688, 1066, 1688, 1066 }
+	{  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   24, 1260,  410, 1900, 1066 },
+	{  10,    3, 1710,  362, 1900, 1066 },
+	{  95,   32, 1400,  490, 1900, 1066 }, /*  4 640x480 */
+	{  95,   42, 1470,  610, 1900, 1066 }, /*  5 800x600 */
+	{  95,   64, 1750,  784, 1900, 1066 }, /*  6 1024x768 */
+	{  95,   94, 1900, 1055, 1900, 1066 }, /*  7 1280x1024 */
+	{  41,   31, 1900,  806, 1900, 1066 }, /*  8 1280x768 */
+	{  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch */
+	{  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
+	{  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch */
+	{   1,    1, 1900, 1066, 1900, 1066 }  /* 12 1680x1050 */
 };
 
 static const SiS_LCDDataStruct  SiS_StLCD1600x1200Data[] =
@@ -1041,422 +1115,29 @@
 	{ 1, 1,2160,1250, 2160, 1250 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData1600x1200[] =
-{
-        {1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-	{1,  1, 2160, 1250, 2048, 1250},
-};
-
 static const SiS_LCDDataStruct  SiS_NoScaleData[] =
 {
-	{ 1, 1, 800, 449, 800, 449 },
+	{ 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
 	{ 1, 1, 800, 449, 800, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
 	{ 1, 1, 900, 449, 900, 449 },
-	{ 1, 1, 800, 525, 800, 525 },
-	{ 1, 1,1056, 628,1056, 628 },
-	{ 1, 1,1344, 806,1344, 806 },
-	{ 1, 1,1688,1066,1688,1066 },
-        { 1, 1,1688, 802,1688, 802 },  /* 1280x768: 802 was 806 in both cases */
-        { 1, 1,2160,1250,2160,1250 },  /* 1600x1200 */
-	{ 1, 1,1800,1000,1800,1000 }   /* 1280x960 */
-};
-
-/* *** LCDA *** */
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_1[]=
-{
-	{  960, 438,1344, 806},
-	{  960, 388,1344, 806},
-	{ 1040, 438,1344, 806},
-	{ 1040, 388,1344, 806},
-	{  960, 518,1344, 806},   /* 640x480 */
-	{ 1120, 638,1344, 806},   /* 800x600 */
-	{ 1344, 806,1344, 806},   /* 1024x768 */
-#if 0
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 438,1344, 806},
-	{ 840, 409,1344, 806},
-	{ 840, 518,1344, 806},   /* 640x480 */
-	{1050, 638,1344, 806},   /* 800x600 */
-	{1344, 806,1344, 806},   /* 1024x768 */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1024x768Data_2[]=
-{
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_1[]=
-{ /* Acer, Compaq */
-	{1048, 442,1688,1066},
-	{1048, 392,1688,1066},
-	{1128, 442,1688,1066},
-	{1128, 392,1688,1066},
-	{1048, 522,1688,1066},
-	{1208, 642,1688,1066},
-	{1432, 810,1688,1066},
-	{1688,1066,1688,1066}
+	{ 1, 1, 800, 525, 800, 525 },  /* 0x04: 320x240, 640x480  */
+	{ 1, 1,1056, 628,1056, 628 },  /* 0x05: 400x300, 800x600  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x06: 512x384, 1024x768 */
+	{ 1, 1,1688,1066,1688,1066 },  /* 0x07: 1280x1024 */
+        { 1, 1,1688, 802,1688, 802 },  /* 0x08: 1280x768: Fujitsu, TMDS only */
+        { 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,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)  */
 };
 
-static const SiS_LVDSDataStruct  SiS_LCDA1280x1024Data_2[]=
-{ /* Corrected (illegal in Acer, correct in Compaq) */
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066},
-	{1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_1[]=
-{ /* Clevo */
-        { 928, 416, 1688,1066},
-	{ 928, 366, 1688,1066},
-	{1008, 416, 1688,1066},
-	{1008, 366, 1688,1066},
-	{1200, 530, 1688,1066},
-	{1088, 616, 1688,1066},
-	{1312, 784, 1688,1066},
-	{1568,1040, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1400x1050Data_2[]=
-{ /* Clevo */
-    	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066},
-	{1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo (Temporary data)  */
-	{1200, 450, 2048,1250},
-	{1200, 400, 2048,1250},
-	{1280, 450, 2048,1250},
-	{1280, 400, 2048,1250},
-	{1200, 530, 2048,1250},
-	{1360, 650, 2048,1250},
-	{1584, 818, 2048,1250},
-	{1688,1066, 2048,1250},
-	{1688,1066, 2048,1250},
-	{2048,1250, 2048,1250}   /* this should be correct */
-#if 0
-	{2160,1250, 2048,1250}   /* ? */
-#endif
-};
-
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_2[]=
-{ /* Clevo (Temporary data. Seems invalid.) */
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250},
-	{2160,1250, 2160,1250}
-};
-
-/* LVDS SKEW for LCDA */
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_1[]=
-{  /* 1024x768 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},   /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1076_2[]=
-{  /* 1024x768; not expanded */
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1184, 622 },
-	{ 1184, 597 },
-	{ 1152, 650 },  /* 622 */
-	{ 1232, 722 },
-	{    0, 0   },  /* 805; was 0, 0 -> top line cut away (26/09/03) */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_1[]=
-{  /* 1280x1024 */
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 ,    0},
-	{ 0 , 1065},  /* Acer */
-	{ 0 ,    0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1210_2[]=
-{  /* 1280x1024; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_1[]=
-{  /* 1400x1050 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 1065}   /* Was 0,0 */
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1296_2[]=
-{  /* 1400x1050; not expanded */
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 741 },
-	{ 1308, 716 },
-	{ 1308, 781 },
-	{ 1388, 841 },
-	{ 1500, 925 },
-	{ 1628,1053 },
-	{    0,1065 }
-#if 0
-	{ 808 , 740},
-	{ 0   , 715},
-	{ 632 , 740},
-	{ 632 , 715},
-	{ 1307, 780},
-	{ 1387,1157},
-	{ 1499, 924},
-	{ 1627,1052},
-	{ 0 , 0}
-#endif
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_1[]=
-{  /* 1600x1200 */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-static const SiS_LVDSDesStruct SiS_PanelType1600_2[]=
-{  /* 1600x1200; not expanded */
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
-#ifdef SIS315H
-
-/* LCDA CRT1 custom data */
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1[]=
-{
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x86,0x1f,
-   0x5e,0x82,0x5d,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x4f,0x82,0x58,0x06,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x63,0x96,0x6c,0x1a,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x7f,0x92,0x88,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x9f,0x92,0xa8,0x16,0x28,0x5a,
-   0x00,0x84,0xff,0xff,0x29,0x01,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Compaq1280x1024_LCDACRT1_1_H[]=
-{
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0xb8,0x1f,
-   0x90,0x84,0x8f,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x3c,0x4f,0x4f,0x82,0x58,0x06,0x86,0xd1,
-   0xbc,0x80,0xbb,0xbb,0xe5,0x00,0x00,0x06,
-   0x01}},
- {{0x56,0x27,0x27,0x9a,0x30,0x1e,0x08,0x3e,
-   0xe0,0x84,0xdf,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x31,0x84,0x3a,0x88,0x80,0xf0,
-   0x58,0x8c,0x57,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x3f,0x92,0x48,0x96,0x28,0xf5,
-   0x00,0x84,0xff,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1[]=
-{
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x97,0x1f,
-   0x60,0x87,0x5d,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x4f,0x97,0x55,0x86,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x63,0x8B,0x69,0x1A,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x26,
-   0x01}},
- {{0xA3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xFf,0xFf,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_1_H[]=
-{
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0xc4,0x1f,
-   0x92,0x89,0x8f,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x2b,0x03,0x97,0x1f,
-   0x60,0x87,0x5D,0x5D,0x83,0x01,0x00,0x44,
-   0x00}},
- {{0x4b,0x27,0x27,0x8f,0x32,0x1b,0x04,0x3e,
-   0xE2,0x89,0xDf,0xDf,0x05,0x00,0x00,0x45,
-   0x00}},
- {{0x55,0x31,0x31,0x99,0x46,0x1d,0x7c,0xf0,
-   0x5A,0x8F,0x57,0x57,0x7D,0x20,0x00,0x55,
-   0x01}},
- {{0x63,0x3F,0x3F,0x87,0x4A,0x93,0x24,0xF5,
-   0x02,0x88,0xFF,0xFF,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2[]=
-{
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LCDACRT1DataStruct  Clevo1024x768_LCDACRT1_2_H[]=
-{
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x7f,0x86,0xdf,0xdf,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x71,0x31,0x31,0x95,0x46,0x97,0x24,0xf1,
-   0xbb,0x82,0x57,0x57,0x25,0x10,0x00,0x01,
-   0x01 }},
- {{0x63,0x3f,0x3f,0x87,0x46,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-#endif  /* 315 */
 
 /**************************************************************/
 /* LVDS ----------------------------------------------------- */
@@ -1507,9 +1188,7 @@
 	{ 848, 389,1060, 629},
 	{ 848, 518,1060, 629},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS800x600Data_2[]=
@@ -1520,9 +1199,7 @@
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
 	{1056, 628,1056, 628},
-	{1056, 628,1056, 628},
-	{ 800, 449,1000, 644},
-	{ 800, 525,1000, 635}
+	{1056, 628,1056, 628}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_1[]=
@@ -1534,8 +1211,6 @@
 	{ 840, 518,1344, 806},   /* 640x480 */
 	{1050, 638,1344, 806},   /* 800x600 */
 	{1344, 806,1344, 806},   /* 1024x768 */
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_2[]=
@@ -1547,11 +1222,8 @@
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
 };
 
-
 static const SiS_LVDSDataStruct  SiS_LVDS1280x1024Data_1[]=
 {
 	{1048, 442,1688,1066},
@@ -1702,9 +1374,7 @@
 	{ 840, 560,1344, 800},
 	{ 840, 689,1344, 800},
 	{1050, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 789},
-	{ 800, 525,1280, 785}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_2[] =
@@ -1715,9 +1385,7 @@
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
 	{1344, 800,1344, 800},
-	{1344, 800,1344, 800},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 800,1344, 800}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_1[] =
@@ -1728,9 +1396,7 @@
 	{ 840, 409,1344, 806},
 	{ 840, 518,1344, 806},
 	{1050, 638,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_2[] =
@@ -1741,9 +1407,7 @@
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
 	{1344, 806,1344, 806},
-	{1344, 806,1344, 806},
-	{ 800, 449,1280, 801},
-	{ 800, 525,1280, 813}
+	{1344, 806,1344, 806}
 };
 
 /* Pass 1:1 data */
@@ -1756,7 +1420,7 @@
 	{ 800, 525,  800, 525},  /*  640x480   */
 	{1056, 628, 1056, 628},  /*  800x600   */
 	{1344, 806, 1344, 806},  /* 1024x768   */
-	{1344,1066, 1344,1066},  /* 1280x1024  */  /* INSERTED ! */
+	{1688,1066, 1688,1066},  /* 1280x1024  */  /* INSERTED ! */
  	{1688, 806, 1688, 806},  /* 1280x768   */
 	/* No other panels ! */
 };
@@ -1871,36 +1535,6 @@
         {1160, 840,1160, 840}
 };
 
-/* LVDS Skew */
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_1[]=
-{
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 8,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0,   0},
-	{ 0, 806},
-	{ 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_PanelTypeNS_2[] =
-{
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0},
-	{ 0 , 0}
-};
-
 /* Chrontel TV Skew */
 
 static const SiS_LVDSDesStruct  SiS_CHTVUNTSCDesData[]=
@@ -2439,63 +2073,6 @@
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
-   0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-
 /**************************************************************/
 /* COMMON --------------------------------------------------- */
 /**************************************************************/
@@ -2756,7 +2333,8 @@
    { 0x0000 }
 };
 
-USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
+USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
+			  int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
                           USHORT CustomT, int LCDwith, int LCDheight);
 USHORT  SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
@@ -2777,6 +2355,7 @@
 void	SiS_DisplayOff(SiS_Private *SiS_Pr);
 void	SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
 void	SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void	SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 void	SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
@@ -2787,6 +2366,7 @@
 USHORT	SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
               USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo);
 void	SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
+void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 #ifdef LINUX_XF86
 BOOLEAN	SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
 BOOLEAN	SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
diff -urN linux-2.4.26-pre2/drivers/video/sis/init301.c linux-2.4.26-pre3/drivers/video/sis/init301.c
--- linux-2.4.26-pre2/drivers/video/sis/init301.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/init301.c	2004-03-13 07:43:23.000000000 -0800
@@ -34,13 +34,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -76,10 +73,6 @@
 
 #include "init301.h"
 
-#if 0
-#define TWNEWPANEL
-#endif
-
 #ifdef SIS300
 #include "oem300.h"
 #endif
@@ -91,6 +84,8 @@
 #define SiS_I2CDELAY      1000
 #define SiS_I2CDELAYSHORT  150
 
+static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
+
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
 /*********************************************/
@@ -98,146 +93,75 @@
 void
 SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
-  else
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+   else
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
 void
 SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  if(HwInfo->jChipType >= SIS_315H)
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
-  else
-     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
+   if(HwInfo->jChipType >= SIS_315H)
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
+   else
+      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
 }
 
 /*********************************************/
-/*            HELPER: Enable CRT2            */
+/*            HELPER: Write SR11             */
 /*********************************************/
 
-void
-SiS_EnableCRT2(SiS_Private *SiS_Pr)
+static void
+SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
 {
-  SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
+   if(HwInfo->jChipType >= SIS_661) DataAND &= 0x0f;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 }
 
 /*********************************************/
 /*    HELPER: Get Pointer to LCD structure   */
 /*********************************************/
 
-/* For 661 series only */
 #ifdef SIS315H
-#if 0   /* Need to wait until hardware using this really exists */
 static UCHAR *
-GetLCDPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int tabletype,
-             USHORT ModeNo, USHORT ModeIdIndex, USHORT RRTI)
+GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  UCHAR *ROMAddr =  HwInfo->pjVirtualRomBase;
-  UCHAR *tableptr = NULL;
-  UCHAR tablelengths[] = { 8, 7, 6, 6, 8, 6, 0, 0, 0 };
-  USHORT modeflag, CRT2Index, tablelength, lcdid, myid, tableptri;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT2CRTC;
-     /* This is total bullshit: */
-     if(SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO == SIS_RI_720x576) CRT2Index = 10;
-  }
-
-  if(tabletype <= 1) {
-#if 0	/* Not yet implemented */
-     if(ModeNo <= 0x13) {
-        CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex]. + 5;
-     } else {
-        CRT2Index = SiS_Pr->SiS_RefIndex[RRTI]. + 5;
-     }
-     if(tabletype & 1) CRT2Index >>= 4;
-#endif
-  }
-
-  CRT2Index &= 0x0f;
-
-  tablelength = tablelengths[tabletype];
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     if((tabletype == 5) || (tabletype == 7)) tablelength = 8;
-     if((tabletype == 3) || (tabletype == 8)) tablelength = 8;
-  }
-
-  if(!tablelength) return NULL;
-
-  tableptri = ROMAddr[0x222] | (ROMAddr[0x223] << 8);
-  tableptri += (tabletype << 1);
-  if(!tableptri) return NULL;
-  tableptr = &ROMAddr[tableptri];
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   UCHAR  *myptr = NULL;
+   USHORT romindex = 0;
 
-  do {
-     lcdid = tableptr[0];
-     if(lcdid == 0xff) break;
-     myid = SiS_Pr->SiS_LCDResInfo;
-     if((lcdid & 0x80) && (lcdid != 0x80)) {
-        lcdid &= 0x7f;
-	myid = SiS_Pr->SiS_LCDTypeInfo;
-     }
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) myid &= ~0x1f;
-
-     if(myid == lcdid) {
-	lcdid = tableptr[1] | (tableptr[2] << 8);
-	myid = SiS_Pr->SiS_LCDInfo661;
-	if(modeflag & HalfDCLK) myid |= 0x200;
-	if(ModeNo <= 0x13)      myid |= 0x400;
-	lcdid &= myid;
-	myid = tableptr[3] | (tableptr[4] << 8);
-	if(lcdid == myid) break;
-     }
-     tableptr += 7;
-  } while (1);
-
-  if(lcdid == myid) {
-     lcdid = tableptr[5] | (tableptr[6] << 8);
-     lcdid += (tablelength * CRT2Index);
-     return((UCHAR *)&ROMAddr[lcdid]);
-  }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-  return NULL;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      myptr = (UCHAR *)SiS_LCDStruct661;
+      romindex = SISGETROMW(0x100);  /* 10c, 0.93: 10e */
+      if(romindex) {
+         romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26);
+         myptr = &ROMAddr[romindex];
+      }
+   }
+   return myptr;
 }
-#endif
 
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static USHORT
+GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   USHORT lcdres = SiS_Pr->SiS_LCDResInfo;
-   USHORT lcdtype = SiS_Pr->SiS_LCDTypeInfo;
-   USHORT romindex=0;
-   UCHAR  *myptr = NULL;
-   UCHAR  lcdid;
+   USHORT romptr = 0;
 
-   if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-      romindex = ROMAddr[0x256] | (ROMAddr[0x257] << 8);
-   }
-   if(romindex) {
-      myptr = &ROMAddr[romindex];
-   } else {
-      myptr = (UCHAR *)SiS_LCDStruct661;
-   }
+   /* Use the BIOS tables only for LVDS panels; DVI is unreliable
+    * due to the variaty of panels the BIOS doesn't know about.
+    */
 
-   while(myptr[0] != 0xff) {
-      lcdid = myptr[0];
-      if((lcdid & 0x80) && (lcdid != 0x80)) {
-         lcdres = lcdtype;
-	 lcdid &= 0x7f;
-      }
-      if(lcdid == lcdres) break;
-      myptr += 26;
+   if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+      romptr = SISGETROMW(0x102);  /* 2ad */
+      romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
-   if(myptr[0] == 0xff) return NULL;
 
-   return myptr;
+   return(romptr);
 }
 #endif
 
@@ -250,71 +174,72 @@
                    USHORT RefreshRateTableIndex, USHORT *i,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,infoflag;
-
-  tempbx = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+  USHORT checkmask=0,modeid,infoflag;
 
-  tempax = 0;
+  modeid = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID;
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 
-      	tempax |= SupportRAMDAC2;
+      	checkmask |= SupportRAMDAC2;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   tempax |= SupportRAMDAC2_135;
+	   checkmask |= SupportRAMDAC2_135;
 	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      tempax |= SupportRAMDAC2_162;
+	      checkmask |= SupportRAMDAC2_162;
 	      if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-		 tempax |= SupportRAMDAC2_202;
+		 checkmask |= SupportRAMDAC2_202;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
 	if(HwInfo->jChipType >= SIS_315H) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	         if(tempbx == 0x2e) {  /* 640x480 */
-		    tempax |= Support64048060Hz;
-		 }
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	         if(modeid == 0x2e) checkmask |= Support64048060Hz;
 	      }
 	   }
 	}
 
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-      	tempax |= SupportHiVision;
+      	checkmask |= SupportHiVision;
 
      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 
-        tempax |= SupportTV;
+        checkmask |= SupportTV;
 	if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	   tempax |= SupportTV1024;
+	   checkmask |= SupportTV1024;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	         checkmask |= SupportYPbPr750p;
+	      }
+	   }
 	}
 
      }
 
-  } else {	/* for LVDS  */
+  } else {	/* LVDS */
 
      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      	if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-           tempax |= SupportCHTV;
+           checkmask |= SupportCHTV;
       	}
      }
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     	tempax |= SupportLCD;
+     	checkmask |= SupportLCD;
      }
 
   }
 
   /* Look backwards in table for matching CRT2 mode */
-  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == tempbx; (*i)--) {
+  for(; SiS_Pr->SiS_RefIndex[RefreshRateTableIndex+(*i)].ModeID == modeid; (*i)--) {
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
      if((*i) == 0) break;
   }
 
@@ -322,17 +247,17 @@
    * for a matching CRT2 mode if no mode was found yet.
    */
   for((*i) = 0; ; (*i)++) {
-     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != tempbx) {
-     	return(0);
+     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].ModeID != modeid) {
+     	return FALSE;
      }
      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex + (*i)].Ext_InfoFlag;
-     if(infoflag & tempax) return(1);
+     if(infoflag & checkmask) return TRUE;
   }
-  return(1);
+  return TRUE;
 }
 
 /*********************************************/
-/*              Get rate pointer             */
+/*              Get rate index               */
 /*********************************************/
 
 USHORT
@@ -357,13 +282,11 @@
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     	if(modeflag & HalfDCLK) return(0);
+     	if(modeflag & HalfDCLK) return 0;
      }
   }
 
-  if(ModeNo < 0x14) return(0xFFFF);
-
-  /* CR33 holds refresh rate index for CRT1 [3:0] and CRT2 [7:4]. */
+  if(ModeNo < 0x14) return 0xFFFF;
 
   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
   backupindex = index;
@@ -378,7 +301,7 @@
 	}
 	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	   if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
-              temp = LCDRefreshIndex[SiS_Pr->SiS_LCDResInfo];
+              temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
               if(index > temp) index = temp;
 	   }
 	}
@@ -451,37 +374,39 @@
 /*    HELPER: GET SOME DATA FROM BIOS ROM    */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23c] << 8) | ROMAddr[0x23b];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23b);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
 
 static BOOLEAN
 SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR *ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase;
   USHORT temp,temp1;
-  UCHAR *ROMAddr;
 
-  if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
         temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xff) >> 4);
-        temp1 = (ROMAddr[0x23e] << 8) | ROMAddr[0x23d];
-        if(temp1 & temp) return(1);
+        temp1 = SISGETROMW(0x23d);
+        if(temp1 & temp) return TRUE;
      }
   }
-  return(0);
+  return FALSE;
 }
+#endif
 
 /*********************************************/
 /*          HELPER: DELAY FUNCTIONS          */
@@ -555,7 +480,7 @@
          } else {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
          }
-	 if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	 if(SiS_Pr->SiS_UseROM) {
             if(ROMAddr[0x220] & 0x40) {
                if(!(DelayTime & 0x01)) {
 	          Delay = (USHORT)ROMAddr[0x225];
@@ -573,7 +498,15 @@
 
 #ifdef SIS315H
 
-      if(HwInfo->jChipType >= SIS_330) return;
+      if(HwInfo->jChipType >= SIS_661) {
+
+         if(!(DelayTime & 0x01)) {
+	    SiS_DDC2Delay(SiS_Pr, 0x1000);
+         } else {
+	    SiS_DDC2Delay(SiS_Pr, 0x4000);
+         }
+
+      } else if(HwInfo->jChipType >= SIS_330) return;
 
       if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
@@ -598,7 +531,7 @@
                } else {
        		  Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
                }
-	       if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
+	       if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
                   if(ROMAddr[0x13c] & 0x40) {
                      if(!(DelayTime & 0x01)) {
 	    	        Delay = (USHORT)ROMAddr[0x17e];
@@ -619,10 +552,7 @@
          } else {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
          }
-	 Delay <<= 2;
-	 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	    Delay <<= 5;
-	 }
+	 Delay <<= 8;
 	 SiS_DDC2Delay(SiS_Pr, Delay);
 
       }
@@ -737,10 +667,7 @@
 static BOOLEAN
 SiS_Is301B(SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-  if(flag >= 0xb0) return TRUE;
+  if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
   return FALSE;
 }
 
@@ -804,6 +731,27 @@
 
 #ifdef SIS315H
 static BOOLEAN
+SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
+     if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+  }
+  return FALSE;
+}
+#endif
+
+#ifdef SIS315H
+static BOOLEAN
+SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
+  return FALSE;
+}
+#endif
+
+#ifdef SIS315H
+static BOOLEAN
 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   USHORT flag;
@@ -956,7 +904,7 @@
    if(!(SiS_Pr->SiS_ChSW)) return;
 
 #ifndef LINUX_XF86
-   SiS_SetRegLong(0xcf8,0x80000874);		   /* get ACPI base */
+   SiS_SetRegLong(0xcf8,0x80000874);		       /* get ACPI base */
    acpibase = SiS_GetRegLong(0xcfc);
 #else
    acpibase = pciReadLong(0x00000800, 0x74);
@@ -974,22 +922,19 @@
 }
 
 void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
-              USHORT ModeIdIndex,PSIS_HW_INFO HwInfo,
-	      int checkcrt2mode)
+SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+              PSIS_HW_INFO HwInfo, int checkcrt2mode)
 {
   USHORT tempax,tempbx,temp;
   USHORT modeflag, resinfo=0;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-   	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   SiS_Pr->SiS_SetFlag = 0;
@@ -1001,11 +946,12 @@
     	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 #if 0
    	if(HwInfo->jChipType < SIS_661) {
-	   if(SiS_Pr->SiS_YPbPr & YPbPrModeMask) {
+	   /* NO - YPbPr not set yet ! */
+	   if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
 	      temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); 	/* 0x83 */
 	      temp |= SetCRT2ToHiVision;   					/* 0x80 */
    	   }
-	   if(SiS_Pr->SiS_YPbPr & YPbPrSetSVideo) {
+	   if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
 	      temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode); 	/* 0x83 */
 	      temp |= SetCRT2ToSVIDEO;  					/* 0x08 */
 	   }
@@ -1040,16 +986,28 @@
        	      if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
           	 tempbx |= SetCRT2ToLCDA;
 	      }
-	      if(HwInfo->jChipType >= SIS_661) {
-	         if(SiS_Pr->SiS_VBType & (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
-	            if(temp & 0x04) {
-		       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
-		       if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
-		       else             tempbx |= SetCRT2ToYPbPr525750;
-		    }
-	         }
-  	      }
-    	   }
+	   }
+
+	   if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
+	      tempbx &= ~(SetCRT2ToRAMDAC);
+	   }
+
+	   if(HwInfo->jChipType >= SIS_661) {
+	      tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
+	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	      if(SiS_Pr->SiS_VBType & (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
+	         if(temp & 0x04) {
+		    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+		    if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+		    else             tempbx |= SetCRT2ToYPbPr525750;
+		 }
+	      } else if(SiS_Pr->SiS_VBType & (VB_SIS301 | VB_SIS301B | VB_SIS302B)) {
+	         if(temp & 0x04) {
+		    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+		    if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+		 }
+	      }
+  	   }
 
 	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 	      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1111,24 +1069,12 @@
 				SetPALTV 	   |
 				SwitchCRT2	   |
 				SetSimuScanMode );
-      	   if(tempbx & SetCRT2ToLCDA) {
-              tempbx &= (clearmask | SetCRT2ToLCDA);
-      	   }
-	   if(tempbx & SetCRT2ToRAMDAC) {
-              tempbx &= (clearmask | SetCRT2ToRAMDAC);
-      	   }
-	   if(tempbx & SetCRT2ToLCD) {
-              tempbx &= (clearmask | SetCRT2ToLCD);
-      	   }
-	   if(tempbx & SetCRT2ToSCART) {
-              tempbx &= (clearmask | SetCRT2ToSCART);
-      	   }
-	   if(tempbx & SetCRT2ToHiVision) {
-              tempbx &= (clearmask | SetCRT2ToHiVision);
-      	   }
-	   if(tempbx & SetCRT2ToYPbPr525750) {
-	      tempbx &= (clearmask | SetCRT2ToYPbPr525750);
-	   }
+      	   if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
+	   if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
+	   if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
+	   if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
+	   if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
+	   if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
    	} else {
 	   if(HwInfo->jChipType >= SIS_315H) {
 	      if(tempbx & SetCRT2ToLCDA) {
@@ -1156,14 +1102,12 @@
       	   }
     	}
 
-    	if(!(tempbx & DriverMode)){
-      	   tempbx |= SetSimuScanMode;
-    	}
+    	if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
 
 	/* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
 	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
 	   if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
-	       ((tempbx & SetCRT2ToLCD) && (SiS_Pr->SiS_VBType & VB_NoLCD)) ) {
+	       ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
 	       modeflag &= (~CRT2Mode);
 	   }
 	}
@@ -1237,21 +1181,40 @@
 void
 SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+
+  UCHAR temp;
+
   /* Note: This variable is only used on 30xLV systems.
    * CR38 has a different meaning on LVDS/CH7019 systems.
    * On 661 and later, these bits moved to CR35.
+   *
+   * On 301, 301B, only HiVision 1080i is supported.
+   * On 30xLV, 301C, only YPbPr 1080i is supported.
    */
 
   SiS_Pr->SiS_YPbPr = 0;
-#ifdef SIS315H
-  if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   SiS_Pr->SiS_YPbPr = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x38) >> 3);
+  if(HwInfo->jChipType >= SIS_661) return;
+
+  if(SiS_Pr->SiS_VBType) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+     }
+  }
+
+  if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
+        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+	if(temp & 0x08) {
+	   switch((temp >> 4)) {
+	   case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
+	   case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
+	   case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
+	   case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+	   }
 	}
      }
   }
-#endif /* SIS315H */
+
 }
 
 /*********************************************/
@@ -1290,7 +1253,7 @@
 	   if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
         }
         if(temp) {
-           if(romindex && ROMAddr && SiS_Pr->SiS_UseROM) {
+           if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
 	      OutputSelect = ROMAddr[romindex];
 	      if(!(OutputSelect & EnablePALMN)) {
                  SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
@@ -1312,8 +1275,8 @@
         }
 	/* Translate HiVision/YPbPr to our new flags */
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	   if(SiS_Pr->SiS_YPbPr == YPbPr750)           SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-	   else if(SiS_Pr->SiS_YPbPr == YPbPr525)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+	   if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+	   else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
 	   else	if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
 	   else					       SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
 	   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
@@ -1387,6 +1350,22 @@
 	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 	   SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
 	}
+	if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+	   if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+	      SiS_Pr->SiS_TVMode |= TVAspect169;
+	   } else {
+	      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+	      if(temp1 & 0x02) {
+		 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+		    SiS_Pr->SiS_TVMode |= TVAspect169;
+		 } else {
+		    SiS_Pr->SiS_TVMode |= TVAspect43LB;
+		 }
+	      } else {
+		 SiS_Pr->SiS_TVMode |= TVAspect43;
+	      }
+	   }
+	}
      }
   }
 
@@ -1396,6 +1375,7 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
         SiS_Pr->SiS_TVMode |= TVSetPAL;
+	SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
         if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
 	   SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
@@ -1409,6 +1389,7 @@
      }
 
      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+        /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
         if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
            if(resinfo == SIS_RI_1024x768) {
               SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
@@ -1433,15 +1414,48 @@
   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
 
 #ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "(init301.c: TVMode %x)\n", SiS_Pr->SiS_TVMode);
+  xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
 #endif 
-
 }
 
 /*********************************************/
 /*               GET LCD INFO                */
 /*********************************************/
 
+static USHORT
+SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+{
+   USHORT temp = SiS_Pr->SiS_LCDResInfo;
+   /* Translate my LCDResInfo to BIOS value */
+   if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
+   if(temp == Panel_1280x768_3)  temp = Panel_1280x768;
+   return temp;
+}
+
+static void
+SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+#ifdef SIS315H
+   UCHAR  *ROMAddr;
+
+   if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+      SiS_Pr->PanelHT  = SISGETROMW(6);
+      SiS_Pr->PanelVT  = SISGETROMW(8);
+      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_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_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+   }
+#endif
+}
+
 void
 SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 		  PSIS_HW_INFO HwInfo)
@@ -1457,49 +1471,57 @@
          { 0,  1,  2,  3,  7,  4,  5,  8,
 	   0,  0, 10,  0,  0,  0,  0, 15 };
 
-  SiS_Pr->SiS_LCDResInfo = 0;
+  SiS_Pr->SiS_LCDResInfo  = 0;
   SiS_Pr->SiS_LCDTypeInfo = 0;
-  SiS_Pr->SiS_LCDInfo = 0;
+  SiS_Pr->SiS_LCDInfo     = 0;
+  SiS_Pr->PanelHRS        = 999; /* HSync start */
+  SiS_Pr->PanelHRE        = 999; /* HSync end */
+  SiS_Pr->PanelVRS        = 999; /* VSync start */
+  SiS_Pr->PanelVRE        = 999; /* VSync end */
 
-  if(SiS_Pr->UseCustomMode) {
+  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(ModeNo <= 0x13) {
-    	modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
-
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 
-  if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+  if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+     SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
+  } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
   } else {
      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
   }
   temp &= 0x0f;
   if(HwInfo->jChipType < SIS_315H) {
-      /* Translate 300 series LCDRes to 315 series for unified usage */
-      temp = SiS300SeriesLCDRes[temp];
+     /* Translate 300 series LCDRes to 315 series for unified usage */
+     temp = SiS300SeriesLCDRes[temp];
   }
-  SiS_Pr->SiS_LCDResInfo = temp;
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
-	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  if(HwInfo->jChipType == SIS_550) {
+     if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
+     if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
   }
 
-  if((!SiS_Pr->CP_HaveCustomData) || (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_PanelCustom)) {
-     if(SiS_Pr->SiS_LCDResInfo > SiS_Pr->SiS_PanelMax)
-  	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_Panel1024x768;
-  }
+  if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	/* SiS LVDS */
+     if(temp == Panel310_1280x768) {
+        temp = Panel_1280x768_2;
+#ifdef SIS315H
+	if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((myptr[8] | (myptr[9] << 8)) == 798) temp = Panel_1280x768_3;
+	}
+#endif
+     }
+  } 
+
+  SiS_Pr->SiS_LCDResInfo = temp;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
@@ -1509,113 +1531,285 @@
      }
   }
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMin301;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMinLVDS)
+	SiS_Pr->SiS_LCDResInfo = SiS_Pr->SiS_PanelMinLVDS;
+  }
+
+  SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+  SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+
   switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_800x600:   SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1024x768:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1280x1024: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_640x480_3:
+     case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
      case Panel_640x480_2:
-     case Panel_640x480:   SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480; break;
-     case Panel_1024x600:  SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600; break;
-     case Panel_1152x864:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864; break;
-     case Panel_1280x960:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960; break;
-     case Panel_1152x768:  SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1400x1050: SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050; break;
-     case Panel_1280x768:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768; break;
-     case Panel_1600x1200: SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200; break;
-     case Panel_320x480:   SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480; break;
-     case Panel_Custom:    SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
-    			   SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
-			   break;
-     case Panel_Barco1366: SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024; break;
-     case Panel_848x480:   SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480; break;
-     default:		   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768; break;
+     case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+     			    			      SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK28;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK28;
+			    break;
+     case Panel_800x600:    SiS_Pr->PanelXRes =  800; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1056; SiS_Pr->PanelVT   =  628;
+			    SiS_Pr->PanelHRS  =   40; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    4;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK40;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK40;
+			    break;
+     case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   24;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    if(HwInfo->jChipType < SIS_315H) {
+			       SiS_Pr->PanelHRS = 23;
+			       			      SiS_Pr->PanelVRE  =    5;
+			    }
+     			    SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
+     			    break;
+     case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
+     			    break;
+     case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
+     			    SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
+			    SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
+			    SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
+			    /* Data above for TMDS (projector); get from BIOS for LVDS */
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK81_315;
+			    break;
+     case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
+			    SiS_Pr->PanelHRS  =   16; SiS_Pr->PanelHRE  =   64;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x768_3: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  798;
+			    SiS_Pr->PanelHRS   =  64; SiS_Pr->PanelHRE  =  128;
+			    SiS_Pr->PanelVRS   =   3; SiS_Pr->PanelVRE  =    7;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_3;
+			    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_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
+     			    SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
+		 	    if(resinfo == SIS_RI_1280x1024) {
+			       SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
+			       SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
+			    }
+			    break;
+     case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
+     			    SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
+			    SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
+			    SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
+     			    SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
+			    SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
+			    SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
+			    SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
+			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+			    break;
+     case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
+    			    SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+			    SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
+			    SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
+			    if(SiS_Pr->CP_PreferredIndex != -1) {
+			       SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
+    			       SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRE  = SiS_Pr->CP_HSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRS  = SiS_Pr->CP_VSyncStart[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelVRE  = SiS_Pr->CP_VSyncEnd[SiS_Pr->CP_PreferredIndex];
+			       SiS_Pr->PanelHRS -= SiS_Pr->PanelXRes;
+			       SiS_Pr->PanelHRE -= SiS_Pr->PanelHRS;
+			       SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
+			       SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
+			    }
+			    break;
+     case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
+     			    SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+     			    break;
+     case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
+     			    SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+     			    break;
+     default:		    SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
+     			    SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+			    break;
   }
 
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-  if(HwInfo->jChipType < SIS_661) {
-     temp &= ~0xe;
-  } else {
+  SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
+
+  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+
 #ifdef SIS315H
-     if(!(temp & 0x10)) {
-        if(temp & 0x08) temp |= LCDPass11;
+  if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
-     temp &= ~0xe;
      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-        myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-        if(myptr) {
-           if(myptr[2] & 0x01) temp |= LCDDualLink;
-        }
+        if(SiS_Pr->SiS_ROMNew) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	} else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  } else if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
+     if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
+        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	}
+     }
+  }
 #endif
+
+  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+     /* Always center screen on LVDS (if scaling is disabled) */
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        /* Always center screen on SiS LVDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     } else {
+        /* By default, pass 1:1 on SiS TMDS (if scaling is disabled) */
+        SiS_Pr->SiS_LCDInfo |= LCDPass11;
+        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+     }
   }
-  SiS_Pr->SiS_LCDInfo = temp;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24 */
+        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
      }
   }
 
-  if(!(SiS_Pr->UsePanelScaler))        SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-  else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-	   /* For non-standard LCD resolution, we let the panel scale */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e) {
-	      /* We do not scale to 1280x960 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(((HwInfo->jChipType >= SIS_315H) && (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
-	      ((HwInfo->jChipType < SIS_315H)  && (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
-	      /* We do not scale to 1280x768 (B/C bridges only) */
-              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      /* No non-scaling data available for LV bridges */
-	      SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           /* No idea about the timing and zoom factors */
-           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
-	      /* We do not scale to 1280x1024 (all bridges) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-	      /* No idea about the timing and zoom factors (C bridge only) */
-	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-	   }
-	}
-	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-              if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	         SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
-	      }
-	   }
+        switch(SiS_Pr->SiS_LCDResInfo) {
+        case Panel_Custom:
+		/* For non-standard LCD resolution, we let the panel scale */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x720:
+	      	if(SiS_Pr->PanelHT == 1650) {
+		   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		}
+	case Panel_1280x768:	/* TMDS only */
+		/* No idea about the timing and zoom factors */
+           	SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		break;
+	case Panel_1280x960:
+	 	SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+		break;
+	case Panel_1280x1024:
+	        if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+		   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16) {
+	      	      /* We do not scale to 1280x720/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+	           if(((HwInfo->jChipType >= SIS_315H) &&
+		       (ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25)) ||
+	              ((HwInfo->jChipType < SIS_315H)  &&
+		       (ModeNo == 0x55 || ModeNo == 0x5a || ModeNo == 0x5b))) {
+	              /* We do not scale to 1280x768 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		break;
+	case Panel_1400x1050:
+		if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
+	      	   /* We do not scale to 1280x1024 (all bridges) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
+	case Panel_1600x1200:
+		if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	      	   /* No idea about the timing and zoom factors (C bridge only) */
+	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	   	}
+		break;
 	}
      }
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     if(HwInfo->jChipType < SIS_661) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) {
-           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-	   SiS_Pr->SiS_LCDInfo |= LCDPass11;
-	}
-     }
-#endif
-  } else {
 #ifdef SIS300
+  if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
               if(!(ROMAddr[0x235] & 0x02)) {
 	         SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
@@ -1627,34 +1821,59 @@
            SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
 	}
      }
+  }
 #endif
+
+  /* Special cases */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
+
+  if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+     SiS_Pr->SiS_LCDInfo |= LCDPass11;
+  }
+
+  /* (In)validate LCDPass11 flag */
+  if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+     SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
   }
 
-  /* Trumpion: Assume non-expanding */
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION != 0) {
-     SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+  /* Special cases */
+  if( (SiS_Pr->SiS_IF_DEF_FSTN)              ||
+      (SiS_Pr->SiS_IF_DEF_DSTN)              ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelHRS = 999;
+     SiS_Pr->PanelHRE = 999;
   }
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     SiS_Pr->SiS_LCDInfo &= (~LCDPass11);
+  if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+     SiS_Pr->PanelVRS = 999;
+     SiS_Pr->PanelVRE = 999;
   }
 
 #ifdef SIS315H
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	/* Enable 302LV/302ELV dual link mode.
-	 * For 661, this is done above.
-	 */
-        if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)) {
-	   /* (Sets this in SenseLCD; new paneltypes) */
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
-        if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
-	   SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-	}
+     if(!(SiS_Pr->SiS_ROMNew)) {
+        if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	   /* Enable 302LV/302ELV dual link mode.
+	    * For 661, this is done above.
+	    */
+           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
+	      /* (Sets this in SenseLCD; new paneltypes) */
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
+	      SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+	   }
+        }
      }
   }
 #endif
@@ -1662,37 +1881,37 @@
   if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
 
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   if(ModeNo > 0x13) {
-	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                 if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
-                    SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+	   if(ModeNo == 0x12) {
+	      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	         SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
+	   } else if(ModeNo > 0x13) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+	         if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	            if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+		    }
 		 }
-              }
-           }
-        }
-	if(ModeNo == 0x12) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	      SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	      }
 	   }
 	}
      }
 
      if(modeflag & HalfDCLK) {
-        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-           if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-	      if(!(((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (HwInfo->jChipType < SIS_315H)) &&
-	                                      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480))) {
-                 if(ModeNo > 0x13) {
-                    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-                       if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-                       if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-                    }
-                 }
-	      } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-           } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-        } else SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
+	   SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+	} else if(ModeNo > 0x13) {
+           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+           }
+	}
      }
 
   }
@@ -1705,14 +1924,6 @@
      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
   }
 
-  SiS_Pr->SiS_LCDInfo661 = 0;
-  if(SiS_Pr->SiS_SetFlag & LCDVESATiming) SiS_Pr->SiS_LCDInfo661 |= 0x0001;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) SiS_Pr->SiS_LCDInfo661 |= 0x0002;
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11)     SiS_Pr->SiS_LCDInfo661 |= 0x0008;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) SiS_Pr->SiS_LCDInfo661 |= 0x0010;
-  SiS_Pr->SiS_LCDInfo661 |= (SiS_Pr->SiS_LCDInfo & 0xe0);
-  if(SiS_Pr->SiS_LCDInfo & LCDDualLink)   SiS_Pr->SiS_LCDInfo661 |= 0x0100;
-
 #ifdef LINUX_KERNEL
 #ifdef TWDEBUG
   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
@@ -1734,54 +1945,21 @@
 SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx;
-  const USHORT LCDXlat0VCLK[4]    = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat1VCLK[4]   = {VCLK40,       VCLK40,       VCLK40,       VCLK40};
-  const USHORT LVDSXlat4VCLK[4]   = {VCLK28,       VCLK28,       VCLK28,       VCLK28};
-#ifdef SIS300
-  const USHORT LCDXlat1VCLK300[4] = {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LCDXlat2VCLK300[4] = {VCLK108_2_300,VCLK108_2_300,VCLK108_2_300,VCLK108_2_300};
-  const USHORT LVDSXlat2VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-  const USHORT LVDSXlat3VCLK300[4]= {VCLK65_300,   VCLK65_300,   VCLK65_300,   VCLK65_300};
-#endif
-#ifdef SIS315H
-  const USHORT LCDXlat1VCLK310[4] = {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LCDXlat2VCLK310[4] = {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-  const USHORT LVDSXlat2VCLK310[4]= {VCLK65_315,   VCLK65_315,   VCLK65_315,   VCLK65_315};
-  const USHORT LVDSXlat3VCLK310[4]= {VCLK108_2_315,VCLK108_2_315,VCLK108_2_315,VCLK108_2_315};
-#endif
-  USHORT CRT2Index,VCLKIndex=0;
-  USHORT modeflag,resinfo;
-  const UCHAR  *CHTVVCLKPtr = NULL;
-  const USHORT *LCDXlatVCLK1 = NULL;
-  const USHORT *LCDXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK2 = NULL;
-  const USHORT *LVDSXlatVCLK3 = NULL;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-#ifdef SIS315H
-     LCDXlatVCLK1 = LCDXlat1VCLK310;
-     LCDXlatVCLK2 = LCDXlat2VCLK310;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK310;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK310;
-#endif
-  } else {
-#ifdef SIS300
-     LCDXlatVCLK1 = LCDXlat1VCLK300;
-     LCDXlatVCLK2 = LCDXlat2VCLK300;
-     LVDSXlatVCLK2 = LVDSXlat2VCLK300;
-     LVDSXlatVCLK3 = LVDSXlat3VCLK300;
-#endif
-  }
+  USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
+  USHORT modeflag,resinfo,tempbx;
+  const UCHAR *CHTVVCLKPtr = NULL;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+     if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
@@ -1789,50 +1967,18 @@
      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         CRT2Index >>= 6;
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      /*  LCD */
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {      	/*  LCD */
 
            if(HwInfo->jChipType < SIS_315H) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-	         VCLKIndex = LCDXlat0VCLK[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	    	 VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	         VCLKIndex = VCLK81_300;	/* guessed */
-	      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		 VCLKIndex = VCLK108_3_300;
-		 if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_300;
-	      } else {
-	    	 VCLKIndex = LCDXlatVCLK2[CRT2Index];
-	      }
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
 	   } else {
-	      if( (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) ||
-	          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-      	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-		    VCLKIndex = VCLK81_315;  	/* guessed */
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-		    VCLKIndex = VCLK108_2_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    VCLKIndex = VCLK162_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-		    VCLKIndex = VCLK108_3_315;
-		    if(resinfo == SIS_RI_1280x1024) VCLKIndex = VCLK100_315;
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-		    VCLKIndex = LCDXlatVCLK1[CRT2Index];
-	         } else {
-		    VCLKIndex = LCDXlatVCLK2[CRT2Index];
-      	         }
-	      } else {
-                 VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));  /*  Port 3cch */
-         	 VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        	 if(ModeNo > 0x13) {
-          	    VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-        	 }
+	      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;
+		 }
 		 if(ModeNo <= 0x13) {
 		    if(HwInfo->jChipType <= SIS_315PRO) {
 		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
@@ -1848,34 +1994,28 @@
 	      }
 	   }
 
-        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 /*  TV */
+        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                 	/*  TV */
 
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) VCLKIndex = HiTVVCLKDIV2;
-     	      else                                  VCLKIndex = HiTVVCLK;
+              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) 		VCLKIndex = HiTVVCLKDIV2;
+     	      else                                  		VCLKIndex = HiTVVCLK;
               if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-            	 if(modeflag & Charx8Dot) 	    VCLKIndex = HiTVSimuVCLK;
-            	 else 			  	    VCLKIndex = HiTVTextVCLK;
+            	 if(modeflag & Charx8Dot) 	    		VCLKIndex = HiTVSimuVCLK;
+            	 else 			  	    		VCLKIndex = HiTVTextVCLK;
               }
-           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) VCLKIndex = YPbPr750pVCLK - TVCLKBASE_315;
-	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   VCLKIndex = TVVCLKDIV2;
-	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     VCLKIndex = TVVCLKDIV2;
-           else         		            	  VCLKIndex = TVVCLK;
+           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) 	VCLKIndex = YPbPr750pVCLK;
+	   else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)   	VCLKIndex = TVVCLKDIV2;
+	   else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)     	VCLKIndex = TVVCLKDIV2;
+           else         		            	  	VCLKIndex = TVVCLK;
 
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex += TVCLKBASE_300;
-  	   } else {
-	      VCLKIndex += TVCLKBASE_315;
-	   }
+	   if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+  	   else 	                    VCLKIndex += TVCLKBASE_315;
 
-        } else {         					/* VGA2 */
+        } else {         						/* VGA2 */
 
-           VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-          	 VCLKIndex &= 0x3f;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
 		 if( (HwInfo->jChipType == SIS_630) &&
 		     (HwInfo->jChipRevision >= 0x30)) {
 		    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
@@ -1888,12 +2028,9 @@
 
      } else {   /* If not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	   if(HwInfo->jChipType < SIS_315H) {
-              VCLKIndex &= 0x3f;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 		  (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -1906,7 +2043,7 @@
 
      VCLKIndex = CRT2Index;
 
-     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {  /* programming CRT2 */
+     if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
         if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
 
@@ -1942,32 +2079,16 @@
 
         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
-	   VCLKIndex >>= 6;
-     	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480))
-     	      VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480   ||
-	           SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-		   SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)
-	      VCLKIndex = LVDSXlat4VCLK[VCLKIndex];
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-     	      VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)
-              VCLKIndex = LVDSXlatVCLK2[VCLKIndex];
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)
-	      VCLKIndex = VCLK68_315;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	      VCLKIndex = VCLK162_315;
-     	   else
-	      VCLKIndex = LVDSXlatVCLK3[VCLKIndex];
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-	      /* Special Timing: Barco iQ Pro R series */
-	      VCLKIndex = 0x44;
+	   if(HwInfo->jChipType < SIS_315H) {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx300;
+	   } else {
+	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
 	   }
 
+	   /* Special Timing: Barco iQ Pro R series */
+	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
+
+	   /* Special Timing: 848x480 parallel lvds */
 	   if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	      if(HwInfo->jChipType < SIS_315H) {
 		 VCLKIndex = VCLK34_300;
@@ -1980,28 +2101,22 @@
 
         } else {
 
-	   VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-           VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-           if(ModeNo > 0x13) {
-              VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	      if(HwInfo->jChipType < SIS_315H) {
-    	 	 VCLKIndex &= 0x3F;
+	   VCLKIndex = VCLKIndexGEN;
+	   if(HwInfo->jChipType < SIS_315H) {
+              if(ModeNo > 0x13) {
+		 if( (HwInfo->jChipType == SIS_630) &&
+                     (HwInfo->jChipRevision >= 0x30) ) {
+		    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
+	         }
               }
-	      if( (HwInfo->jChipType == SIS_630) &&
-                  (HwInfo->jChipRevision >= 0x30) ) {
-		 if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
-	      }
 	   }
         }
 
      } else {  /* if not programming CRT2 */
 
-        VCLKIndex = (UCHAR)SiS_GetRegByte((USHORT)(SiS_Pr->SiS_P3ca+0x02));
-        VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-        if(ModeNo > 0x13) {
-           VCLKIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-           if(HwInfo->jChipType < SIS_315H) {
-	      VCLKIndex &= 0x3F;
+        VCLKIndex = VCLKIndexGEN;
+	if(HwInfo->jChipType < SIS_315H) {
+           if(ModeNo > 0x13) {
 	      if( (HwInfo->jChipType != SIS_630) &&
 	          (HwInfo->jChipType != SIS_300) ) {
 		 if(VCLKIndex == 0x1b) VCLKIndex = 0x35;
@@ -2045,12 +2160,10 @@
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
   
   /* BIOS does not do this (neither 301 nor LVDS) */
@@ -2168,8 +2281,8 @@
         }
 
         if((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301)) {
-	   if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	      (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)) {
+	   if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)) {
 	      tempah |= 0x80;
 	   }
         } else {
@@ -2196,9 +2309,9 @@
        	   }
         }
 
-	if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  ||
-	   ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) &&
+	if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+	   (SiS_Pr->SiS_LCDResInfo == Panel_1280x960)  ||
+	   ((SiS_Pr->SiS_LCDResInfo == Panel_Custom) &&
 	    (SiS_Pr->CP_MaxX >= 1280) && (SiS_Pr->CP_MaxY >= 960))) {
 	   tempah |= 0x80;
         }
@@ -2336,7 +2449,7 @@
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
 	}
 
-	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here */
+	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here (old BIOS) */
 
 #endif /* SIS315H */
 
@@ -2398,14 +2511,8 @@
 USHORT
 SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
 {
-  USHORT resindex;
-
-  if(ModeNo <= 0x13)
-     resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  else
-     resindex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-
-  return(resindex);
+  if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+  else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
 }
 
 static void
@@ -2415,8 +2522,12 @@
   USHORT xres,yres,modeflag=0,resindex;
 
   if(SiS_Pr->UseCustomMode) {
-     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = SiS_Pr->CHDisplay;
-     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+     xres = SiS_Pr->CHDisplay;
+     if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
+     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+     yres = SiS_Pr->CVDisplay;
+     if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
+     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
      return;
   }
 
@@ -2431,7 +2542,7 @@
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if((!SiS_Pr->SiS_IF_DEF_DSTN) && (!SiS_Pr->SiS_IF_DEF_FSTN)) {
+  if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
 
      if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
         if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
@@ -2442,72 +2553,64 @@
         }
      }
 
-     if(ModeNo > 0x13) {
-  	if(modeflag & HalfDCLK)       xres *= 2;
-  	if(modeflag & DoubleScanMode) yres *= 2;
-     }
+     if(modeflag & HalfDCLK)       xres *= 2;
+     if(modeflag & DoubleScanMode) yres *= 2;
 
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
            if(xres == 720) xres = 640;
-	} else {
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {           /* 301BDH */
-	        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-                   if(xres == 720) xres = 640;
-		}
-		if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	           yres = 400;
-	           if(HwInfo->jChipType >= SIS_315H) {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	           } else {
-	              if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	           }
-	        }
-	   } else {
-	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-	         if(xres == 720) xres = 640;
-	      }
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(yres == 1024) yres = 1056;
-      		    }
-		 } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-		    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-		       /* BIOS bug - does this regardless of scaling */
-      		       if(yres == 400) yres = 405;
-		    }
-      		    if(yres == 350) yres = 360;
-      		    if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-        	       if(yres == 360) yres = 375;
-      		    }
-   	         } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-      		    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        	       if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-          	          if(yres == 350) yres = 357;
-          	          if(yres == 400) yres = 420;
-            	          if(yres == 480) yres = 525;
-        	       }
-      		    }
-    	         }
+	}
+
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   switch(SiS_Pr->SiS_LCDResInfo) {
+	   case Panel_1024x768:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+          	    if(yres == 350) yres = 357;
+          	    if(yres == 400) yres = 420;
+            	    if(yres == 480) yres = 525;
+        	 }
+      	      }
+	      break;
+	   case Panel_1280x1024:
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+		 /* BIOS bug - does this regardless of scaling */
+      		 if(yres == 400) yres = 405;
 	      }
+      	      if(yres == 350) yres = 360;
+      	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+                 if(yres == 360) yres = 375;
+      	      }
+	      break;
+	   case Panel_1600x1200:
+	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        	 if(yres == 1024) yres = 1056;
+      	      }
+	      break;
 	   }
 	}
+
   } else {
-    	if(xres == 720) xres = 640;
-	if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-	   yres = 400;
-	   if(HwInfo->jChipType >= SIS_315H) {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-	   } else {
-	      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-	   }
-	   if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-	      yres = 480;
-	   }
+
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+           if(xres == 720) xres = 640;
 	}
+     } else if(xres == 720) xres = 640;
+
+     if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+	yres = 400;
+        if(HwInfo->jChipType >= SIS_315H) {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+        } else {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+        }
+        if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
+     }
+
   }
   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
@@ -2522,103 +2625,84 @@
 		   USHORT RefreshRateTableIndex, USHORT *ResIndex,
 		   USHORT *DisplayType)
  {
-  USHORT tempbx,modeflag=0;
-  USHORT Flag,CRT2CRTC;
+  USHORT modeflag=0;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
         if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
      }
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
   } else
      return FALSE;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     CRT2CRTC = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  Flag = 1;
-  tempbx = 0;
-  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-        Flag = 0;
-        tempbx = 18;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-      	   tempbx += 2;
-	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
-	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	   }
-	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-	      tempbx = 18;  /* PALM uses NTSC data */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-	      tempbx = 20;  /* PALN uses PAL data  */
-	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
-	   }
-        }
+  (*ResIndex) &= 0x3F;
+
+  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+     (*DisplayType) = 18;
+     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+      	(*DisplayType) += 2;
+	if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	   if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
+	}
+	if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	   (*DisplayType) = 18;  /* PALM uses NTSC data */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	} else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	   (*DisplayType) = 20;  /* PALN uses PAL data  */
+	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+	}
+     }
+  } else {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:   (*DisplayType) = 50; break;
+     case Panel_640x480_2: (*DisplayType) = 52; break;
+     case Panel_640x480_3: (*DisplayType) = 54; break;
+     case Panel_800x600:   (*DisplayType) =  0; break;
+     case Panel_1024x600:  (*DisplayType) = 23; break;
+     case Panel_1024x768:  (*DisplayType) =  4; break;
+     case Panel_1152x768:  (*DisplayType) = 27; break;
+     case Panel_1280x768:  (*DisplayType) = 40; break;
+     case Panel_1280x1024: (*DisplayType) =  8; break;
+     case Panel_1400x1050: (*DisplayType) = 14; break;
+     case Panel_1600x1200: (*DisplayType) = 36; break;
+     default: return FALSE;
      }
-  }
-  if(Flag) {
-     tempbx = SiS_Pr->SiS_LCDResInfo;
-     tempbx -= SiS_Pr->SiS_PanelMinLVDS;
-     if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 6;
-        if(modeflag & HalfDCLK) tempbx += 3;
-     } else {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-           tempbx = 14;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-           tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-           tempbx = 27;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempbx = 36;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-           tempbx = 40;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 2;
-	   if(modeflag & HalfDCLK) tempbx++;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-           tempbx = 54;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-           tempbx = 52;
-	   if(modeflag & HalfDCLK) tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-           tempbx = 50;
-	   if(modeflag & HalfDCLK) tempbx++;
-        }
 
+     if(modeflag & HalfDCLK) (*DisplayType)++;
+
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+     case Panel_640x480_2:
+     case Panel_640x480_3:
+        break;
+     default:
+        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
      }
+
      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 12;
-	if(modeflag & HalfDCLK) tempbx++;
+        (*DisplayType) = 12;
+	if(modeflag & HalfDCLK) (*DisplayType)++;
      }
   }
 
 #if 0
   if(SiS_Pr->SiS_IF_DEF_FSTN) {
      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
-        tempbx = 22;
+        (*DisplayType) = 22;
      }
   }
 #endif
 
-  *ResIndex = CRT2CRTC & 0x3F;
-  *DisplayType = tempbx;
   return TRUE;
 }
 
@@ -2627,8 +2711,7 @@
 	       USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
 	       PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx=0,tempal=0;
-  USHORT Flag,resinfo=0;
+  USHORT tempbx=0,tempal=0,resinfo=0;
 
   if(ModeNo <= 0x13) {
      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2641,55 +2724,30 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-	   tempbx = 15;
-  	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 20;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 21;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 22;
- 	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 23;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 24;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 25;
-#if 0
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 26;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 27;
-	   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 28;
-#endif
- 	} else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)       tempbx = 13;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempbx = 14;
-	      else {
-	         tempbx = 29;
-		 if(ModeNo >= 0x13) {
-	            /* see below */
-	            if(resinfo == SIS_RI_1280x960) tempal = 10;
-	         }
-              }
-	   } else {
-	      tempbx = 29;
-	      if(ModeNo >= 0x13) {
-	         /* 1280x768 and 1280x960 have same CRT2CRTC,
-	          * so we change it here if 1280x960 is chosen
-	          */
-	         if(resinfo == SIS_RI_1280x960) tempal = 10;
+        tempbx = SiS_Pr->SiS_LCDResInfo;
+	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
+
+  	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {  /* Pass 1:1 only (center-screen handled outside) */
+	   tempbx = 100;
+	   if(ModeNo >= 0x13) {
+	      tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+	      if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	         (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	         /* Special for Fujitsu 7911 (VL-17WDX8), others custom */
+	         if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        tempal = 0x08;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) tempal = 0x0f;
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) tempal = 0x10;
 	      }
-   	   }
-	} else {
-      	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_Panel1024x768;
-      	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-              tempbx += 10;
-       	   }
+	   }
 	}
 
 #ifdef SIS315H
 	if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	      tempbx = 50;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         tempbx = 51;
-	      else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx = 52;
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+	         tempbx = 200;
+	         if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+	      }
 	   }
 	}
 #endif
@@ -2697,10 +2755,11 @@
      } else {						  	/* TV */
 
      	if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-           if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode);
+           /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
            tempbx = 2;
            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 13;
+	      tempbx = 13;
+              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
            }
 	} else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 	   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
@@ -2727,9 +2786,14 @@
 	   }
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-	         if(resinfo == SIS_RI_1024x768) {
+	         if(resinfo == SIS_RI_1024x768) tempal = 8;
+	      }
+	      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+		 if((resinfo == SIS_RI_720x576) ||
+	            (resinfo == SIS_RI_768x576)) {
 	            tempal = 8;
 	         }
+		 if(resinfo == SIS_RI_1280x720) tempal = 9;
 	      }
 	   }
 	}
@@ -2740,70 +2804,54 @@
 
   } else {   /* LVDS, 301B-DH (if running on LCD) */
 
-     Flag = 1;
      tempbx = 0;
-     if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-           Flag = 0;
-           tempbx = 10;
-	   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	      tempbx += 2;
-	      if(SiS_Pr->SiS_ModeType > ModeVGA) {
-		 if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
-	      }
-	      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-		 tempbx = 90;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-		 tempbx = 92;
-		 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-	      }
-           }
-        }
-     }
-
-     if(Flag) {
-
-	if(SiS_Pr->SiS_LCDResInfo <= SiS_Pr->SiS_Panel1280x1024) {
-	   tempbx = SiS_Pr->SiS_LCDResInfo - SiS_Pr->SiS_PanelMinLVDS;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 3;
-
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 82;
-	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+        tempbx = 10;
+	if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	   tempbx += 2;
+	   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+	      if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
 	   }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768) {
-	   tempbx = 18;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-	   tempbx = 6;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	   tempbx = 30;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-	   tempbx = 15;
-  	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) {
-	   tempbx = 16;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 2;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   tempbx = 8;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-	   tempbx = 21;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelBarco1366) {
-	   tempbx = 80;
-   	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+	      tempbx = 90;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+	      tempbx = 92;
+	      if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+	   }
+        }
+     } else {
+        switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:   tempbx = 6;  break;
+	case Panel_640x480_2: tempbx = 30; break;
+	case Panel_640x480_3: tempbx = 30; break;
+	case Panel_800x600:   tempbx = 0;  break;
+	case Panel_1024x600:  tempbx = 15; break;
+	case Panel_1024x768:  tempbx = 2;  break;
+	case Panel_1152x768:  tempbx = 17; break;
+	case Panel_1280x768:  tempbx = 18; break;
+	case Panel_1280x1024: tempbx = 4;  break;
+	case Panel_1400x1050: tempbx = 8;  break;
+	case Panel_1600x1200: tempbx = 21; break;
+	case Panel_Barco1366: tempbx = 80; break;
+	}
+
+	switch(SiS_Pr->SiS_LCDResInfo) {
+	case Panel_640x480:
+	case Panel_640x480_2:
+	case Panel_640x480_3:
+	   break;
+	default:
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
 	}
 
-	if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-	   tempbx = 7;
-        }
+	if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
 
-	if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+	if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+	   tempbx = 82;
+	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
+	} else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
 	   tempbx = 84;
 	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx++;
 	}
@@ -2811,45 +2859,17 @@
      }
 
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) tempal = 7;
+        if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) tempal = 7;
   	if(HwInfo->jChipType < SIS_315H) {
 	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
 	}
      }
 
-     *CRT2Index = tempbx;
-     *ResIndex = tempal & 0x1F;
+     (*CRT2Index) = tempbx;
+     (*ResIndex) = tempal & 0x1F;
   }
 }
 
-#ifdef SIS315H
-static void
-SiS_GetCRT2PtrA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-		USHORT RefreshRateTableIndex,USHORT *CRT2Index,
-		USHORT *ResIndex)
-{
-  USHORT tempbx,tempal;
-
-  tempbx = SiS_Pr->SiS_LCDResInfo;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)      tempbx = 4;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempbx = 3;
-  else tempbx -= SiS_Pr->SiS_Panel1024x768;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 5;
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  /* No customs required yet (Clevo, Compaq, etc) */
-
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-#endif
-
 static void
 SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
                    USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
@@ -2910,8 +2930,7 @@
 
 static void
 SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                    USHORT RefreshRateTableIndex,
-		    PSIS_HW_INFO HwInfo)
+                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
    USHORT CRT2Index, ResIndex;
    const SiS_LVDSDataStruct *LVDSData = NULL;
@@ -2929,23 +2948,55 @@
       SiS_Pr->SiS_RY4COE = 0;
    }
 
-   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-      SiS_GetCRT2PtrA(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex);
-
-      switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_1;   break;
-	case  3:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_1;   break;
-	case  4:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_1;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_2;    break;
-      	case  6:  LVDSData = SiS_Pr->SiS_LCDA1280x1024Data_2;   break;
-	case  8:  LVDSData = SiS_Pr->SiS_LCDA1400x1050Data_2;   break;
-	case  9:  LVDSData = SiS_Pr->SiS_LCDA1600x1200Data_2;   break;
-	default:  LVDSData = SiS_Pr->SiS_LCDA1024x768Data_1;    break;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+	    if(SiS_Pr->UseCustomMode) {
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
+	       SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+	    } else {
+	       if(ModeNo < 0x13) {
+	          ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	       } else {
+	          ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+		  /* Special for our 3 types, others custom (works with default) */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  768)) {
+	             if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768)        ResIndex = 0x08;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_2) ResIndex = 0x0f;
+		     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768_3) ResIndex = 0x10;
+	          }
+		  /* Special for 1280x720 TMDS <> LVDS */
+		  if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 1280) &&
+	             (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes ==  720)) {
+		     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		        if(SiS_Pr->PanelHT == 1344) ResIndex = 0x12;
+		     }
+	          }
+	       }
+	       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+               SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+               SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+               SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+	    }
+	 } else {
+     	    SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+	 }
+      } else {
+	 /* This handles custom modes and custom panels */
+	 SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+         SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
+         SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
+	 SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+	 SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
       }
+
+      SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
+
 #endif
 
    } else {
@@ -2956,7 +3007,7 @@
       }
 
       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                     &CRT2Index, &ResIndex, HwInfo);
+                     		&CRT2Index, &ResIndex, HwInfo);
 
       /* 301BDH needs LVDS Data */
       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
@@ -2964,72 +3015,59 @@
       }
 
       switch (CRT2Index) {
-      	case  0:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
-      	case  1:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      	case  2:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
-      	case  3:  LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
-      	case  4:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
-      	case  5:  LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
-	case  6:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
-        case  7:  LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
-	case  8:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
-	case  9:  LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
-      	case 10:  LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
-      	case 11:  LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
-      	case 12:  LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
-      	case 13:  LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
-      	case 14:  LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
-	case 15:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
-	case 16:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
-	case 17:  LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
-	case 18:  LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
-	case 19:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
-	case 20:  LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
-	case 21:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
-	case 22:  LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
-	case 30:  LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
-	case 80:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
-	case 81:  LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
-	case 82:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
-	case 83:  LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
-	case 84:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
-	case 85:  LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
-	case 90:  LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
-      	case 91:  LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
-      	case 92:  LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
-      	case 93:  LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
-	case 99:  LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
-	default:  LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-      }
-   }
-
-   SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
-   SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
-   SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
-   SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
-
-   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-      if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-         SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-      }
+      	 case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
+	 case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
+      	 case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+	 case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
+      	 case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
+      	 case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
+	 case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
+         case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
+	 case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
+	 case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
+      	 case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
+      	 case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
+      	 case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
+      	 case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
+      	 case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
+	 case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
+	 case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
+	 case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
+	 case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
+	 case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
+	 case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
+	 case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
+	 case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
+	 case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
+	 case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
+	 case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
+	 case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
+	 case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
+	 case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
+	 case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
+	 case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
+      	 case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
+      	 case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
+      	 case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
+	 case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;	       break;  /* Super Overscan */
+	 default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+      }
+
+      SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+      SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+      SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
+      SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
 
-   } else {
-
-      if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
+      if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-               if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-	          SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-                  SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-
-	 	  if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-		     if(ResIndex < 0x08) {
-		        SiS_Pr->SiS_HDE = 1280;
-                        SiS_Pr->SiS_VDE = 1024;
-		     }
-		  }
+            if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+	       SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+               SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+	       if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+		  if(ResIndex < 0x08) {
+		     SiS_Pr->SiS_HDE = 1280;
+                     SiS_Pr->SiS_VDE = 1024;
+                  }
                }
             }
          }
@@ -3051,14 +3089,12 @@
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
   
   SiS_Pr->SiS_NewFlickerMode = 0;
@@ -3086,6 +3122,7 @@
      } else {
 
         SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -3094,19 +3131,20 @@
                     &CRT2Index,&ResIndex,HwInfo);
 
      switch(CRT2Index) {
-       case  2:  TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
-       case  3:  TVPtr = SiS_Pr->SiS_ExtPALData;    break;
-       case  4:  TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
-       case  5:  TVPtr = SiS_Pr->SiS_Ext525iData;   break;
-       case  6:  TVPtr = SiS_Pr->SiS_Ext525pData;   break;
-       case  7:  TVPtr = SiS_Pr->SiS_Ext750pData;   break;
-       case  8:  TVPtr = SiS_Pr->SiS_StPALData;     break;
-       case  9:  TVPtr = SiS_Pr->SiS_StNTSCData;    break;
-       case 10:  TVPtr = SiS_Pr->SiS_St525iData;    break;
-       case 11:  TVPtr = SiS_Pr->SiS_St525pData;    break;
-       case 12:  TVPtr = SiS_Pr->SiS_St750pData;    break;
-       case 14:  TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
-       default:  TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
+        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
+        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
+        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
+        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
+        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
+        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
+        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
+        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
+        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
+        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
+        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
+        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
+        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
      }
 
      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3123,9 +3161,11 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-        if(resinfo == SIS_RI_1024x768)  SiS_Pr->SiS_NewFlickerMode = 0x40;
-        if(resinfo == SIS_RI_1280x1024) SiS_Pr->SiS_NewFlickerMode = 0x40;
-        if(resinfo == SIS_RI_1280x720)  SiS_Pr->SiS_NewFlickerMode = 0x40;
+        if((resinfo == SIS_RI_1024x768)  ||
+           (resinfo == SIS_RI_1280x1024) ||
+           (resinfo == SIS_RI_1280x720)) {
+	   SiS_Pr->SiS_NewFlickerMode = 0x40;
+	}
 
         if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
 
@@ -3135,10 +3175,12 @@
            if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
               SiS_Pr->SiS_HT = StHiTVHT;
               SiS_Pr->SiS_VT = StHiTVVT;
+#if 0
               if(!(modeflag & Charx8Dot)) {
                  SiS_Pr->SiS_HT = StHiTextTVHT;
                  SiS_Pr->SiS_VT = StHiTextTVVT;
               }
+#endif
            }
         }
 
@@ -3183,10 +3225,11 @@
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
+     SiS_Pr->SiS_RVBHCMAX  = 1;
+     SiS_Pr->SiS_RVBHCFACT = 1;
+
      if(SiS_Pr->UseCustomMode) {
 
-        SiS_Pr->SiS_RVBHCMAX  = 1;
-        SiS_Pr->SiS_RVBHCFACT = 1;
         SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
         SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
         SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
@@ -3196,58 +3239,68 @@
 
      } else {
 
-        SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                      &CRT2Index,&ResIndex,HwInfo);
+        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+
+           SiS_Pr->SiS_VGAHT     = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VGAVT     = SiS_Pr->PanelVT;
+           SiS_Pr->SiS_HT        = SiS_Pr->PanelHT;
+           SiS_Pr->SiS_VT        = SiS_Pr->PanelVT;
+
+	} else {
+
+           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+                          &CRT2Index,&ResIndex,HwInfo);
 
-        switch(CRT2Index) {
-         case  0: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;        break; /* VESA Timing */
-         case  1: LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;       break; /* VESA Timing */
-         case  5: LCDPtr = SiS_Pr->SiS_StLCD1024x768Data;         break; /* Obviously unused */
-         case  6: LCDPtr = SiS_Pr->SiS_StLCD1280x1024Data;        break; /* Obviously unused */
-         case 10: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;        break; /* Non-VESA Timing */
-         case 11: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;       break; /* Non-VESA Timing */
-         case 13: LCDPtr = SiS_Pr->SiS_NoScaleData1024x768;       break; /* Non-expanding */
-         case 14: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;      break; /* Non-expanding */
-         case 15: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;           break; /* 1280x960 */
-         case 20: LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;       break; /* VESA Timing */
-         case 21: LCDPtr = SiS_Pr->SiS_NoScaleData1400x1050;      break; /* Non-expanding (let panel scale) */
-         case 22: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;        break; /* Non-VESA Timing (let panel scale) */
-         case 23: LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;       break; /* VESA Timing */
-         case 24: LCDPtr = SiS_Pr->SiS_NoScaleData1600x1200;      break; /* Non-expanding */
-         case 25: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;        break; /* Non-VESA Timing */
-         case 26: LCDPtr = SiS_Pr->SiS_ExtLCD1280x768Data;        break; /* VESA Timing */
-         case 27: LCDPtr = SiS_Pr->SiS_NoScaleData1280x768;       break; /* Non-expanding */
-         case 28: LCDPtr = SiS_Pr->SiS_StLCD1280x768Data;         break; /* Non-VESA Timing */
-         case 29: LCDPtr = SiS_Pr->SiS_NoScaleData;	          break; /* Generic no-scale data */
-#ifdef SIS315H
-	 case 50: LCDPtr = (SiS_LCDDataStruct *)SiS310_ExtCompaq1280x1024Data;	break;
-	 case 51: LCDPtr = SiS_Pr->SiS_NoScaleData1280x1024;			break;
-	 case 52: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;	  		break;
-#endif
-         default: LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;	  break;
-        }
-
-        SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
-        SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
-        SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
-        SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
-        SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
-        SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+           switch(CRT2Index) {
+	      case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+	      case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
+	      case Panel_1280x720      :
+	      case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
+	      case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
+              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
+	      case Panel_1280x768_3    :
+	      case Panel_1280x768_3+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x768_3Data;    break;
+	      case Panel_1280x800      :
+	      case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
+	      case Panel_1280x960      :
+	      case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
+              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
+              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
+              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
+              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
+              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
+	      case Panel_1680x1050     :
+	      case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
+	      case 100		       : LCDPtr = SiS_Pr->SiS_NoScaleData;	    break;
+#ifdef SIS315H
+	      case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
+	      case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+#endif
+              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+           }
 
 #ifdef TWDEBUG
-        xf86DrvMsg(0, X_INFO,
-    	    "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+           xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
 #endif
 
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-           tempax = 1024;
+           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
+           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
+           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
+           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
+           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+
+        }
+
+	tempax = SiS_Pr->PanelXRes;
+        tempbx = SiS_Pr->PanelYRes;
+
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
            if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
               if(HwInfo->jChipType < SIS_315H) {
                  if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
                  else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-                 else                               tempbx = 768;
-              } else {
-                 tempbx = 768;
               }
            } else {
               if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
@@ -3256,43 +3309,27 @@
               else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
               else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
               else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-              else                               tempbx = 768;
            }
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-           tempax = 1280;
-           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
-           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
-           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
-           else                               tempbx = 1024;
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960) {
-           tempax = 1280;
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
            if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
            else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
            else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
-           else                                tempbx = 960;
-	} else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) &&
-	          (HwInfo->jChipType >= SIS_661)) {
-	   tempax = 1400;
-	   tempbx = 1050;
-	   if(SiS_Pr->SiS_VGAVDE == 1024) {
-	      tempax = 1280;
-	      tempbx = 1024;
-	   }
-        } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-           tempax = 1600;
-	   tempbx = 1200;
-	   if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+	   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
               if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
               else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
            }
-        } else {
-	   tempax = SiS_Pr->PanelXRes;
-           tempbx = SiS_Pr->PanelYRes;
-	}
+        }
+
         if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
            tempax = SiS_Pr->SiS_VGAHDE;
            tempbx = SiS_Pr->SiS_VGAVDE;
         }
+
         SiS_Pr->SiS_HDE = tempax;
         SiS_Pr->SiS_VDE = tempbx;
      }
@@ -3306,31 +3343,15 @@
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-           SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-        } else {
-
-	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-
-	      /* Need LVDS Data for LCD on 301B-DH */
-	      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-	   } else {
-
-	      SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
-           }
-
-        }
-
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
      } else {
-
-     	SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-
+	if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+	   /* Need LVDS Data for LCD on 301B-DH */
+	   SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+	} else {
+	   SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        }
      }
 
   } else {
@@ -3341,7 +3362,7 @@
 }
 
 /*********************************************/
-/*            GET LVDS DES DATA              */
+/*         GET LVDS DES (SKEW) DATA          */
 /*********************************************/
 
 static void
@@ -3349,106 +3370,55 @@
                   USHORT RefreshRateTableIndex, USHORT *PanelIndex,
 		  USHORT *ResIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal,modeflag;
+  USHORT modeflag;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
-  tempbx = 0;
+  (*ResIndex) &= 0x1F;
+  (*PanelIndex) = 0;
+
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        tempbx = 50;
-        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) tempbx += 2;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
+        (*PanelIndex) = 50;
+        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
         /* Nothing special needed for SOverscan    */
-        /*     PALM uses NTSC data, PALN uses PAL data */
+        /* PALM uses NTSC data, PALN uses PAL data */
      }
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     tempbx = SiS_Pr->SiS_LCDTypeInfo;
+     *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
      if(HwInfo->jChipType >= SIS_661) {
         /* As long as we don's use the BIOS tables, we
 	 * need to convert the TypeInfo as for 315 series
 	 */
-        tempbx = SiS_Pr->SiS_LCDResInfo - 1;
+        (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
      }
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 16;
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        tempbx = 32;
-        if(modeflag & HalfDCLK) tempbx++;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        (*PanelIndex) += 16;
+        if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+           (*PanelIndex) = 32;
+           if(modeflag & HalfDCLK) (*PanelIndex)++;
+	}
      }
   }
 
   if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-        tempal = 0x07;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
+        (*ResIndex) = 7;
         if(HwInfo->jChipType < SIS_315H) {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) tempal++;
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
         }
      }
   }
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
-}
-
-#ifdef SIS315H
-static void
-SiS_GetLVDSDesPtrA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex, USHORT *PanelIndex, USHORT *ResIndex,
-		   PSIS_HW_INFO HwInfo)
-{
-  USHORT tempbx=0,tempal;
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      tempbx = 2;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempbx = 3;
-  else tempbx = SiS_Pr->SiS_LCDResInfo - 2;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)  tempbx += 4;
-
-  if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-	   tempbx = 80;
-	   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-	}
-     }
-  }
-  if((SiS_Pr->SiS_CustomT == CUT_UNIWILL1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_UNIWILL10242)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 82;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-	tempbx = 84;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-	tempbx = 86;
-	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-     }
-  }
-
-  if(ModeNo <= 0x13)
-     tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  *PanelIndex = tempbx;
-  *ResIndex = tempal & 0x1F;
 }
-#endif
 
 static void
 SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
@@ -3458,39 +3428,43 @@
   USHORT PanelIndex,ResIndex;
   const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
 
-  if((SiS_Pr->UseCustomMode) ||
-     (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     SiS_Pr->SiS_LCDHDES = 0;
-     SiS_Pr->SiS_LCDVDES = 0;
+  SiS_Pr->SiS_LCDHDES = 0;
+  SiS_Pr->SiS_LCDVDES = 0;
+
+  if( (SiS_Pr->UseCustomMode) 		         ||
+      (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
+      ((SiS_Pr->SiS_VBType & VB_SISVB) &&
+       (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
+       (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
      return;
   }
 
   if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-     SiS_GetLVDSDesPtrA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                        &PanelIndex, &ResIndex, HwInfo);
-
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;  /* --- expanding --- */
-     	case  1: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_1;  break;
-	case  2: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_1;  break;
-	case  3: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_1;  break;
-     	case  4: PanelDesPtr = SiS_Pr->LVDS1024x768Des_2;   break;  /* --- non expanding --- */
-     	case  5: PanelDesPtr = SiS_Pr->LVDS1280x1024Des_2;  break;
-	case  6: PanelDesPtr = SiS_Pr->LVDS1400x1050Des_2;  break;
-	case  7: PanelDesPtr = SiS_Pr->LVDS1600x1200Des_2;  break;
-	case 80: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_1;   break;  /*  custom  */
-	case 81: PanelDesPtr = (SiS_LVDSDesStruct *)Clevo1024x768Des_2;   break;
-	case 82: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_1; break;
-	case 83: PanelDesPtr = (SiS_LVDSDesStruct *)Uniwill1024x768Des_2; break;
-	case 84: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_1; break;
-	case 85: PanelDesPtr = (SiS_LVDSDesStruct *)Compaq1280x1024Des_2; break;
-	case 86: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_1;    break;  /*  custom  */
-	case 87: PanelDesPtr = (SiS_LVDSDesStruct *)Asus1024x768Des_2;    break;
-	default: PanelDesPtr = SiS_Pr->LVDS1024x768Des_1;   break;
+     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        /* non-pass 1:1 only, see above */
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+	}
+     }
+     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+        switch(SiS_Pr->SiS_CustomT) {
+        case CUT_UNIWILL1024:
+        case CUT_UNIWILL10242:
+        case CUT_CLEVO1400:
+	   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	   break;
+	}
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+	   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
+	      SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+	   }
+	}
      }
 #endif
 
@@ -3499,87 +3473,68 @@
      SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
                        &PanelIndex, &ResIndex, HwInfo);
 
-     switch (PanelIndex)
-     {
-     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;   break;   /* ---  */
-     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;   break;
-     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;   break;
-     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;   break;
-     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;   break;
-     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;   break;
-     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;   break;
-     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;   break;
-     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;   break;
-     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;   break;
-     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;   break;
-     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;   break;
-     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;   break;
-     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;   break;
-     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;   break;
-     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;   break;
-     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;   break;    /* --- */
-     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;   break;
-     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;   break;
-     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;   break;
-     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;   break;
-     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;   break;
-     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;   break;
-     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;   break;
-     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;   break;
-     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;   break;
-     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;   break;
-     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;   break;
-     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;   break;
-     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;   break;
-     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;   break;
-     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;   break;
-	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;   break;    /* pass 1:1 */
-	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;   break;
-     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData;   break; /* TV */
-     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData;   break;
-     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;    break;
-     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;    break;
-	default:
-		 if(HwInfo->jChipType < SIS_315H)
-		    PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;
-		 else
-		    PanelDesPtr = SiS_Pr->SiS_PanelType01_1;
-		 break;
-     }
-  }
-  SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
-  SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
-
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD){
-     if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        if(ModeNo <= 0x13) {
-           modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	   if(!(modeflag & HalfDCLK)) {
-	      SiS_Pr->SiS_LCDHDES = 632;
-	   }
-        }
-     } else {
-        if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024) {
-              if(SiS_Pr->SiS_LCDResInfo >= SiS_Pr->SiS_Panel1024x768) {
-                 if(ModeNo <= 0x13) {
-	            modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-	            if(HwInfo->jChipType < SIS_315H) {
-	               if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
-	            } else {
-	               if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)
-	                  SiS_Pr->SiS_LCDHDES = 480;
-                       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                  SiS_Pr->SiS_LCDHDES = 804;
-		       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                  SiS_Pr->SiS_LCDHDES = 704;
-                       if(!(modeflag & HalfDCLK)) {
-                          SiS_Pr->SiS_LCDHDES = 320;
-	                  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)
-	                     SiS_Pr->SiS_LCDHDES = 632;
-		          else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)
-	                     SiS_Pr->SiS_LCDHDES = 542;
-                       }
+     switch(PanelIndex) {
+     	case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
+     	case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
+     	case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
+     	case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
+     	case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
+     	case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
+     	case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
+     	case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
+     	case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
+     	case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
+     	case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
+     	case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
+     	case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
+     	case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
+     	case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
+     	case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
+     	case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
+     	case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
+     	case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
+     	case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
+     	case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
+     	case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
+     	case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
+     	case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
+     	case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
+     	case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
+     	case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
+     	case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
+     	case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
+     	case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
+     	case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
+     	case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
+	case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
+	case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
+     	case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
+     	case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
+     	case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
+     	case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
+	default: return;
+     }
+
+     SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+     SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+     if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+        if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+	   if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
+        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+	         if(HwInfo->jChipType < SIS_315H) {
+	            if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
+	         } else {
+	            if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
+                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+		    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
+                    if(!(modeflag & HalfDCLK)) {
+                       SiS_Pr->SiS_LCDHDES = 320;
+	               if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+		       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
                     }
                  }
               }
@@ -3590,18 +3545,6 @@
 }
 
 /*********************************************/
-/*          SET CRT2 AUTO-THRESHOLD          */
-/*********************************************/
-
-#ifdef SIS315H
-static void
-SiS_CRT2AutoThreshold(SiS_Private *SiS_Pr)
-{
-  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
-}
-#endif
-
-/*********************************************/
 /*           DISABLE VIDEO BRIDGE            */
 /*********************************************/
 
@@ -3617,7 +3560,6 @@
 #endif
   USHORT temp=0;
 
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
@@ -3651,7 +3593,7 @@
 	   } else {
 
 	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	         SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	      }
 	      if(SiS_Is301B(SiS_Pr)) {
@@ -3668,7 +3610,7 @@
 	      if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	          (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
 	         SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	      }
 	   }
 
@@ -3686,7 +3628,7 @@
 #ifdef SET_EMI
 	         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 		    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-	               SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		    }
 		 }
 #endif
@@ -3916,10 +3858,12 @@
       } else {     /* ============ For 301 ================ */
 
         if(HwInfo->jChipType < SIS_315H) {
+#ifdef SIS300
            if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	      SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	   }
+#endif
 	}
 
         SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
@@ -3937,12 +3881,14 @@
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 	} else {
+#ifdef SIS300
             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
 	    if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	        (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
 		SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+		SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	    }
+#endif
 	}
 
       }
@@ -3962,7 +3908,7 @@
 	      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
 	   }
 	   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	      SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	   }
 	} else {
@@ -3973,7 +3919,7 @@
 		    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
 		       SiS_DisplayOff(SiS_Pr);
 	            }
-	            SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
                  }
               }
@@ -3992,7 +3938,7 @@
 	if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
 	    (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
 	   SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+	   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	}
 
 #endif  /* SIS300 */
@@ -4032,7 +3978,7 @@
 	}
 
 	if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x08);
+	   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	   SiS_PanelDelay(SiS_Pr, HwInfo, 3);
 	}
 
@@ -4101,14 +4047,14 @@
 	   if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	      if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
 	 	 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		 SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xFB,0x04);
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
 	      }
 	   }
         }
 
 #endif  /* SIS315H */
 
-    }  /* 310 series */
+    }  /* 315 series */
 
   }  /* LVDS */
 
@@ -4176,7 +4122,7 @@
 	    if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
 	       (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
 	       /* This is only for LCD output on 301B-DH via LVDS */
-	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	       if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
 	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	       }
@@ -4195,7 +4141,7 @@
 		           SiS_PanelDelay(SiS_Pr, HwInfo, 1);
                        }
 		       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                       SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,0xF7,0x00);
+                       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
                    }
 	       }
             } else {
@@ -4229,29 +4175,18 @@
 	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
 		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		  }
 #endif
 	       }
 
                if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
 	          tempah = 0x10;
-		  if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		     (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
-		        if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
-			   tempah = 0x08;
-			} else {
-			   tempah = 0x18;
-			}
-		     }
-		     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-		  } else {
-	             if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	                tempah = 0x08;
-                     }
-		     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+		  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) &&
@@ -4300,13 +4235,11 @@
 
 	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
 	          tempah = 0x10;
-		  if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {
-		     tempah = 0x18;
-		     if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) == 0x0c) {
-		        tempah = 0x08;
-		     }
+		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+		     else 			       tempah = 0x08;
 		  }
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
 	       }
 	       
 	    }
@@ -4316,10 +4249,7 @@
 	       if(SiS_BridgeInSlave(SiS_Pr)) {
                   tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
                   if(!(tempah & SetCRT2ToRAMDAC)) {
-		     if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		        (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		        if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04)) temp |= 0x20;
-		     } else temp |= 0x20;
+		     if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
 		  }
                }
                SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
@@ -4385,7 +4315,7 @@
 	       if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
 	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		  }
 #endif
 	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
@@ -4630,7 +4560,7 @@
 
        if(HwInfo->jChipType < SIS_315H) {
           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	  }
        }
@@ -4663,7 +4593,7 @@
        if(HwInfo->jChipType < SIS_315H) {
           if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
 	  }
        }
 
@@ -4681,13 +4611,13 @@
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	  }
-          SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	  if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	  }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_DisplayOn(SiS_Pr);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
@@ -4712,7 +4642,7 @@
         	   SiS_PanelDelay(SiS_Pr, HwInfo, 1);
 	        }
 	        SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
              }
 	  }
        }
@@ -4725,12 +4655,12 @@
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 	  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xFB);
+	     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
 	     SiS_PanelDelay(SiS_Pr, HwInfo, 0);
           }
        }
 
-       SiS_EnableCRT2(SiS_Pr);
+       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
 
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
@@ -4804,7 +4734,7 @@
        	  if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
 	     if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 		SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x11,0xF7);
+		SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
 	     }
 	  }
        }
@@ -4821,33 +4751,31 @@
 /*         SET PART 1 REGISTER GROUP         */
 /*********************************************/
 
-/********** Set CRT2 OFFSET / PITCH **********/
+/* Set CRT2 OFFSET / PITCH */
 static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr,USHORT ModeNo,
-                  USHORT ModeIdIndex ,USHORT RefreshRateTableIndex,
-	          PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
+	          USHORT RRTI, PSIS_HW_INFO HwInfo)
 {
   USHORT offset;
   UCHAR temp;
 
   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
 
-  offset = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                         HwInfo);
+  offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) offset >>= 1;
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+     (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+     offset >>= 1;
+  }
 
-  temp = (UCHAR)(offset & 0xFF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,temp);
-  temp = (UCHAR)(offset >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
   temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
   if(offset % 8) temp++;
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
 }
 
-/************* Set CRT2 Sync *************/
+/* Set CRT2 sync and PanelLink mode */
 static void
 SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
                 PSIS_HW_INFO HwInfo)
@@ -4869,23 +4797,27 @@
      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
         tempah = SiS_Pr->SiS_LCDInfo;
      } else tempah = infoflag >> 8;
-
      tempah &= 0xC0;
-
      tempah |= 0x20;
      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
         if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
            (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-	   tempah |= 0xc0;
+	   tempah |= 0xf0;
+        }
+	if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+            (SiS_Pr->SiS_IF_DEF_DSTN) ||
+            (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+            (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+           tempah |= 0x30;
         }
      }
-
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(HwInfo->jChipType >= SIS_315H) {
            tempah >>= 3;
+	   tempah &= 0x18;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+	   /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
         } else {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
         }
@@ -4902,19 +4834,21 @@
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {			/* 630 - 301B(-DH) */
 
 	   tempah = infoflag >> 8;
+	   tempbl = 0;
            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	         tempah = SiS_Pr->SiS_LCDInfo;
+		 tempbl = (tempah >> 6) & 0x03;
               }
            }
            tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
- 	   tempah &= 0x3f;
-  	   tempah |= tempbl;
+  	   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	   }
 
         } else {							/* 630 - 301 */
 
@@ -4932,43 +4866,72 @@
 
 #ifdef SIS315H  /* ------- 315 series ------ */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - 30xLV */
+        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	  		/* 315 - LVDS */
 
-	   if(((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) ||
-	      ((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050))) {
+	   tempbl = 0;
+	   if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+	      (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
 	      tempah = infoflag >> 8;
+	      if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+	        tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+	      }
+	   } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
+	             (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+       	      tempah = infoflag >> 8;
+	      tempbl = 0x03;
 	   } else {
               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+	      tempbl = (tempah >> 6) & 0x03;
+	      tempbl |= 0x08;
+	      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+	      }
+	   }
 
-        } else {							/* 315 - 301, 301B */
+        } else {							/* 315 - TMDS */
 
-           tempah = infoflag >> 8;
+           tempah = tempbl = infoflag >> 8;
 	   if(!SiS_Pr->UseCustomMode) {
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      tempbl = 0;
+	      if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	         if(ModeNo <= 0x13) {
+	            tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  	         }
+	      }
+	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	         if(SiS_Pr->SiS_LCDInfo & LCDSync) {
 	            tempah = SiS_Pr->SiS_LCDInfo;
+		    tempbl = (tempah >> 6) & 0x03;
 	         }
 	      }
 	   }
 	   tempah &= 0xC0;
-
            tempah |= 0x20;
            if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-
-	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* TEST, imitate BIOS bug */
-	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-	         tempah |= 0xc0;
+	   if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	      /* Imitate BIOS bug */
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
+	   }
+	   if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+	      tempah >>= 3;
+	      tempah &= 0x18;
+	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+	   } else {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+		 }
 	      }
 	   }
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
 
         }
 #endif  /* SIS315H */
@@ -4976,7 +4939,7 @@
    }
 }
 
-/******** Set CRT2 FIFO on 300/630/730 *******/
+/* Set CRT2 FIFO on 300/630/730 */
 #ifdef SIS300
 static void
 SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
@@ -5031,7 +4994,7 @@
 
   if(!SiS_Pr->CRT1UsesCustomMode) {
 
-     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 	/* get CRT1 ModeNo */
+     CRT1ModeNo = SiS_Pr->SiS_CRT1Mode;                                 /* get CRT1 ModeNo */
      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
      SiS_Pr->SiS_SelectCRT2Rate = 0;
@@ -5040,7 +5003,7 @@
      if(CRT1ModeNo >= 0x13) {
         index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
         index &= 0x3F;
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;				/* Get VCLK */
+        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;			/* Get VCLK */
 
 	colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex); 	/* Get colordepth */
         colorth >>= 1;
@@ -5050,9 +5013,9 @@
   } else {
 
      CRT1ModeNo = 0xfe;
-     VCLK = SiS_Pr->CSRClock_CRT1;						/* Get VCLK */
+     VCLK = SiS_Pr->CSRClock_CRT1;					/* Get VCLK */
      data2 = (SiS_Pr->CModeFlag_CRT1 & ModeInfoFlag) - 2;
-     switch(data2) {								/* Get color depth */
+     switch(data2) {							/* Get color depth */
         case 0 : colorth = 1; break;
         case 1 : colorth = 1; break;
         case 2 : colorth = 2; break;
@@ -5199,10 +5162,10 @@
 
        index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
                                refreshratetableindex,HwInfo);
-       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                         	/* Get VCLK  */
+       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
 
        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-          if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+          if(SiS_Pr->SiS_UseROM) {
 	     if(ROMAddr[0x220] & 0x01) {
                 VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
 	     }
@@ -5212,11 +5175,11 @@
     } else {
 
        CRT2ModeNo = 0xfe;
-       VCLK = SiS_Pr->CSRClock;							/* Get VCLK */
+       VCLK = SiS_Pr->CSRClock;					/* Get VCLK */
 
     }
 
-    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex);   	/* Get colordepth */
+    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
     colorth >>= 1;
     if(!colorth) colorth++;
 
@@ -5235,8 +5198,8 @@
     if(HwInfo->jChipType == SIS_300) {
        if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
        else             temp = (temp & (~0x1F)) | 0x16;
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-       		temp = (temp & (~0x1F)) | 0x13;
+       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       	  temp = (temp & (~0x1F)) | 0x13;
        }
     } else {
        if( ( (HwInfo->jChipType == SIS_630) ||
@@ -5266,280 +5229,21 @@
 }
 #endif
 
-/**** Set CRT2 FIFO on 315/330 series ****/
-#ifdef SIS315H
-static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr)
-{
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3F,0x04);
-}
-#endif
-
-/*************** Set LCD-A ***************/
+/* Set CRT2 FIFO on 315/330 series */
 #ifdef SIS315H
 static void
-SiS_SetGroup1_LCDA(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT modeflag,resinfo;
-  USHORT push2,tempax,tempbx,tempcx,temp;
-  ULONG tempeax=0,tempebx,tempecx,tempvcfact;
-
-  /* This is not supported with LCDA */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
-
-  if(IS_SIS330) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* Xabre 1.01.03 */
-  } else if(IS_SIS740) {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 740/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 740/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);			/* 740/301LV, 301BDH */
-     }
-  } else {
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {					/* 650/LVDS */
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);      	/* 650/LVDS */
-	SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);			/* 650/LVDS 1.10.07 */
-     } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);			/* 650/30xLv 1.10.6s */
-     }
-  }
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
-
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  temp = (tempax & 0x0007);                        		/* BPLHDESKEW[2:0]   */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                         /* Part1_1Ah  */
-  temp = (tempax >> 3) & 0x00FF;                               	/* BPLHDESKEW[10:3]  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                         /* Part1_16h  */
-
-  tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-     tempbx = SiS_Pr->PanelXRes;
-  }
-
-  tempax += tempbx;	                                    	/* HDE + HSKEW = lcdhdee  */
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
-
-  temp = tempax;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(temp & 0x07) temp += 8;
-  }
-  temp >>= 3;                                        		/* BPLHDEE  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                        	/* Part1_17h  */
-
-  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;     	            	/* (HT-HDE) / 4  */
-
-  /* 650/30xLV 1.10.6s, 740/LVDS */
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x28;
- 	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  tempcx = 0x18;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x30;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x40;
-	else                                                          tempcx = 0x30;
-     }
-  }
-
-  tempcx += tempax;  	                                  	/* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
-
-  temp = (tempcx >> 3) & 0x00FF;				/* BPLHRS */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                 		/* Part1_14h  */
-
-  temp += 10;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   temp += 6;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      temp++;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	         temp += 7;
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		    temp -= 10;
-		 }
-	      }
-	   }
-	}
-     }
-  }
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x07) << 5);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                         /* Part1_15h  */
-
-  if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-     tempax = SiS_Pr->PanelYRes;
-  } else {
-     tempax = SiS_Pr->SiS_VGAVDE;
-  }
-
-  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  push2 = tempbx;
-
-  tempcx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 2;
-
-  if( ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) ||
-      ((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 1;
-   	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 3;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 1;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 1;
-	else                                                           tempcx = 0x0057;
-     }
-  }
-
-  tempbx += tempcx;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     tempbx++;                                                	/* BPLVRS  */
-  }
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                             /* Part1_18h  */
-
-  tempcx >>= 3;
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 3;
-   	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 5;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 2;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 2;
-	}
-     }
-  }
-  tempcx += tempbx;
-  tempcx++;                                                	/* BPLVRE  */
-  temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     temp |= 0xC0;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp); 		/* Part1_19h  */
-  } else {
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)   temp |= 0x40;
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     /* Don't check Part1Port,0x00 -> is not being set if LCDA! */
-     /* We check SR06 instead here: */
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10) temp |= 0x80;
-     }
-  } else {
-     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x07,temp);            /* Part1_1Ah */
-
-  tempbx = push2;                                      		/* BPLVDEE */
-
-  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* NPLVDES */
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-        if(resinfo == SIS_RI_800x600) tempcx++;
-     }
-  }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     tempbx = tempcx = SiS_Pr->SiS_VGAVDE;
-     tempbx--;
-  }
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempcx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);                          /* Part1_1Dh */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);                          /* Part1_1Ch  */
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);                          /* Part1_1Bh  */
-
-  tempeax = SiS_Pr->SiS_VGAVDE << 18;
-  tempebx = SiS_Pr->SiS_VDE;
-  temp = (USHORT)(tempeax % tempebx);
-  tempeax = tempeax / tempebx;
-  if(temp) tempeax++;
-  tempvcfact = tempeax;
-
-  temp = (USHORT)(tempeax & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
-
-  temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
-
-  temp = (USHORT)((tempeax & 0x00030000) >> 16);
-  if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
-
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
-     temp = (USHORT)(tempeax & 0x00FF);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
-     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
-     temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
-     temp = 0;
-     if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
-  }
-
-  tempeax = SiS_Pr->SiS_VGAHDE << 16;
-  tempebx = SiS_Pr->SiS_HDE;
-  temp = tempeax % tempebx;
-  tempeax /= tempebx;
-  if(temp) tempeax++;
-  if(tempebx == SiS_Pr->SiS_VGAHDE) tempeax = 0xFFFF;
-  tempecx = tempeax;
-  tempeax = ((SiS_Pr->SiS_VGAHDE << 16) / tempecx) - 1;
-  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
-  temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);                          /* Part1_1Fh  */
-
-  tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-  tempbx = (USHORT)(tempeax & 0x0FFFF);
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
-
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)  tempbx = 1;
-
-  temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempecx >> 8) & 0x07);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);                         /* Part1_20h */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);                         /* Part1_21h */
-
-  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
-  if(modeflag & HalfDCLK) tempecx >>= 1;
-  temp = (USHORT)((tempecx & 0x0000FF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);                         /* Part1_22h */
-
-  temp = (USHORT)(tempecx & 0x000000FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
+  USHORT temp;
 
-  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+  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;
   }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,temp);
 }
-#endif  /* SIS 315 */
+#endif
 
 static USHORT
 SiS_GetVGAHT2(SiS_Private *SiS_Pr)
@@ -5552,31 +5256,37 @@
   return((USHORT) tempax);
 }
 
-/******* Set Part 1 / SiS bridge *********/
+/* Set Part 1 / SiS bridge slave mode */
 static void
 SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
                   PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
 {
   USHORT  push1,push2;
   USHORT  tempax,tempbx,tempcx,temp;
-  USHORT  resinfo,modeflag;
+  USHORT  resinfo,modeflag,xres=0;
   unsigned char p1_7, p1_8;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+     xres = SiS_Pr->CHDisplay;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   /* The following is only done if bridge is in slave mode: */
 
+  if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
+     if(xres >= 1600) {
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
+     }
+  }
+
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
@@ -5637,21 +5347,20 @@
      } else {
         if(!(modeflag & HalfDCLK)) {
            temp -= 4;
-           if((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x960) &&
-	      (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200)) {
+           if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
+	      (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
               if(SiS_Pr->SiS_VGAHDE >= 800) {
                  temp -= 7;
 	         if(HwInfo->jChipType < SIS_315H) {
-	            /* 650/301LV(x) does not do this, 630/301B, 300/301LV do */
                     if(SiS_Pr->SiS_ModeType == ModeEGA) {
                        if(SiS_Pr->SiS_VGAVDE == 1024) {
                           temp += 15;
-                          if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+                          if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
 		  	     temp += 7;
                        }
                     }
 	         }
-		 if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+		 if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
                     if(SiS_Pr->SiS_VGAHDE >= 1280) {
                        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
 		    }
@@ -5715,6 +5424,10 @@
 	      p1_7 = 0xab;
 	   }
 	}
+     } else {
+        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+	   if(modeflag & HalfDCLK) p1_7 = 0x30;
+	}
      }
   }
 
@@ -5737,7 +5450,7 @@
   else if(tempbx == 525) tempbx = 480;
   push2 = tempbx;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
       	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
            if     (tempbx == 350) tempbx += 5;
            else if(tempbx == 480) tempbx += 5;
@@ -5783,7 +5496,7 @@
 	tempbx += (tempax << 1);
      }
   } else if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1400x1050) {
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
 	tempbx += (tempax << 1);
      }
   }
@@ -5860,521 +5573,465 @@
      }
   }
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                	/* 0x1A SR0E */
+
+  temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
 }
 
-/*********** Set Part 1 / LVDS ***********/
+/* Setup panel link
+ * This is used for LVDS, LCDA and Chrontel TV output
+ * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
+ */
 static void
 SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
- 		   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  USHORT modeflag, resinfo;
-  USHORT push1, push2, tempax, tempbx, tempcx, temp;
+  USHORT modeflag,resinfo;
+  USHORT push2,tempax,tempbx,tempcx,temp;
+  ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+  BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
+#ifdef SIS300
+  USHORT crt2crtc;
+#endif
 #ifdef SIS315H
   USHORT pushcx;
 #endif
-  ULONG  tempeax=0, tempebx, tempecx, tempvcfact=0;
-
-  /* This is not supported on LVDS */
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
-  if(SiS_Pr->UseCustomMode) return;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
+#ifdef SIS300
+     crt2crtc = 0;
+#endif
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS300
+     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+#endif
   }
 
-  /* Set up Panel Link */
+  /* is lvds if really LVDS, or SiS 301B-DH with external LVDS transmitter */
+  if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+     ((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     islvds = TRUE;
+  }
 
-  /* 1. Horizontal setup */
+  /* is really sis if sis bridge, but not 301B-DH */
+  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+     issis = TRUE;
+  }
 
-  tempax = SiS_Pr->SiS_LCDHDES;
-
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) &&
-         (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
-  	   tempax -= 8;
+  if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+        chkdclkfirst = TRUE;
      }
   }
 
-  tempcx = SiS_Pr->SiS_HT;    				  /* Horiz. Total */
-
-  tempbx = SiS_Pr->SiS_HDE;                               /* Horiz. Display End */
-
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-     SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-     tempbx >>= 1;
-  }
-
-  if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   tempbx = SiS_Pr->PanelXRes;
-	} else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   tempbx = SiS_Pr->PanelXRes;
-	   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-	      tempbx = 800;
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         tempbx = 1024;
+#ifdef SIS315H
+  if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+     if(IS_SIS330) {
+        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+     } else if(IS_SIS740) {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x03);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
+        }
+     } else {
+        if(islvds) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xfb,0x04);
+	   SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
+        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
+	         (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+	         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
 	      }
 	   }
         }
      }
   }
-  tempcx = (tempcx - tempbx) >> 2;		 /* HT-HDE / 4 */
-
-  push1 = tempax;
-
-  tempax += tempbx;
-
-  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
+#endif
 
-  push2 = tempax;
+  /* Horizontal */
 
-  if((!SiS_Pr->SiS_IF_DEF_FSTN) &&
-     (!SiS_Pr->SiS_IF_DEF_DSTN) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-     	      if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)        tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)  tempcx = 0x0018;
-     	      else if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768) ) {
-	  	   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0017;  /* A901; sometimes 0x0018; */
-		      } else {
-		         tempcx = 0x0017;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0018;
-#endif
-		      }
-		   } else {
-		      tempcx = 0x0018;
-		   }
-	      }
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0028;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0030;
-	      else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0040;
+  tempax = SiS_Pr->SiS_LCDHDES;
+  if(islvds) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
+           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+  	      tempax -= 8;
 	   }
-        }
+	}
      }
   }
 
-  tempcx += tempax;                              /* lcdhrs  */
-  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
+  temp = (tempax & 0x0007);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);			/* BPLHDESKEW[2:0]   */
+  temp = (tempax >> 3) & 0x00FF;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);			/* BPLHDESKEW[10:3]  */
 
-  tempax = tempcx >> 3;                          /* BPLHRS */
-  temp = tempax & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);		 /* Part1_14h; Panel Link Horizontal Retrace Start  */
-
-  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-     temp = (tempax & 0x00FF) + 2;
-  } else {
-     temp = (tempax & 0x00FF) + 10;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if((!SiS_Pr->SiS_IF_DEF_DSTN) &&
-	   (!SiS_Pr->SiS_IF_DEF_FSTN) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-	   (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-	   (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      temp += 6;
-              if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	         temp++;
-	         if(HwInfo->jChipType >= SIS_315H) {
-	            if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1024x768) {
-	               temp += 7;
-		       if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1600x1200) {
-		          temp -= 0x14;
-			  if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x768) {
-			     temp -= 10;
-			  }
-		       }
-	            }
-	         }
-	      }
-           }
-        }
+  tempbx = SiS_Pr->SiS_HDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
+        tempbx >>= 1;
+     }
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        tempbx = SiS_Pr->PanelXRes;
      }
   }
 
-  temp &= 0x1F;
-  temp |= ((tempcx & 0x0007) << 5);
-#if 0
-  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       /* WRONG? BIOS loads cl, not ah */
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);    	 /* Part1_15h; Panel Link Horizontal Retrace End/Skew */
+  tempax += tempbx;
+  if(tempax >= SiS_Pr->SiS_HT) tempax -= SiS_Pr->SiS_HT;
 
-  tempbx = push2;
-  tempcx = push1;                                /* lcdhdes  */
+  temp = tempax;
+  if(temp & 0x07) temp += 8;
+  temp >>= 3;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);			/* BPLHDEE  */
 
-  temp = (tempcx & 0x0007);                      /* BPLHDESKEW  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);   	 /* Part1_1Ah; Panel Link Vertical Retrace Start (2:0) */
+  tempcx = (SiS_Pr->SiS_HT - tempbx) >> 2;
 
-  tempcx >>= 3;                                  /* BPLHDES */
-  temp = (tempcx & 0x00FF);
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--; */
-  }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);    	 /* Part1_16h; Panel Link Horizontal Display Enable Start  */
-
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     if(tempbx & 0x07) tempbx += 8;
-  }
-  tempbx >>= 3;                                  /* BPLHDEE  */
-  temp = tempbx & 0x00FF;
-#if 0 /* Not 550 FSTN */
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(ModeNo == 0x5b) temp--;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelHRS != 999) tempcx = SiS_Pr->PanelHRS;
+     }
   }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);   	 /* Part1_17h; Panel Link Horizontal Display Enable End  */
 
-  /* 2. Vertical setup */
+  tempcx += tempax;
+  if(tempcx >= SiS_Pr->SiS_HT) tempcx -= SiS_Pr->SiS_HT;
 
-  if(HwInfo->jChipType < SIS_315H) {
-     tempcx = SiS_Pr->SiS_VGAVT;
-     tempbx = SiS_Pr->SiS_VGAVDE;
-     if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) && (SiS_Pr->SiS_CustomT != CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-           if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	      tempbx = SiS_Pr->PanelYRes;
+  temp = (tempcx >> 3) & 0x00FF;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+           switch(ModeNo) {
+           case 0x04:
+           case 0x05:
+           case 0x0d: temp = 0x56; break;
+           case 0x10: temp = 0x60; break;
+           case 0x13: temp = 0x5f; break;
+           case 0x40:
+           case 0x41:
+           case 0x4f:
+           case 0x43:
+           case 0x44:
+           case 0x62:
+           case 0x56:
+           case 0x53:
+           case 0x5d:
+           case 0x5e: temp = 0x54; break;
            }
-	}
+        }
      }
-     tempcx -= tempbx;
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);			/* BPLHRS */
 
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     temp += 2;
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        temp += 8;
+        if(SiS_Pr->PanelHRE != 999) {
+           temp = tempcx + SiS_Pr->PanelHRE;
+	   if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
+	   temp >>= 3;
+        }
+     }
   } else {
-
-     tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;           /* VGAVT-VGAVDE  */
-
+     temp += 10;
   }
 
-  tempbx = SiS_Pr->SiS_LCDVDES;	   		 	 	/* VGAVDES  */
-  push1 = tempbx;
+  temp &= 0x1F;
+  temp |= ((tempcx & 0x07) << 5);
+#if 0
+  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;       		/* WRONG? BIOS loads cl, not ah */
+#endif
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);			/* BPLHRE */
 
-  tempax = SiS_Pr->SiS_VGAVDE;
+  /* Vertical */
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-           tempax = 600;
-	   if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel800x600) {
-	      tempax = 768;
-	   }
-	}
-     } else if( (SiS_Pr->SiS_IF_DEF_TRUMPION == 0)   &&
-                (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-                ((SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) ||
-	         (SiS_Pr->SiS_IF_DEF_FSTN) ||
-	         (SiS_Pr->SiS_IF_DEF_DSTN)) ) {
+  tempax = SiS_Pr->SiS_VGAVDE;
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	tempax = SiS_Pr->PanelYRes;
      }
   }
 
-  tempbx += tempax;
+  tempbx = SiS_Pr->SiS_LCDVDES + tempax;
   if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
 
   push2 = tempbx;
 
-  tempcx >>= 1;
-
-  if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
-     (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) {
-	tempcx = 0x0017;
-     } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
-	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0003;
-  	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)) tempcx = 0x0003;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0001;
-           else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0001;
-	   else 							  tempcx = 0x0057;
-        } else  {
-     	   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)         tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0001;
-     	   else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) ||
-	           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)) {
-		   if(HwInfo->jChipType < SIS_315H) {
-		      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		         tempcx = 0x0002;   /* A901; sometimes 0x0003; */
-		      } else {
-			 tempcx = 0x0002;
-#ifdef TWNEWPANEL
-			 tempcx = 0x0003;
-#endif
-		      }
-		   } else tempcx = 0x0003;
-           }
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)  tempcx = 0x0003;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) tempcx = 0x0001;
-     	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) tempcx = 0x0001;
-	   else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) tempcx = 0x0001;
-     	   else 							 tempcx = 0x0057;
+  tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
+  if(HwInfo->jChipType < SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+	   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
 	}
      }
   }
+  if(islvds) tempcx >>= 1;
+  else       tempcx >>= 2;
 
-  tempbx += tempcx;			 	/* BPLVRS  */
-
-  if((HwInfo->jChipType < SIS_315H) ||
-     (SiS_Pr->SiS_IF_DEF_FSTN) ||
-     (SiS_Pr->SiS_IF_DEF_DSTN)) {
-     tempbx++;
+  if( (SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+      (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) 		    &&
+      (SiS_Pr->PanelVRS != 999) ) {
+     tempcx = SiS_Pr->PanelVRS;
+     tempbx += tempcx;
+     if(issis) tempbx++;
+  } else {
+     tempbx += tempcx;
+     if(HwInfo->jChipType < SIS_315H) tempbx++;
+     else if(issis)                   tempbx++;
   }
 
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;	/* BPLVRS  */
 
   temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);       	 /* Part1_18h; Panel Link Vertical Retrace Start  */
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x10) temp = 0xa9;
+     }
+  }
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
 
   tempcx >>= 3;
+  tempcx++;
 
-  if((!(SiS_Pr->SiS_LCDInfo & LCDPass11)) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-     (SiS_Pr->SiS_CustomT != CUT_BARCO1024) &&
-     (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if( (HwInfo->jChipType < SIS_315H) &&
-            (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) )     tempcx = 0x0001;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2)  tempcx = 0x0002;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600)    tempcx = 0x0003;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600)   tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1152x768)   tempcx = 0x0005;
-	else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x768)   tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)  tempcx = 0x0005;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)  tempcx = 0x0002;
-        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)  tempcx = 0x0011;
-        else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  {
-     		if(HwInfo->jChipType < SIS_315H) {
-		   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		      tempcx = 0x0004;   /* A901; Other BIOS sets 0x0005; */
-		   } else {
-		      tempcx = 0x0004;
-#ifdef TWNEWPANEL
-		      tempcx = 0x0005;
-#endif
-		   }
-		} else {
-		   tempcx = 0x0005;
-		}
-        }
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+        if(SiS_Pr->PanelVRE != 999) tempcx = SiS_Pr->PanelVRE;
      }
   }
 
-  tempcx = tempcx + tempbx + 1;                  /* BPLVRE  */
+  tempcx += tempbx;
   temp = tempcx & 0x000F;
-  if(SiS_Pr->SiS_IF_DEF_FSTN ||
-     SiS_Pr->SiS_IF_DEF_DSTN ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-     (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848)) {
-     temp |= 0x30;
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xf0,temp); /* Part1_19h; Panel Link Vertical Retrace End (3:0); Misc.  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0xF0,temp);	/* BPLVRE  */
 
-  temp = ((tempbx & 0x0700) >> 8) << 3;          /* BPLDESKEW =0 */
+  temp = ((tempbx >> 8) & 0x07) << 3;
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
      if(SiS_Pr->SiS_HDE != 640) {
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)   temp |= 0x40;
+        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
      }
-  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE)  temp |= 0x40;
-  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)           temp |= 0x40;
-  if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     if(HwInfo->jChipType >= SIS_315H) {
-        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
-           temp |= 0x80;
+  } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
+  if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
+  tempbx = 0x87;
+  if((HwInfo->jChipType >= SIS_315H) ||
+     (HwInfo->jChipRevision >= 0x30)) {
+     tempbx = 0x07;
+     if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
+     }
+     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+     if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+	   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
+	} else {
+	   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) temp |= 0x80;
+	}
+     }
+  }
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
+
+  tempbx = push2;                                      		/* BPLVDEE */
+
+  tempcx = SiS_Pr->SiS_LCDVDES;                        		/* BPLVDES */
+
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_640x480:
+        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+        tempcx = SiS_Pr->SiS_VGAVDE;
+	break;
+     case Panel_800x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_800x600) tempcx++;
         }
-     } else {
-	if( (HwInfo->jChipType == SIS_630) ||
-	    (HwInfo->jChipType == SIS_730) ) {
-	   if(HwInfo->jChipRevision >= 0x30) {
-	      temp |= 0x80;
+	break;
+     case Panel_1024x600:
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+           if(resinfo == SIS_RI_1024x600) tempcx++;
+           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	      if(resinfo == SIS_RI_800x600) tempcx++;
 	   }
-	}
+        }
+	break;
+     case Panel_1024x768:
+        if(HwInfo->jChipType < SIS_315H) {
+           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+              if(resinfo == SIS_RI_1024x768) tempcx++;
+	   }
+        }
+	break;
      }
   }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,0x87,temp);  /* Part1_1Ah; Panel Link Control Signal (7:3); Vertical Retrace Start (2:0) */
 
-  if (HwInfo->jChipType < SIS_315H) {
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempcx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
+  /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
 
-#ifdef SIS300      /* 300 series */
+  /* Vertical scaling */
 
-        tempeax = SiS_Pr->SiS_VGAVDE << 6;
-        temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-        tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
-        if(temp != 0) tempeax++;
-        tempebx = tempeax;                         /* BPLVCFACT  */
+  if(HwInfo->jChipType < SIS_315H) {
 
-  	if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
-	   tempebx = 0x003F;
-	}
+#ifdef SIS300      /* 300 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 6;
+     temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
+     tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+     if(temp) tempeax++;
 
-  	temp = (USHORT)(tempebx & 0x00FF);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      /* Part1_1Eh; Panel Link Vertical Scaling Factor */
+     if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
 
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);      	/* BPLVCFACT */
+     tempvcfact = temp;
 #endif /* SIS300 */
 
   } else {
 
 #ifdef SIS315H  /* 315 series */
+     tempeax = SiS_Pr->SiS_VGAVDE << 18;
+     tempebx = SiS_Pr->SiS_VDE;
+     temp = (tempeax % tempebx);
+     tempeax = tempeax / tempebx;
+     if(temp) tempeax++;
+     tempvcfact = tempeax;
 
-        if(HwInfo->jChipType == SIS_740) {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x03);
-        } else {
-	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,0x23);
-	}
-
-	tempeax = SiS_Pr->SiS_VGAVDE << 18;
-    	temp = (USHORT)(tempeax % (ULONG)SiS_Pr->SiS_VDE);
-    	tempeax = tempeax / SiS_Pr->SiS_VDE;
-    	if(temp != 0) tempeax++;
-    	tempebx = tempeax;                         /* BPLVCFACT  */
-        tempvcfact = tempeax;
-    	temp = (USHORT)(tempebx & 0x00FF);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);      /* Part1_37h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00FF00) >> 8);
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);      /* Part1_36h; Panel Link Vertical Scaling Factor */
-    	temp = (USHORT)((tempebx & 0x00030000) >> 16);
-	temp &= 0x03;
-    	if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);      /* Part1_35h; Panel Link Vertical Scaling Factor */
-
-#endif /* SIS315H */
-
-  }
-
-  tempbx = push2;                                  /* BPLVDEE  */
-  tempcx = push1;
-
-  push1 = temp;
-
-  if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-   	if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
-		if(HwInfo->jChipType < SIS_315H) {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x600) {
-      				if(resinfo == SIS_RI_1024x600) tempcx++;
-				if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-					if(resinfo == SIS_RI_800x600) tempcx++;
-		    		}
-			} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-				if(resinfo == SIS_RI_1024x768) tempcx++; /* Doesnt make sense anyway... */
-			} else  if(resinfo == SIS_RI_1024x768) tempcx++;
-		} else {
-			if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel800x600) {
-      				if(resinfo == SIS_RI_800x600)  tempcx++;
-			}
-		}
-	}
-  }
+     temp = (USHORT)(tempeax & 0x00FF);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
+     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
+     temp = (USHORT)((tempeax & 0x00030000) >> 16);
+     if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        tempcx = SiS_Pr->SiS_VGAVDE;
-        tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+        temp = (USHORT)(tempeax & 0x00FF);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
+        temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
+        temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
+        temp = 0;
+        if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x30,0xf3,temp);
      }
-  }
-
-  temp = ((tempbx & 0x0700) >> 8) << 3;
-  temp |= ((tempcx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);     	/* Part1_1Dh; Vertical Display Overflow; Control Signal */
-
-  temp = tempbx & 0x00FF;
-  /* if(SiS_Pr->SiS_IF_DEF_FSTN) temp++;  */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,temp);      	/* Part1_1Ch; Panel Link Vertical Display Enable End  */
+#endif
 
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,temp);      	/* Part1_1Bh; Panel Link Vertical Display Enable Start  */
+  }
 
-  /* 3. Additional horizontal setup (scaling, etc) */
+  /* Horizontal scaling */
 
-  tempecx = SiS_Pr->SiS_VGAHDE;
-  if(HwInfo->jChipType >= SIS_315H) {
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempecx >>= 1;
-     }
+  tempeax = SiS_Pr->SiS_VGAHDE;		/* 1f = ( (VGAHDE * 65536) / ( (VGAHDE * 65536) / HDE ) ) - 1*/
+  if(chkdclkfirst) {
+     if(modeflag & HalfDCLK) tempeax >>= 1;
   }
-  tempebx = SiS_Pr->SiS_HDE;
-  if(tempecx == tempebx) tempeax = 0xFFFF;
-  else {
-     tempeax = tempecx;
-     tempeax <<= 16;
-     temp = (USHORT)(tempeax % tempebx);
-     tempeax = tempeax / tempebx;
+  tempebx = tempeax << 16;
+  if(SiS_Pr->SiS_HDE == tempeax) {
+     tempecx = 0xFFFF;
+  } else {
+     tempecx = tempebx / SiS_Pr->SiS_HDE;
      if(HwInfo->jChipType >= SIS_315H) {
-        if(temp) tempeax++;
+        if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
      }
   }
-  tempecx = tempeax;
 
   if(HwInfo->jChipType >= SIS_315H) {
-     tempeax = SiS_Pr->SiS_VGAHDE;
-     if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        if(modeflag & HalfDCLK) tempeax >>= 1;
-     }
-     tempeax <<= 16;
-     tempeax = (tempeax / tempecx) - 1;
+     tempeax = (tempebx / tempecx) - 1;
   } else {
      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
   }
-  tempecx <<= 16;
-  tempecx |= (tempeax & 0xFFFF);
+  tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);  	 /* Part1_1Fh; Panel Link DDA Operational Number in each horiz. line */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
 
-  tempbx = SiS_Pr->SiS_VDE;
   if(HwInfo->jChipType >= SIS_315H) {
      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   } else {
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     tempbx = push1 & 0x3f;
+     tempbx = tempvcfact & 0x3f;
      if(tempbx == 0) tempbx = 64;
      tempeax /= tempbx;
-     tempbx = (USHORT)(tempeax & 0x0FFFF);
+     tempbx = (USHORT)(tempeax & 0xFFFF);
   }
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) tempbx--;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) tempbx = 1;
-     else if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480)  tempbx = 1;
+     else if(SiS_Pr->SiS_LCDResInfo != Panel_640x480)             tempbx = 1;
   }
 
-  temp = ((tempbx & 0xFF00) >> 8) << 3;
-  temp |= (USHORT)((tempecx & 0x0700) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);  	/* Part1_20h; Overflow register */
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,temp);  	/* Part1_21h; Panel Link Vertical Accumulator Register */
+  temp = ((tempbx >> 8) & 0x07) << 3;
+  temp = temp | ((tempecx >> 8) & 0x07);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
 
-  tempecx >>= 16;                               /* BPLHCFACT  */
-  if((HwInfo->jChipType < SIS_315H) || (SiS_Pr->SiS_IF_DEF_FSTN) || (SiS_Pr->SiS_IF_DEF_DSTN)) {
+  tempecx >>= 16;   	                                  	/* BPLHCFACT  */
+  if(!chkdclkfirst) {
      if(modeflag & HalfDCLK) tempecx >>= 1;
   }
   temp = (USHORT)((tempecx & 0xFF00) >> 8);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);     	/* Part1_22h; Panel Link Horizontal Scaling Factor High */
-
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
   temp = (USHORT)(tempecx & 0x00FF);
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);         /* Part1_22h; Panel Link Horizontal Scaling Factor Low */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
 
-  /* 630/301B and 630/LVDS do something for 640x480 panels here */
+#ifdef SIS315H
+  if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	}
+     } else {
+        if(islvds) {
+           if(HwInfo->jChipType == SIS_740) {
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
+           } else {
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
+           }
+        }
+     }
+  }
+#endif
+
+#ifdef SIS300
+  if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+     int i;
+     UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
+     UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+     UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
+     for(i=0; i<5; i++) {
+        SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+     }
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(ModeNo == 0x13) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
+	   }
+	} else if(ModeNo == 0x10) {
+	   for(i=0; i<4; i++) {
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_1[0]);
+	      SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode10_2[0]);
+	   }
+	}
+     }
+     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
+  }
+#endif
 
 #ifdef SIS315H
   if(SiS_Pr->SiS_IF_DEF_FSTN || SiS_Pr->SiS_IF_DEF_DSTN) {
@@ -6384,10 +6041,10 @@
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x28,0x87);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x007,0x03);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
      tempax = SiS_Pr->SiS_HDE;                       		/* Blps = lcdhdee(lcdhdes+HDE) + 64 */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax += 64;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
@@ -6401,8 +6058,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
 
      tempax = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 1;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
@@ -6410,8 +6067,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
 
      tempeax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempeax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
      tempeax <<= 2;                       			/* BDxFIFOSTOP = (HDE*4)/128 */
      tempebx = 128;
      temp = (USHORT)(tempeax % tempebx);
@@ -6425,8 +6082,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
 
      tempax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempax >>= 4;                        			/* BDxWadroff = HDE*4/8/8 */
      pushcx = tempax;
      temp = tempax & 0x00FF;
@@ -6435,8 +6092,8 @@
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
 
      tempax = SiS_Pr->SiS_VDE;                             	/* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
      tempeax = (tempax * pushcx);
      tempebx = 0x00100000 + tempeax;
      temp = (USHORT)tempebx & 0x000000FF;
@@ -6478,496 +6135,422 @@
      }
   }
 #endif  /* SIS315H */
-
 }
 
-/************** Set Part 1 ***************/
+/* Set Part 1 */
 static void
 SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
-  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+  UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT  temp=0, tempax=0, tempbx=0, tempcx=0;
-  USHORT  pushbx=0, CRT1Index=0;
+  USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
   USHORT  tempbl=0;
 #endif
-  USHORT  modeflag, resinfo=0;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     return;
+  }
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-	modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-    	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
+     CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-
-#ifdef SIS315H
-     SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-     SiS_SetGroup1_LCDA(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
-#endif
-
-  } else {
+  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-     if( (HwInfo->jChipType >= SIS_315H) &&
+  if( ! ((HwInfo->jChipType >= SIS_315H) &&
          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
-	 (SiS_Pr->SiS_VBInfo & SetInSlaveMode) ) {
+         (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
 
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
-
-     } else {
-
-        SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex,
-      		          RefreshRateTableIndex, HwInfo);
-
-        if (HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 #ifdef SIS300
-    	      SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+  	SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
 #endif
-        } else {
+     } else {
 #ifdef SIS315H
-              SiS_SetCRT2FIFO_310(SiS_Pr);
+        SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
 #endif
-	}
-
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+     }
 
-	/* 1. Horizontal setup */
+     /* 1. Horizontal setup */
 
-        if(HwInfo->jChipType < SIS_315H ) {
+     if(HwInfo->jChipType < SIS_315H ) {
 
 #ifdef SIS300   /* ------------- 300 series --------------*/
 
-    		temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   			/* BTVGA2HT 0x08,0x09 */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                   /* CRT2 Horizontal Total */
+    	temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;   		  /* BTVGA2HT 0x08,0x09 */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-    		temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
-    		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);          /* CRT2 Horizontal Total Overflow [7:4] */
+    	temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-    		temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                       /* BTVGA2HDEE 0x0A,0x0C */
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                   /* CRT2 Horizontal Display Enable End */
+    	temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
+    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
-    		pushbx = SiS_Pr->SiS_VGAHDE + 12;                               /* bx  BTVGA@HRS 0x0B,0x0C */
-    		tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
-    		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;
-		   }
+	pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
+    	tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+    	tempbx = pushbx + tempcx;
+    	tempcx <<= 1;
+    	tempcx += tempbx;
 
-      		   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-		      unsigned char cr4, cr14, cr5, cr15;
-		      if(SiS_Pr->UseCustomMode) {
-		         cr4  = SiS_Pr->CCRT1CRTC[4];
-			 cr14 = SiS_Pr->CCRT1CRTC[14];
-			 cr5  = SiS_Pr->CCRT1CRTC[5];
-			 cr15 = SiS_Pr->CCRT1CRTC[15];
-		      } else {
-		         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-			 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-			 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-			 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-		      }
-        	      tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
-        	      tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
-      		   }
-
-    		   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) && (resinfo == SIS_RI_1024x768)){
-        	      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)){
-      			 tempbx = 1040;
-      			 tempcx = 1042;
-      		      }
-    		   }
-	        }
+    	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 */
 
-    		temp = tempbx & 0x00FF;
-    		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                   /* CRT2 Horizontal Retrace Start */
 #endif /* SIS300 */
 
- 	} else {
+     } else {
 
 #ifdef SIS315H  /* ------------------- 315/330 series --------------- */
 
-	        tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HT 0x08,0x09 */
-		if(modeflag & HalfDCLK) {
-		    if(SiS_Pr->SiS_VBType & VB_SISVB) {
-		       tempcx >>= 1;
-		    } else {
-		       tempax = SiS_Pr->SiS_VGAHDE >> 1;
-		       tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
-		       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-			  tempcx = SiS_Pr->SiS_HT - tempax;
-		       }
-		    }
-		}
-		tempcx--;
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HT 0x08,0x09 */
+	if(modeflag & HalfDCLK) {
+	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	      tempcx >>= 1;
+	   } else {
+	      tempax = SiS_Pr->SiS_VGAHDE >> 1;
+	      tempcx = SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE + tempax;
+	      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+	         tempcx = SiS_Pr->SiS_HT - tempax;
+	      }
+	   }
+	}
+	tempcx--;
 
-		temp = tempcx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);                  /* CRT2 Horizontal Total */
+	temp = tempcx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-		temp = ((tempcx & 0xff00) >> 8) << 4;
-		SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);         /* CRT2 Horizontal Total Overflow [7:4] */
+	temp = ((tempcx & 0xff00) >> 8) << 4;
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-		tempcx = SiS_Pr->SiS_VGAHT;				       /* BTVGA2HDEE 0x0A,0x0C */
-		tempbx = SiS_Pr->SiS_VGAHDE;
-		tempcx -= tempbx;
-		tempcx >>= 2;
-		if(modeflag & HalfDCLK) {
-		   tempbx >>= 1;
-		   tempcx >>= 1;
-		}
-		tempbx += 16;
+	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
+	tempbx = SiS_Pr->SiS_VGAHDE;
+	tempcx -= tempbx;
+	tempcx >>= 2;
+	if(modeflag & HalfDCLK) {
+	   tempbx >>= 1;
+	   tempcx >>= 1;
+	}
+	tempbx += 16;
 
-		temp = tempbx & 0xff;
-		SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                  /* CRT2 Horizontal Display Enable End */
+	temp = tempbx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
-		pushbx = tempbx;
-		tempcx >>= 1;
-		tempbx += tempcx;
-		tempcx += tempbx;
-
-		if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-		   if(HwInfo->jChipType >= SIS_661) {
-		      if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ||
-		         (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-			 if(resinfo == SIS_RI_1280x1024) {
-		            tempcx = 0x30;
-			 } else if(resinfo == SIS_RI_1600x1200) {
-			    tempcx = 0xff;
-			 }
-		      }
-		   }
+	pushbx = tempbx;
+	tempcx >>= 1;
+	tempbx += tempcx;
+	tempcx += tempbx;
 
-		   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_VBType & VB_SISVB) {
 
-             	   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 = 1042;
-      	     	   }
+	   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;
+		 } else if(resinfo == SIS_RI_1600x1200) {
+		    tempcx = 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;
+	   }
 
-		temp = tempbx & 0xff;
-	 	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);                 /* CRT2 Horizontal Retrace Start */
-#endif  /* SIS315H */
+           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;
+           }
 
-     	}  /* 315/330 series */
+	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	      tempbx = 1040;
+      	      tempcx = 1044;   /* HWCursor bug! */
+      	   }
 
-  	/* The following is done for all bridge/chip types/series */
+        }
 
-  	tempax = tempbx & 0xFF00;
-  	tempbx = pushbx;
-  	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-  	tempax |= (tempbx & 0xFF00);
-  	temp = (tempax & 0xFF00) >> 8;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                        /* Overflow */
+	temp = tempbx & 0xff;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
+#endif  /* SIS315H */
 
-  	temp = tempcx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                        /* CRT2 Horizontal Retrace End */
+     }  /* 315/330 series */
 
-  	/* 2. Vertical setup */
+     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);
 
-  	tempcx = SiS_Pr->SiS_VGAVT - 1;
-  	temp = tempcx & 0x00FF;
+     temp = tempcx & 0x00FF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                 /* CRT2 Horizontal Retrace End */
 
-	if(HwInfo->jChipType < SIS_661) {
-           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-	      if(HwInfo->jChipType < SIS_315H) {
-	         if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-	            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
-	               temp--;
-	            }
-                 }
-	      } else {
- 	         temp--;
+     /* 2. Vertical setup */
+
+     tempcx = SiS_Pr->SiS_VGAVT - 1;
+     temp = tempcx & 0x00FF;
+
+     if(HwInfo->jChipType < SIS_661) {
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	   if(HwInfo->jChipType < SIS_315H) {
+	      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+	         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
+	            temp--;
+	         }
               }
-           } else if(HwInfo->jChipType >= SIS_315H) {
-	      temp--;
-	   }
+	   } else {
+ 	      temp--;
+           }
+        } else if(HwInfo->jChipType >= SIS_315H) {
+	   temp--;
 	}
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                        /* CRT2 Vertical Total */
+     }
+     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 */
-
-  	temp = ((tempbx & 0xFF00) << 3) >> 8;
-  	temp |= ((tempcx & 0xFF00) >> 8);
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                        /* Overflow (and HWCursor Test Mode) */
-
-	if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-           tempbx++;
-   	   tempax = tempbx;
-	   tempcx++;
-	   tempcx -= tempax;
-	   tempcx >>= 2;
-	   tempbx += tempcx;
-	   if(tempcx < 4) tempcx = 4;
-	   tempcx >>= 2;
-	   tempcx += tempbx;
-	   tempcx++;
-	} else {
-  	   tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
-  	   tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
-	}
+     tempbx = SiS_Pr->SiS_VGAVDE - 1;
+     temp = tempbx & 0x00FF;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                 /* CRT2 Vertical Display Enable End */
 
-  	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     temp = ((tempbx & 0xFF00) << 3) >> 8;
+     temp |= ((tempcx & 0xFF00) >> 8);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow (and HWCursor Test Mode) */
+
+     if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
+        tempbx++;
+   	tempax = tempbx;
+	tempcx++;
+	tempcx -= tempax;
+	tempcx >>= 2;
+	tempbx += tempcx;
+	if(tempcx < 4) tempcx = 4;
+	tempcx >>= 2;
+	tempcx += tempbx;
+	tempcx++;
+     } else {
+  	tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
+  	tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
+     }
 
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+
+	if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CVSyncStart;
+	   tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
+	}
+
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr8, cr7, cr13, cr9;
 	   if(SiS_Pr->UseCustomMode) {
-	      tempbx = SiS_Pr->CVSyncStart;
-	      tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
-	   }
+	      cr8  = SiS_Pr->CCRT1CRTC[8];
+	      cr7  = SiS_Pr->CCRT1CRTC[7];
+	      cr13 = SiS_Pr->CCRT1CRTC[13];
+	      cr9  = SiS_Pr->CCRT1CRTC[9];
+	   } else {
+	      cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+	   }
+      	   tempbx = cr8;
+      	   if(cr7 & 0x04)  tempbx |= 0x0100;
+      	   if(cr7 & 0x80)  tempbx |= 0x0200;
+      	   if(cr13 & 0x08) tempbx |= 0x0400;
+      	   tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
+    	}
+     }
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
-    	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	      unsigned char cr8, cr7, cr13, cr9;
-	      if(SiS_Pr->UseCustomMode) {
-	         cr8  = SiS_Pr->CCRT1CRTC[8];
-		 cr7  = SiS_Pr->CCRT1CRTC[7];
-		 cr13 = SiS_Pr->CCRT1CRTC[13];
-		 cr9  = SiS_Pr->CCRT1CRTC[9];
-	      } else {
-	         cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
-		 cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-		 cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-		 cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
-	      }
-      	      tempbx = cr8;
-      	      if(cr7 & 0x04)  tempbx |= 0x0100;
-      	      if(cr7 & 0x80)  tempbx |= 0x0200;
-      	      if(cr13 & 0x08) tempbx |= 0x0400;
-      	      tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
-    	   }
-  	}
-  	temp = tempbx & 0x00FF;
-  	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);           /* 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 & 0xFF00) >> 8) << 4;
+     temp |= (tempcx & 0x000F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
 
-  	/* 3. Panel compensation delay */
+     /* 3. Panel delay compensation */
 
-  	if(HwInfo->jChipType < SIS_315H) {
+     if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300  /* ---------- 300 series -------------- */
 
-	   if(SiS_Pr->SiS_VBType & VB_SISVB) {
-	        temp = 0x20;
+	if(SiS_Pr->SiS_VBType & VB_SISVB) {
+	   temp = 0x20;
 
-		if(HwInfo->jChipType == SIS_300) {
-		   temp = 0x10;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_VBType & VB_SIS301) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-		}
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)     temp = 0x24;
-		if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)       temp = 0x2c;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-      		   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
-      		   else 					temp = 0x20;
-    	        }
-		if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
-				temp = ROMAddr[0x221];
-			else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
-				temp = ROMAddr[0x222];
-		        else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)
-				temp = ROMAddr[0x223];
-			else
-				temp = ROMAddr[0x224];
-			temp &= 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-			temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
-	   } else {
-	        temp = 0x20;
-		if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-		   if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) temp = 0x04;
-		}
-		if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-		    if(ROMAddr[0x220] & 0x80) {
-		        temp = ROMAddr[0x220] & 0x3c;
-		    }
-		}
-		if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-		   if(SiS_Pr->PDC) {
-		      temp = SiS_Pr->PDC & 0x3c;
-		   }
-		}
+	   if(HwInfo->jChipType == SIS_300) {
+	      temp = 0x10;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
+	   }
+	   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 & SetCRT2ToHiVision) {
+      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
+      	      else 					temp = 0x20;
+    	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+	   	    temp = ROMAddr[0x221];
+		 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
+		    temp = ROMAddr[0x222];
+		 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
+		    temp = ROMAddr[0x223];
+		 else
+		    temp = ROMAddr[0x224];
+		 temp &= 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
+	   }
+
+	} else {
+	   temp = 0x20;
+	   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+	      if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) temp = 0x04;
+	   }
+	   if(SiS_Pr->SiS_UseROM) {
+	      if(ROMAddr[0x220] & 0x80) {
+	         temp = ROMAddr[0x220] & 0x3c;
+	      }
+	   }
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	      if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
 	   }
+        }
 
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x03C,temp);         /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
 
 #endif  /* SIS300 */
 
-  	} else {
+     } else {
 
 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
 
-   	   if(HwInfo->jChipType < SIS_661) {
-
-	      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(HwInfo->jChipType < SIS_661) {
 
-                 temp = 0x10;
-                 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  temp = 0x2c;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) temp = 0x20;
-    	         if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x960)  temp = 0x24;
-		 if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom)    temp = 0x2c;
-		 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-		    temp = 0x08;
-		    if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-		       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  temp = 0x2c;
-      		       else 					temp = 0x20;
-		    }
-		 }
-		 if((SiS_Pr->SiS_VBType & VB_SIS301B302B) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-		    tempbl = 0x00;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(HwInfo->jChipType < SIS_330) {
-		          if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		       } else {
-		          if(ROMAddr[0x1bc] & 0x80) tempbl = 0xf0;
-		       }
-		    }
-		 } else {  /* LV (550/301LV checks ROM byte, other LV BIOSes do not) */
-		    tempbl = 0xF0;
-		 }
-		 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {
-		    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-		       if(SiS_Pr->PDC) {
-		          temp = SiS_Pr->PDC;
-		          tempbl = 0;
-		       }
-		    }
-		 }
+	   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-	      } else {  /* LVDS */
+	      if(HwInfo->jChipType == SIS_740) temp = 0x03;
+	      else 		               temp = 0x00;
 
-	         if(HwInfo->jChipType == SIS_740) {
-		    temp = 0x03;
-	         } else {
-		    temp = 0x00;
-		 }
-	 	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
-		 tempbl = 0xF0;
-		 if(HwInfo->jChipType == SIS_650) {
-		    if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-		       if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
-		    }
+	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
+	      tempbl = 0xF0;
+	      if(HwInfo->jChipType == SIS_650) {
+		 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+		    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
 		 }
+	      }
 
-		 if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
-		    temp = 0x08;
-		    tempbl = 0;
-		    if((ROMAddr) && (SiS_Pr->SiS_UseROM)) {
-		       if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
-		    }
+	      if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) {
+		 temp = 0x08;
+		 tempbl = 0;
+		 if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+		    if(ROMAddr[0x13c] & 0x80) tempbl = 0xf0;
 		 }
 	      }
 
 	      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,tempbl,temp);	    /* Panel Link Delay Compensation */
+	   }
 
-	   } /* < 661 */
+	} /* < 661 */
 
-    	   tempax = 0;
-    	   if (modeflag & DoubleScanMode) tempax |= 0x80;
-    	   if (modeflag & HalfDCLK)       tempax |= 0x40;
-    	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+    	tempax = 0;
+    	if (modeflag & DoubleScanMode) tempax |= 0x80;
+    	if (modeflag & HalfDCLK)       tempax |= 0x40;
+    	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
 
-  	}
-
-     }  /* Slavemode */
+     }
 
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+  }  /* Slavemode */
 
+  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
         /* For 301BDH with LCD, we set up the Panel Link */
-        if( (SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ) {
-
-	    SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                       HwInfo, RefreshRateTableIndex);
-
-        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-
-    	    SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex,
-	                      HwInfo, RefreshRateTableIndex);
-        }
-
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+    	SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     }
+  } else {
+     if(HwInfo->jChipType < SIS_315H) {
+	SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
      } else {
-
-        if(HwInfo->jChipType < SIS_315H) {
-
-	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex,
-	                        HwInfo, RefreshRateTableIndex);
+	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+    	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+           }
 	} else {
-
-	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-              if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-    	          SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                              HwInfo,RefreshRateTableIndex);
-              }
-	   } else {
-	      SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,
-	                         HwInfo,RefreshRateTableIndex);
-	   }
-
+	   SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
 	}
-
      }
-  } /* LCDA */
+  }
 }
 
 /*********************************************/
@@ -6978,9 +6561,8 @@
 static UCHAR *
 SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    const UCHAR  *tableptr = NULL;
-   USHORT a, b, p = 0;
+   USHORT       a, b, p = 0;
 
    a = SiS_Pr->SiS_VGAHDE;
    b = SiS_Pr->SiS_HDE;
@@ -6989,62 +6571,32 @@
       b = SiS_Pr->SiS_VDE;
    }
 
-   if((ROMAddr = (UCHAR *)HwInfo->pjVirtualRomBase) && SiS_Pr->SiS_UseROM) {
-
-      if(a < b) {
-         p = ROMAddr[0x278] | (ROMAddr[0x279] << 8);
-      } else if(a == b) {
-         p = ROMAddr[0x27a] | (ROMAddr[0x27b] << 8);
-      } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    p = ROMAddr[0x27e] | (ROMAddr[0x27f] << 8);
-	 } else {
-	    p = ROMAddr[0x27c] | (ROMAddr[0x27d] << 8);
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	 p = ROMAddr[0x280] | (ROMAddr[0x281] << 8);
-	    else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) p = ROMAddr[0x282] | (ROMAddr[0x283] << 8);
-	    else 				 	 p = ROMAddr[0x284] | (ROMAddr[0x285] << 8);
-	 } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-	    p = ROMAddr[0x286] | (ROMAddr[0x287] << 8);
-	 }
-	 do {
-	    if((ROMAddr[p] | ROMAddr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((ROMAddr[p] | ROMAddr[p+1] << 8) != 0xffff);
-	 if((ROMAddr[p] | ROMAddr[p+1] << 8) == 0xffff) p -= 0x42;
-      }
-      p += 2;
-      return(&ROMAddr[p]);
-
+   if(a < b) {
+      tableptr = SiS_Part2CLVX_1;
+   } else if(a == b) {
+      tableptr = SiS_Part2CLVX_2;
    } else {
-
-      if(a < b) {
-         tableptr = SiS_Part2CLVX_1;
-      } else if(a == b) {
-         tableptr = SiS_Part2CLVX_2;
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+	 tableptr = SiS_Part2CLVX_4;
       } else {
-         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-	    tableptr = SiS_Part2CLVX_4;
-	 } else {
-	    tableptr = SiS_Part2CLVX_3;
-	 }
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-	    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;
-	 }
-	 do {
-	    if((tableptr[p] | tableptr[p+1] << 8) == a) break;
-	    p += 0x42;
-	 } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
-	 if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
+	 tableptr = SiS_Part2CLVX_3;
       }
-      p += 2;
-      return((UCHAR *)&tableptr[p]);
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+	 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;
+      }
+      do {
+	 if((tableptr[p] | tableptr[p+1] << 8) == a) break;
+	 p += 0x42;
+      } while((tableptr[p] | tableptr[p+1] << 8) != 0xffff);
+      if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
    }
+   p += 2;
+   return((UCHAR *)&tableptr[p]);
 }
 
 static void
@@ -7055,7 +6607,7 @@
    int i, j;
    UCHAR temp;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return; 
 
    tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
    for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
@@ -7072,49 +6624,97 @@
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
 }
 
-static void
+static BOOLEAN
 SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 		    USHORT RefreshRateTableIndex,USHORT *CRT2Index,
 		    USHORT *ResIndex,PSIS_HW_INFO HwInfo)
 {
-  USHORT tempbx,tempal;
-
+  
+  if(HwInfo->jChipType < SIS_315H) return FALSE;
+  
   if(ModeNo <= 0x13)
-      	tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-      	tempal = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-  tempbx = SiS_Pr->SiS_LCDResInfo;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx += 16;
-  else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx += 32;
+  (*ResIndex) &= 0x3f;
+  (*CRT2Index) = 0;
 
-  if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tempbx = 100;
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 101;
-  	else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 102;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+        (*CRT2Index) = 200;
      }
-  } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-           tempbx = 103;
-           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)      tempbx = 104;
-  	   else if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 105;
-	}
-     }
-  }  else if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) tempbx = 106;
+  }
+
+  if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
      }
   }
+  return(((*CRT2Index) != 0));
+}
+#endif
+
+#ifdef SIS300
+static void
+SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+{
+   USHORT tempcx;
+   const UCHAR atable[] = {
+       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
+       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
+   };
+
+   if(!SiS_Pr->UseCustomMode) {
+      if( ( ( (HwInfo->jChipType == SIS_630) ||
+              (HwInfo->jChipType == SIS_730) ) &&
+            (HwInfo->jChipRevision > 2) )  &&
+          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
+          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+         if(ModeNo == 0x13) {
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+         } else {
+            if((crt2crtc & 0x3F) == 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+            }
+         }
+      }
+
+      if(HwInfo->jChipType < SIS_315H) {
+         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+            crt2crtc &= 0x1f;
+            tempcx = 0;
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  tempcx += 7;
+               }
+            }
+            tempcx += crt2crtc;
+            if(crt2crtc >= 4) {
+               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+            }
 
-  *CRT2Index = tempbx;
-  *ResIndex = tempal & 0x3F;
+            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                  if(crt2crtc == 4) {
+                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+                  }
+               }
+            }
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+         }
+      }
+   }
 }
-#endif
 
-#ifdef SIS300
 /* For ECS A907. Highly preliminary. */
 static void
 SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
@@ -7183,15 +6783,81 @@
 	if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750)) {
 	   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
 	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	   } else {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x15);
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x14);  /* 15 */
+	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1a);  /* 1b */
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1b);
 	}
      }
   } else {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x21);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x5a);
+     if((ModeNo == 0x38) || (ModeNo == 0x4a) || (ModeNo == 0x64) ||
+        (ModeNo == 0x52) || (ModeNo == 0x58) || (ModeNo == 0x5c)) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 5a */
+     } else {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1a);  /* 21 */
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x53);  /* 5a */
+     }
+  }
+}
+
+static void
+SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+{
+  USHORT temp;
+
+  if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
+     if(SiS_Pr->SiS_VGAVDE == 525) {
+	temp = 0xc3;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
+     } else if(SiS_Pr->SiS_VGAVDE == 420) {
+	temp = 0x4d;
+	if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	   temp++;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+	}
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
+     }
+  }
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
+	if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
+	   /* Not always for LV, see SetGrp2 */
+	}
+	temp = 1;
+	if(ModeNo <= 0x13) temp = 3;
+	SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
+     }
+#if 0
+     /* 651+301C, for 1280x768 - do I really need that? */
+     if((SiS_Pr->SiS_PanelXRes == 1280) && (SiS_Pr->SiS_PanelYRes == 768)) {
+        if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+	   if(((SiS_Pr->SiS_HDE == 640) && (SiS_Pr->SiS_VDE == 480)) ||
+	      ((SiS_Pr->SiS_HDE == 320) && (SiS_Pr->SiS_VDE == 240))) {
+	      SiS_SetReg(SiS_Part2Port,0x01,0x2b);
+	      SiS_SetReg(SiS_Part2Port,0x02,0x13);
+	      SiS_SetReg(SiS_Part2Port,0x04,0xe5);
+	      SiS_SetReg(SiS_Part2Port,0x05,0x08);
+	      SiS_SetReg(SiS_Part2Port,0x06,0xe2);
+	      SiS_SetReg(SiS_Part2Port,0x1c,0x21);
+	      SiS_SetReg(SiS_Part2Port,0x1d,0x45);
+	      SiS_SetReg(SiS_Part2Port,0x1f,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x20,0x00);
+	      SiS_SetReg(SiS_Part2Port,0x21,0xa9);
+	      SiS_SetReg(SiS_Part2Port,0x23,0x0b);
+	      SiS_SetReg(SiS_Part2Port,0x25,0x04);
+	   }
+	}
+     }
+#endif
   }
 }
 
@@ -7200,36 +6866,26 @@
 	      PSIS_HW_INFO HwInfo)
 {
   USHORT      i, j, tempax, tempbx, tempcx, temp;
-  USHORT      push1, push2, modeflag, crt2crtc;
+  USHORT      push1, push2, modeflag, crt2crtc, bridgeoffset;
   ULONG       longtemp, tempeax;
   const       UCHAR *PhasePoint;
   const       UCHAR *TimingPoint;
 #ifdef SIS315H
   USHORT      resindex, CRT2Index;
   const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
-#endif
-#ifdef SIS300
-  const UCHAR atable[] = {
-       0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
-       0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
-  };
-#endif  
 
-#ifdef SIS315H   
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 #endif
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     crt2crtc = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	crt2crtc = 0;
-     } else {
-        modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-    	crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
   }
 
   temp = 0;
@@ -7238,26 +6894,25 @@
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART)     temp |= 0x02;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)  temp |= 0x01;
 
-  /* Disable SVIDEO and CVBS signal */
-  if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-     (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-        temp |= 0x0c;
-     }
-  }
+  if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) 	      temp |= 0x10;
+
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
 
   PhasePoint  = SiS_Pr->SiS_PALPhase;
   TimingPoint = SiS_Pr->SiS_PALTiming;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
+     TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
         TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-           if(modeflag & Charx8Dot) TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-           else                     TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
+	   TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
+#if 0
+           if(!(modeflag & Charx8Dot))  TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
+#endif
         }
-     } else TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
+     }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 
@@ -7267,41 +6922,32 @@
 
      PhasePoint = SiS_Pr->SiS_NTSCPhase;
 
-  } else {
-
-     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+  } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
 
-        TimingPoint = SiS_Pr->SiS_PALTiming;
-        PhasePoint  = SiS_Pr->SiS_PALPhase;
+     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+         ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+	   (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+        PhasePoint = SiS_Pr->SiS_PALPhase2;
+     }
 
-        if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-            ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-	      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-           PhasePoint = SiS_Pr->SiS_PALPhase2;
-        }
+  } else {
 
-     } else {
+     TimingPoint = SiS_Pr->SiS_NTSCTiming;
+     PhasePoint  = SiS_Pr->SiS_NTSCPhase;
+     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
+	PhasePoint = SiS_Pr->SiS_PALPhase;
+     }
 
-        temp |= 0x10;
-        TimingPoint = SiS_Pr->SiS_NTSCTiming;
-        PhasePoint  = SiS_Pr->SiS_NTSCPhase;
+     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
+	 ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+	   (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+        PhasePoint = SiS_Pr->SiS_NTSCPhase2;
 	if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-	   PhasePoint = SiS_Pr->SiS_PALPhase;
+	   PhasePoint = SiS_Pr->SiS_PALPhase2;
 	}
-
-        if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-	    ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-	      (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-           PhasePoint = SiS_Pr->SiS_NTSCPhase2;
-	   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-	      PhasePoint = SiS_Pr->SiS_PALPhase2;
-	   }
-        }
-
      }
 
   }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
 
   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
      PhasePoint = SiS_Pr->SiS_PALMPhase;
@@ -7356,7 +7002,7 @@
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) 	tempax = 950;
   else if(SiS_Pr->SiS_TVMode & TVSetPAL)      	tempax = 520;
-  else 			            		tempax = 440;
+  else 			            		tempax = 440; /* NTSC, YPbPr 525, 750 */
 
   if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
@@ -7372,10 +7018,10 @@
      temp = tempax + (USHORT)TimingPoint[1];
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
+     if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x19);
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x52);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
         } else {
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7388,10 +7034,8 @@
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx--;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,temp);
-  temp = (tempcx & 0xFF00) >> 8;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,(tempcx & 0xff));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
 
   tempcx++;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx++;
@@ -7400,24 +7044,16 @@
   push1 = tempcx;
 
   tempcx += 7;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempcx -= 4;
-  }
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,temp);
+  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 = TimingPoint[j] | (TimingPoint[j+1] << 8);
   tempbx += tempcx;
 
-  push2 = tempbx;
-
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
   temp = ((tempbx & 0xFF00) >> 8) << 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp);
 
-  tempbx = push2;
-
   tempbx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      tempbx -= 4;
@@ -7427,32 +7063,27 @@
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
 
   j += 2;
-  tempcx += ((TimingPoint[j] | ((TimingPoint[j+1]) << 8)));
+  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);
 
   tempcx += 8;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempcx -= 4;
-  }
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,temp);
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx = push1;
 
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
-  temp = (tempcx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx -= 11;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
      tempcx = SiS_GetVGAHT2(SiS_Pr) - 1;
   }
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
 
   tempbx = SiS_Pr->SiS_VDE;
   if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
@@ -7488,9 +7119,7 @@
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
            if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {   /* SetFlag?? */
-	         if(ModeNo == 0x03) temp++;
-	      }
+	      if(ModeNo == 0x03) temp++;
 	   }
         }
      }
@@ -7499,20 +7128,19 @@
 
   temp = (tempcx >> 8) & 0x0F;
   temp |= (((tempbx >> 8) << 6) & 0xC0);
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750 | SetCRT2ToSCART))) {
+  if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
      temp |= 0x10;
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToSVIDEO)) temp |= 0x20;
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
 
-  if((HwInfo->jChipType > SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
-           if( (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) ) {
-              SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
-	   }
-        }
+  /* TEST qqqq */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+     for(i=0x01, j=0; i<=0x2D; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
+     }
+     for(i=0x39; i<=0x45; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
      }
   }
 
@@ -7524,21 +7152,27 @@
 	}
      }
      tempbx -= 3;
-     if(HwInfo->jChipType >= SIS_661) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
+     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;
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,temp);
-
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
   }
 
   tempbx = 0;
@@ -7597,10 +7231,8 @@
         tempbx = 0x0369;
         tempcx = 0x0061;
      }
-     temp = (tempbx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,temp);
-     temp = (tempcx & 0x00FF) ;
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
      temp = (tempcx & 0x0300) >> (8 - 2);
      temp |= ((tempbx >> 8) & 0x03);
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
@@ -7644,13 +7276,12 @@
   tempbx = SiS_Pr->SiS_HDE;
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   tempbx--;			         	/* RHACTE = HDE - 1 */
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
   temp = (tempbx & 0xFF00) >> 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
 
   temp = 0x01;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(SiS_Pr->SiS_VGAHDE >= 1024) {
            temp = 0x02;
@@ -7665,14 +7296,12 @@
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0B,temp);
 
   tempbx = SiS_Pr->SiS_VDE - 1;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
   temp = ((tempbx & 0xFF00) >> 8) & 0x07;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
 
   tempcx = SiS_Pr->SiS_VT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
 
   temp = ((tempcx & 0xFF00) >> 8) << 5;
 
@@ -7683,31 +7312,7 @@
      }
   }
 
-  /* Must do special for Compaq1280; Acer1280 OK, Clevo1400 OK, COMPAL1400 OK */
-  /* Compaq1280 panel loses sync if using CR37 sync info. */
-  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-     if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-	if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-	   (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024)) {
-	   if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	      temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	   }
-	} else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400) &&
-	          (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)) {
-	   temp |= 0x03;
-	} else {
-           temp |= (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) >> 6);
-	   temp |= 0x08;
-	   if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) temp |= 0x04;
-	}
-     } else {
-        if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-	   temp |= ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-	}
-     }
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1A,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
 
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x0A,0xF0);
@@ -7715,154 +7320,13 @@
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x17,0xFB);
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x18,0xDF);
 
-#if 0  /* Use the 315/330 series code for now */
-  if((HwInfo->jChipType >= SIS_661)          &&
-     (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-     (ROMAddr && SiS_Pr->SiS_UseROM)) {
-
-      /* This is done for the LVDS bridges only, since
-       * the TMDS panels already work correctly with
-       * the old code. Besides, we only do that if
-       * we can get the data from the ROM, I am tired
-       * of carrying a lot of tables around.
-       */
-
-#ifdef SIS315H 							/* ------------ 661/741/760 series --------- */
-      UCHAR *myptr = NULL, myptr1 = NULL;
-
-      myptr = (UCHAR *)GetLCDPtr661(SiS_Pr, HwInfo, 6, ModeNo, ModeIdIndex, RefreshRateTableIndex);
-      myptr1 = (UCHAR *)GetLCDStructPtr661(SiS_Pr, HwInfo);
-
-      tempbx = (myptr[3] | (myptr[4] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelYRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = SiS_Pr->SiS_VDE;
-      }
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempbx);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempcx);
-
-      tempcx &= 0x07ff;
-      tempbx &= 0x07ff;
-      temp = (tempcx >> 8) << 3;
-      temp |= (tempbx >> 8);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
-
-      tempbx = (myptr[4] | (myptr[5] << 8)) >> 4;
-      tempcx = myptr1[6];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = myptr[7];
-
-      tempcx += tempbx;
-      if(tempcx >= SiS_Pr->SiS_VT) tempcx -= SiS_Pr->SiS_VT;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);
-      temp = tempcx & 0x000f;
-      temp |= ((tempbx & 0x0f00) >> 4);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[0] | (myptr[1] << 8)) & 0x0fff;
-      tempcx = SiS_Pr->PanelXRes;
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempcx = SiS_Pr->SiS_HDE;
-
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV)                 tempbx++;
-      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,tempbx);
-      temp = ((tempbx & 0xff00) >> 8) << 4;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x20,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempcx);
-      temp = tempcx >> 8;
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x25,temp);
-
-      tempax = SiS_Pr->SiS_HT;
-      tempbx = (myptr[1] | (myptr[2] << 8)) >> 4;
-      tempcx = myptr1[5];
-      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-         tempcx = myptr[6];
-      }
-      if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-         tempax >>= 1;
-	 tempbx >>= 1;
-	 tempcx >>= 1;
-      }
-      if(SiS_Pr->SiS_VBType & VB_SIS302LV) tempbx++;
-
-      tempcx += tempbx;
-      if(tempcx >= tempax) tempcx -= tempax;
-
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1c,tempbx);
-      temp = (tempbx & 0x0f00) >> 4;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1d,0x0f,temp);
-      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempcx);
-
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-         if(SiS_Pr->SiS_VGAVDE == 525) {
-	    temp = 0xc3;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	 } else if(SiS_Pr->SiS_VGAVDE == 420) {
-	    temp = 0x4d;
-	    if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	       temp++;
-	       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	    }
-	    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	 }
-      }
-
-#endif
-
-  } else
-#endif
-         if((HwInfo->jChipType >= SIS_315H)                    &&
-            (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)            &&
-            ((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768)  ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-             (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) ) {
-
-#ifdef SIS315H 							/* ------------- 315/330 series ------------ */
-
-      SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &CRT2Index, &resindex, HwInfo);
-
+#ifdef SIS315H
+  if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
+                          			&CRT2Index, &resindex, HwInfo)) {
       switch(CRT2Index) {
-        case Panel_1024x768      : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;  break;  /* "Normal" */
-        case Panel_1280x1024     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_1; break;
-	case Panel_1400x1050     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_1; break;
-	case Panel_1600x1200     : CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_1; break;
-        case Panel_1024x768  + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_2;  break;  /* Non-Expanding */
-        case Panel_1280x1024 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_2; break;
-	case Panel_1400x1050 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_2; break;
-	case Panel_1600x1200 + 16: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_2; break;
-        case Panel_1024x768  + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;  /* VESA Timing */
-        case Panel_1280x1024 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1280x1024_3; break;
-	case Panel_1400x1050 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1400x1050_3; break;
-	case Panel_1600x1200 + 32: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1600x1200_3; break;
-	case 100:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_1; break;  /* Custom */
-	case 101:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_2; break;
-	case 102:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Compaq1280x1024_3; break;
-	case 103:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_1; break;    /* Custom */
-	case 104:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_2; break;
-	case 105:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Clevo1024x768_3; break;
-	case 106:		   CRT2Part2Ptr = (SiS_Part2PortTblStruct *)SiS310_CRT2Part2_Asus1024x768_3; break;
-	default:                   CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;  break;
+        case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
+	case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
+	default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
       }
 
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7879,58 +7343,34 @@
       SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
 
-      if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-        if(SiS_Pr->SiS_VGAVDE == 525) {
-	  temp = 0xc3;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
-	} else if(SiS_Pr->SiS_VGAVDE == 420) {
-	  temp = 0x4d;
-	  if(SiS_Pr->SiS_ModeType <= ModeVGA) {
-	     temp++;
-	     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
-	  }
-	  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-	}
-     }
+      SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-	   /* See Sync above, 0x1a */
-	   temp = 1;
-	   if(ModeNo <= 0x13) temp = 3;
-	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x0b,temp);
-	}
-     }
+      
+  } else {
 #endif
-
-  } else {   /* ------ 300 series and other bridges, other LCD resolutions ------ */
-
-      /* Using this on the 301B with an auto-expanding 1024 panel (CR37=1) makes
-       * the panel scale at modes < 1024 (no black bars); if the panel is non-expanding,
-       * the bridge scales all modes to 1024.
-       * !!! Malfunction at 640x480 and 640x400 when panel is auto-expanding - black screen !!!
-       */
-
-    tempcx = SiS_Pr->SiS_VT;
-    tempbx = SiS_Pr->PanelYRes;
+	  
+    /* Checked for 1024x768, 1280x1024, 1400x1050, 1600x1200 */
+    /*             Clevo dual-link 1024x768 */
+    /* 		   Compaq 1280x1024 has HT 1696 sometimes (calculation OK, if given HT is correct)  */
+    /*		   Acer: OK, but uses different setting for VESA timing at 640/800/1024 and 640x400 */
 
     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-       tempbx = SiS_Pr->SiS_VDE - 1;
-       tempcx--;
-    }
-
-    tempax = 1;
-    if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-       if(tempbx != SiS_Pr->SiS_VDE) {
-          tempax = tempbx;
-          if(tempax < SiS_Pr->SiS_VDE) {
-             tempax = 0;
-             tempcx = 0;
+       if((SiS_Pr->SiS_LCDInfo & LCDPass11) || (SiS_Pr->PanelYRes == SiS_Pr->SiS_VDE)) {
+          tempbx = SiS_Pr->SiS_VDE - 1;
+          tempcx = SiS_Pr->SiS_VT - 1;
+       } else {
+          tempbx = SiS_Pr->SiS_VDE + ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+	  tempcx = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VDE) / 2);
+       }
+    } else {
+       tempbx = SiS_Pr->PanelYRes;
+       tempcx = SiS_Pr->SiS_VT;
+       tempax = 1;
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          tempax = SiS_Pr->PanelYRes;
+	  /* if(SiS_Pr->SiS_VGAVDE == 525) tempax += 0x3c;   */  /* 651+301C */
+          if(SiS_Pr->PanelYRes < SiS_Pr->SiS_VDE) {
+             tempax = tempcx = 0;
           } else {
              tempax -= SiS_Pr->SiS_VDE;
           }
@@ -7946,23 +7386,46 @@
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
 #endif
 
-    temp = tempcx & 0x00FF;   				/* RVEQ1EQ=lcdvdes */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,temp);
-    temp = tempbx & 0x00FF;   				/* RVEQ2EQ=lcdvdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,temp);
+    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);
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
-    tempbx = SiS_Pr->SiS_VT;    /* push2; */
-    tempax = SiS_Pr->SiS_VDE;   /* push1; */
-    tempcx = (tempbx - tempax) >> 4;
-    tempbx += tempax;
-    tempbx >>= 1;
-    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx -= 10;
+    tempax = SiS_Pr->SiS_VDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       tempax = SiS_Pr->PanelYRes;
+    }
+    tempcx = (SiS_Pr->SiS_VT - tempax) >> 4;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+	  tempcx = (SiS_Pr->SiS_VT - tempax) / 10;
+       }
+    }
+
+    tempbx = ((SiS_Pr->SiS_VT + SiS_Pr->SiS_VDE) >> 1) - 1;
+    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(SiS_Pr->PanelYRes != SiS_Pr->SiS_VDE) {
+          if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) { /* ? */
+             tempax = SiS_Pr->SiS_VT - SiS_Pr->PanelYRes;
+	     if(tempax % 4) { tempax >>= 2; tempax++; }
+	     else           { tempax >>= 2;           }
+             tempbx -= (tempax - 1);
+	  } else tempbx -= 10;
+       }
+    }
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       tempbx++;
+       if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (crt2crtc == 6)) {
+          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+	     tempbx = 770;
+	     tempcx = 3;
+	  }
+       }
+    }
 
-    /* non-expanding: lcdvrs = tempbx = ((VT + VDE) / 2) - 10 */
+    /* non-expanding: lcdvrs = ((VT + VDE) / 2) - 10 */
 
     if(SiS_Pr->UseCustomMode) {
        tempbx = SiS_Pr->CVSyncStart;
@@ -7972,8 +7435,7 @@
     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;   				/* RTVACTEE = lcdvrs */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
 
     temp = ((tempbx & 0xFF00) >> 8) << 4;
     tempbx += (tempcx + 1);
@@ -7990,149 +7452,106 @@
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
-    /* Code from 630/301B (I+II) BIOS */
-
 #ifdef SIS300
-    if(!SiS_Pr->UseCustomMode) {
-       if( ( ( (HwInfo->jChipType == SIS_630) ||
-               (HwInfo->jChipType == SIS_730) ) &&
-             (HwInfo->jChipRevision > 2) )  &&
-           (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) &&
-           (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
-           (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-          if(ModeNo == 0x13) {
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
-          } else {
-             if((crt2crtc & 0x3F) == 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
-             }
-          }
-       }
-
-       if(HwInfo->jChipType < SIS_315H) {
-          if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
-             crt2crtc &= 0x1f;
-             tempcx = 0;
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   tempcx += 7;
-                }
-             }
-             tempcx += crt2crtc;
-             if(crt2crtc >= 4) {
-                SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
-             }
+    SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+#endif
 
-             if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-                if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                   if(crt2crtc == 4) {
-                      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
-                   }
-                }
-             }
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
-             SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
-          }
+    bridgeoffset = 7;
+    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
+    if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
+    if(SiS_IsDualLink(SiS_Pr, HwInfo))        		 bridgeoffset++;
+
+    temp = 0;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+	  if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
        }
     }
-#endif
-
-    tempcx = (SiS_Pr->SiS_HT - SiS_Pr->SiS_HDE) >> 2;     /* (HT - HDE) >> 2 */
-    tempbx = SiS_Pr->SiS_HDE + 7;            		  /* lcdhdee         */
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       tempbx += 2;
+    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] */
+
+    tempcx = SiS_Pr->SiS_HT;
+    tempax = tempbx = SiS_Pr->SiS_HDE;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
+          tempax = SiS_Pr->PanelXRes;
+          tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+       }
+    }
+    if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+       tempcx >>= 1;
+       tempbx >>= 1;
+       tempax >>= 1;		
     }
-    push1 = tempbx;
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;    			          /* RHEQPLE = lcdhdee */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,temp);
-    temp = (tempbx & 0xFF00) >> 8;
+    tempbx += bridgeoffset;
+
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
+    temp = (tempbx >> 8) & 0x0f;
     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
 
-    temp = 7;
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-       temp += 2;
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	  /* RHBLKE = lcdhdes[7:0] */
-    SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x20,0x0F);	  /* lcdhdes [11:8] */
+    tempcx = (tempcx - tempax) >> 2;
 
     tempbx += tempcx;
     push2 = tempbx;
 
-    if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncStart + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+          if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+             if(SiS_Pr->SiS_HDE == 1280) tempbx = (tempbx & 0xff00) | 0x47;
+	  }
        }
     }
 
+    if(SiS_Pr->UseCustomMode) {
+       tempbx = SiS_Pr->CHSyncStart;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
+    }
+
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHBURSTS = lcdhrs */
-    if(!SiS_Pr->UseCustomMode) {
-       if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-          if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-             if(SiS_Pr->SiS_HDE == 1280) temp = 0x47;
-          }
-       }
-    }
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
     temp = (tempbx & 0x0F00) >> 4;
     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
 
     tempbx = push2;
+
     tempcx <<= 1;
+    if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) tempcx >>= 2;
+    }
     tempbx += tempcx;
 
     if(SiS_Pr->UseCustomMode) {
-       tempbx = SiS_Pr->CHSyncEnd + 7;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          tempbx += 2;
-       }
+       tempbx = SiS_Pr->CHSyncEnd;
+       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       tempbx += bridgeoffset;
     }
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
 #endif
 
-    temp = tempbx & 0x00FF;            		          /* RHSYEXP2S = lcdhre */
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,temp);
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);	    /* lcdhre */
 
-    if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-       if(SiS_Pr->SiS_VGAVDE == 525) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-    	     temp=0xC6;
-          else
-       	     temp=0xC3;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xB3);
-       } else if(SiS_Pr->SiS_VGAVDE == 420) {
-          if(SiS_Pr->SiS_ModeType <= ModeVGA)
-	     temp=0x4F;
-          else
-       	     temp=0x4D;
-          SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
-       }
-    }
+    SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
 #ifdef SIS300
-    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex,
-                        RefreshRateTableIndex, ModeNo);
+    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
 #endif
-
-  } /* HwInfo */
+#ifdef SIS315H
+  } /* CRT2-LCD from table */
+#endif  
 }
 
 /*********************************************/
@@ -8143,26 +7562,14 @@
 SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
 {
-  USHORT modeflag, i;
-  const UCHAR  *tempdi;
+  USHORT 	i;
+  const UCHAR  	*tempdi;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 
-  if(ModeNo<=0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
-  }
-
 #ifndef SIS_CP
   SiS_SetReg(SiS_Pr->SiS_Part3Port,0x00,0x00);
-#endif
-
-#ifdef SIS_CP
+#else
   SIS_CP_INIT301_CP
 #endif
 
@@ -8185,9 +7592,6 @@
      tempdi = SiS_Pr->SiS_HiTVGroup3Data;
      if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
         tempdi = SiS_Pr->SiS_HiTVGroup3Simu;
-        if(!(modeflag & Charx8Dot)) {
-           tempdi = SiS_Pr->SiS_HiTVGroup3Text;
-        }
      }
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
      if(!(SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
@@ -8196,7 +7600,7 @@
      }
   }
   if(tempdi) {
-     for(i=0; i<=0x3E; i++){
+     for(i=0; i<=0x3E; i++) {
         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
      }
      if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
@@ -8206,17 +7610,92 @@
      }
   }
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) {
 #ifdef SIS_CP
-     SIS_CP_INIT301_CP2
+  SIS_CP_INIT301_CP2
 #endif
-  }
 }
 
 /*********************************************/
 /*         SET PART 4 REGISTER GROUP         */
 /*********************************************/
 
+#ifdef SIS315H
+static void
+SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
+{
+   USHORT temp, temp1, temp2;
+
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
+   temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
+   temp = (USHORT)((int)(temp) + shift);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
+   temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
+   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
+   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
+}
+
+static void
+SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                    USHORT ModeNo, USHORT ModeIdIndex)
+{
+   USHORT temp, temp1, resinfo = 0;
+
+   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0x08);
+   temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x3a);
+   if(!(temp & 0x01)) {
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
+      if(HwInfo->jChipType < SIS_661) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
+      }
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      temp = 0x0000;
+      else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
+      else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
+      else					   temp = 0x0402;
+      if(HwInfo->jChipType >= SIS_661) {
+         temp1 = 0;
+	 if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
+	 if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+      } else {
+         temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
+	 if(temp1 == 0x01) temp |= 0x01;
+	 if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+
+      if(HwInfo->jChipType >= SIS_661) { 		/* ? */
+         if(SiS_Pr->SiS_TVMode & TVAspect43) {
+            if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+	       if(resinfo == SIS_RI_1024x768) {
+	          SiS_ShiftXPos(SiS_Pr, 97);
+	       } else {
+	          SiS_ShiftXPos(SiS_Pr, 111);
+	       }
+	    } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+	       SiS_ShiftXPos(SiS_Pr, 136);
+	    }
+         }
+      }
+   }
+}
+#endif
+
 static void
 SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                  USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -8254,7 +7733,6 @@
   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
 }
 
-/* Set 301 VGA2 registers */
 static void
 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   	      USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
@@ -8265,14 +7743,12 @@
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
+  } else if(SiS_Pr->UseCustomMode) {
+     modeflag = SiS_Pr->CModeFlag;
+     resinfo = 0;
   } else {
-     if(SiS_Pr->UseCustomMode) {
-        modeflag = SiS_Pr->CModeFlag;
-	resinfo = 0;
-     } else {
-    	modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-     }
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
   if(HwInfo->jChipType >= SIS_315H) {
@@ -8298,7 +7774,7 @@
 #ifdef SET_EMI
 	   if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	   }
 #endif
@@ -8311,29 +7787,24 @@
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,temp);
 
   tempbx = SiS_Pr->SiS_RVBHCMAX;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
 
-  temp2 = (((tempbx & 0xFF00) >> 8) << 7) & 0x00ff;
+  temp2 = (tempbx >> 1) & 0x0080;
 
   tempcx = SiS_Pr->SiS_VGAHT - 1;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
 
-  temp = (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
-  temp2 |= temp;
+  temp2 |= (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
 
   tempcx = SiS_Pr->SiS_VGAVT - 1;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV))  tempcx -= 5;
-
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,temp);
+  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
 
-  temp = temp2 | ((tempcx & 0xFF00) >> 8);
+  temp = temp2 | (tempcx >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK)  tempbx >>= 1;
+  if(modeflag & HalfDCLK) tempbx >>= 1;
   if(HwInfo->jChipType >= SIS_661) {
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   }
@@ -8370,7 +7841,7 @@
   }
 
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
         temp |= 0x0A;
   }
 
@@ -8420,14 +7891,11 @@
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	if(tempax > 800) tempax -= 800;
-     } else {
+     } else /* if(SiS_Pr->SiS_VBInfo & TvNoHiviNoYPbPr) */ {    /* 651+301C */
         if(tempax > 800) {
 	   tempbx = 8;
-           if(tempax == 1024)
-	      tempax *= 25;
-           else
-	      tempax *= 20;
-
+           if(tempax == 1024) tempax *= 25;
+           else	              tempax *= 20;
 	   temp = tempax % 32;
 	   tempax /= 32;
 	   tempax--;
@@ -8436,9 +7904,10 @@
      }
      tempax--;
      temp = ((tempax & 0xFF00) >> 8) & 0x03;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* From 1.10.7w */
+     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);
@@ -8489,7 +7958,7 @@
 #ifdef SET_EMI
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
 #endif
@@ -8504,7 +7973,6 @@
 /*         SET PART 5 REGISTER GROUP         */
 /*********************************************/
 
-/* Set 301 Palette address port registers */
 static void
 SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
               PSIS_HW_INFO HwInfo)
@@ -8514,7 +7982,7 @@
 
   if(SiS_Pr->SiS_ModeType == ModeVGA) {
      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
-        SiS_EnableCRT2(SiS_Pr);
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
         SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
      }
   }
@@ -8532,11 +8000,8 @@
   USHORT ResIndex,DisplayType;
   const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+  if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+  else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
@@ -8544,7 +8009,9 @@
      return;
 
   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                          &ResIndex, &DisplayType))) return;
+                          &ResIndex, &DisplayType))) {
+     return;
+  }
 
   if(HwInfo->jChipType < SIS_315H) {
      if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
@@ -8552,16 +8019,16 @@
 
   switch(DisplayType) {
     case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
-    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
-    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
-    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
-    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
-    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
-    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
-    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
-    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
-    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
-    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
+    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
+    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
+    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
+    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
+    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
+    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
+    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
+    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
+    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
     case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
     case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
     case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
@@ -8600,7 +8067,7 @@
     default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
   }
 
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);                        /*unlock cr0-7  */
+  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
 
   tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
@@ -8635,12 +8102,6 @@
   tempah <<= 5;
   if(modeflag & DoubleScanMode)  tempah |= 0x080;
   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
-
-  /* 650/LVDS BIOS - doesn't make sense */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(modeflag & HalfDCLK)
-        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-  }
 }
 
 /*********************************************/
@@ -8655,7 +8116,7 @@
   USHORT clkbase, vclkindex=0;
   UCHAR  sr2b, sr2c;
 
-  if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel640x480) || (SiS_Pr->SiS_IF_DEF_TRUMPION == 1)) {
+  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
         if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
 	   RefreshRateTableIndex--;
@@ -8672,7 +8133,7 @@
   sr2c = SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if(SiS_Pr->SiS_UseROM) {
 	if(ROMAddr[0x220] & 0x01) {
            sr2b = ROMAddr[0x227];
 	   sr2c = ROMAddr[0x228];
@@ -8687,7 +8148,6 @@
      }
   }
 
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
   SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase,sr2b);
   SiS_SetReg(SiS_Pr->SiS_P3c4,clkbase+1,sr2c);
@@ -8712,9 +8172,9 @@
   const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
 
   if(ModeNo <= 0x13)
-    	tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
   else
-    	tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+     tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
   TVType = 0;
   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
@@ -8732,16 +8192,16 @@
 	}
   }
   switch(TVType) {
-    	case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
-    	case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
-    	case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
-    	case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-	case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
-    	case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
-    	case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
-    	case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
-	case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
-	default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+     case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+     case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
+     case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+     case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+     case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+     case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+     case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+     case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+     default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
   }
   resindex = tempcl & 0x3F;
 
@@ -9013,21 +8473,21 @@
   /* Set up Power up/down timing */
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
         else    			          tableptr = table1024_740;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
 	if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
         else					  tableptr = table1400_740;
      } else return;
   } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         tableptr = table1024_650;
-     } else if((SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) ||
-	       (SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200)) {
+     } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+	       (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
         tableptr = table1400_650;
      } else return;
   }
@@ -9063,45 +8523,35 @@
   int i;
 
   if(HwInfo->jChipType == SIS_740) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_740;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_740;
-     } else return;
-  } else {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
-        tableptr = table1024_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
-        tableptr = table1280_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
-        tableptr = table1400_650;
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) {
-        tableptr = table1600_650;
-     } else return;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_740;
+     else return;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_650;
+     else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) tableptr = table1600_650;
+     else return;
   }
 
   tempbh = SiS_GetCH701x(SiS_Pr,0x74);
   if((tempbh == 0xf6) || (tempbh == 0xc7)) {
      tempbh = SiS_GetCH701x(SiS_Pr,0x73);
      if(tempbh == 0xc8) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) return;
      } else if(tempbh == 0xdb) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) return;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) return;
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) return;
      } else if(tempbh == 0xde) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) return;
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) return;
      }
   }
 
-  if(HwInfo->jChipType == SIS_740) {
-     tempbh = 0x0d;
-  } else {
-     tempbh = 0x0c;
-  }
+  if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
+  else     			   tempbh = 0x0c;
+
   for(i = 0; i < tempbh; i++) {
      SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
   }
@@ -9488,13 +8938,12 @@
 
    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
 
-   /* Set up Panel Link for LVDS, 301BDH and 30xLV(for LCDA) */
+   /* Set up Panel Link for LVDS and LCDA */
+   SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
        ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
       SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-   } else {
-      SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    }
 
 #ifdef LINUX_XF86
@@ -9521,11 +8970,16 @@
 #endif
       	   SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
       	   SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+#ifdef SIS315H
+	   SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+#endif
       	   SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
 
+	   SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
 	   /* For 301BDH (Panel link initialization): */
 	   if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-	      if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
+	      if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
 		 if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
 		    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 		       SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
@@ -9540,28 +8994,25 @@
 
    } else {
 
-        if(SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel640x480) {
-	   if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
-    	      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
-	                      RefreshRateTableIndex,HwInfo);
-	   }
+        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+
+        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+    	   SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 	}
 
-        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
-	                RefreshRateTableIndex,HwInfo);
+        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
 
 	if(SiS_Pr->SiS_SetFlag & LowModeTests) {
      	   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 	      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 	         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-#ifdef SIS315H		 
+#ifdef SIS315H
 		    SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
-#endif		    
+#endif
 		 }
 	      }
 	      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,
-		               RefreshRateTableIndex);
+       		 SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
 	      }
      	   }
 	}
@@ -9572,7 +9023,7 @@
    if(HwInfo->jChipType < SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(SiS_Pr->SiS_UseOEM) {
-	    if((SiS_Pr->SiS_UseROM) && ROMAddr && (SiS_Pr->SiS_UseOEM == -1)) {
+	    if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
 	       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	          SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
 	       			    RefreshRateTableIndex);
@@ -9605,13 +9056,11 @@
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 	 if(HwInfo->jChipType < SIS_661) {
 	    SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-            if(SiS_Pr->SiS_UseOEM) {
-               SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
-            }
+            SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
 	 } else {
 	    SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 	 }
-         SiS_CRT2AutoThreshold(SiS_Pr);
+         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
       }
    }
 #endif
@@ -9625,7 +9074,7 @@
    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 	 /* Disable LCD panel when using TV */
-	 SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x11,0x0C);
+	 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
       } else {
 	 /* Disable TV when using LCD */
 	 SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
@@ -9648,6 +9097,7 @@
 SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
   /* Switch on LCD backlight on SiS30xLV */
+  SiS_DDC2Delay(SiS_Pr,0xff00);
   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
      SiS_WaitVBRetrace(SiS_Pr,HwInfo);
@@ -9663,12 +9113,81 @@
   /* Switch off LCD backlight on SiS30xLV */
   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+  SiS_DDC2Delay(SiS_Pr,0xe000);
 }
 
 /*********************************************/
 /*          DDC RELATED FUNCTIONS            */
 /*********************************************/
 
+static void
+SiS_SetupDDCN(SiS_Private *SiS_Pr)
+{
+  SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
+  SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
+  if((SiS_Pr->SiS_DDC_Index == 0x11) && (SiS_Pr->SiS_SensibleSR11)) {
+     SiS_Pr->SiS_DDC_NData &= 0x0f;
+     SiS_Pr->SiS_DDC_NClk  &= 0x0f;
+  }
+}
+
+#ifdef SIS300
+static UCHAR *
+SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  int i, j, num;
+  USHORT tempah,temp;
+  UCHAR *mydataptr;
+
+  for(i=0; i<20; i++) {				/* Do 20 attempts to write */
+     mydataptr = dataptr;
+     num = *mydataptr++;
+     if(!num) return mydataptr;
+     if(i) {
+        SiS_SetStop(SiS_Pr);
+	SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;		/* Set start condition */
+     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write DAB (S0=0=write) */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     tempah = *mydataptr++;
+     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);	/* Write register number */
+     if(temp) continue;				/*    (ERROR: no ack) */
+     for(j=0; j<num; j++) {
+        tempah = *mydataptr++;
+        temp = SiS_WriteDDC2Data(SiS_Pr,tempah);/* Write DAB (S0=0=write) */
+	if(temp) break;
+     }
+     if(temp) continue;
+     if(SiS_SetStop(SiS_Pr)) continue;
+     return mydataptr;
+  }
+  return NULL;
+}
+
+static BOOLEAN
+SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+
+  SiS_SetSwitchDDC2(SiS_Pr);
+
+  while(*dataptr) {
+     dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
+     if(!dataptr) return FALSE;
+  }
+#ifdef TWDEBUG
+  xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
+#endif
+  return TRUE;
+}
+#endif
+
 /* The Chrontel 700x is connected to the 630/730 via
  * the 630/730's DDC/I2C port.
  *
@@ -9704,18 +9223,32 @@
   return FALSE;
 }
 
+#ifdef SIS300
+/* Write Trumpion register */
+void
+SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
+  SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;              	/* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;              	/* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_SetChReg(SiS_Pr, tempbx, 0);
+}
+#endif
+
 /* Write to Chrontel 700x */
 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
 void
 SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
 
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
   }
 
   if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
@@ -9723,6 +9256,7 @@
      SiS_Pr->SiS_DDC_Index = 0x0a;		/* Bit 7 = SC;  Bit 6 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x80;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x40;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
 
      SiS_SetChReg(SiS_Pr, tempbx, 0x80);
   }
@@ -9736,19 +9270,18 @@
   SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
+  SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;  		/* DAB (Device Address Byte) */
-
   SiS_SetChReg(SiS_Pr, tempbx, 0);
 }
 
 void
 SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      SiS_SetCH700x(SiS_Pr,tempbx);
-   else
-      SiS_SetCH701x(SiS_Pr,tempbx);
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     SiS_SetCH700x(SiS_Pr,tempbx);
+  else
+     SiS_SetCH701x(SiS_Pr,tempbx);
 }
 
 static USHORT
@@ -9780,6 +9313,21 @@
   return 0xFFFF;
 }
 
+#ifdef SIS300
+/* Read from Trumpion */
+USHORT
+SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
+{
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;	/* DAB */
+  SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
+  SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
+  SiS_SetupDDCN(SiS_Pr);
+  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
+  return(SiS_GetChReg(SiS_Pr,0));
+}
+#endif
+
 /* Read from Chrontel 700x */
 /* Parameter is [Register no (S7-S0)] */
 USHORT
@@ -9787,13 +9335,13 @@
 {
   USHORT result;
 
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
 
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;		/* Bit 0 = SC;  Bit 1 = SD */
      SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
      SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_SetupDDCN(SiS_Pr);
   }
 
   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
@@ -9804,6 +9352,7 @@
      SiS_Pr->SiS_DDC_Index = 0x0a;
      SiS_Pr->SiS_DDC_Data  = 0x80;
      SiS_Pr->SiS_DDC_Clk   = 0x40;
+     SiS_SetupDDCN(SiS_Pr);
 
      result = SiS_GetChReg(SiS_Pr,0x80);
   }
@@ -9818,7 +9367,7 @@
   SiS_Pr->SiS_DDC_Index = 0x11;			/* Bit 0 = SC;  Bit 1 = SD */
   SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
   SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
-  SiS_Pr->SiS_DDC_DataShift = 0x00;
+  SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;		/* DAB */
 
   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
@@ -9831,10 +9380,10 @@
 USHORT
 SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
 {
-   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-      return(SiS_GetCH700x(SiS_Pr, tempbx));
-   else
-      return(SiS_GetCH701x(SiS_Pr, tempbx));
+  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
+     return(SiS_GetCH700x(SiS_Pr, tempbx));
+  else
+     return(SiS_GetCH701x(SiS_Pr, tempbx));
 }
 
 /* Our own DDC functions */
@@ -9942,6 +9491,8 @@
     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
 
+    SiS_SetupDDCN(SiS_Pr);
+
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
     		SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
@@ -9986,11 +9537,15 @@
 {
    SiS_SetSCLKLow(SiS_Pr);
    if(yesno) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data, SiS_Pr->SiS_DDC_Data);
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);
    } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data, 0);
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      0);
    }
    SiS_SetSCLKHigh(SiS_Pr);
 }
@@ -10215,6 +9770,8 @@
    for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
    SiS_Pr->CP_HaveCustomData = FALSE;
    SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
+   SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
+   SiS_Pr->CP_PreferredIndex = -1;
 
    if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
    if(pSiS->VBFlags & VB_30xBDH) return 0;
@@ -10309,12 +9866,14 @@
 	 SiS_Pr->CP_PreferredY = yres;
 
          switch(xres) {
+#if 0	    /* Treat as custom */
             case 800:
 	        if(yres == 600) {
 	     	   paneltype = Panel_800x600;
 	     	   checkexpand = TRUE;
 	        }
 	        break;
+#endif
             case 1024:
 	        if(yres == 768) {
 	     	   paneltype = Panel_1024x768;
@@ -10352,9 +9911,11 @@
 #if 0	    /* Treat this as custom, as we have no valid timing data yet */
 	    case 1600:
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
-	           if(yres == 1200) {
-	              paneltype = Panel310_1600x1200;
-		      checkexpand = TRUE;
+		   if(pSiS->VBFlags & VB_301C) {
+	              if(yres == 1200) {
+	                 paneltype = Panel310_1600x1200;
+		         checkexpand = TRUE;
+		      }
 	           }
 	        }
       	        break;
@@ -10480,6 +10041,10 @@
 	          if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
 		  if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+		  if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
+	             SiS_Pr->CP_PreferredIndex = i;
+	          }
+
 		  SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
 		  SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
 
@@ -10560,28 +10125,20 @@
       SiS_Pr->CP_MaxX = xres = buffer[0x76] | (buffer[0x77] << 8);
       SiS_Pr->CP_MaxY = yres = buffer[0x78] | (buffer[0x79] << 8);
       switch(xres) {
+#if 0
          case 800:
 	     if(yres == 600) {
 	     	paneltype = Panel_800x600;
 	     	checkexpand = TRUE;
 	     }
 	     break;
+#endif
          case 1024:
 	     if(yres == 768) {
 	     	paneltype = Panel_1024x768;
 	     	checkexpand = TRUE;
 	     }
 	     break;
-	 case 1152:
-	     if(yres == 768) {
-	        if(pSiS->VGAEngine == SIS_300_VGA) {
-		   paneltype = Panel300_1152x768;
-		} else {
-		   paneltype = Panel310_1152x768;
-		}
-	     	checkexpand = TRUE;
-	     }
-	     break;
 	 case 1280:
 	     if(yres == 960) {
 	        if(pSiS->VGAEngine == SIS_315_VGA) {
@@ -10606,9 +10163,11 @@
 #if 0    /* Treat this one as custom since we have no timing data yet */
 	 case 1600:
 	     if(pSiS->VGAEngine == SIS_315_VGA) {
-	        if(yres == 1200) {
-	           paneltype = Panel310_1600x1200;
-		   checkexpand = TRUE;
+	        if(pSiS->VBFlags & VB_301C) {
+	           if(yres == 1200) {
+	              paneltype = Panel310_1600x1200;
+		      checkexpand = TRUE;
+		   }
 	        }
 	     }
       	     break;
@@ -10710,6 +10269,10 @@
 
 	       if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
 
+	       if((SiS_Pr->CP_MaxX == xres) && (SiS_Pr->CP_MaxY == yres)) {
+	          SiS_Pr->CP_PreferredIndex = i;
+	       }
+
 	       SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
 	       SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
 	       SiS_Pr->CP_SyncValid[i] = TRUE;
@@ -10764,10 +10327,11 @@
    if(paneltype) {
        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
-       cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf1,cr37);
        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
+       cr37 &= 0xf1;
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf3,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);
@@ -10861,7 +10425,7 @@
    }
 
    if(foundcrt) {
-       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
+      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
    }
    return(0);
 }
@@ -10903,11 +10467,15 @@
 SiS_SetStart(SiS_Private *SiS_Pr)
 {
   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			           /* (SC->low)  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);             /* SD->high */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+    		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);             			   /* SD->high */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* SC->high */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,0x00);                             /* SD->low = start condition */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  0x00);                             			   /* SD->low = start condition */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* (SC->low) */
   return 0;
 }
@@ -10918,11 +10486,15 @@
 SiS_SetStop(SiS_Private *SiS_Pr)
 {
   if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;			           /* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,0x00);          		   /* SD->low   */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  	          SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  0x00);          		   			   /* SD->low   */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* SC->high  */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);  	   /* SD->high = stop condition */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);  	   			   /* SD->high = stop condition */
   if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;			           /* (SC->high) */
   return 0;
 }
@@ -10937,11 +10509,15 @@
   for(i=0; i<8; i++) {
     SiS_SetSCLKLow(SiS_Pr);				                      /* SC->low */
     if(tempax & flag) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);            /* Write bit (1) to SD */
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      SiS_Pr->SiS_DDC_Data);            		      /* Write bit (1) to SD */
     } else {
-      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                      ~SiS_Pr->SiS_DDC_Data,0x00);                            /* Write bit (0) to SD */
+      SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+      		      SiS_Pr->SiS_DDC_Index,
+                      SiS_Pr->SiS_DDC_NData,
+		      0x00);                            		      /* Write bit (0) to SD */
     }
     SiS_SetSCLKHigh(SiS_Pr);				                      /* SC->high */
     flag >>= 1;
@@ -10959,8 +10535,10 @@
   for(i=0; i<8; i++) {
     getdata <<= 1;
     SiS_SetSCLKLow(SiS_Pr);
-    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                    ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);
+    SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+    		    SiS_Pr->SiS_DDC_Index,
+                    SiS_Pr->SiS_DDC_NData,
+		    SiS_Pr->SiS_DDC_Data);
     SiS_SetSCLKHigh(SiS_Pr);
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
@@ -10971,8 +10549,10 @@
 USHORT
 SiS_SetSCLKLow(SiS_Private *SiS_Pr)
 {
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Clk,0x00);      		/* SetSCLKLow()  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NClk,
+		  0x00);      					/* SetSCLKLow()  */
   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
   return 0;
 }
@@ -10982,8 +10562,10 @@
 {
   USHORT temp, watchdog=1000;
 
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Clk,SiS_Pr->SiS_DDC_Clk);  	/* SetSCLKHigh()  */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NClk,
+		  SiS_Pr->SiS_DDC_Clk);  			/* SetSCLKHigh()  */
   do {
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
@@ -11005,10 +10587,12 @@
   USHORT tempah;
 
   SiS_SetSCLKLow(SiS_Pr);				           /* (SC->low) */
-  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index,
-                  ~SiS_Pr->SiS_DDC_Data,SiS_Pr->SiS_DDC_Data);     /* (SD->high) */
+  SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
+  		  SiS_Pr->SiS_DDC_Index,
+                  SiS_Pr->SiS_DDC_NData,
+		  SiS_Pr->SiS_DDC_Data);     			   /* (SD->high) */
   SiS_SetSCLKHigh(SiS_Pr);				           /* SC->high = clock impulse for ack */
-  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);/* Read SD */
+  tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
   SiS_SetSCLKLow(SiS_Pr);				           /* SC->low = end of clock impulse */
   if(tempah & SiS_Pr->SiS_DDC_Data) return(1);			   /* Ack OK if bit = 0 */
   else return(0);
@@ -11028,13 +10612,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x128] | (ROMAddr[0x129] << 8);
+     romptr = SISGETROMW(0x128);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x12a] | (ROMAddr[0x12b] << 8);
+        romptr = SISGETROMW(0x12a);
   } else {
-     romptr = ROMAddr[0x1a8] | (ROMAddr[0x1a9] << 8);
+     romptr = SISGETROMW(0x1a8);
      if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
-        romptr = ROMAddr[0x1aa] | (ROMAddr[0x1ab] << 8);
+        romptr = SISGETROMW(0x1aa);
   }
   return(romptr);
 }
@@ -11046,13 +10630,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
+     romptr = SISGETROMW(0x120);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+        romptr = SISGETROMW(0x122);
   } else {
-     romptr = ROMAddr[0x1a0] | (ROMAddr[0x1a1] << 8);
+     romptr = SISGETROMW(0x1a0);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x1a2] | (ROMAddr[0x1a3] << 8);
+        romptr = SISGETROMW(0x1a2);
   }
   return(romptr);
 }
@@ -11064,13 +10648,13 @@
   USHORT romptr;
 
   if(HwInfo->jChipType < SIS_330) {
-     romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);
+     romptr = SISGETROMW(0x114);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+        romptr = SISGETROMW(0x11a);
   } else {
-     romptr = ROMAddr[0x194] | (ROMAddr[0x195] << 8);
+     romptr = SISGETROMW(0x194);
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
-        romptr = ROMAddr[0x19a] | (ROMAddr[0x19b] << 8);
+        romptr = SISGETROMW(0x19a);
   }
   return(romptr);
 }
@@ -11092,9 +10676,9 @@
      }
   }
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050)      index -= 5;
-  else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1600x1200) index -= 6;
+  index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
+  else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
   index--;
   index *= 3;
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -11107,12 +10691,9 @@
 {
   USHORT index;
 
-  index = SiS_Pr->SiS_LCDResInfo & 0x0F;
-  index--;
-  index *= 3;
-  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
+  index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
+  if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
   else if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) index++;
-
   return index;
 }
 
@@ -11122,8 +10703,10 @@
   USHORT index;
 
   index = 0;
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) index++;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index++;  /* HiVision uses PAL */
+  if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) index = 2;
+
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) index = 0;
 
   index <<= 1;
 
@@ -11136,7 +10719,7 @@
 }
 
 static ULONG
-GetOEMTVPtr661_2(SiS_Private *SiS_Pr)
+GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
 {
    USHORT index = 0, temp = 0;
 
@@ -11153,7 +10736,7 @@
    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-	 index += 8;
+	 index += addme;
 	 temp++;
       }
       temp += 0x0100;
@@ -11161,16 +10744,37 @@
    return(ULONG)(index | (temp << 16));
 }
 
+static ULONG
+GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+}
+
+#if 0
+static ULONG
+GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+{
+   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+}
+#endif
+
 static int
 GetOEMTVPtr661(SiS_Private *SiS_Pr)
 {
    int index = 0;
 
-   if(SiS_Pr->SiS_TVMode & TVSetPAL)       index = 2;
-   if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
-   if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   if(SiS_Pr->SiS_TVMode & TVSetPAL)          index = 2;
+   if(SiS_Pr->SiS_ROMNew) {
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 10;
+   } else {
+      if(SiS_Pr->SiS_TVMode & TVSetHiVision)  index = 4;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) index = 6;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) index = 8;
+      if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) index = 10;
+   }
 
    if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) index++;
 
@@ -11184,15 +10788,21 @@
   USHORT delay=0,index,myindex,temp,romptr=0;
   BOOLEAN dochiptest = TRUE;
 
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
+  } else {
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x35,0x7f);
+  }
+
   /* Find delay (from ROM, internal tables, PCI subsystem) */
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {			/* ------------ VGA */
      
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
         romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
-	if(!romptr) return;
-	delay = ROMAddr[romptr];
-     } else {
+     }
+     if(romptr) delay = ROMAddr[romptr];
+     else {
         delay = 0x04;
         if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
 	   if(IS_SIS650) {
@@ -11204,8 +10814,7 @@
 	   } else {
 	      delay = 0x0c;
 	   }
-	}
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+	} else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
            delay = 0x00;
 	}
      }
@@ -11214,13 +10823,39 @@
 
      BOOLEAN gotitfrompci = FALSE;
 
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+     /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
+
+     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	if(SiS_Pr->PDC != -1) {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((SiS_Pr->PDC >> 1) & 0x0f));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((SiS_Pr->PDC & 0x01) << 7));
+	   return;
+	}
+     } else {
+	if(SiS_Pr->PDCA != -1) {
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDCA << 3) & 0xf0));
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((SiS_Pr->PDCA & 0x01) << 6));
+	   return;
+	}
+     }
 
-     /* Could we detect a PDC for LCD? If yes, use it */
+     /* Custom Panel? */
 
-     if(SiS_Pr->PDC) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) {
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((SiS_Pr->PDC & 0x0f) << 4));
+	   delay = 0x00;
+	   if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	      delay = 0x20;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
+	} else {
+	   delay = 0x0c;
+	   if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
+	   else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = 0x03;
+	   }
+	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,delay);
 	}
         return;
      }
@@ -11233,7 +10868,7 @@
      switch(SiS_Pr->SiS_CustomT) {
      case CUT_COMPAQ1280:
      case CUT_COMPAQ12802:
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x03;
@@ -11241,15 +10876,13 @@
 	break;
      case CUT_CLEVO1400:
      case CUT_CLEVO14002:
-	/* if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) { */
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
-	   delay = 0x02;
-	/* } */
+	gotitfrompci = TRUE;
+	dochiptest = FALSE;
+	delay = 0x02;
 	break;
      case CUT_CLEVO1024:
      case CUT_CLEVO10242:
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   gotitfrompci = TRUE;
 	   dochiptest = FALSE;
 	   delay = 0x33;
@@ -11270,21 +10903,16 @@
 
            if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
 
-              if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-#if 0	         /* Always use the second pointer on 650; some BIOSes */
+              if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	         /* Always use the second pointer on 650; some BIOSes */
                  /* still carry old 301 data at the first location    */
-	         romptr = ROMAddr[0x120] | (ROMAddr[0x121] << 8);
-	         if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-#endif
-	            romptr = ROMAddr[0x122] | (ROMAddr[0x123] << 8);
+	         /* romptr = SISGETROMW(0x120);                       */
+	         /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	         romptr = SISGETROMW(0x122);
 	         if(!romptr) return;
 	         delay = ROMAddr[(romptr + index)];
 	      } else {
-                 delay = SiS310_LCDDelayCompensation_650301B[myindex];
-#if 0
-	         if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-	            delay = SiS310_LCDDelayCompensation_650301B[myindex];
-#endif
+                 delay = SiS310_LCDDelayCompensation_650301LV[myindex];
 	      }
 
           } else {
@@ -11295,34 +10923,34 @@
 
           }
 
-        } else if((ROMAddr) && SiS_Pr->SiS_UseROM &&
-	          (SiS_Pr->SiS_LCDResInfo != SiS_Pr->SiS_Panel1280x1024)) {
+        } else if(SiS_Pr->SiS_UseROM 			      &&
+		  (!(SiS_Pr->SiS_ROMNew))		      &&
+	          (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
+		  (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
 
+	   /* Data for 1280x1024 wrong in 301B BIOS */
            romptr = GetLCDromptr(SiS_Pr, HwInfo);
 	   if(!romptr) return;
 	   delay = ROMAddr[(romptr + index)];
 
         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-	   if(IS_SIS650) {
-              delay = SiS310_LCDDelayCompensation_LVDS650[myindex];
-	   } else {
-	      delay = SiS310_LCDDelayCompensation_LVDS740[myindex];
-	   }
+	   if(IS_SIS740) delay = 0x03;
+	   else          delay = 0x00;
 
 	} else {
 
            delay = SiS310_LCDDelayCompensation_301[myindex];
-           if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-#if 0 	      /* This data is (like the one in the BIOS) wrong. */
-	      if(IS_SIS550650740660) {
-	         delay = SiS310_LCDDelayCompensation_650301B[myindex];
-	      } else {
-#endif
-                 delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
-#if 0
-	      }
-#endif
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	      if(IS_SIS740) delay = 0x01;  /* ? */
+	      else          delay = 0x03;
+	   } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	      if(IS_SIS740) delay = 0x01;
+	      else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
 	   }
 
         }
@@ -11342,23 +10970,19 @@
 
         if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
 
-           if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-#if 0	      /* Always use the second pointer on 650; some BIOSes */
+           if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
+	      /* Always use the second pointer on 650; some BIOSes */
               /* still carry old 301 data at the first location    */
-              romptr = ROMAddr[0x114] | (ROMAddr[0x115] << 8);
-	      if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-#endif
-	         romptr = ROMAddr[0x11a] | (ROMAddr[0x11b] << 8);
+              /* romptr = SISGETROMW(0x114);			   */
+	      /* if(SiS_Pr->SiS_VBType & VB_SIS302LV)              */
+	      romptr = SISGETROMW(0x11a);
 	      if(!romptr) return;
 	      delay = ROMAddr[romptr + index];
 
 	   } else {
 
 	      delay = SiS310_TVDelayCompensation_301B[index];
-#if 0
-	      if(SiS_Pr->SiS_VBType & VB_SIS302LV)
-	         delay = SiS310_TVDelayCompensation_301B[index];
-#endif		
+
 	   }
 
         } else {
@@ -11384,7 +11008,7 @@
 	   }
         }
 
-     } else if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+     } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 
         romptr = GetTVromptr(SiS_Pr, HwInfo);
 	if(!romptr) return;
@@ -11400,14 +11024,16 @@
         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 	   if(IS_SIS740) {
 	      delay = SiS310_TVDelayCompensation_740301B[index];
+	      /* LV: use 301 data? BIOS bug? */
 	   } else {
               delay = SiS310_TVDelayCompensation_301B[index];
+	      if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x02;
 	   }
 	}
 
      }
 
-     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) {  /* LCDA */
+     if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
 	delay &= 0x0f;
 	dochiptest = FALSE;
      }
@@ -11470,18 +11096,21 @@
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
 
   temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  	  /* 0: NTSC, 1: PAL, 2: HiTV */
+  temp >>= 1;  	  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
   temp1 = temp;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x260] | (ROMAddr[0x261] << 8);
-	temp1 = GetOEMTVPtr661(SiS_Pr);
+        temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
+        romptr = SISGETROMW(0x260);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x360);
+	}
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x192] | (ROMAddr[0x193] << 8);
+        romptr = SISGETROMW(0x192);
      } else {
-        romptr = ROMAddr[0x112] | (ROMAddr[0x113] << 8);
+        romptr = SISGETROMW(0x112);
      }
   }
 
@@ -11503,24 +11132,25 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,temp1,romptr=0;
 
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;              	/* 0: NTSC, 1: PAL, 2: HiTV */
-  temp1 = temp;
+  temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1; 	/* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
-  if(ModeNo<=0x13)
+  if(ModeNo <= 0x13)
      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
   else
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
 
-  if(ROMAddr && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
      if(HwInfo->jChipType >= SIS_661) {
-	romptr = ROMAddr[0x26c] | (ROMAddr[0x26d] << 8);
+        romptr = SISGETROMW(0x26c);
+        if(HwInfo->jChipType >= SIS_760) {
+	   romptr = SISGETROMW(0x36c);
+	}
 	temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
      } else if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x1a4] | (ROMAddr[0x1a5] << 8);
+        romptr = SISGETROMW(0x1a4);
      } else {
-        romptr = ROMAddr[0x124] | (ROMAddr[0x125] << 8);
+        romptr = SISGETROMW(0x124);
      }
   }
 
@@ -11538,62 +11168,15 @@
 SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
            USHORT ModeNo,USHORT ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index, myindex, oldindex,temp, i, j, flag1 = 0, flag2 = 0, romptr = 0;
-  ULONG  lindex;
+  USHORT index, temp, i, j;
 
-  if(ModeNo<=0x13) {
-    index =  SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+  if(ModeNo <= 0x13) {
+     index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
   } else {
-    index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
-  }
-
-  oldindex = index;
-
-  if((HwInfo->jChipType >= SIS_661) && ROMAddr && SiS_Pr->SiS_UseROM) {
-     if(ModeNo > 0x13) {
-        index =  SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndexROM661;
-     }
-     lindex = GetOEMTVPtr661_2(SiS_Pr);
-     if(lindex & 0x00ff0000) flag1 = 1;
-     if(lindex & 0xff000000) flag2 = 1;
-     lindex &= 0xffff;
-
-     /* NTSC-J: Use PAL filters */
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) lindex = 1;
-
-     romptr = ROMAddr[0x268] | (ROMAddr[0x269] << 8);
-     if(flag1) myindex = index * 7;
-     else      myindex = index << 2;
-
-     if(romptr) {
-        romptr += (lindex << 1);
-        romptr = (ROMAddr[romptr] | (ROMAddr[romptr+1] << 8)) + myindex;
-	if(romptr) {
-           if((!flag1) && (flag2)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x35,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x36,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,0x00);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,ROMAddr[romptr++]);
-           } else {
-	      for(i=0x35; i<=0x38; i++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	      for(j=0, i=0x48; i<=0x4a; i++, j++) {
-                 SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr++]);
-              }
-           }
-           return;
-	}
-     }
+     index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
   }
 
-  index = oldindex;
-
-  temp = GetTVPtrIndex(SiS_Pr);
-  temp >>= 1;  			/* 0: NTSC, 1: PAL, 2: HiTV */
+  temp = GetTVPtrIndex(SiS_Pr) >> 1;  /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ)	     temp = 1;  /* NTSC-J uses PAL */
   else if(SiS_Pr->SiS_TVMode & TVSetPALM)    temp = 3;  /* PAL-M */
@@ -11627,21 +11210,11 @@
   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
 
-  if(HwInfo->jChipType >= SIS_661) {
-     lindex = GetOEMTVPtr661_2(SiS_Pr) & 0xffff;
+  if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+     lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
      lindex <<= 2;
-     if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-        romptr = ROMAddr[0x264] | (ROMAddr[0x265] << 8);
-     }
-     if(romptr) {
-	romptr += lindex;
-	for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
-        }
-     } else {
-        for(j=0, i=0x31; i<=0x34; i++, j++) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
-        }
+     for(j=0, i=0x31; i<=0x34; i++, j++) {
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
      }
      return;
   }
@@ -11659,20 +11232,20 @@
   /* 0: NTSC Graphics, 1: NTSC Text,    2: PAL Graphics,
    * 3: PAL Text,      4: HiTV Graphics 5: HiTV Text
    */
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-     romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+  if(SiS_Pr->SiS_UseROM) {
+     romptr = SISGETROMW(0x116);
      if(HwInfo->jChipType >= SIS_330) {
-        romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+        romptr = SISGETROMW(0x196);
      }
      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-        romptr = ROMAddr[0x11c] | (ROMAddr[0x11d] << 8);
+        romptr = SISGETROMW(0x11c);
 	if(HwInfo->jChipType >= SIS_330) {
-	   romptr = ROMAddr[0x19c] | (ROMAddr[0x19d] << 8);
+	   romptr = SISGETROMW(0x19c);
 	}
 	if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
-	   romptr = ROMAddr[0x116] | (ROMAddr[0x117] << 8);
+	   romptr = SISGETROMW(0x116);
 	   if(HwInfo->jChipType >= SIS_330) {
-              romptr = ROMAddr[0x196] | (ROMAddr[0x197] << 8);
+              romptr = SISGETROMW(0x196);
            }
 	}
      }
@@ -11695,19 +11268,19 @@
      }
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     if((!(SiS_Pr->SiS_TVMode & TVSetPAL)) && (ModeNo > 0x13)) {
+  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+     if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
         if((resinfo == SIS_RI_640x480) ||
 	   (resinfo == SIS_RI_800x600)) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
-	} else if (resinfo == SIS_RI_1024x768) {
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
-	      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x21);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0xf0);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xf5);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7f);
+	} else if(resinfo == SIS_RI_1024x768) {
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x31,0x1e);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x32,0x8b);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x33,0xfb);
+	   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x34,0x7b);
 	}
      }
   }
@@ -11722,12 +11295,12 @@
    if(SiS_Pr->UseCustomMode) return;
 
    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-       SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
-          SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-       }
+      SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      if(SiS_Pr->SiS_VBType & VB_SIS301) {
+         SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      }
    }
 }
 
@@ -11735,65 +11308,104 @@
 SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
                 USHORT ModeIdIndex, USHORT RTI)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
    USHORT delay = 0, romptr = 0, index;
-   UCHAR  *myptr = NULL;
-   UCHAR  temp;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
 
    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
       return;
 
-   delay = SiS_Pr->SiS_RefIndex[RTI].Ext_PDC;
+   /* 1. New ROM: VGA2 and LCD/LCDA-Pass1:1 */
+
+   if(SiS_Pr->SiS_ROMNew) {
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) 			||
+         ((SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+	  (SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+         index = 25;
+         if(SiS_Pr->UseCustomMode) {
+	    index = SiS_Pr->CSRClock;
+         } else if(ModeNo > 0x13) {
+            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+            index = SiS_Pr->SiS_VCLKData[index].CLOCK;
+         }
+	 if(index < 25) index = 25;
+         index = ((index / 25) - 1) << 1;
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) index++;
+	 romptr = SISGETROMW(0x104);  /* 0x4ae */
+         delay = ROMAddr[romptr + index];
+         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
+         } else {
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+         }
+         return;
+      }
+   }
+
+   /* 2. Old ROM: VGA2 and LCD/LCDA-Pass 1:1 */
 
-   delay &= 0xf0;
-   delay >>= 4;
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) delay <<= 12;  /* BIOS: 8, wrong */
+   if(SiS_Pr->UseCustomMode) delay = 0x04;
+   else if(ModeNo <= 0x13)   delay = 0x04;
+   else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
+   delay |= (delay << 8);
 
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+      /* 3. TV */
+
       index = GetOEMTVPtr661(SiS_Pr);
-      if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-         romptr = ROMAddr[0x25c] | (ROMAddr[0x25d] << 8);
-         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-            romptr = ROMAddr[0x25e] | (ROMAddr[0x25f] << 8);
-         }
-      }
-      if(romptr) myptr = &ROMAddr[romptr];
-      if(!myptr) {
-         myptr = (UCHAR *)SiS_TVDelay661_301;
-	 if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-	    myptr = (UCHAR *)SiS_TVDelay661_301B;
-	 }
+      if(SiS_Pr->SiS_ROMNew) {
+         romptr = SISGETROMW(0x106);  /* 0x4ba */
+         delay = ROMAddr[romptr + index];
+      } else {
+         delay = 0x04;
       }
-      delay = myptr[index];
-      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) delay >>= 4;  /* Should test dual edge */
+
    } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-      if(SiS_Pr->PDC) {
-         delay = SiS_Pr->PDC & 0x0f;
-	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 12);
-         }
-      } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) {
-         delay = 0x4444;  /* TEST THIS */
-      } else if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-         myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-         if(myptr) delay = myptr[4];
-         else delay = 0x44;
-         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            delay |= (delay << 8);
+
+      /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
+
+      if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
+          ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+
+	 /* For LV, the BIOS must know about the correct value */
+	 delay = ROMAddr[romptr + 0x0d];		/* LCD  */
+	 delay |= (ROMAddr[romptr + 0x0c] << 8);	/* LCDA */
+
+      } else {
+
+         /* TMDS: Set our own, since BIOS has no idea - TODO: Find out about values */
+         if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+            if((SiS_Pr->PanelXRes <= 1024) && (SiS_Pr->PanelYRes <= 768)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1280) && (SiS_Pr->PanelYRes <= 1024)) {
+	       delay = 0x0404;
+            } else if((SiS_Pr->PanelXRes <= 1400) && (SiS_Pr->PanelYRes <= 1050)) {
+	       delay = 0x1004;
+            } else
+	       delay = 0x0000;
          }
+
       }
-   }
 
-   temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2d);
-   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToRAMDAC)) {
-      temp &= 0xf0;
-      temp |= (delay & 0x000f);
+      /* 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) {
-      temp &= 0x0f;
-      temp |= ((delay & 0xf000) >> 8);
+      delay >>= 8;
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,((delay << 3) & 0xf0));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x20,0xbf,((delay & 0x01) << 6));
+   } else {
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0xf0,((delay >> 1) & 0x0f));
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,0x7f,((delay & 0x01) << 7));
    }
-   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,temp);
 }
 
 static void
@@ -11802,38 +11414,50 @@
    USHORT infoflag;
    UCHAR temp;
 
-   infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
-   if(ModeNo <= 0x13) {
-      infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
-   }
-   infoflag &= 0xc0;
    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+
+      if(ModeNo <= 0x13) {
+         infoflag = SiS_GetRegByte(SiS_Pr->SiS_P3ca+2);
+      } else if(SiS_Pr->UseCustomMode) {
+         infoflag = SiS_Pr->CInfoFlag;
+      } else {
+         infoflag = SiS_Pr->SiS_RefIndex[RTI].Ext_InfoFlag;
+      }
+      infoflag &= 0xc0;
+
       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-      if(temp & 0x20) infoflag = temp;
+      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+         temp &= 0x3f;
+	 temp |= infoflag;
+      } else {
+         if(temp & 0x20) infoflag = temp;
+      }
       if(temp & 0x01) infoflag |= 0x01;
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-      temp = 0x0c;
-      if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
-      temp |= (infoflag >> 6);
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
-   }
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      temp = 0;
-      if(infoflag & 0x01) temp |= 0x80;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
-      temp = 0x30;
-      if(infoflag & 0x01) temp = 0x20;
-      infoflag &= 0xc0;
-      temp |= infoflag;
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+         temp = 0x0c;
+         if(infoflag & 0x01) temp ^= 0x14;  /* BIOS: 18, wrong */
+         temp |= (infoflag >> 6);
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xe0,temp);
+      } else {
+         temp = 0;
+         if(infoflag & 0x01) temp |= 0x80;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1a,0x7f,temp);
+         temp = 0x30;
+         if(infoflag & 0x01) temp = 0x20;
+         infoflag &= 0xc0;
+         temp |= infoflag;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0f,temp);
+      }
+
    }
 }
 
 static void
 SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   UCHAR *myptr;
+   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   USHORT romptr, temp1, temp2;
 
    if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
       if(SiS_Pr->LVDSHL != -1) {
@@ -11841,16 +11465,22 @@
       }
    }
 
-   myptr = GetLCDStructPtr661(SiS_Pr, HwInfo);
-   if(myptr) {
-      if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
-         if(SiS_Pr->LVDSHL == -1) {
-            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE0,myptr[1] & 0x1f);
-	 } else {
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xE3,myptr[1] & 0x1c);
-	 }
+   if(SiS_Pr->SiS_ROMNew) {
+
+      if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
+         if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+            temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
+	    temp2 = 0xfc;
+	    if(SiS_Pr->LVDSHL != -1) {
+	      temp1 &= 0xfc;
+	      temp2 = 0xf3;
+	    }
+	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
+         }
+         temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
       }
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0x3f,myptr[2] & 0xc0);
+
    }
 }
 
@@ -11871,7 +11501,7 @@
          SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-         if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
+         if(SiS_Pr->SiS_VBType & VB_SIS301) {
             SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
          }
       }
@@ -11900,7 +11530,7 @@
      }
   }
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
   if(SiS_Pr->UseCustomMode) return;
 
   switch(SiS_Pr->SiS_CustomT) {
@@ -11930,7 +11560,7 @@
   }
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
         /* Maybe all panels? */
         if(SiS_Pr->LVDSHL == -1) {
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11941,7 +11571,7 @@
 
   if(SiS_Pr->SiS_CustomT == CUT_CLEVO10242) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(SiS_Pr->LVDSHL == -1) {
 	      /* Maybe all panels? */
               SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11961,15 +11591,15 @@
   }
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 #ifdef SET_EMI
 	if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x30,0x00);
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 	}
 #endif
-     } else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1280x1024) {
+     } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
         if(SiS_Pr->LVDSHL == -1) {
            /* Maybe ACER only? */
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,0x01);
@@ -11977,9 +11607,9 @@
      }
      tempch = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1400x1050) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
 	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1f,0x76);
-	} else if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	} else if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if(tempch == 0x03) {
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x02);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,0x25);
@@ -12060,7 +11690,7 @@
 	tempbh >>= 4;
 	tempbl = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x04);
 	tempbx = (tempbh << 8) | tempbl;
-	if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
 	   if((resinfo == SIS_RI_1024x768) || (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD))) {
 	      if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
 	      	 tempbx = 770;
@@ -12151,19 +11781,16 @@
 
     tempbx = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f) - 2;
     if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 4;
-    if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel1024x768) {
+    if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx += 3;
     }
-    if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+    if(SiS_Pr->SiS_UseROM) {
        if(ROMAddr[0x235] & 0x80) {
           tempbx = SiS_Pr->SiS_LCDTypeInfo;
           if(Flag) {
-	     romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	     if(romptr) {
-	        tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	     } else {
-	        tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
-	     }
+	     romptr = SISGETROMW(0x255);
+	     if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	     else       tempbx = customtable300[SiS_Pr->SiS_LCDTypeInfo];
              if(tempbx == 0xFF) return 0xFFFF;
           }
 	  tempbx <<= 1;
@@ -12174,13 +11801,10 @@
   } else {
 
     if(Flag) {
-       if((ROMAddr) && SiS_Pr->SiS_UseROM) {
-          romptr = ROMAddr[0x255] | (ROMAddr[0x256] << 8);
-	  if(romptr) {
-	     tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
-	  } else {
-	     tempbx = 0xff;
-	  }
+       if(SiS_Pr->SiS_UseROM) {
+          romptr = SISGETROMW(0x255);
+	  if(romptr) tempbx = ROMAddr[romptr + SiS_Pr->SiS_LCDTypeInfo];
+	  else 	     tempbx = 0xff;
        } else {
           tempbx = customtable630[SiS_Pr->SiS_LCDTypeInfo];
        }
@@ -12204,12 +11828,12 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_PanelCustom) return;
+  if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x02)) return;
-     romptr = ROMAddr[0x24b] | (ROMAddr[0x24c] << 8);
+     romptr = SISGETROMW(0x24b);
   }
 
   /* The Panel Compensation Delay should be set according to tables
@@ -12219,7 +11843,7 @@
    * Thus we don't set this if the user select a custom pdc or if
    * we otherwise detected a valid pdc.
    */
-  if(SiS_Pr->PDC) return;
+  if(SiS_Pr->PDC != -1) return;
 
   temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
 
@@ -12231,7 +11855,7 @@
   if(HwInfo->jChipType != SIS_300) {
      if(romptr) {
 	romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += index;
 	temp = ROMAddr[romptr];
      } else {
@@ -12242,21 +11866,21 @@
         }
      }
   } else {
-     if((ROMAddr) && SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
+     if(SiS_Pr->SiS_UseROM && (ROMAddr[0x235] & 0x80)) {
 	if(romptr) {
 	   romptr += (temp * 2);
-	   romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	   romptr = SISGETROMW(romptr);
 	   romptr += index;
 	   temp = ROMAddr[romptr];
 	} else {
 	   temp = SiS300_OEMLCDDelay5[temp][index];
 	}
      } else {
-        if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+        if(SiS_Pr->SiS_UseROM) {
 	   romptr = ROMAddr[0x249] | (ROMAddr[0x24a] << 8);
 	   if(romptr) {
 	      romptr += (temp * 2);
-	      romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	      romptr = SISGETROMW(romptr);
 	      romptr += index;
 	      temp = ROMAddr[romptr];
 	   } else {
@@ -12279,7 +11903,7 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if((SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
      if(!(ROMAddr[0x237] & 0x04)) return;
      /* No rom pointer in BIOS header! */
@@ -12329,10 +11953,10 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x02)) return;
-     romptr = ROMAddr[0x241] | (ROMAddr[0x242] << 8);
+     romptr = SISGETROMW(0x241);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12341,7 +11965,7 @@
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
@@ -12352,7 +11976,7 @@
      }
   }
   temp &= 0x3c;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);
 }
 
 static void
@@ -12362,10 +11986,10 @@
   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
   USHORT index,temp,romptr=0;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x04)) return;
-     romptr = ROMAddr[0x243] | (ROMAddr[0x244] << 8);
+     romptr = SISGETROMW(0x243);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12374,14 +11998,14 @@
 
   if(romptr) {
      romptr += (temp * 2);
-     romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+     romptr = SISGETROMW(romptr);
      romptr += index;
      temp = ROMAddr[romptr];
   } else {
      temp = SiS300_OEMTVFlicker[temp][index];
   }
   temp &= 0x70;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);  /* index 0A D[6:4] */
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0A,0x8F,temp);
 }
 
 static void
@@ -12395,10 +12019,10 @@
 
   if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetNTSCJ | TVSetPALM | TVSetPALN)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x08)) return;
-     romptr = ROMAddr[0x245] | (ROMAddr[0x246] << 8);
+     romptr = SISGETROMW(0x245);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12412,7 +12036,7 @@
   } else {
      if(romptr) {
         romptr += (temp * 2);
-	romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	romptr = SISGETROMW(romptr);
 	romptr += (index * 4);
         for(i=0x31, j=0; i<=0x34; i++, j++) {
 	   SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
@@ -12434,10 +12058,10 @@
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
 
-  if((ROMAddr) && SiS_Pr->SiS_UseROM) {
+  if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
      if(!(ROMAddr[0x238] & 0x10)) return;
-     romptr = ROMAddr[0x247] | (ROMAddr[0x248] << 8);
+     romptr = SISGETROMW(0x247);
   }
 
   temp = GetOEMTVPtr(SiS_Pr);
@@ -12458,7 +12082,7 @@
   } else {
       if((romptr) && (!(SiS_Pr->SiS_TVMode & (TVSetPALM|TVSetPALN)))) {
          romptr += (temp * 2);
-	 romptr = ROMAddr[romptr] | (ROMAddr[romptr + 1] << 8);
+	 romptr = SISGETROMW(romptr);
 	 romptr += (index * 4);
 	 for(i=0x35, j=0; i<=0x38; i++, j++) {
        	    SiS_SetReg(SiS_Pr->SiS_Part2Port,i,ROMAddr[romptr + j]);
diff -urN linux-2.4.26-pre2/drivers/video/sis/init301.h linux-2.4.26-pre3/drivers/video/sis/init301.h
--- linux-2.4.26-pre2/drivers/video/sis/init301.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/init301.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -91,29 +88,41 @@
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
     0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
     0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-    0x03,0x0a,0x65,0x9d,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53,
+    0x03,0x0a,0x65,0x8d /*0x9d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50 /*0x53*/,
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
     0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
     0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
+    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
     0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
-    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+    0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
     0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
   },
   {
+#if 1
     0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
     0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9f,0x16,0x59,0x2b,0x13,
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x21 /*0x2b*/,0x13,
     0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
-    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+    0x4b,0x4b,0x65 /*0x6f*/,0x2f,0x63,0x92,0x0f,0x40,
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
     0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
+#endif
+#if 0
+    0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c,  /* TEST (0.93) - BAD */
+    0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
+    0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
+    0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
+    0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
+    0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
+    0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
+    0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+#endif
   }
 };
 
@@ -139,7 +148,7 @@
     0x18, 0x1d, 0x23, 0x28, 0x4c, 0xaa, 0x01
 };
 
-/* 301C / 302ELV (?) extended Part2 TV registers */
+/* 301C / 302ELV extended Part2 TV registers */
 
 static const UCHAR SiS_Part2CLVX_1[] = {
     0x00,0x00,
@@ -208,7 +217,7 @@
     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,0x7C,0x0D,0x18,0x7F,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D /* 0x7D? */ ,0x7C,0x0D,0x18,0x7F,
     0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
     0xFF,0xFF,
 };
@@ -217,19 +226,80 @@
 #ifdef SIS315H
 /* 661 et al LCD data structure */
 static const UCHAR SiS_LCDStruct661[] = {
-    /* 1600x1200 */
-    0x0B,0xEA,0x81,0x10,0x00,0xC0,0x03,0x21,0x5A,0x23,0x5A,0x23,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1400x1050 */
-    0x09,0xEA,0x81,0x80,0xA3,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
-    /* 1280x1024 */
-    0x03,0xEA,0x81,0x40,0xA1,0x70,0x03,0x19,0xD2,0x2A,0xF8,0x2F,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x30,0x10,
     /* 1024x768 */
-    0x02,0xEA,0x80,0x00,0x11,0x88,0x06,0x0B,0xF5,0x6C,0x35,0x62,0x02,
-    0x14,0x0A,0x02,0x00,0x30,0x10,0x5A,0x10,0x10,0x0A,0xC0,0x28,0x10,
-    0xFF,
+/*  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,
+    /*  | 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,
+    /* 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,
+    /* 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,
+    /* 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,
+    /* 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
+    /* 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,
+    /* 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? */
+    /* 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
+};
+#endif
+
+#ifdef SIS300
+static UCHAR SiS300_TrumpionData[7][80] = {
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xBC,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x09,0x04,0x04,0x05,
+    0x04,0x0C,0x09,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5A,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x27,0x00,0x80,0x02,
+    0x20,0x03,0x07,0x00,0x5E,0x01,0x0D,0x02,0x60,0x0C,0x30,0x11,0x00,0x00,0x04,0x23,
+    0x00,0x00,0x03,0x80,0x03,0x28,0x06,0x08,0x40,0x11,0x00,0x11,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x90,0x01,0xFF,0x0F,0xF4,0x19,0x01,0x00,0x05,0x01,0x00,0x04,0x05,
+    0x04,0x0C,0x02,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEC,0x57,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xD9,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x59,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
 };
 #endif
 
@@ -271,6 +341,12 @@
 void   	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
 void   	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 #endif /* 315 */
+#ifdef SIS300
+void    SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+USHORT  SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
+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);
@@ -338,5 +414,6 @@
 extern void     SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO,USHORT ModeNo,
                             USHORT ModeIdIndex);
 
+extern void	SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
 
 #endif
diff -urN linux-2.4.26-pre2/drivers/video/sis/initdef.h linux-2.4.26-pre3/drivers/video/sis/initdef.h
--- linux-2.4.26-pre2/drivers/video/sis/initdef.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/initdef.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -72,6 +69,8 @@
 #define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
 #define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
 
+#define SISGETROMW(x)		(ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
+
 /* SiS_VBType */
 #define VB_SIS301	      	0x0001
 #define VB_SIS301B        	0x0002
@@ -102,7 +101,7 @@
 #define SetNotSimuMode          0x0400
 #define SetNotSimuTVMode        SetNotSimuMode
 #define SetDispDevSwitch        0x0800
-#define SetCRT2ToYPbPr525750    0x0800   /* 661 */
+#define SetCRT2ToYPbPr525750    0x0800   
 #define LoadDACFlag             0x1000
 #define DisableCRT2Display      0x2000
 #define DriverMode              0x4000
@@ -145,7 +144,7 @@
 #define SupportCHTV 		0x0800
 #define Support64048060Hz       0x0800  /* Special for 640x480 LCD */
 #define SupportHiVision         0x0010
-#define SupportYPbPr            0x1000  /* TODO */
+#define SupportYPbPr750p        0x1000  
 #define SupportLCD              0x0020
 #define SupportRAMDAC2          0x0040	/* All           (<= 100Mhz) */
 #define SupportRAMDAC2_135      0x0100  /* All except DH (<= 135Mhz) */
@@ -174,20 +173,23 @@
 #define TVSetPALM		0x0004
 #define TVSetPALN		0x0008
 #define TVSetCHOverScan		0x0010
-#define TVSetYPbPr525i		0x0020
-#define TVSetYPbPr525p		0x0040
-#define TVSetYPbPr750p		0x0080
-#define TVSetHiVision		0x0100
-#define TVSetTVSimuMode		0x0800
-#define TVRPLLDIV2XO		0x1000
-#define TVSetNTSC1024		0x2000
-
-/* YPbPr flag (>=315, <661; YPbPr not supported yet) */
-#define YPbPr750                0x0001	/* 750p (must be a single bit, checked logially) */
-#define YPbPr525                0x0002	/* 525p (must be a single bit, checked logially) */
-#define YPbPrHiVision           0x0003	/* HiVision */
-#define YPbPrModeMask           (YPbPr750 | YPbPr525 | YPbPrHiVision)
-#define YPbPrSetSVideo     	0x0004	/* (sets SVIDEO flag) */
+#define TVSetYPbPr525i		0x0020 /* new 0x10 */
+#define TVSetYPbPr525p		0x0040 /* new 0x20 */
+#define TVSetYPbPr750p		0x0080 /* new 0x40 */
+#define TVSetHiVision		0x0100 /* new 0x80; = 1080i, software-wise identical */
+#define TVSetTVSimuMode		0x0200 /* new 0x200, prev. 0x800 */
+#define TVRPLLDIV2XO		0x0400 /* prev 0x1000 */
+#define TVSetNTSC1024		0x0800 /* new 0x100, prev. 0x2000 */
+#define TVAspect43		0x2000
+#define TVAspect169		0x4000
+#define TVAspect43LB		0x8000
+
+/* YPbPr flag (>=315, <661; converted to TVMode) */
+#define YPbPr525p               0x0001
+#define YPbPr750p               0x0002
+#define YPbPr525i               0x0004
+#define YPbPrHiVision           0x0008
+#define YPbPrModeMask           (YPbPr750p | YPbPr525p | YPbPr525i | YPbPrHiVision)
 
 /* SysFlags (to identify special versions) */
 #define SF_Is651                0x0001
@@ -198,6 +200,7 @@
 #define SF_IsM661		0x0020
 #define SF_IsM741		0x0040
 #define SF_IsM760		0x0080
+#define SF_760UMA		0x8000
 
 /* CR32 (Newer 630, and 315 series)
 
@@ -223,11 +226,11 @@
    [2]    1 = PALM (if D0 = 1)
    [3]    1 = PALN (if D0 = 1)
    [4]    1 = Overscan (Chrontel only)
-   [7:5]  (only if D2 in CR38 is set; not supported yet)
+   [7:5]  (only if D2 in CR38 is set)
           000  525i
  	  001  525p
 	  010  750p
-	  011  HiVision (Should be 1080i, but...)
+	  011  1080i (or HiVision on 301, 301B)
 
    These bits are being translated to TVMode flag.
 
@@ -269,7 +272,7 @@
 #define LCDRGB18Bit           0x0001
 #define LCDNonExpanding       0x0010
 #define LCDSync               0x0020
-#define LCDPass11             0x0100
+#define LCDPass11             0x0100   /* 0: center screen, 1: Pass 1:1 data */
 #define LCDDualLink	      0x0200
 
 #define DontExpandLCD	      LCDNonExpanding
@@ -281,13 +284,13 @@
 /* CR38 (315 series) */
 #define EnableDualEdge 		0x01
 #define SetToLCDA		0x02   /* LCD channel A (301C/302B/30x(E)LV and 650+LVDS only) */
-#define EnableSiSYPbPr          0x04   /* YPbPr on SiS bridge (not used; also on 661) */
 #define EnableCHScart           0x04   /* Scart on Ch7019 (unofficial definition - TW) */
 #define EnableCHYPbPr           0x08   /* YPbPr on Ch7019 (480i HDTV); only on 650/Ch7019 systems */
-#define EnableYPbPr750          0x08   /* Enable 750P YPbPr mode (30xLV/301C only) (not supported) */
-#define EnableYPbPr525          0x10   /* Enable 525P YPbPr mode (30xLV/301C only) (not supported) */
-#define EnableYPbPrHiVision     0x18   /* Enable HiVision (not supported) */
-#define EnableYPbPrsetSVideo    0x20   /* Enable YPbPr and set SVideo */
+#define EnableSiSYPbPr          0x08   /* Enable YPbPr mode (30xLV/301C only) */
+#define EnableYPbPr525i         0x00   /* Enable 525i YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr525p         0x10   /* Enable 525p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr750p         0x20   /* Enable 750p YPbPr mode (30xLV/301C only) (mask 0x30) */
+#define EnableYPbPr1080i        0x30   /* Enable 1080i YPbPr mode (30xLV/301C only) (mask 0x30) */
 #define EnablePALM              0x40   /* 1 = Set PALM */
 #define EnablePALN              0x80   /* 1 = Set PALN */
 #define EnableNTSCJ             EnablePALM  /* Not BIOS */
@@ -305,10 +308,10 @@
 #define EnablePALMN             0x40   /* Romflag: 1 = Allow PALM/PALN */
 
 /* CR39 (650 only) */
-#define LCDPass1_1		0x01   /* LVDS only; set by driver to pass 1:1 data to LVDS output  */
+#define LCDPass1_1		0x01   /* 0: center screen, 1: pass 1:1 data output  */
 #define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
 
-/* CR39 (661 and later; not yet implemented)
+/* CR39 (661 and later)
    D[1:0] YPbPr Aspect Ratio
           00 4:3 letterbox
 	  01 4:3
@@ -316,6 +319,11 @@
 	  11 4:3
 */
 
+/* CR3B (651+301C)
+   D[1:0] YPbPr Aspect Ratio
+          ?
+*/
+
 /* CR79 (315/330 series only; not 661 and later)
    [3-0] Notify driver
          0001 Mode Switch event (set by BIOS)
@@ -343,7 +351,7 @@
 #define Panel300_1024x600       0x06
 #define Panel300_1152x768       0x07
 #define Panel300_1280x768       0x0a
-#define Panel300_320x480        0x0e 	/* fstn - TW: This is fake, can be any */
+#define Panel300_320x480        0x0e 	/* fstn - This is fake, can be any */
 #define Panel300_Custom		0x0f
 #define Panel300_Barco1366      0x10
 
@@ -363,8 +371,24 @@
 #define Panel310_320x480        0x0e    /* fstn - TW: This is fake, can be any */
 #define Panel310_Custom		0x0f
 
+#define Panel661_800x600        0x01
+#define Panel661_1024x768       0x02
+#define Panel661_1280x1024      0x03
+#define Panel661_640x480        0x04
+#define Panel661_1024x600       0x05
+#define Panel661_1152x864       0x06
+#define Panel661_1280x960       0x07
+#define Panel661_1152x768       0x08
+#define Panel661_1400x1050      0x09
+#define Panel661_1280x768       0x0a
+#define Panel661_1600x1200      0x0b
+#define Panel661_1280x800       0x0c
+#define Panel661_1680x1050      0x0d
+#define Panel661_1280x720       0x0e
+#define Panel661_Custom		0x0f
+
 #define Panel_800x600           0x01	/* Unified values */
-#define Panel_1024x768          0x02
+#define Panel_1024x768          0x02    /* MUST match BIOS values from 0-e */
 #define Panel_1280x1024         0x03
 #define Panel_640x480           0x04
 #define Panel_1024x600          0x05
@@ -372,16 +396,19 @@
 #define Panel_1280x960          0x07
 #define Panel_1152x768          0x08	/* LVDS only */
 #define Panel_1400x1050         0x09
-#define Panel_1280x768          0x0a    /* LVDS only */
+#define Panel_1280x768          0x0a    /* 30xB/C and LVDS only (BIOS: all) */
 #define Panel_1600x1200         0x0b
-#define Panel_640x480_2		0x0c
-#define Panel_640x480_3		0x0d
-#define Panel_320x480           0x0e    /* fstn - TW: This is fake, can be any */
-#define Panel_Custom		0x0f
-#define Panel_Barco1366         0x10
-#define Panel_848x480		0x11
-#define Panel_1280x800		0x12    /* 661etc: 0x0c */
-#define Panel_1680x1050         0x13    /* 661etc: 0x0d */
+#define Panel_1280x800		0x0c    /* 661etc  */
+#define Panel_1680x1050         0x0d    /* 661etc  */
+#define Panel_1280x720		0x0e    /* 661etc  */
+#define Panel_Custom		0x0f	/* MUST BE 0x0f (for DVI DDC detection */
+#define Panel_320x480           0x10    /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_Barco1366         0x11
+#define Panel_848x480		0x12
+#define Panel_640x480_2		0x13    /* SiS 550 */
+#define Panel_640x480_3		0x14    /* SiS 550 */
+#define Panel_1280x768_2        0x15	/* 30xLV */
+#define Panel_1280x768_3        0x16    /* 30xLV */
 
 /* Index in ModeResInfo table */
 #define SIS_RI_320x200    0
@@ -413,6 +440,8 @@
 #define SIS_RI_1152x768  26
 #define SIS_RI_768x576   27
 #define SIS_RI_1360x1024 28
+#define SIS_RI_1680x1050 29
+#define SIS_RI_1280x800  30
 
 /* CR5F */
 #define IsM650                  0x80
@@ -440,14 +469,22 @@
 #define VCLK108_3_300           0x42   /* Index in VCLKData table (300) */
 #define VCLK100_300             0x43   /* Index in VCLKData table (300) */
 #define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
+#define VCLK_CUSTOM_300		0x46
 #define VCLK65_315              0x0b   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_2_315           0x19   /* Index in (VB)VCLKData table (315) */
 #define VCLK81_315		0x5b   /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315             0x21   /* Index in (VB)VCLKData table (315) */
+#define VCLK162_315             0x5e   /* Index in (VB)VCLKData table (315) */
 #define VCLK108_3_315           0x45   /* Index in VBVCLKData table (315) */
 #define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
-#define VCLK34_315              0x55   /* Index in VBVCLKData table (315) */
+#define VCLK34_315              0x55
 #define VCLK68_315		0x0d
+#define VCLK69_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 TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
 #define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
@@ -457,7 +494,7 @@
 #define HiTVVCLK                0x03   /* Index relative to TVCLKBASE */
 #define HiTVSimuVCLK            0x04   /* Index relative to TVCLKBASE */
 #define HiTVTextVCLK            0x05   /* Index relative to TVCLKBASE */
-#define YPbPr750pVCLK		0x0f   /* NOT relative to TVCLKBASE ! */
+#define YPbPr750pVCLK		0x25   /* Index relative to TVCLKBASE; was 0x0f NOT relative */
 
 /* ------------------------------ */
 
diff -urN linux-2.4.26-pre2/drivers/video/sis/oem300.h linux-2.4.26-pre3/drivers/video/sis/oem300.h
--- linux-2.4.26-pre2/drivers/video/sis/oem300.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/oem300.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
diff -urN linux-2.4.26-pre2/drivers/video/sis/oem310.h linux-2.4.26-pre3/drivers/video/sis/oem310.h
--- linux-2.4.26-pre2/drivers/video/sis/oem310.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/oem310.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -72,7 +69,7 @@
 };
 
 /* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const UCHAR SiS310_LCDDelayCompensation_650301B[] =	   	/* 30xB,LV */
+static const UCHAR SiS310_LCDDelayCompensation_650301LV[] =	   	/* 650 + 30xLV */
 {
 		 0x01,0x01,0x01,    /*   800x600 */
 		 0x01,0x01,0x01,    /*  1024x768 */
@@ -91,65 +88,7 @@
 		 0x02,0x02,0x02
 };
 
-/* This data is correct, so we use it instead of the table above */
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
-{
-		 0x01,0x01,0x01,    /*   800x600 */
-		 0x0C,0x0C,0x0C,    /*  1024x768 */
-		 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_LCDDelayCompensation_LVDS650[] =   	/* LVDS */
-{
-                 0x00,0x00,0x00,    /*   800x600 */
-		 0x00,0x00,0x00,    /*  1024x768 */
-		 0x00,0x00,0x00,    /* 1280x1024 */
-		 0x00,0x00,0x00,    /*   640x480 (unknown) */
-		 0x00,0x00,0x00,    /*  1024x600 (unknown) */
-		 0x00,0x00,0x00,    /*  1152x864 (unknown) */
-		 0x00,0x00,0x00,    /*  1280x960 (guessed) */
-		 0x00,0x00,0x00,    /*  1152x768 (unknown) */
-		 0x00,0x00,0x00,    /* 1400x1050 */
-		 0x00,0x00,0x00,    /*  1280x768  (guessed) */
-		 0x00,0x00,0x00,    /* 1600x1200 */
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00
-};
-
-static const UCHAR SiS310_LCDDelayCompensation_LVDS740[] =   	/* LVDS */
-{
-                 0x03,0x03,0x03,    /*   800x600 */
-		 0x03,0x03,0x03,    /*  1024x768 */
-		 0x03,0x03,0x03,    /* 1280x1024 */
-		 0x03,0x03,0x03,    /*   640x480 (unknown) */
-		 0x03,0x03,0x03,    /*  1024x600 (unknown) */
-		 0x03,0x03,0x03,    /*  1152x864 (unknown) */
-		 0x03,0x03,0x03,    /*  1280x960 (guessed) */
-		 0x03,0x03,0x03,    /*  1152x768 (unknown) */
-		 0x03,0x03,0x03,    /* 1400x1050 */
-		 0x03,0x03,0x03,    /*  1280x768  (guessed) */
-		 0x03,0x03,0x03,    /* 1600x1200 */
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00,
-		 0x00,0x00,0x00
-};
-
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  /* M650/651 301LV */
+static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =	  	/* M650/651 301LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -168,7 +107,7 @@
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   /* M650/651 302LV */
+static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =	   	/* M650/651 302LV */
 {
                  0x33,0x33,0x33,    /*   800x600 (guessed) */
 		 0x33,0x33,0x33,    /*  1024x768 */
@@ -187,6 +126,25 @@
 		 0x33,0x33,0x33
 };
 
+static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
+{
+		 0x01,0x01,0x01,    /*   800x600 */
+		 0x0C,0x0C,0x0C,    /*  1024x768 */
+		 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 */
@@ -208,13 +166,6 @@
 		 0x05,0x05
 };
 
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
-{
-		 0x0a,0x0a,
-		 0x0a,0x0a,
-		 0x0a,0x0a
-};
-
 static const UCHAR SiS310_TVDelayCompensation_651301LV[] =	/* M650, 651, 301LV */
 {
 		 0x33,0x33,
@@ -249,6 +200,13 @@
 		 0x44,0x44
 };
 
+static const UCHAR SiS310_TVDelayCompensation_LVDS[] =		/* LVDS */
+{
+		 0x0a,0x0a,
+		 0x0a,0x0a,
+		 0x0a,0x0a
+};
+
 static const UCHAR SiS310_TVAntiFlick1[6][2] =
 {
             {0x4,0x0},
@@ -451,141 +409,6 @@
 	{    1,   1,1696,1066,1696,1066}
 };
 
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_1[] =
-{
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x35,0x1B,0xA0,0xC0,0x80,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x3F,0x1B,0xD0,0xF0,0xB0,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x45,0x1C,0x20,0x3F,0xFF,0xB8,0x23,0x0A,0x07,0x14,0x8A,0x12}},
- {{0x49,0x1C,0x40,0x7F,0xFF,0xAD,0x23,0x0A,0x07,0xF3,0x8A,0x12}},
- {{0x4C,0x1C,0x18,0x2F,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x48,0x1C,0x15,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_2[] =
-{
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x2B,0x12,0xD9,0xE5,0xD5,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x22,0x12,0xC0,0xCC,0xBC,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x33,0x13,0x01,0x0D,0xFD,0x2C,0x23,0x98,0x27,0x3E,0x08,0x42}},
- {{0x3F,0x1B,0x3D,0x49,0x39,0x54,0x23,0xC0,0x27,0x66,0x30,0x42}},
- {{0x33,0x1B,0x91,0x9D,0x8D,0x8C,0x23,0xF8,0x27,0x9E,0x68,0x42}},
- {{0x43,0x24,0x11,0x1D,0x0D,0xCC,0x23,0x38,0x37,0xDE,0xA8,0x42}},
- {{0x43,0x24,0x21,0x29,0x19,0xEA,0x23,0x0A,0x07,0x32,0xC6,0x42}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Compaq1280x1024_3[] =
-{
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBD,0x23,0x0A,0x07,0x23,0x8A,0x12}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}},
- {{0x47,0x1C,0x14,0x29,0xFF,0xBE,0x23,0x0A,0x07,0x26,0x8A,0x42}}
-};
-
-/* LCDA CRT2 data is std */
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Compaq1280x1024Des_2[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-/* Clevo L285/287 (dual-link 1024x768) */
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_1[] =
-{
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x2C,0x12,0x9A,0xAE,0x88,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0C,0xE6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x12,0xC9,0xDC,0xB6,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_2[] =
-{
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xE0,0x12,0xB1,0x47,0x30,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0xCC,0x12,0x89,0x47,0x1C,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xF4,0x12,0xD9,0x47,0x44,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
-#if 0
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x25,0x12,0x51,0x6E,0x48,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x2C,0x12,0x38,0x55,0x2F,0xC1,0x35,0xB1,0x47,0xE9,0x71,0x33}},
- {{0x2D,0x12,0x79,0x96,0x70,0x99,0x35,0x89,0x47,0xC1,0x49,0x33}},
- {{0x29,0x12,0xB5,0xD2,0xAC,0xE9,0x35,0xD9,0x47,0x11,0x99,0x33}},
- {{0x36,0x13,0x13,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-#endif
-};
-
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Clevo1024x768_3[] =
-{
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}}, /* Corrected */
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x36,0x13,0x13,0x25,0xFF,0x32,0x22,0x0A,0x07,0x82,0x0A,0x12}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xC9,0x25,0xFF,0x59,0x45,0x09,0x07,0xF9,0x09,0x24}}
-};
-
-/* CRT2 data is std */
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Clevo1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
 /* Asus A2xxxH _2 */
 
 static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
@@ -601,52 +424,6 @@
  {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-static const SiS_LVDSDesStruct Asus1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 }
-};
-
-static const SiS_LVDSDesStruct Asus1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 622 },
-  { 1232, 722 },
-  {    0,   0 }
-};
-
-/* CRT2 data is std */
-
-/* Uniwill N243S9, ECS A928 */
 
-static const SiS_LVDSDesStruct Uniwill1024x768Des_1[] =
-{
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 0 },
-  { 0, 805 }
-};
-
-static const SiS_LVDSDesStruct Uniwill1024x768Des_2[] =
-{
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1184, 622 },
-  { 1184, 597 },
-  { 1152, 650 },
-  { 1232, 722 },
-  {    0, 805 },
-};
 
 
diff -urN linux-2.4.26-pre2/drivers/video/sis/osdef.h linux-2.4.26-pre3/drivers/video/sis/osdef.h
--- linux-2.4.26-pre2/drivers/video/sis/osdef.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/osdef.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -54,95 +51,77 @@
  */
 
 /* The choices are: */
-
 #define LINUX_KERNEL	   /* Kernel framebuffer */
 /* #define LINUX_XF86 */   /* XFree86 */
 
-/**********************************************************************/
-#ifdef LINUX_KERNEL  /* -------------------------- */
-#include <linux/config.h>
-#include <linux/version.h>
-
-#ifdef CONFIG_FB_SIS_300
-#define SIS300
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-#define SIS315H
-#endif
-
-#if 1
-#define SISFBACCEL	/* Include 2D acceleration */
-#endif
-
-#endif
-
-#ifdef LINUX_XF86 /* ----------------------------- */
-#define SIS300
-#define SIS315H
-#endif
-
-/**********************************************************************/
-#ifdef LINUX_XF86
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-#ifdef LINUX_KERNEL
-#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#define SiS_MemoryCopy(Destination,Soruce,Length) memcpy(Destination,Soruce,Length)
-#endif
-
-/**********************************************************************/
-
 #ifdef OutPortByte
 #undef OutPortByte
-#endif /* OutPortByte */
+#endif
 
 #ifdef OutPortWord
 #undef OutPortWord
-#endif /* OutPortWord */
+#endif
 
 #ifdef OutPortLong
 #undef OutPortLong
-#endif /* OutPortLong */
+#endif
 
 #ifdef InPortByte
 #undef InPortByte
-#endif /* InPortByte */
+#endif
 
 #ifdef InPortWord
 #undef InPortWord
-#endif /* InPortWord */
+#endif
 
 #ifdef InPortLong
 #undef InPortLong
-#endif /* InPortLong */
+#endif
 
 /**********************************************************************/
-/*  LINUX XF86                                                        */
+/*  LINUX KERNEL                                                      */
 /**********************************************************************/
 
-#ifdef LINUX_XF86
-#define OutPortByte(p,v) outb((CARD16)(p),(CARD8)(v))
-#define OutPortWord(p,v) outw((CARD16)(p),(CARD16)(v))
-#define OutPortLong(p,v) outl((CARD16)(p),(CARD32)(v))
-#define InPortByte(p)    inb((CARD16)(p))
-#define InPortWord(p)    inw((CARD16)(p))
-#define InPortLong(p)    inl((CARD16)(p))
+#ifdef LINUX_KERNEL
+#include <linux/config.h>
+#include <linux/version.h>
+
+#ifdef CONFIG_FB_SIS_300
+#define SIS300
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#define SIS315H
+#endif
+
+#if 1
+#define SISFBACCEL	/* Include 2D acceleration */
+#endif
+
+#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))
+#define InPortByte(p)    inb((SISIOADDRESS)(p))
+#define InPortWord(p)    inw((SISIOADDRESS)(p))
+#define InPortLong(p)    inl((SISIOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
 #endif
 
 /**********************************************************************/
-/*  LINUX KERNEL                                                      */
+/*  XFree86                                                           */
 /**********************************************************************/
 
-#ifdef LINUX_KERNEL
-#define OutPortByte(p,v) outb((u8)(v),(u16)(p))
-#define OutPortWord(p,v) outw((u16)(v),(u16)(p))
-#define OutPortLong(p,v) outl((u32)(v),(u16)(p))
-#define InPortByte(p)    inb((u16)(p))
-#define InPortWord(p)    inw((u16)(p))
-#define InPortLong(p)    inl((u16)(p))
+#ifdef LINUX_XF86
+#define SIS300
+#define SIS315H
+
+#define OutPortByte(p,v) outb((IOADDRESS)(p),(CARD8)(v))
+#define OutPortWord(p,v) outw((IOADDRESS)(p),(CARD16)(v))
+#define OutPortLong(p,v) outl((IOADDRESS)(p),(CARD32)(v))
+#define InPortByte(p)    inb((IOADDRESS)(p))
+#define InPortWord(p)    inw((IOADDRESS)(p))
+#define InPortLong(p)    inl((IOADDRESS)(p))
+#define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
 #endif
 
 
diff -urN linux-2.4.26-pre2/drivers/video/sis/sis_accel.c linux-2.4.26-pre3/drivers/video/sis/sis_accel.c
--- linux-2.4.26-pre2/drivers/video/sis/sis_accel.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/sis_accel.c	2004-03-13 07:43:23.000000000 -0800
@@ -77,9 +77,8 @@
 #include "sis_accel.h"
 #include "sis.h"
 
-extern struct     video_info ivideo;
-extern VGA_ENGINE sisvga_engine;
-extern int sisfb_accel;
+extern struct   video_info ivideo;
+extern int 	sisfb_accel;
 
 static const int sisALUConv[] =
 {
@@ -337,7 +336,7 @@
 
 void sisfb_syncaccel(void)
 {
-    if(sisvga_engine == SIS_300_VGA) {
+    if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
     	SiS300Sync();
 #endif
@@ -357,7 +356,7 @@
    if(!ivideo.accel)
    	return 0;
    
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       SiS300Sync();
 #endif
@@ -393,7 +392,7 @@
 		 break;
    }
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
       SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
@@ -432,7 +431,7 @@
    if(area->sy < area->dy) ydir = 0;
    else                    ydir = 1;
 
-   if(sisvga_engine == SIS_300_VGA) {
+   if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
       SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
@@ -494,7 +493,7 @@
 	if(srcy < dsty) ydir = 0;
 	else            ydir = 1;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
@@ -509,10 +508,6 @@
 	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
 	   SiS310Sync();
-#if 0
-	   printk(KERN_INFO "sis_bmove sx %d sy %d dx %d dy %d w %d h %d\n",
-		srcx, srcy, dstx, dsty, width, height);
-#endif
 #endif
 	}
 }
@@ -527,7 +522,7 @@
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForSolidFill(color, 3, 0);
@@ -616,7 +611,7 @@
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
 	   SiS300SetupForSolidFill(0, 0x0a, 0);
diff -urN linux-2.4.26-pre2/drivers/video/sis/sis_accel.h linux-2.4.26-pre3/drivers/video/sis/sis_accel.h
--- linux-2.4.26-pre2/drivers/video/sis/sis_accel.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/sis_accel.h	2004-03-13 07:43:23.000000000 -0800
@@ -158,7 +158,15 @@
 #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) \
@@ -171,6 +179,7 @@
 	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
 #define MMIO_OUT32(base, offset, val) \
 	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
+#endif
 
 /* ------------- SiS 300 series -------------- */
 
diff -urN linux-2.4.26-pre2/drivers/video/sis/sis_main.c linux-2.4.26-pre3/drivers/video/sis/sis_main.c
--- linux-2.4.26-pre2/drivers/video/sis/sis_main.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/sis_main.c	2004-03-13 07:43:23.000000000 -0800
@@ -47,9 +47,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 #include <linux/vmalloc.h>
-#endif
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
@@ -87,14 +85,18 @@
 #include "sis.h"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#error "This version of sisfb requires at least 2.6.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 	/* TW: no debugging */
+#undef SISFBDEBUG 	/* no debugging */
 
 #ifdef SISFBDEBUG
 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -118,170 +120,23 @@
 
 /* --------------- Hardware Access Routines -------------------------- */
 
-void sisfb_set_reg4(u16 port, unsigned long data)
-{
-	outl((u32) (data & 0xffffffff), port);
-}
-
-u32 sisfb_get_reg3(u16 port)
-{
-	u32 data;
-
-	data = inl(port);
-	return (data);
-}
-
-/* ------------ Interface for init & mode switching code ------------- */
-
-BOOLEAN
-sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+/* These are used on x86 hardware during probe only */
+static void __devinit
+sisfb_set_reg4(u16 port, u32 data)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
-
-	if (!set)
-		DPRINTK("sisfb: Get VGA offset 0x%lx\n", offset);
-	else
-		DPRINTK("sisfb: Set offset 0x%lx to 0x%lx\n", offset, *value);
-
-	if (!init) {
-		init = TRUE;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("sisfb: Current: 0x%x, target: 0x%x\n",
-			         pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-			           && (pdev->device == ivideo.chip_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
-	}
-
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d VGA device.\n",
-				ivideo.chip_id);
-		return FALSE;
-	}
-
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
-
-	return TRUE;
+	outl((u32)(data & 0xffffffff), port);
 }
 
-BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	unsigned long offset, unsigned long set, unsigned long *value)
+static u32 __devinit
+sisfb_get_reg3(u16 port)
 {
-	static struct pci_dev *pdev = NULL;
-	static unsigned char init = 0, valid_pdev = 0;
-	u16 nbridge_id = 0;
-
-	if (!init) {
-		init = TRUE;
-		switch (ivideo.chip) {
-#ifdef CONFIG_FB_SIS_300
-		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;
-#endif
-#ifdef CONFIG_FB_SIS_315
-		case SIS_550:
-			nbridge_id = PCI_DEVICE_ID_SI_550;
-			break;
-		case SIS_650:
-			nbridge_id = PCI_DEVICE_ID_SI_650;
-			break;
-		case SIS_740:
-			nbridge_id = PCI_DEVICE_ID_SI_740;
-			break;
-		case SIS_661:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_741:
-			nbridge_id = PCI_DEVICE_ID_SI_741;
-			break;
-		case SIS_660:
-			nbridge_id = PCI_DEVICE_ID_SI_660;
-			break;
-		case SIS_760:
-			nbridge_id = PCI_DEVICE_ID_SI_760;
-			break;
-#endif
-		default:
-			nbridge_id = 0;
-			break;
-		}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			DPRINTK("Current: 0x%x, target: 0x%x\n",
-					pdev->device, ivideo.chip_id);
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-					&& (pdev->device == nbridge_id)) {
-				valid_pdev = TRUE;
-				break;
-			}
-		}
-	}
-
-	if (!valid_pdev) {
-		printk(KERN_DEBUG "sisfb: Can't find SiS %d North Bridge device.\n",
-				nbridge_id);
-		return FALSE;
-	}
-
-	if (set == 0)
-		pci_read_config_dword(pdev, offset, (u32 *)value);
-	else
-		pci_write_config_dword(pdev, offset, (u32)(*value));
-
-	return TRUE;
+	return((u32)inl(port));
 }
 
 /* ------------------ Internal helper routines ----------------- */
 
-static BOOLEAN sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
-{
-	int htotal, vtotal;
-	unsigned int dclock, hsync;
-
-	if(!monitor->datavalid) return TRUE;
-
-	if(mode_idx < 0) return FALSE;
-
-	if(rate < (monitor->vmin - 1)) return FALSE;
-	if(rate > (monitor->vmax + 1)) return FALSE;
-
-	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
-	                          &htotal, &vtotal, rate_idx)) {
-		dclock = (htotal * vtotal * rate) / 1000;
-		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
-		hsync = dclock / htotal;
-		if(hsync < (monitor->hmin - 1)) return FALSE;
-		if(hsync > (monitor->hmax + 1)) return FALSE;
-        } else {
-	  	return FALSE;
-	}
-	return TRUE;
-};
-
-static BOOLEAN sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
+static BOOLEAN __devinit
+sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
 	int i, j, xres, yres, refresh, index;
 	u32 emodes;
@@ -381,7 +236,8 @@
  	return(monitor->datavalid);
 }
 
-static void sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
+static void __devinit
+sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
 {
 	USHORT  temp, i, realcrtno = crtno;
    	u8      buffer[256];
@@ -396,7 +252,7 @@
 
 	if((sisfb_crt1off) && (!crtno)) return;
 
-    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, realcrtno, 0, &buffer[0]);
+    	temp = SiS_HandleDDC(&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;
@@ -411,7 +267,7 @@
       	   if(temp & 0x02) {
 	      i = 3;  /* Number of retrys */
 	      do {
-	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine,
+	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine,
 				     realcrtno, 1, &buffer[0]);
 	      } while((temp) && i--);
               if(!temp) {
@@ -431,7 +287,8 @@
 	}
 }
 
-static void sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+static void __init
+sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
 {
 	int i = 0, j = 0;
 
@@ -467,7 +324,8 @@
 	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
 }
 
-static void sisfb_search_mode(char *name, BOOLEAN quiet)
+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;
@@ -538,17 +396,145 @@
 
 }
 
-static int sisfb_validate_mode(int myindex, unsigned long vbflags)
+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)
+{
+	int htotal, vtotal;
+	unsigned int dclock, hsync;
+
+	if(!monitor->datavalid) return TRUE;
+
+	if(mode_idx < 0) return FALSE;
+
+	if(rate < (monitor->vmin - 1)) return FALSE;
+	if(rate > (monitor->vmax + 1)) return FALSE;
+
+	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
+	                          &htotal, &vtotal, rate_idx)) {
+		dclock = (htotal * vtotal * rate) / 1000;
+		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+		hsync = dclock / htotal;
+		if(hsync < (monitor->hmin - 1)) return FALSE;
+		if(hsync > (monitor->hmax + 1)) return FALSE;
+        } else {
+	  	return FALSE;
+	}
+	return TRUE;
+}
+
+static int
+sisfb_validate_mode(int myindex, unsigned long vbflags)
 {
-   u16 xres, yres, myres;
+   u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(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(sisvga_engine == SIS_315_VGA) {
+   if(ivideo.sisvga_engine == SIS_315_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
    }
 #endif
@@ -557,7 +543,7 @@
 
    switch (vbflags & VB_DISPTYPE_DISP2) {
      case CRT2_LCD:
-	switch (sishw_ext.ulCRT2LCDType) {
+	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;
@@ -571,6 +557,9 @@
 	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;
 	}
 
@@ -602,21 +591,21 @@
 	   }
 	}
 
-	if(SiS_GetModeID_LCD(sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
+	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);
 	}
 	break;
 
-     case CRT2_TV:  
-	if(SiS_GetModeID_TV(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+     case CRT2_TV:
+	if(SiS_GetModeID_TV(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
 	   return(-1);
 	}
 	break;
 
      case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+        if(SiS_GetModeID_VGA2(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
 	   return(-1);
 	}
@@ -626,49 +615,9 @@
      return(myindex);
 }
 
-static void 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 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 u8 sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+static u8
+sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
 {
 	u16 xres, yres;
 	int i = 0;
@@ -676,37 +625,37 @@
 	xres = sisbios_mode[mode_idx].xres;
 	yres = sisbios_mode[mode_idx].yres;
 
-	sisfb_rate_idx = 0;
+	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) {
-				sisfb_rate_idx = sisfb_vrate[i].idx;
+				ivideo.rate_idx = sisfb_vrate[i].idx;
 				break;
 			} 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);
-					sisfb_rate_idx = sisfb_vrate[i].idx;
+					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);
-					sisfb_rate_idx = sisfb_vrate[i-1].idx;
+					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);
-	           		sisfb_rate_idx = sisfb_vrate[i].idx;
+	           		ivideo.rate_idx = sisfb_vrate[i].idx;
 		   		break;
 	       		}
 		}
 		i++;
 	}
-	if (sisfb_rate_idx > 0) {
-		return sisfb_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);
@@ -714,78 +663,27 @@
 	}
 }
 
-static void 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 |= sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void sisfb_search_specialtiming(const char *name)
-{
-	int i = 0;
-	BOOLEAN found = FALSE;
-
-	if(name == NULL)
-		return;
-
-	if(!strnicmp(name, "none", 4)) {
-	        SiS_Pr.SiS_CustomT = CUT_FORCENONE;
-		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
-	} else {
-	   while(mycustomttable[i].chipID != 0) {
-	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
-		 SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-		 found = TRUE;
-		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%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_bridgeisslave(void)
+static BOOLEAN
+sisfb_bridgeisslave(void)
 {
    unsigned char P1_00;
 
    if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
 
    inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((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;
    }
 }
 
-static BOOLEAN sisfballowretracecrt1(void)
+static BOOLEAN
+sisfballowretracecrt1(void)
 {
-   unsigned char temp;
+   u8 temp;
 
    inSISIDXREG(SISCR,0x17,temp);
    if(!(temp & 0x80)) return FALSE;
@@ -796,16 +694,17 @@
    return TRUE;
 }
 
-static BOOLEAN sisfbcheckvretracecrt1(void)
+static BOOLEAN
+sisfbcheckvretracecrt1(void)
 {
-
    if(!sisfballowretracecrt1()) return FALSE;
 
    if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
    else 			   return FALSE;
 }
 
-static void sisfbwaitretracecrt1(void)
+static void
+sisfbwaitretracecrt1(void)
 {
    int watchdog;
 
@@ -817,11 +716,12 @@
    while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
-static BOOLEAN sisfbcheckvretracecrt2(void)
+static BOOLEAN
+sisfbcheckvretracecrt2(void)
 {
    unsigned char temp, reg;
 
-   switch(sisvga_engine) {
+   switch(ivideo.sisvga_engine) {
    case SIS_300_VGA:
    	reg = 0x25;
 	break;
@@ -837,7 +737,8 @@
    else 	   return TRUE;
 }
 
-static BOOLEAN sisfb_CheckVBRetrace(void)
+static BOOLEAN
+sisfb_CheckVBRetrace(void)
 {
    if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
       if(sisfb_bridgeisslave()) {
@@ -849,7 +750,8 @@
    return(sisfbcheckvretracecrt1());
 }
 
-static int sisfb_myblank(int blank)
+static int
+sisfb_myblank(int blank)
 {
    u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
    BOOLEAN backlight = TRUE;
@@ -912,8 +814,8 @@
           ((sisfb_thismonitor.datavalid) &&
            (sisfb_thismonitor.feature & 0xe0))) {
 
-	 if(sisvga_engine == SIS_315_VGA) {
-	    setSISIDXREG(SISCR, 0x63, 0xbf, cr63);
+	 if(ivideo.sisvga_engine == SIS_315_VGA) {
+	    setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 	 }
 
 	 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
@@ -929,7 +831,7 @@
 	 } else {
 	    SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
 	 }
-      } else if(sisvga_engine == SIS_315_VGA) {
+      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
 	 if(ivideo.vbflags & VB_CHRONTEL) {
 	    if(backlight) {
 	       SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
@@ -939,19 +841,19 @@
 	 }
       }
 
-      if(((sisvga_engine == SIS_300_VGA) &&
+      if(((ivideo.sisvga_engine == SIS_300_VGA) &&
           (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((sisvga_engine == SIS_315_VGA) &&
+         ((ivideo.sisvga_engine == SIS_315_VGA) &&
           ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
           setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
       }
 
-      if(sisvga_engine == SIS_300_VGA) {
+      if(ivideo.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(sisvga_engine == SIS_315_VGA) {
+      } 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);
@@ -971,7 +873,8 @@
 
 /* ----------- FBDev related routines for all series ----------- */
 
-static void sisfb_set_vparms(void)
+static void
+sisfb_set_vparms(void)
 {
    switch(ivideo.video_bpp) {
    case 8:
@@ -997,7 +900,8 @@
    }
 }
 
-static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+static int
+sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      struct fb_info *info)
 {
 	unsigned int htotal = 0, vtotal = 0; 
@@ -1034,11 +938,6 @@
 	   ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
 	} else ivideo.refresh_rate = 60;
 
-#if 0
-	printk(KERN_DEBUG "sisfb: Change mode to %dx%dx%d-%dHz\n",
-		var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);
-#endif		
-
 	old_mode = sisfb_mode_idx;
 	sisfb_mode_idx = 0;
 
@@ -1047,7 +946,7 @@
 		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)) {
-			sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+			ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
 			found_mode = 1;
 			break;
 		}
@@ -1067,14 +966,14 @@
 	}
 
 	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
-		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+		ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
 		ivideo.refresh_rate = 60;
 	}
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	if(sisfb_thismonitor.datavalid) {
 	   if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-	                         sisfb_rate_idx, ivideo.refresh_rate)) {
+	                         ivideo.rate_idx, ivideo.refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
@@ -1087,8 +986,8 @@
 #endif
 		sisfb_pre_setmode();
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
-			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", sisfb_mode_no);
+		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
+			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo.mode_no);
 			return -EINVAL;
 		}
 
@@ -1114,7 +1013,7 @@
 		ivideo.current_pixclock = var->pixclock;
 		ivideo.current_refresh_rate = ivideo.refresh_rate;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                sisfb_lastrates[sisfb_mode_no] = ivideo.refresh_rate;
+                sisfb_lastrates[ivideo.mode_no] = ivideo.refresh_rate;
 #endif
 		
 		sisfb_post_setmode();
@@ -1123,7 +1022,8 @@
 	return 0;
 }
 
-static int sisfb_pan_var(struct fb_var_screeninfo *var)
+static int
+sisfb_pan_var(struct fb_var_screeninfo *var)
 {
 	unsigned int base;
 
@@ -1154,22 +1054,23 @@
         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
 	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
 	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(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, sisfb_CRT2_write_enable, 0x01);
+		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(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)
+static void
+sisfb_bpp_to_var(struct fb_var_screeninfo *var)
 {
 	switch(var->bits_per_pixel) {
 	   case 8:
@@ -1202,7 +1103,8 @@
 	}
 }
 
-void sis_dispinfo(struct ap_data *rec)
+void
+sis_dispinfo(struct ap_data *rec)
 {
 	rec->minfo.bpp      = ivideo.video_bpp;
 	rec->minfo.xres     = ivideo.video_width;
@@ -1228,7 +1130,8 @@
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
 
-static void sisfb_crtc_to_var(struct fb_var_screeninfo *var)
+static void
+sisfb_crtc_to_var(struct fb_var_screeninfo *var)
 {
 	u16 VRE, VBE, VRS, VBS, VDE, VT;
 	u16 HRE, HBE, HRS, HBS, HDE, HT;
@@ -1417,10 +1320,11 @@
 
 }
 
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+static int
+sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
 			 unsigned *transp, struct fb_info *fb_info)
 {
-	if (regno >= ivideo.video_cmap_len)
+	if(regno >= ivideo.video_cmap_len)
 		return 1;
 
 	*red = sis_palette[regno].red;
@@ -1430,24 +1334,25 @@
 	return 0;
 }
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+static int
+sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
                            unsigned transp, struct fb_info *fb_info)
 {
-	if (regno >= ivideo.video_cmap_len)
+	if(regno >= ivideo.video_cmap_len)
 		return 1;
 
 	sis_palette[regno].red = red;
 	sis_palette[regno].green = green;
 	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));
@@ -1473,7 +1378,8 @@
 	return 0;
 }
 
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var,
+static void
+sisfb_set_disp(int con, struct fb_var_screeninfo *var,
                            struct fb_info *info)
 {
 	struct fb_fix_screeninfo fix;
@@ -1502,7 +1408,7 @@
 
 	save_flags(flags);
 
-	switch (ivideo.video_bpp) {
+	switch(ivideo.video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	   case 8:
 #ifdef SISFBACCEL
@@ -1548,12 +1454,13 @@
 	}
 }
 
-static void sisfb_do_install_cmap(int con, struct fb_info *info)
+static void
+sisfb_do_install_cmap(int con, struct fb_info *info)
 {
-        if (con != currcon)
+        if(con != 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,
@@ -1561,7 +1468,8 @@
 }
 
 
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_get_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
 	if(con == -1)
@@ -1577,7 +1485,8 @@
 	return 0;
 }
 
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_set_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
 	int err;
@@ -1611,10 +1520,11 @@
 	return 0;
 }
 
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+static int
+sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
-        if (con == currcon)
+        if(con == currcon)
 		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
 
 	else if (fb_display[con].cmap.len)
@@ -1625,18 +1535,19 @@
 	return 0;
 }
 
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+static int
+sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
 	int err;
 
-	if (!fb_display[con].cmap.len) {
+	if(!fb_display[con].cmap.len) {
 		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
 		if (err)
 			return err;
 	}
         
-	if (con == currcon)
+	if(con == currcon)
 		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
 
 	else
@@ -1645,17 +1556,18 @@
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var, int con,
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var, int con,
 			     struct fb_info* info)
 {
 	int err;
 
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+	if(var->vmode & FB_VMODE_YWRAP) {
+		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;
 	}
 
@@ -1665,7 +1577,7 @@
 
 	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
 		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
@@ -1673,15 +1585,16 @@
 	return 0;
 }
 
-static int sisfb_mmap(struct fb_info *info, struct file *file,
+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;
-	u32 len, mmio_off;
+	unsigned long len, mmio_off;
 
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
+	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
 
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
@@ -1701,7 +1614,7 @@
 		if(var.accel_flags) return -EINVAL;
 
 		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
 	start &= PAGE_MASK;
@@ -1712,18 +1625,19 @@
 	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
 
 #if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
+	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))
+	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)
+static void
+sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
 {
 	struct display *p = &fb_display[currcon];
 	u16 c;
@@ -1737,7 +1651,7 @@
 	widthb = (fontwidth(p) + 7) / 8;
 
 	c = gly->ch & p->charmask;
-	if (fontwidth(p) <= 8)
+	if(fontwidth(p) <= 8)
 		cdat = p->fontdata + c * fontheight(p);
 	else
 		cdat = p->fontdata + (c * fontheight(p) << 1);
@@ -1747,12 +1661,14 @@
 	gly->ngmask = size;
 }
 
-static int sisfb_update_var(int con, struct fb_info *info)
+static int
+sisfb_update_var(int con, struct fb_info *info)
 {
         return(sisfb_pan_var(&fb_display[con].var));
 }
 
-static int sisfb_switch(int con, struct fb_info *info)
+static int
+sisfb_switch(int con, struct fb_info *info)
 {
 	int cols, rows;
 
@@ -1784,7 +1700,8 @@
 	return 1;
 }
 
-static void sisfb_blank(int blank, struct fb_info *info)
+static void
+sisfb_blank(int blank, struct fb_info *info)
 {
 	sisfb_myblank(blank);
 }
@@ -1794,17 +1711,20 @@
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
-static int sisfb_open(struct fb_info *info, int user)
+static int
+sisfb_open(struct fb_info *info, int user)
 {
     return 0;
 }
 
-static int sisfb_release(struct fb_info *info, int user)
+static int
+sisfb_release(struct fb_info *info, int user)
 {
     return 0;
 }
 
-static int sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
 {
 	int rc = 16;		
 
@@ -1820,19 +1740,20 @@
 	return rc;
 }
 
-static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *info)
+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))
+	if(regno >= sisfb_get_cmap_len(&info->var))
 		return 1;
 
-	switch (info->var.bits_per_pixel) {
+	switch(info->var.bits_per_pixel) {
 	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));
@@ -1854,7 +1775,8 @@
 	return 0;
 }
 
-static int sisfb_set_par(struct fb_info *info)
+static int
+sisfb_set_par(struct fb_info *info)
 {
 	int err;
 
@@ -1866,8 +1788,9 @@
 	return 0;
 }
 
-static int sisfb_check_var(struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+static int
+sisfb_check_var(struct fb_var_screeninfo *var,
+                   struct fb_info *info)
 {
 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
 	unsigned int drate = 0, hrate = 0, maxyres;
@@ -1912,7 +1835,6 @@
 	}
 
 	if(!found_mode) {
-
                 search_idx = 0;
 		while(sisbios_mode[search_idx].mode_no != 0) {
 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
@@ -2051,32 +1973,33 @@
 	return 0;
 }
 
-static int sisfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info* info)
+static int
+sisfb_pan_display(struct fb_var_screeninfo *var,
+		     struct fb_info* info)
 {
 	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->vmode & FB_VMODE_YWRAP) {
+		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)
+		if(var->xoffset + info->var.xres > info->var.xres_virtual ||
+		   var->yoffset + info->var.yres > info->var.yres_virtual)
 			return -EINVAL;
 	}
-    
+
 	if((err = sisfb_pan_var(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
 		info->var.vmode &= ~FB_VMODE_YWRAP;
@@ -2084,12 +2007,13 @@
 	return 0;
 }
 
-static int sisfb_mmap(struct fb_info *info, struct file *file,
+static int
+sisfb_mmap(struct fb_info *info, struct file *file,
 		      struct vm_area_struct *vma)
 {
 	unsigned long start;
 	unsigned long off;
-	u32 len, mmio_off;
+	unsigned long len, mmio_off;
 
 	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
 
@@ -2110,7 +2034,7 @@
 		if(info->var.accel_flags) return -EINVAL;
 
 		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
 	start &= PAGE_MASK;
@@ -2131,7 +2055,8 @@
 	return 0;
 }
 
-static int sisfb_blank(int blank, struct fb_info *info)
+static int
+sisfb_blank(int blank, struct fb_info *info)
 {
 	return(sisfb_myblank(blank));
 }
@@ -2207,8 +2132,8 @@
 		{
 			unsigned long myhwcoffset = 0;
 
-			if(sisfb_caps & HW_CURSOR_CAP)
-				myhwcoffset = sisfb_hwcursor_vbase -
+			if(ivideo.caps & HW_CURSOR_CAP)
+				myhwcoffset = ivideo.hwcursor_vbase -
 				    (unsigned long) ivideo.video_vbase;
 
 			return put_user(myhwcoffset, (unsigned long *)arg);
@@ -2231,14 +2156,19 @@
 			x.chip_id = ivideo.chip_id;
 			x.memory = ivideo.video_size / 1024;
 			x.heapstart = ivideo.heapstart / 1024;
-			x.fbvidmode = sisfb_mode_no;
-			x.sisfb_caps = sisfb_caps;
+			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 = sisfb_detectedpdc;
-			x.sisfb_lcda = sisfb_detectedlcda;
+			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;
@@ -2287,8 +2217,9 @@
 }
 
 
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
+static int
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+	      struct fb_info *info)
 {
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
@@ -2301,7 +2232,7 @@
 	fix->smem_start = ivideo.video_base;
 
         if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-	    if(sisvga_engine == SIS_300_VGA) {
+	    if(ivideo.sisvga_engine == SIS_300_VGA) {
 	       if(ivideo.video_size > 0x1000000) {
 	          	fix->smem_len = 0xc00000;
 	       } else if(ivideo.video_size > 0x800000)
@@ -2327,8 +2258,8 @@
 	fix->ywrapstep   = 0;
 	fix->line_length = ivideo.video_linelength;
 	fix->mmio_start  = ivideo.mmio_base;
-	fix->mmio_len    = sisfb_mmio_size;
-	if(sisvga_engine == SIS_300_VGA) 
+	fix->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))
 	   fix->accel    = FB_ACCEL_SIS_XABRE;
@@ -2338,7 +2269,7 @@
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	fix->reserved[0] = ivideo.video_size & 0xFFFF;
 	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = sisfb_caps;
+	fix->reserved[2] = ivideo.caps;
 #endif
 
 	return 0;
@@ -2386,14 +2317,14 @@
 
 #ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
 
-static int sisfb_get_dram_size_300(void)
+static int __devinit sisfb_get_dram_size_300(void)
 {
 	struct pci_dev *pdev = NULL;
 	int pdev_valid = 0;
 	u8  pci_data, reg;
 	u16 nbridge_id;
 
-	switch (ivideo.chip) {
+	switch(ivideo.chip) {
 	   case SIS_540:
 		nbridge_id = PCI_DEVICE_ID_SI_540;
 		break;
@@ -2408,7 +2339,7 @@
 		break;
 	}
 
-	if (nbridge_id == 0) {  /* 300 */
+	if(nbridge_id == 0) {   /* 300 */
 
 	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
 		ivideo.video_size =
@@ -2427,7 +2358,7 @@
 				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:
@@ -2464,7 +2395,7 @@
 
 #ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740/330/661/741/760 */
 
-static int sisfb_get_dram_size_315(void)
+static int __devinit sisfb_get_dram_size_315(void)
 {
 	u8  reg = 0;
 
@@ -2480,9 +2411,7 @@
 		return 0;
 
 	} else if(ivideo.chip == SIS_661 ||
-	          ivideo.chip == SIS_741 ||
-		  ivideo.chip == SIS_660 ||
-		  ivideo.chip == SIS_760) {
+	          ivideo.chip == SIS_741) {
 
 		inSISIDXREG(SISCR, 0x79, reg);
 		reg &= 0xf0;
@@ -2490,6 +2419,22 @@
 		ivideo.video_size = (1 << reg) << 20;
 		return 0;
 
+	} else if(ivideo.chip == SIS_660 ||
+		  ivideo.chip == SIS_760) {
+
+		ivideo.video_size = 0;
+		inSISIDXREG(SISCR, 0x79, reg);
+		reg &= 0xf0;
+		reg >>= 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);
@@ -2529,38 +2474,18 @@
 
 /* -------------- video bridge detection --------------- */
 
-static void sisfb_detect_VB_connect()
+static void __devinit sisfb_detect_VB_connect()
 {
 	u8 sr16, sr17, cr32, temp;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 	
 		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
 	      
 		if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
-	
-			/* Old BIOSes store the detected CRT2 type in SR17
-		 	 * instead of CR32. However, since our detection
-			 * routines store their results to CR32, we now copy
-			 * the remaining bits (for LCD and VGA) to CR32 for
-			 * unified usage.
-			 * SR17[0] CRT1    [1] LCD     [2] TV    [3] VGA2
-			 *     [4] AVIDEO  [5] SVIDEO
-			 */
-
-#if 0
-			if (sr17 & 0x01) orSISIDXREG(SISCR, 0x32, SIS_CRT1);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_CRT1);
-
-			if (sr17 & 0x02) orSISIDXREG(SISCR, 0x32, SIS_VB_LCD);
-			else		 andSISIDXREG(SISCR, 0x32, ~SIS_VB_LCD);
 
-			/* no HiVision and no DVI connector here */
-			andSISIDXREG(SISCR, 0x32, ~0xc0);
-#endif
-		
 			/* PAL/NTSC is stored on SR16 on such machines */
-			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
+			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;
@@ -2574,69 +2499,54 @@
 	
 	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
 
-	if (cr32 & SIS_CRT1)
+	if(cr32 & SIS_CRT1) {
 		sisfb_crt1off = 0;
-	else {
-		if (cr32 & 0x5F)
-			sisfb_crt1off = 1;
-		else
-			sisfb_crt1off = 0;
+	} else {
+		if (cr32 & 0x5F) sisfb_crt1off = 1;
+		else		 sisfb_crt1off = 0;
 	}
 
 	ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
 
-	if (cr32 & SIS_VB_TV)
-		ivideo.vbflags |= CRT2_TV;
-	if (cr32 & SIS_VB_LCD)
-		ivideo.vbflags |= CRT2_LCD;
-	if (cr32 & SIS_VB_CRT2)
-		ivideo.vbflags |= CRT2_VGA;
+	if(cr32 & SIS_VB_TV)   ivideo.vbflags |= CRT2_TV;
+	if(cr32 & SIS_VB_LCD)  ivideo.vbflags |= CRT2_LCD;
+	if(cr32 & SIS_VB_CRT2) ivideo.vbflags |= CRT2_VGA;
 		
-	/* TW: Detect/set TV plug & type */
-	if(sisfb_tvplug != -1)
-	        ivideo.vbflags |= sisfb_tvplug;
+	/* 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;
-		
-	if (!(ivideo.vbflags & (TV_PAL | TV_NTSC))) {
-		if(sisvga_engine == SIS_300_VGA) {
+	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.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;
+			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;
 	    	}
 	}
 
-	/* TW: Copy forceCRT1 option to CRT1off if option is given */
-    	if (sisfb_forcecrt1 != -1) {
+	/* Copy forceCRT1 option to CRT1off if option is given */
+    	if(sisfb_forcecrt1 != -1) {
     		if(sisfb_forcecrt1) sisfb_crt1off = 0;
 		else                sisfb_crt1off = 1;
     	}
 
 }
 
-static void sisfb_get_VB_type(void)
+static void __devinit sisfb_get_VB_type(void)
 {
 	u8 vb_chipid;
 	u8 reg;
@@ -2648,7 +2558,6 @@
 	ivideo.hasVB = HASVB_NONE;
 	sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
 	sishw_ext.Is301BDH = FALSE;
-	sishw_ext.usExternalChip = 0;
 
 	inSISIDXREG(SISPART4, 0x00, vb_chipid);
 	switch (vb_chipid) {
@@ -2693,27 +2602,9 @@
 		break;
 	   case 0x02:
 		ivideo.hasVB = HASVB_302;
-		inSISIDXREG(SISPART4, 0x01, reg);
-		if(reg < 0xd0) {
-			ivideo.vbflags |= VB_302B;
-			sishw_ext.ujVBChipID = VB_CHIP_302B;
-			inSISIDXREG(SISPART4,0x23,reg);
-		  	if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
-			   printk(KERN_INFO "%s SiS302B-DH %s\n", stdstr, bridgestr);
-			} else {
-			   printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
-			}
-		} else if(reg < 0xe0) {
-		 	ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
-			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
-		} else if(reg <= 0xe1) {
-			ivideo.vbflags |= VB_302LV;
-			sishw_ext.ujVBChipID = VB_CHIP_302LV;
-			printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
-		}
+		ivideo.vbflags |= VB_302B;
+		sishw_ext.ujVBChipID = VB_CHIP_302B;
+		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
 		break;
 	}
 
@@ -2721,49 +2612,70 @@
 		inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
-		if(sisvga_engine == SIS_300_VGA) {
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
 			switch (reg) {
 			   case SIS_EXTERNAL_CHIP_LVDS:
 				ivideo.hasVB = HASVB_LVDS;
 				ivideo.vbflags |= VB_LVDS;
-				sishw_ext.usExternalChip = 0x01;
 				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_TRUMPION:
 				ivideo.hasVB = HASVB_TRUMPION;
-				sishw_ext.usExternalChip = 0x02;
+				ivideo.vbflags |= VB_TRUMPION;
 				printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
 				ivideo.hasVB = HASVB_CHRONTEL;
 				ivideo.vbflags |= VB_CHRONTEL;
-				sishw_ext.usExternalChip = 0x04;
 				printk(KERN_INFO "%s %s\n", stdstr, chrstr);
 				break;
 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
 				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
 				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
 				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
 				break;
 			}
+#endif
 		} 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;
-				sishw_ext.usExternalChip = 0x01;
 				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
 				break;
 		   	   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
 				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
 				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				sishw_ext.usExternalChip = 0x05;
 				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
 				break;
 			}
+#endif
+		} 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);
+				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);
+				break;
+			   case 0x04:
+			        ivideo.hasVB = HASVB_NONE;
+				ivideo.vbflags |= (VB_LVDS | VB_CONEXANT);
+				printk(KERN_INFO "%s Conexant video bridge\n", stdstr);
+				break;
+			}
+#endif
 		}
-	
+
 	}
 	
 	if(ivideo.vbflags & VB_SISBRIDGE) {
@@ -2776,8 +2688,7 @@
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN
-sisfb_test_DDC1(void)
+static BOOLEAN __devinit sisfb_test_DDC1(void)
 {
     unsigned short old;
     int count = 48;
@@ -2789,8 +2700,7 @@
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void
-sisfb_sense_crt1(void)
+static void __devinit sisfb_sense_crt1(void)
 {
     unsigned char SR1F, CR63=0, CR17;
     unsigned short temp = 0xffff;
@@ -2802,10 +2712,10 @@
     andSISIDXREG(SISSR,0x1F,0x3F);
     if(SR1F & 0xc0) mustwait = TRUE;
 
-    if(sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,0x63,CR63);
+    if(ivideo.sisvga_engine == SIS_315_VGA) {
+       inSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,CR63);
        CR63 &= 0x40;
-       andSISIDXREG(SISCR,0x63,0xBF);
+       andSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF);
     }
 
     inSISIDXREG(SISCR,0x17,CR17);
@@ -2823,7 +2733,7 @@
 
     i = 3;
     do {
-       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, sisvga_engine, 0, 0, NULL);
+       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, 0, 0, NULL);
     } while(((temp == 0) || (temp == 0xffff)) && i--);
 
     if((temp == 0) || (temp == 0xffff)) {
@@ -2834,8 +2744,8 @@
        orSISIDXREG(SISCR,0x32,0x20);
     }
 
-    if(sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,0x63,0xBF,CR63);
+    if(ivideo.sisvga_engine == SIS_315_VGA) {
+       setSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF,CR63);
     }
 
     setSISIDXREG(SISCR,0x17,0x7F,CR17);
@@ -2844,8 +2754,7 @@
 }
 
 /* Determine and detect attached devices on SiS30x */
-int
-SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+static int __devinit SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
 {
     int temp;
 
@@ -2860,8 +2769,7 @@
     return((temp == tempch));
 }
 
-void
-SiS_Sense30x(void)
+static void __devinit SiS_Sense30x(void)
 {
   u8 backupP4_0d,backupP2_00;
   u8 svhs_bl, svhs_bh;
@@ -2880,7 +2788,7 @@
   inSISIDXREG(SISPART2,0x00,backupP2_00);
   outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
 
-  if(sisvga_engine == SIS_300_VGA) {
+  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;
@@ -2890,20 +2798,21 @@
 		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(SISPART4,0x01,myflag);
-	if(myflag & 0x04) {
-	   vga2_bh = 0x00; vga2_bl = 0xfd;
-	   svhs_bh = 0x00; svhs_bl = 0xdd;
-	   cvbs_bh = 0x00; cvbs_bl = 0xee;
-	}
+
 	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)) {
@@ -2968,10 +2877,6 @@
        }
     }
 
-    if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
-       orSISIDXREG(SISPART4,0x0d,0x04);
-    }
-
     haveresult = 0;
     for(j = 0; j < 10; j++) {
        result = 0;
@@ -3014,11 +2919,9 @@
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
 }
 
-/* TW: Determine and detect attached TV's on Chrontel */
-void
-SiS_SenseCh(void)
+/* Determine and detect attached TV's on Chrontel */
+static void __devinit SiS_SenseCh(void)
 {
-
    u8 temp1, temp2;
 #ifdef CONFIG_FB_SIS_300
    unsigned char test[3];
@@ -3143,16 +3046,17 @@
 
 /* ------------------------ Heap routines -------------------------- */
 
-static int sisfb_heap_init(void)
+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;
+	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)
@@ -3162,7 +3066,7 @@
 	agp_kern_info  *agp_info;
 	agp_memory     *agp;
 #endif
-	u32            agp_phys;
+	unsigned long  agp_phys;
 #endif
 #endif
 /*     The heap start is either set manually using the "mem" parameter, or
@@ -3179,8 +3083,8 @@
  *     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(sisvga_engine == SIS_300_VGA) {
+     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) {
@@ -3194,8 +3098,7 @@
      } else {
            ivideo.heapstart = sisfb_mem * 1024;
      }
-     sisfb_heap_start =
-	       (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
+     sisfb_heap_start = (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
      printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",
      					(int)(ivideo.heapstart / 1024));
 
@@ -3203,8 +3106,8 @@
      sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
 
 #ifdef CONFIG_FB_SIS_315
-     if (sisvga_engine == SIS_315_VGA) {
-        /* Now initialize the 310 series' command queue mode.
+     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
@@ -3275,12 +3178,11 @@
 	agp_enabled = 0;
 #endif
 
-	/* TW: Now select the queue mode */
+	/* Now select the queue mode */
 
-	if ((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
+	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_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
         } else if (sisfb_queuemode == VM_CMD_QUEUE) {
 		cmd_type = VM_CMD_QUEUE;
 		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");
@@ -3326,7 +3228,7 @@
 
 		*cmdq_baseport = agp_phys;
 
-		sisfb_caps |= AGP_CMD_QUEUE_CAP;
+		ivideo.caps |= AGP_CMD_QUEUE_CAP;
 #endif
 		break;
 
@@ -3345,10 +3247,8 @@
 
 		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
 
-		sisfb_caps |= VM_CMD_QUEUE_CAP;
+		ivideo.caps |= VM_CMD_QUEUE_CAP;
 
-		DPRINTK("sisfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
 		break;
 
 	   default:  /* MMIO */
@@ -3366,18 +3266,16 @@
 
 		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
 
-		sisfb_caps |= MMIO_CMD_QUEUE_CAP;
+		ivideo.caps |= MMIO_CMD_QUEUE_CAP;
 
-		DPRINTK("sisfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
 		break;
 	}
      } /* sisvga_engine = 315 */
 #endif
 
 #ifdef CONFIG_FB_SIS_300
-     if (sisvga_engine == SIS_300_VGA) {
-  	    /* TW: Now initialize TurboQueue. TB is always located at the very
+     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;
@@ -3396,26 +3294,22 @@
 
 		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
 
-		sisfb_caps |= TURBO_QUEUE_CAP;
+		ivideo.caps |= TURBO_QUEUE_CAP;
 
 		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
 		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
-		DPRINTK("sisfb: TurboQueue start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, TURBO_QUEUE_AREA_SIZE/1024);
+
 	    }
      }
 #endif
-     /* TW: 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 >= sisfb_hwcursor_size) {
-		sisfb_heap_end -= sisfb_hwcursor_size;
-		sisfb_heap_size -= sisfb_hwcursor_size;
-		sisfb_hwcursor_vbase = sisfb_heap_end;
+     /* 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;
 
-		sisfb_caps |= HW_CURSOR_CAP;
-
-		DPRINTK("sisfb: Hardware Cursor start at 0x%lx, size is %dK\n",
-			sisfb_heap_end, sisfb_hwcursor_size/1024);
+		ivideo.caps |= HW_CURSOR_CAP;
      }
 
      sisfb_heap.poha_chain = NULL;
@@ -3449,14 +3343,15 @@
      return 0;
 }
 
-static SIS_OH *sisfb_poh_new_node(void)
+static SIS_OH *
+sisfb_poh_new_node(void)
 {
 	int           i;
 	unsigned long cOhs;
 	SIS_OHALLOC   *poha;
 	SIS_OH        *poh;
 
-	if (sisfb_heap.poh_freelist == NULL) {
+	if(sisfb_heap.poh_freelist == NULL) {
 		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
 		if(!poha) return NULL;
 
@@ -3466,7 +3361,7 @@
 		cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
-		for (i = cOhs - 1; i != 0; i--) {
+		for(i = cOhs - 1; i != 0; i--) {
 			poh->poh_next = poh + 1;
 			poh = poh + 1;
 		}
@@ -3481,13 +3376,14 @@
 	return (poh);
 }
 
-static SIS_OH *sisfb_poh_allocate(unsigned long size)
+static SIS_OH *
+sisfb_poh_allocate(unsigned long size)
 {
 	SIS_OH *pohThis;
 	SIS_OH *pohRoot;
 	int     bAllocated = 0;
 
-	if (size > sisfb_heap.max_freesize) {
+	if(size > sisfb_heap.max_freesize) {
 		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
 			(unsigned int) size / 1024);
 		return (NULL);
@@ -3495,7 +3391,7 @@
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
+	while(pohThis != &sisfb_heap.oh_free) {
 		if (size <= pohThis->size) {
 			bAllocated = 1;
 			break;
@@ -3503,19 +3399,19 @@
 		pohThis = pohThis->poh_next;
 	}
 
-	if (!bAllocated) {
+	if(!bAllocated) {
 		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
 
-	if (size == pohThis->size) {
+	if(size == pohThis->size) {
 		pohRoot = pohThis;
 		sisfb_delete_node(pohThis);
 	} else {
 		pohRoot = sisfb_poh_new_node();
 
-		if (pohRoot == NULL) {
+		if(pohRoot == NULL) {
 			return (NULL);
 		}
 
@@ -3534,7 +3430,8 @@
 	return (pohRoot);
 }
 
-static void sisfb_delete_node(SIS_OH *poh)
+static void
+sisfb_delete_node(SIS_OH *poh)
 {
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
@@ -3544,10 +3441,10 @@
 
 	poh_prev->poh_next = poh_next;
 	poh_next->poh_prev = poh_prev;
-
 }
 
-static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+static void
+sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
 {
 	SIS_OH *pohTemp;
 
@@ -3560,7 +3457,8 @@
 	poh->poh_next = pohTemp;
 }
 
-static SIS_OH *sisfb_poh_free(unsigned long base)
+static SIS_OH *
+sisfb_poh_free(unsigned long base)
 {
 	SIS_OH *pohThis;
 	SIS_OH *poh_freed;
@@ -3581,7 +3479,7 @@
 		poh_freed = poh_freed->poh_next;
 	}
 
-	if (!foundNode)  return (NULL);
+	if(!foundNode)  return(NULL);
 
 	sisfb_heap.max_freesize += poh_freed->size;
 
@@ -3591,12 +3489,11 @@
 
 	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &sisfb_heap.oh_free) {
-		if (pohThis->offset == ulUpper) {
+	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;
@@ -3604,42 +3501,43 @@
 
 	sisfb_delete_node(poh_freed);
 
-	if (poh_prev && poh_next) {
+	if(poh_prev && poh_next) {
 		poh_prev->size += (poh_freed->size + poh_next->size);
 		sisfb_delete_node(poh_next);
 		sisfb_free_node(poh_freed);
 		sisfb_free_node(poh_next);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_prev) {
+	if(poh_prev) {
 		poh_prev->size += poh_freed->size;
 		sisfb_free_node(poh_freed);
-		return (poh_prev);
+		return(poh_prev);
 	}
 
-	if (poh_next) {
+	if(poh_next) {
 		poh_next->size += poh_freed->size;
 		poh_next->offset = poh_freed->offset;
 		sisfb_free_node(poh_freed);
-		return (poh_next);
+		return(poh_next);
 	}
 
 	sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
 
-	return (poh_freed);
+	return(poh_freed);
 }
 
-static void sisfb_free_node(SIS_OH *poh)
+static void
+sisfb_free_node(SIS_OH *poh)
 {
 	if(poh == NULL) return;
 
 	poh->poh_next = sisfb_heap.poh_freelist;
 	sisfb_heap.poh_freelist = poh;
-
 }
 
-void sis_malloc(struct sis_memreq *req)
+void
+sis_malloc(struct sis_memreq *req)
 {
 	SIS_OH *poh;
 
@@ -3658,7 +3556,8 @@
 	}
 }
 
-void sis_free(unsigned long base)
+void
+sis_free(unsigned long base)
 {
 	SIS_OH *poh;
 
@@ -3672,7 +3571,8 @@
 
 /* --------------------- SetMode routines ------------------------- */
 
-static void sisfb_pre_setmode(void)
+static void
+sisfb_pre_setmode(void)
 {
 	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
 	
@@ -3682,7 +3582,7 @@
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 	
-	cr33 = sisfb_rate_idx & 0x0F;
+	cr33 = ivideo.rate_idx & 0x0F;
 
 	SiS_SetEnableDstn(&SiS_Pr, FALSE);
 	SiS_SetEnableFstn(&SiS_Pr, FALSE);
@@ -3733,7 +3633,7 @@
 		if(sisfb_nocrt2rate) {
 			cr33 |= (sisbios_mode[sisfb_mode_idx].rate_idx << 4);
 		} else {
-			cr33 |= ((sisfb_rate_idx & 0x0F) << 4);
+			cr33 |= ((ivideo.rate_idx & 0x0F) << 4);
 		}
 		break;
 	   default:	/* disable CRT2 */
@@ -3751,7 +3651,7 @@
 	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
 
 #ifdef CONFIG_FB_SIS_315
-        if(sisvga_engine == SIS_315_VGA) {
+        if(ivideo.sisvga_engine == SIS_315_VGA) {
 	   /* Clear LCDA and PAL-N/M bits */
 	   andSISIDXREG(SISCR,0x38,~0x03);
 	   if(ivideo.chip < SIS_661) {
@@ -3765,29 +3665,39 @@
 	SiS_Pr.SiS_UseOEM = sisfb_useoem;
 }
 
-static void sisfb_post_setmode(void)
+static void
+sisfb_post_setmode(void)
 {
 	u8 reg;
 	BOOLEAN crt1isoff = FALSE;
+	BOOLEAN doit = TRUE;
 #ifdef CONFIG_FB_SIS_315
 	u8 reg1;
 #endif
-#ifdef CONFIG_FB_SIS_300
-	BOOLEAN doit = TRUE;
-#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(sisvga_engine == SIS_300_VGA) {
-			inSISIDXREG(SISPART1, 0x00, reg);
+		if(ivideo.sisvga_engine == SIS_300_VGA) {
 			if((reg & 0xa0) == 0x20) {
 				doit = FALSE;
 			}
 		}
 #endif
+#ifdef CONFIG_FB_SIS_315
+		if(ivideo.sisvga_engine == SIS_315_VGA) {
+			if((reg & 0x50) == 0x10) {
+				doit = FALSE;
+			}
+		}
+#endif
 	} else sisfb_crt1off = 0;
 
-	if(sisvga_engine == SIS_300_VGA) {
+	if(ivideo.sisvga_engine == SIS_300_VGA) {
 
 #ifdef CONFIG_FB_SIS_300
 	   if((sisfb_crt1off) && (doit)) {
@@ -3803,7 +3713,7 @@
 	} else {
 
 #ifdef CONFIG_FB_SIS_315
-	   if(sisfb_crt1off) {
+	   if((sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg  = 0x40;
 		reg1 = 0xc0;
@@ -3813,7 +3723,7 @@
 		reg1 = 0x00;
 
 	   }
-	   setSISIDXREG(SISCR, 0x63, ~0x40, reg);
+	   setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, ~0x40, reg);
 	   setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
 #endif
 
@@ -3858,7 +3768,7 @@
 			break;
 		}
 
-		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
 
 		if(ivideo.vbflags & TV_NTSC) {
 
@@ -3931,13 +3841,7 @@
 			}
 		}
 
-		if ((filter >= 0) && (filter <= 7)) {
-			DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter,
-				sis_TV_filter[filter_tb].filter[filter][0],
-				sis_TV_filter[filter_tb].filter[filter][1],
-				sis_TV_filter[filter_tb].filter[filter][2],
-				sis_TV_filter[filter_tb].filter[filter][3]
-			);
+		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]));
@@ -3945,11 +3849,10 @@
 		}
 	  
 	}
-
 }
 
 #ifndef MODULE
-int sisfb_setup(char *options)
+int __init sisfb_setup(char *options)
 {
 	char *this_opt;
 	
@@ -3960,76 +3863,85 @@
 	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
 
         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(!(*this_opt)) continue;
 
-		if (!strnicmp(this_opt, "mode:", 5)) {
+		if(!strnicmp(this_opt, "mode:", 5)) {
 			sisfb_search_mode(this_opt + 5, FALSE);
-		} else if (!strnicmp(this_opt, "vesa:", 5)) {
+		} else if(!strnicmp(this_opt, "vesa:", 5)) {
 			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		} else if (!strnicmp(this_opt, "inverse", 7)) {
+		} else if(!strnicmp(this_opt, "inverse", 7)) {
 			sisfb_inverse = 1;
 			/* fb_invert_cmaps(); */
-		} else if (!strnicmp(this_opt, "font:", 5)) {
-			strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
-			sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
+		} else if(!strnicmp(this_opt, "font:", 5)) {
+		        if(strlen(this_opt + 5) < 40) {
+			   strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
+			   sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
+			}
 #endif
-		} else if (!strnicmp(this_opt, "vrate:", 6)) {
+		} 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)) {
+		} 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)) {
+		} else if(!strnicmp(this_opt, "off", 3)) {
 			sisfb_off = 1;
-		} else if (!strnicmp(this_opt, "crt1off", 7)) {
+		} else if(!strnicmp(this_opt, "crt1off", 7)) {
 			sisfb_crt1off = 1;
-		} else if (!strnicmp(this_opt, "filter:", 7)) {
+		} else if(!strnicmp(this_opt, "filter:", 7)) {
 			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "forcecrt2type:", 14)) {
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
 			sisfb_search_crt2type(this_opt + 14);
-		} else if (!strnicmp(this_opt, "forcecrt1:", 10)) {
+		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if (!strnicmp(this_opt, "tvmode:",7)) {
+                } else if(!strnicmp(this_opt, "tvmode:",7)) {
 		        sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "tvstandard:",11)) {
+                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
 			sisfb_search_tvstd(this_opt + 7);
-                } else if (!strnicmp(this_opt, "mem:",4)) {
+                } else if(!strnicmp(this_opt, "mem:",4)) {
 		        sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "queuemode:", 10)) {
+		} else if(!strnicmp(this_opt, "queuemode:", 10)) {
 			sisfb_search_queuemode(this_opt + 10);
-		} else if (!strnicmp(this_opt, "pdc:", 4)) {
+		} else if(!strnicmp(this_opt, "pdc:", 4)) {
 		        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if (!strnicmp(this_opt, "noaccel", 7)) {
+		} 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, "noypan", 6)) {
+		} else if(!strnicmp(this_opt, "noypan", 6)) {
 		        sisfb_ypan = 0;
-		} else if (!strnicmp(this_opt, "nomax", 5)) {
+		} else if(!strnicmp(this_opt, "nomax", 5)) {
 		        sisfb_max = 0;
-		} else if (!strnicmp(this_opt, "userom:", 7)) {
+		} else if(!strnicmp(this_opt, "userom:", 7)) {
 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "useoem:", 7)) {
+		} else if(!strnicmp(this_opt, "useoem:", 7)) {
 			sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if (!strnicmp(this_opt, "nocrt2rate", 10)) {
+		} else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
 			sisfb_nocrt2rate = 1;
-	 	} else if (!strnicmp(this_opt, "scalelcd:", 9)) {
+	 	} else if(!strnicmp(this_opt, "scalelcd:", 9)) {
 		        unsigned long temp = 2;
 		        temp = simple_strtoul(this_opt + 9, NULL, 0);
 		        if((temp == 0) || (temp == 1)) {
 			   SiS_Pr.UsePanelScaler = temp ^ 1;
 		        }
-		} else if (!strnicmp(this_opt, "specialtiming:", 14)) {
+		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
 			sisfb_search_specialtiming(this_opt + 14);
-		} else if (!strnicmp(this_opt, "lvdshl:", 7)) {
+		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
 		        unsigned long temp = 4;
 		        temp = simple_strtoul(this_opt + 7, NULL, 0);
 		        if((temp >= 0) && (temp <= 3)) {
@@ -4037,11 +3949,17 @@
 		        }
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
 			sisfb_search_mode(this_opt, TRUE);
+#if !defined(__i386__) && !defined(__x86_64__)
+	        } else if(!strnicmp(this_opt, "resetcard", 9)) {
+		  	sisfb_resetcard = 1;
+	        } else if(!strnicmp(this_opt, "videoram:", 9)) {
+		  	sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+#endif
 		} else {
 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
 		}
 
-		/* TW: Acceleration only with MMIO mode */
+		/* Acceleration only with MMIO mode */
 		if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
 			sisfb_accel = 0;
 		}
@@ -4051,177 +3969,448 @@
 }
 #endif
 
-static char *sis_find_rom(void)
+static char * __devinit sis_find_rom(struct pci_dev *pdev)
 {
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
-        unsigned char *rom_base;
-        unsigned char *rom;
-        int  stage;
-        int  i;
-        char sis_rom_sig[] = "Silicon Integrated Systems";
-        char *sis_sig_300[4] = {
-          "300", "540", "630", "730"
-        };
-        char *sis_sig_310[11] = {
-          "315", "315", "315", "5315", "6325", "6325",
-	  "Xabre", "6330", "6330", "6330", "6330"
-        };
-	ushort sis_nums_300[4] = {
-	  SIS_300, SIS_540, SIS_630, SIS_730
-	};
-	unsigned short sis_nums_310[11] = {
-	  SIS_315PRO, SIS_315H, SIS_315, SIS_550, SIS_650, SIS_740,
-	  SIS_330, SIS_661, SIS_741, SIS_660, SIS_760
-	};
+        unsigned char *rom_base, *rom;
+        int  romptr;
+	unsigned short pciid;
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-                stage = 1;
+                rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+		if(!rom_base) continue;
 
-                rom_base = (char *)ioremap(segstart, 0x1000);
+		if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
+		   iounmap(rom_base);
+                   continue;
+		}
 
-                if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
-                   stage = 2;
+		romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+		if(romptr > (0x10000 - 8)) {
+		   iounmap(rom_base);
+		   continue;
+		}
 
-                if (stage != 2) {
-                   iounmap(rom_base);
-                   continue;
-                }
+		rom = rom_base + romptr;
 
+		if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+		   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
+		   iounmap(rom_base);
+		   continue;
+		}
 
-		rom = rom_base + (unsigned short)(*(rom_base + 0x12) | (*(rom_base + 0x13) << 8));
-                if(strncmp(sis_rom_sig, rom, strlen(sis_rom_sig)) == 0) {
-                    stage = 3;
-		}
-                if(stage != 3) {
-                    iounmap(rom_base);
-                    continue;
-                }
-
-		rom = rom_base + (unsigned short)(*(rom_base + 0x14) | (*(rom_base + 0x15) << 8));
-                for(i = 0;(i < 4) && (stage != 4); i++) {
-                    if(strncmp(sis_sig_300[i], rom, strlen(sis_sig_300[i])) == 0) {
-                        if(sis_nums_300[i] == ivideo.chip) {
-			   stage = 4;
-                           break;
-			}
-                    }
-                }
-		if(stage != 4) {
-                   for(i = 0;(i < 11) && (stage != 4); i++) {
-                      if(strncmp(sis_sig_310[i], rom, strlen(sis_sig_310[i])) == 0) {
-		          if(sis_nums_310[i] == ivideo.chip) {
-                             stage = 4;
-                             break;
-			  }
-                      }
-                   }
+		pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+		if(pciid != 0x1039) {
+		   iounmap(rom_base);
+		   continue;
 		}
 
-                if(stage != 4) {
-                        iounmap(rom_base);
-                        continue;
-                }
+		pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+		if(pciid == ivideo.chip_id) return rom_base;
 
-                return rom_base;
+		iounmap(rom_base);
         }
+#else
+	unsigned char *rom_base, *rom, *myrombase = NULL;
+        int  romptr;
+	unsigned short pciid;
+	u32 backup;
+
+	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);
+
+	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));
+	      if(romptr <= (0x10000 - 8)) {
+	         rom = rom_base + romptr;
+		 if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
+		    (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
+		    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((myrombase = vmalloc(65536))) {
+			     memcpy_fromio(myrombase, rom_base, 65536);
+			  }
+		       }
+		    }
+		 }
+	      }
+	   }
+	   iounmap(rom_base);
+	}
+        pci_write_config_dword(pdev, PCI_ROM_ADDRESS, backup);
+	if(myrombase) return myrombase;
 #endif
         return NULL;
 }
 
+#ifdef SIS300
+static int __devinit
+sisfb_chkbuswidth300(ULONG FBAddress)
+{
+	int i, j;
+	USHORT temp;
+	UCHAR reg;
+
+	andSISIDXREG(SISSR,0x15,0xFB);
+	orSISIDXREG(SISSR,0x15,0x04);
+   	outSISIDXREG(SISSR,0x13,0x00);
+   	outSISIDXREG(SISSR,0x14,0xBF);
+
+	for(i=0; i<2; i++) {
+	   temp = 0x1234;
+	   for(j=0; j<4; j++) {
+	      writew(temp, FBAddress);
+	      if(readw(FBAddress) == temp) break;
+	      orSISIDXREG(SISSR,0x3c,0x01);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      andSISIDXREG(SISSR,0x3c,0xfe);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      inSISIDXREG(SISSR,0x05,reg);
+	      temp++;
+	   }
+	}
 
+	writel(0x01234567L, FBAddress);
+	writel(0x456789ABL, (FBAddress+4));
+	writel(0x89ABCDEFL, (FBAddress+8));
+	writel(0xCDEF0123L, (FBAddress+12));
+	inSISIDXREG(SISSR,0x3b,reg);
+	if(reg & 0x01) {
+	   if(readl((FBAddress+12)) == 0xCDEF0123L) return(4);  /* Channel A 128bit */
+	}
+	if(readl((FBAddress+4)) == 0x456789ABL)     return(2);  /* Channel B 64bit */
+	return(1);						/* 32bit */
+}
+
+static void __devinit
+sisfb_setramsize300(void)
+{
+  	ULONG 	FBAddr = (ULONG)sishw_ext.pjVideoMemoryAddress, Addr;
+	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
+	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
+   	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
+   	int     PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
+	const 	USHORT SiS_DRAMType[17][5] = {
+			{0x0C,0x0A,0x02,0x40,0x39},
+			{0x0D,0x0A,0x01,0x40,0x48},
+			{0x0C,0x09,0x02,0x20,0x35},
+			{0x0D,0x09,0x01,0x20,0x44},
+			{0x0C,0x08,0x02,0x10,0x31},
+			{0x0D,0x08,0x01,0x10,0x40},
+			{0x0C,0x0A,0x01,0x20,0x34},
+			{0x0C,0x09,0x01,0x08,0x32},
+			{0x0B,0x08,0x02,0x08,0x21},
+			{0x0C,0x08,0x01,0x08,0x30},
+			{0x0A,0x08,0x02,0x04,0x11},
+			{0x0B,0x0A,0x01,0x10,0x28},
+			{0x09,0x08,0x02,0x02,0x01},
+			{0x0B,0x09,0x01,0x08,0x24},
+			{0x0B,0x08,0x01,0x04,0x20},
+			{0x0A,0x08,0x01,0x02,0x10},
+			{0x09,0x08,0x01,0x01,0x00}
+		};
+
+        buswidth = sisfb_chkbuswidth300(FBAddr);
+
+   	MB2Bank = 16;
+   	Done = 0;
+   	for(i = 6; i >= 0; i--) {
+      	   if(Done) break;
+      	   PseudoRankCapacity = 1 << i;
+      	   for(j = 4; j >= 1; j--) {
+              if(Done) break;
+              PseudoTotalCapacity = PseudoRankCapacity * j;
+              PseudoAdrPinCount = 15 - j;
+              if(PseudoTotalCapacity <= 64) {
+                 for(k = 0; k <= 16; k++) {
+                    if(Done) break;
+                    RankCapacity = buswidth * SiS_DRAMType[k][3];
+                    AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
+                    if(RankCapacity == PseudoRankCapacity)
+                       if(AdrPinCount <= PseudoAdrPinCount) {
+                          if(j == 3) {             /* Rank No */
+                             BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * 1 - 1;
+                          } else {
+                             BankNumHigh = RankCapacity * MB2Bank * j - 1;
+                             BankNumMid  = RankCapacity * MB2Bank * j / 2 - 1;
+                          }
+                          PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+                          PhysicalAdrHigh = BankNumHigh;
+                          PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+                          PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+                          /* Write data */
+                          andSISIDXREG(SISSR,0x15,0xFB); /* Test */
+                          orSISIDXREG(SISSR,0x15,0x04);  /* Test */
+                          TotalCapacity = SiS_DRAMType[k][3] * buswidth;
+                          SR13 = SiS_DRAMType[k][4];
+                          if(buswidth == 4) SR14 = (TotalCapacity - 1) | 0x80;
+                          if(buswidth == 2) SR14 = (TotalCapacity - 1) | 0x40;
+                          if(buswidth == 1) SR14 = (TotalCapacity - 1) | 0x00;
+                          outSISIDXREG(SISSR,0x13,SR13);
+                          outSISIDXREG(SISSR,0x14,SR14);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
+			  writew(((USHORT)PhysicalAdrHigh), Addr);
+                          Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
+                          /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
+			  writew(((USHORT)BankNumMid), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
+                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
+			  writew(((USHORT)PhysicalAdrHalfPage), Addr);
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
+                          /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
+			  writew(((USHORT)PhysicalAdrOtherPage), Addr);
+                          /* Read data */
+                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
+                          data = readw(Addr); /* *((USHORT *)(Addr)); */
+                          if(data == PhysicalAdrHigh) Done = 1;
+                       }  /* if */
+                 }  /* for k */
+              }  /* if */
+      	   }  /* for j */
+   	}  /* for i */
+}
+
+static void __devinit sisfb_post_sis300(void)
+{
+	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+	u16 index, rindex, memtype = 0;
+
+	outSISIDXREG(SISSR,0x05,SIS_PASSWORD);
+
+	if(sishw_ext.UseROM) {
+	   if(sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
+	      memtype = sishw_ext.pjVirtualRomBase[0x52];
+ 	   } else {
+	      inSISIDXREG(SISSR,0x3a,memtype);
+	   }
+	   memtype &= 0x07;
+	}
 
-int __init sisfb_init(void)
+	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) {
+	      index = memtype * 5;
+	      rindex = index + 0x54;
+	      v1 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v2 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v3 = sishw_ext.pjVirtualRomBase[rindex++];
+	      rindex = index + 0x7c;
+	      v4 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v5 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v6 = sishw_ext.pjVirtualRomBase[rindex++];
+	   }
+	}
+	outSISIDXREG(SISSR,0x28,v1);
+	outSISIDXREG(SISSR,0x29,v2);
+	outSISIDXREG(SISSR,0x2a,v3);
+	outSISIDXREG(SISSR,0x2e,v4);
+	outSISIDXREG(SISSR,0x2f,v5);
+	outSISIDXREG(SISSR,0x30,v6);
+	v1 = 0x10;
+	if(sishw_ext.UseROM) v1 = 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) {
+	   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];
+	}
+	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);
+	outSISIDXREG(SISSR,0x18,v4);
+	outSISIDXREG(SISSR,0x19,v5);
+	outSISIDXREG(SISSR,0x1a,v6);
+	outSISIDXREG(SISSR,0x1b,v7);
+	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
+	andSISIDXREG(SISSR,0x15,0xfb);
+	orSISIDXREG(SISSR,0x15,0x04);
+	if(sishw_ext.UseROM) {
+	   if(sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
+	      orSISIDXREG(SISSR,0x19,0x20);
+	   }
+	}
+	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
+	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];
+	}
+	outSISIDXREG(SISSR,0x23,v1);
+	outSISIDXREG(SISSR,0x24,v2);
+	outSISIDXREG(SISSR,0x25,v3);
+	outSISIDXREG(SISSR,0x21,0x84);
+	outSISIDXREG(SISSR,0x22,0x00);
+	outSISIDXREG(SISCR,0x37,0x00);
+	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];
+	}
+	outSISIDXREG(SISPART1,0x02,v1);
+	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];
+	   }
+	   outSISIDXREG(SISPART4,0x0d,v4);
+	   outSISIDXREG(SISPART4,0x0e,v5);
+	   outSISIDXREG(SISPART4,0x10,v6);
+	   outSISIDXREG(SISPART4,0x0f,0x3f);
+	   inSISIDXREG(SISPART4,0x01,reg);
+	   if(reg >= 0xb0) {
+	      inSISIDXREG(SISPART4,0x23,reg);
+	      reg &= 0x20;
+	      reg <<= 1;
+	      outSISIDXREG(SISPART4,0x23,reg);
+	   }
+	} else {
+	   v2 &= ~0x10;
+	}
+	outSISIDXREG(SISSR,0x32,v2);
+	andSISIDXREG(SISPART1,0x24,0xfe);  /* Lock CRT2 */
+	inSISIDXREG(SISSR,0x16,reg);
+	reg &= 0xc3;
+	outSISIDXREG(SISCR,0x35,reg);
+	outSISIDXREG(SISCR,0x83,0x00);
+#if !defined(__i386__) && !defined(__x86_64__)
+	if(sisfb_videoram) {
+	   outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	   reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+	   outSISIDXREG(SISSR,0x14,reg);
+	} 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);
+	   } else {
+	      printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+	      outSISIDXREG(SISSR,0x13,0x28);  /* ? */
+	      outSISIDXREG(SISSR,0x14,0x47);  /* 8MB, 64bit default */
+	   }
+#if !defined(__i386__) && !defined(__x86_64__)
+	}
+#endif
+	if(sishw_ext.UseROM) {
+	   v1 = sishw_ext.pjVirtualRomBase[0xe6];
+	   v2 = sishw_ext.pjVirtualRomBase[0xe7];
+	} else {
+	   inSISIDXREG(SISSR,0x3a,reg);
+	   if((reg & 0x30) == 0x30) {
+	      v1 = 0x04; /* PCI */
+	      v2 = 0x92;
+	   } else {
+	      v1 = 0x14; /* AGP */
+	      v2 = 0xb2;
+	   }
+	}
+	outSISIDXREG(SISSR,0x21,v1);
+	outSISIDXREG(SISSR,0x22,v2);
+}
+#endif
+
+
+int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct pci_dev *pdev = NULL;
-	struct board *b;
-	int pdev_valid = 0;
+	struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
 	u32 reg32;
 	u16 reg16;
 	u8  reg;
+	int sisvga_enabled = 0;
 
-#if 0
-	/* for DOC VB */
-	sisfb_set_reg4(0xcf8,0x800000e0);
-	reg32 = sisfb_get_reg3(0xcfc);
-	reg32 = reg32 | 0x00001000;
-	sisfb_set_reg4(0xcfc,reg32);
-	}
-#endif
-
-	if (sisfb_off)
-		return -ENXIO;
+	if(sisfb_off) return -ENXIO;
 
-	sisfb_registered = 0;
 	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)	
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	memset(&sis_disp, 0, sizeof(sis_disp));
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-	pci_for_each_dev(pdev) {
-#else
-	while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-		for (b = sisdev_list; b->vendor; b++) {
-			if ((b->vendor == pdev->vendor)
-			    && (b->device == pdev->device)) {
-				pdev_valid = 1;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-				sis_fb_info = framebuffer_alloc(0, &pdev->dev);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+	sis_fb_info = framebuffer_alloc(0, &pdev->dev);
 #else
-				sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
+	sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
 #endif
-				if(!sis_fb_info) return -ENOMEM;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-				memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+	if(!sis_fb_info) return -ENOMEM;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3))
+	memset(sis_fb_info, 0, sizeof(*sis_fb_info));
 #endif
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, b->name);
-#else				
-				strcpy(myid, b->name);
-#endif				
-				ivideo.chip_id = pdev->device;
-				pci_read_config_byte(pdev, PCI_REVISION_ID,
-				                     &ivideo.revision_id);
-				pci_read_config_word(pdev, PCI_COMMAND, &reg16);
-				sishw_ext.jChipRevision = ivideo.revision_id;
-				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;
-				break;
-			}
-		}
 
-		if (pdev_valid)
-			break;
-	}
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+	strcpy(sis_fb_info->modename, chipinfo->chip_name);
+#else
+	strcpy(myid, chipinfo->chip_name);
+#endif
 
-	if (!pdev_valid)
-		return -ENODEV;
+	ivideo.chip_id = pdev->device;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo.revision_id);
+	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;
 
-	switch (ivideo.chip_id) {
+	/* Patch special cases */
+	switch(ivideo.chip_id) {
 #ifdef CONFIG_FB_SIS_300
-	   case PCI_DEVICE_ID_SI_300:
-		ivideo.chip = SIS_300;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;  /* New X driver uses 2 buffers */
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
 	   case PCI_DEVICE_ID_SI_630_VGA:
 		{
-			ivideo.chip = SIS_630;
 			sisfb_set_reg4(0xCF8, 0x80000000);
 			reg32 = sisfb_get_reg3(0xCFC);
 			if(reg32 == 0x07301039) {
@@ -4232,46 +4421,12 @@
 				strcpy(myid, "SIS 730");
 #endif
 			}
-			sisvga_engine = SIS_300_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
 			break;
 		}
-	   case PCI_DEVICE_ID_SI_540_VGA:
-		ivideo.chip = SIS_540;
-		sisvga_engine = SIS_300_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
-		break;
 #endif
 #ifdef CONFIG_FB_SIS_315
-	   case PCI_DEVICE_ID_SI_315H:
-		ivideo.chip = SIS_315H;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315:
-		ivideo.chip = SIS_315;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_315PRO:
-		ivideo.chip = SIS_315PRO;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
-	   case PCI_DEVICE_ID_SI_550_VGA:
-		ivideo.chip = SIS_550;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
 	   case PCI_DEVICE_ID_SI_650_VGA:
 	   	{
-			ivideo.chip = SIS_650;  
 			sisfb_set_reg4(0xCF8, 0x80000000);
 			reg32 = sisfb_get_reg3(0xCFC);
 			if(reg32 == 0x07401039) {
@@ -4282,17 +4437,8 @@
 				strcpy(myid, "SIS 740");
 #endif
 			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
 			break;
 		}
-	   case PCI_DEVICE_ID_SI_330:
-		ivideo.chip = SIS_330;
-		sisvga_engine = SIS_315_VGA;
-		sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-		sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
-		break;
 	   case PCI_DEVICE_ID_SI_660_VGA:
 	   	{
 			sisfb_set_reg4(0xCF8, 0x80000000);
@@ -4326,19 +4472,13 @@
 				strcpy(myid, "SIS 661");
 #endif
 			}
-			sisvga_engine = SIS_315_VGA;
-			sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
-			sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
 			break;
 		}
 #endif
-           default:
-	   	kfree(sis_fb_info);
-	        return -ENODEV;
 	}
+
 	sishw_ext.jChipType = ivideo.chip;
 
-	/* for Debug */
 	if( (sishw_ext.jChipType == SIS_315PRO) ||
 	    (sishw_ext.jChipType == SIS_315) )
 		sishw_ext.jChipType = SIS_315H;
@@ -4346,16 +4486,16 @@
 	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 = (unsigned short) sishw_ext.ulIOAddress;
+	ivideo.vga_base = sishw_ext.ulIOAddress;
 
-	sisfb_mmio_size =  pci_resource_len(pdev, 1);
+	ivideo.mmio_size =  pci_resource_len(pdev, 1);
 
 	if(!sisvga_enabled) {
 	   if(pci_enable_device(pdev)) {
 	      kfree(sis_fb_info);
 	      return -EIO;
 	   }
-	}
+	} 
 
 	SiS_Pr.SiS_Backup70xx = 0xff;
         SiS_Pr.SiS_CHOverScan = -1;
@@ -4364,10 +4504,18 @@
 	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);
 
 #ifdef CONFIG_FB_SIS_300
-	/* TW: Find PCI systems for Chrontel/GPIO communication setup */
+	/* Find PCI systems for Chrontel/GPIO communication setup */
 	if(ivideo.chip == SIS_630) {
 	   int i=0;
            do {
@@ -4385,9 +4533,21 @@
 
         outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
-#ifdef MODULE
+	if( (!sisvga_enabled)
+#if !defined(__i386__) && !defined(__x86_64__)
+		  	      || (sisfb_resetcard)
+#endif
+			      			   ) {
+	   int i;
+	   for(i = 0x30; i <= 0x3f; i++) {
+	       outSISIDXREG(SISCR,i,0x00);
+	   }
+	}
+
 	inSISIDXREG(SISCR,0x34,reg);
+	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) {
 	      printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
@@ -4398,41 +4558,31 @@
 #endif	
 #endif
 
-	if (sisvga_engine == SIS_315_VGA) {
-		switch (ivideo.chip) {
-		   case SIS_315H:
-		   case SIS_315:
-		   case SIS_330:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   case SIS_550:
-		   case SIS_650:
-		   case SIS_740:
-		   case SIS_661:
-		   case SIS_741:
-		   case SIS_660:
-		   case SIS_760:
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-			break;
-		   default:
-			break;
-		}
-	} else if (sisvga_engine == SIS_300_VGA) {
-		if (ivideo.chip == SIS_300) {
+	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)
+			if(reg & SIS_SCRATCH_REG_1A_MASK)
 				sishw_ext.bIntegratedMMEnabled = TRUE;
 			else
 				sishw_ext.bIntegratedMMEnabled = FALSE;
 		}
 	}
 
+	ivideo.bios_vbase = ivideo.bios_abase = NULL;
 	if(sisfb_userom) {
-	    sishw_ext.pjVirtualRomBase = sis_find_rom();
+	    sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
+#if defined(__i386__) || defined(__x86_64__)
+	    ivideo.bios_vbase = sishw_ext.pjVirtualRomBase;	/* mapped */
+#else
+	    ivideo.bios_abase = sishw_ext.pjVirtualRomBase;	/* allocated */
+#endif
 	    if(sishw_ext.pjVirtualRomBase) {
-		printk(KERN_INFO "sisfb: Video ROM found and mapped to %p\n",
+		printk(KERN_INFO "sisfb: Video ROM found and %s to %p\n",
+			ivideo.bios_vbase ? "mapped" : "copied",
 		        sishw_ext.pjVirtualRomBase);
 		sishw_ext.UseROM = TRUE;
 	    } else {
@@ -4445,8 +4595,6 @@
 	    printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
 	}
 	sishw_ext.bSkipDramSizing = 0;
-	sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
-	sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
 
         /* Find systems for special custom timing */
 	if(SiS_Pr.SiS_CustomT == CUT_NONE) {
@@ -4502,7 +4650,7 @@
 
 #ifdef CONFIG_FB_SIS_300
 	/* Mode numbers for 1280x768 are different for 300 and 315 series */
-	if(sisvga_engine == SIS_300_VGA) {
+	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;
@@ -4511,36 +4659,38 @@
 #endif
 
 	sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
-	if (sishw_ext.pSR == NULL) {
+	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) {
-	        vfree(sishw_ext.pSR);
+	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(sisvga_engine == SIS_300_VGA) {
-		if(!sisvga_enabled) {
-		        /* Mapping Max FB Size for 300 Init */
-			sishw_ext.pjVideoMemoryAddress
-				= ioremap(ivideo.video_base, 0x4000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-			}
+	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()) {
-		        vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
 			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;
 		}
@@ -4548,12 +4698,16 @@
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-	if (sisvga_engine == SIS_315_VGA) {
-		if (!sisvga_enabled) {
-			/* Mapping Max FB Size for 315 Init */
-			sishw_ext.pjVideoMemoryAddress 
-				= ioremap(ivideo.video_base, 0x8000000);
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
+	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)) {
+				/* 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;
@@ -4562,12 +4716,14 @@
 				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);
-			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
 			kfree(sis_fb_info);
 			return -ENODEV;
 		}
@@ -4575,53 +4731,73 @@
 #endif
 
 	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 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(sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-	if(sisfb_pdc) {
-	    SiS_Pr.PDC = sisfb_pdc;
-	} else {
-	    SiS_Pr.PDC = 0;
+	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_315_VGA) {
+	   if(sisfb_pdca != 0xff) SiS_Pr.PDCA = sisfb_pdca & 0x1f;
 	}
 
-	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);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(ivideo.mmio_base, sisfb_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);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = 
-		ioremap(ivideo.video_base, ivideo.video_size);
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, sisfb_mmio_size);
+	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, ivideo.video_size);
+	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);
+	   	kfree(sis_fb_info);
+	   	return -ENODEV;
+	}
+
+	ivideo.mmio_vbase = 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);
+	   	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);
+	       	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,
-	       sisfb_mmio_size / 1024);
+	       	ivideo.mmio_base, ivideo.mmio_vbase, ivideo.mmio_size / 1024);
 
 	if(sisfb_heap_init()) {
 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
@@ -4631,11 +4807,12 @@
 	
 	ivideo.vbflags = 0;
 
+	ivideo.newrom = SiSDetermineROMLayout661(&SiS_Pr, &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;
-		sishw_ext.usExternalChip = 0;
 
 		sisfb_sense_crt1();
 	
@@ -4645,7 +4822,7 @@
 			sisfb_detect_VB_connect();
 		}
 		
-		ivideo.currentvbflags = ivideo.vbflags & VB_VIDEOBRIDGE;
+		ivideo.currentvbflags = ivideo.vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 		
 		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
 		   if(sisfb_crt2type != -1) {
@@ -4658,7 +4835,7 @@
 		      /* Chrontel 700x TV detection often unreliable, therefore use a
 		       * different default order on such machines
 		       */
-		      if((sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
+		      if((ivideo.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;
@@ -4673,67 +4850,99 @@
 		if(ivideo.vbflags & CRT2_LCD) {
 		   inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
 		   reg &= 0x0f;
-		   if(sisvga_engine == SIS_300_VGA) {
+		   if(ivideo.sisvga_engine == SIS_300_VGA) {
 		      sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   } else if(ivideo.chip >= SIS_661) {
+		      sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
 		   } else {
 		      sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
 		   }
 		}
-		
-		sisfb_detectedpdc = 0;
-
+	
 #ifdef CONFIG_FB_SIS_300
                 /* Save the current PanelDelayCompensation if the LCD is currently used */
-		if(sisvga_engine == SIS_300_VGA) {
+		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,sisfb_detectedpdc);
-			  sisfb_detectedpdc &= 0x3c;
-			  if(SiS_Pr.PDC == 0) {
+		          inSISIDXREG(SISPART1,0x13,ivideo.detectedpdc);
+			  ivideo.detectedpdc &= 0x3c;
+			  if(SiS_Pr.PDC == -1) {
 			     /* Let option override detection */
-			     SiS_Pr.PDC = sisfb_detectedpdc;
+			     SiS_Pr.PDC = ivideo.detectedpdc;
 			  }
-			  printk(KERN_INFO
-			         "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
+			  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+  			         ivideo.detectedpdc);
 		       }
-		       if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		          printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
+		       if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		          printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
 				 SiS_Pr.PDC);
 		       }
 	           }
 		}
 #endif
 
-	        sisfb_detectedlcda = 0xff;
-
 #ifdef CONFIG_FB_SIS_315
+		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)) {
+		      int tmp;
+		      inSISIDXREG(SISPART1,0x13,tmp);
+		      if(tmp & 0x04) {
+		         SiS_Pr.SiS_UseLCDA = TRUE;
+		         ivideo.detectedlcda = 0x03;
+		         printk(KERN_DEBUG
+			        "sisfb: BIOS uses LCDA for low resolution and text modes\n");
+		      }
+	           }
 
-		if(sisvga_engine == SIS_315_VGA) {
 		   /* Save PDC */
 		   if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISCR,0x30,tmp);
-		      if(tmp & 0x20) {
+		      if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
 		         /* Currently on LCD? If yes, read current pdc */
-		         inSISIDXREG(SISPART1,0x2D,sisfb_detectedpdc);
-			 if(SiS_Pr.PDC == 0) {
-			    /* Let option override detection */
-			    SiS_Pr.PDC = sisfb_detectedpdc;
+			 u8 pdc;
+		         inSISIDXREG(SISPART1,0x2D,pdc);
+			 ivideo.detectedpdc  = (pdc & 0x0f) << 1;
+			 ivideo.detectedpdca = (pdc & 0xf0) >> 3;
+			 inSISIDXREG(SISPART1,0x35,pdc);
+			 ivideo.detectedpdc |= ((pdc >> 7) & 0x01);
+			 inSISIDXREG(SISPART1,0x20,pdc);
+			 ivideo.detectedpdca |= ((pdc >> 6) & 0x01);
+			 if(ivideo.newrom) {
+			    /* New ROM invalidates other PDC resp. */
+			    if(ivideo.detectedlcda != 0xff) {
+			       ivideo.detectedpdc = 0xff;
+			    } else {
+			       ivideo.detectedpdca = 0xff;
+			    }
+			 }
+			 if(SiS_Pr.PDC == -1) {
+			    if(ivideo.detectedpdc != 0xff) {
+			       SiS_Pr.PDC = ivideo.detectedpdc;
+			    }
+			 }
+			 if(SiS_Pr.PDCA == -1) {
+			    if(ivideo.detectedpdca != 0xff) {
+			       SiS_Pr.PDCA = ivideo.detectedpdca;
+			    }
+			 }
+			 if(ivideo.detectedpdc != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+  			          ivideo.detectedpdc);
+			 }
+			 if(ivideo.detectedpdca != 0xff) {
+			    printk(KERN_INFO
+			         "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+  			          ivideo.detectedpdca);
 			 }
-			 printk(KERN_INFO
-			        "sisfb: Detected LCD PanelDelayCompensation %d\n",
-  			         sisfb_detectedpdc);
-		      }
-		      if((SiS_Pr.PDC) && (SiS_Pr.PDC != sisfb_detectedpdc)) {
-		         printk(KERN_INFO
-			         "sisfb: Using LCD PanelDelayCompensation %d\n",
-				 SiS_Pr.PDC);
 		      }
+
 		      /* Save EMI */
 		      if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
 		         inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
@@ -4741,57 +4950,41 @@
 			 inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
 			 inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
 			 SiS_Pr.HaveEMI = TRUE;
-			 if(tmp & 0x20) SiS_Pr.HaveEMILCD = TRUE;
+			 if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
+			  	SiS_Pr.HaveEMILCD = TRUE;
+			 }
 		      }
 		   }
 
-		   /* Try to find about LCDA */
-		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
-		      int tmp;
-		      inSISIDXREG(SISCR,0x34,tmp);
-		      if((tmp <= 0x13) || (tmp == 0xff)) {
-		         /* Currently on LCDA? (Some BIOSes leave CR38) */
-		         inSISIDXREG(SISCR,0x38,tmp);
-			 if((tmp & 0x03) == 0x03)  SiS_Pr.SiS_UseLCDA = TRUE;
-			 else {
-			    /* Currently on LCDA? (Some newer BIOSes set D0 in CR35) */
-			    inSISIDXREG(SISCR,0x35,tmp);
-			    if(tmp & 0x01) SiS_Pr.SiS_UseLCDA = TRUE;
-			    else {
-			       /* Currently on LCD? If so, we can find out
-			        * by peeking the mode register
-				*/
-			       inSISIDXREG(SISCR,0x30,tmp);
-			       if(tmp & 0x20) {
-			          inSISIDXREG(SISPART1,0x13,tmp);
-				  if(tmp & 0x04) SiS_Pr.SiS_UseLCDA = TRUE;
-			       }
-			    }
-			 }
+		   /* 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)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+				 SiS_Pr.PDC);
 		      }
-		      if(SiS_Pr.SiS_UseLCDA) {
-		         sisfb_detectedlcda = 0x03;
-		         printk(KERN_DEBUG
-			        "sisfb: Bridge uses LCDA for low resolution and text modes\n");
+		      if((SiS_Pr.PDCA != -1) && (SiS_Pr.PDCA != ivideo.detectedpdca)) {
+		         printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+				 SiS_Pr.PDCA);
 		      }
-	          }
+		   }
+
 		}
 #endif
 
-		if (!sisfb_crt1off) {
+		if(!sisfb_crt1off) {
 		   	sisfb_handle_ddc(&sisfb_thismonitor, 0);
 		} else {
-		   	if ((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-		      	    (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
+		   	if((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+		      	   (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
 		      		sisfb_handle_ddc(&sisfb_thismonitor, 1);
 		   	}
 		}
 
-		if (sisfb_mode_idx >= 0)
+		if(sisfb_mode_idx >= 0)
 			sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
 
-		if (sisfb_mode_idx < 0) {
-			switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(sisfb_mode_idx < 0) {
+			switch(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
 			   case CRT2_LCD:
 				sisfb_mode_idx = DEFAULT_LCDMODE;
 				break;
@@ -4804,19 +4997,19 @@
 			}
 		}
 
-		sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+		ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
 
-		if (ivideo.refresh_rate != 0)
+		if(ivideo.refresh_rate != 0)
 			sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
 
-		if (sisfb_rate_idx == 0) {
-			sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+		if(ivideo.rate_idx == 0) {
+			ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
 			ivideo.refresh_rate = 60;
 		}
 
-		if (sisfb_thismonitor.datavalid) {
+		if(sisfb_thismonitor.datavalid) {
 			if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-			                      sisfb_rate_idx, ivideo.refresh_rate)) {
+			                      ivideo.rate_idx, ivideo.refresh_rate)) {
 				printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 			}
 		}
@@ -4839,13 +5032,14 @@
 
 		sisfb_pre_setmode();
 
-		if (SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
+		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-				sisfb_mode_no);
+				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, sisfb_mmio_size);
+			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
@@ -4877,7 +5071,7 @@
 			
 		sisfb_set_disp(-1, &default_var, sis_fb_info);
 		
-#else		/* --------- For 2.5: Setup a somewhat sane default var ------------ */
+#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,
@@ -4891,10 +5085,10 @@
 		
 		default_var.pixclock = (u32) (1000000000 /
 				sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						sisfb_mode_no, sisfb_rate_idx));
+						ivideo.mode_no, ivideo.rate_idx));
 						
 		if(sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-			 sisfb_mode_no, sisfb_rate_idx,
+			 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,
@@ -4927,23 +5121,24 @@
 		sis_fb_info->par = &ivideo;
 		sis_fb_info->screen_base = 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;
 		
 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
 #endif
 
-		printk(KERN_INFO "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
 
 #ifdef CONFIG_MTRR
 		ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
 				(unsigned int) ivideo.video_size,
 				MTRR_TYPE_WRCOMB, 1);
 		if(ivideo.mtrr) {
-			printk(KERN_INFO "sisfb: Added MTRRs\n");
+			printk(KERN_DEBUG "sisfb: Added MTRRs\n");
 		}
-
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -4951,41 +5146,110 @@
 #endif
 
 		if(register_framebuffer(sis_fb_info) < 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,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, sisfb_mmio_size);
-#endif
+			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
-		sisfb_registered = 1;			
+		ivideo.registered = 1;
+
+		pci_set_drvdata(pdev, sis_fb_info);
 
 		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");
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
 		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename, VER_MAJOR, VER_MINOR,
-	       		VER_LEVEL);		     
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename,
 #else
-		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
-	       		sis_fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
+	       		sis_fb_info->node, myid,
 #endif
+			VER_MAJOR, VER_MINOR, VER_LEVEL);
 
-		printk(KERN_INFO "sisfb: (C) 2001-2003 Thomas Winischhofer.\n");
+		printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
 
 	}	/* if mode = "none" */
+
 	return 0;
 }
 
+/*****************************************************/
+/*                PCI DEVICE HANDLING                */
+/*****************************************************/
+
+static void __devexit sisfb_remove(struct pci_dev *pdev)
+{
+	/* Unmap */
+	iounmap(ivideo.video_vbase);
+	iounmap(ivideo.mmio_vbase);
+	if(ivideo.bios_vbase) iounmap(ivideo.bios_vbase);
+
+	/* Release mem regions */
+	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);
+	}
+#endif
+
+	/* Unregister the framebuffer */
+	if(ivideo.registered) {
+		unregister_framebuffer(sis_fb_info);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
+		framebuffer_release(sis_fb_info);
+#else
+		kfree(sis_fb_info);
+#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
+	 * This sounds easy but is as good as impossible
+	 * on many machines with SiS chip and video bridge
+	 * since text modes are always set up differently
+	 * from machine to machine. Depends on the type
+	 * of integration between chipset and bridge.
+	 */
+	if(ivideo.registered) {
+	   printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
+	}
+};
+
+static struct pci_driver sisfb_driver = {
+	.name		= "sisfb",
+	.id_table 	= sisfb_pci_table,
+	.probe 		= sisfb_probe,
+	.remove 	= __devexit_p(sisfb_remove)
+};
+
+int __init sisfb_init(void)
+{
+	return(pci_module_init(&sisfb_driver));
+}
+
+/*****************************************************/
+/*                      MODULE                       */
+/*****************************************************/
 
 #ifdef MODULE
 
@@ -4997,7 +5261,8 @@
 static char         *forcecrt2type = NULL;
 static int          forcecrt1 = -1;
 static char         *queuemode = NULL;
-static int          pdc = 0;
+static int          pdc = -1;
+static int          pdc1 = -1;
 static int          noaccel = -1;
 static int          noypan  = -1;
 static int	    nomax = -1;
@@ -5011,10 +5276,14 @@
 static int          scalelcd = -1;
 static char	    *specialtiming = NULL;
 static int	    lvdshl = -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/650/651/661/740/741/330/760 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Various others");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Others");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM(mode, "s");
@@ -5068,11 +5337,11 @@
 
 MODULE_PARM(queuemode,   "s");
 MODULE_PARM_DESC(queuemode,
-	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP, VRAM,\n"
-  	  "MMIO. AGP is only available if the kernel has AGP support. The queue mode is\n"
-	  "important to programs using the 2D/3D accelerator of the SiS chip. The modes\n"
-	  "require a totally different way of programming the engines. If any mode than\n"
-	  "MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
+	"\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 */
@@ -5083,16 +5352,16 @@
 	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
 	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
 	  "otherwise at 12288KB. On 315 and Xabre series, the heap is 1MB by default. The\n"
-	  "value is to be specified without 'KB' and should match the MaxXFBMem setting for\n"
-	  "XFree 4.x (x>=2).");
+	  "value is to be specified without 'KB' and should match the MaxXFBMem setting\n"
+	  "for XFree 4.x (x>=2).");
 
 MODULE_PARM(forcecrt2type, "s");
 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 301(B/LV) bridge, parameters SVIDEO, COMPOSITE or SCART can be\n"
-	  "used instead of TV to override the TV detection. (default: [autodetected])");
+	  "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,
@@ -5105,9 +5374,14 @@
         "\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; 3 or 51 on a 315 series chipset. If the problem persists,\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"
-	  "and value from 0 to 255). (default: [autodetected])");
+	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)");
+
+MODULE_PARM(pdc1, "i");
+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,
@@ -5122,9 +5396,10 @@
 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 this\n"
-	  "is set to anything other than 0, sisfb will not do this and thereby enable the user\n"
-	  "to positively specify a virtual Y size of the screen using fbset. (default: 0)\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");
@@ -5156,20 +5431,31 @@
 MODULE_PARM(scalelcd, "i");
 MODULE_PARM_DESC(scalelcd,
 	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-	  "native resolution. Setting it to 0 will disable scaling; if the panel can scale\n"
-	  "by itself, it will probably do this, otherwise you will see a black bar around\n"
-	  "the screen image. Default: [autodetect if panel can scale]");
+	  "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");
 
+#if !defined(__i386__) && !defined(__x86_64__)
+MODULE_PARM(resetcard, "i");
+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");
+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]");
+#endif
 
-int init_module(void)
+int __init sisfb_init_module(void)
 {
-	int err;
-
 	SiS_Pr.UsePanelScaler = -1;
+	SiS_Pr.CenterScreen = -1;
 	SiS_Pr.SiS_CustomT = CUT_NONE;
 	SiS_Pr.LVDSHL = -1;
 
@@ -5230,14 +5516,15 @@
 
 	sisfb_useoem = useoem;
 
-	if (queuemode)        sisfb_search_queuemode(queuemode);
-	
+	if(queuemode)         sisfb_search_queuemode(queuemode);
+
 	/* If other queuemode than MMIO, disable 2D accel and ypan */
 	if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
 	        sisfb_accel = 0;
 	}
 
-        if(pdc) sisfb_pdc = pdc & 0x3c;
+        if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
+	if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
 
 	sisfb_nocrt2rate = nocrt2rate;
 
@@ -5246,55 +5533,30 @@
 
 	if((lvdshl >= 0) && (lvdshl <= 3)) SiS_Pr.LVDSHL = lvdshl;
 
-	if((err = sisfb_init()) < 0) return err;
-
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	/* Release mem regions */
-	release_mem_region(ivideo.video_base, ivideo.video_size);
-	release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
+#if !defined(__i386__) && !defined(__x86_64__)
+        if(resetcard)   sisfb_resetcard = 1;
+	else		sisfb_resetcard = 0;
 
-#ifdef CONFIG_MTRR
-	/* TW: Release MTRR region */
-	if(ivideo.mtrr) {
-		mtrr_del(ivideo.mtrr,
-		      (unsigned int)ivideo.video_base,
-	              (unsigned int)ivideo.video_size);
-	}
+	if(videoram)    sisfb_videoram = videoram;
 #endif
 
-	/* Unregister the framebuffer */
-	if(sisfb_registered) {
-		unregister_framebuffer(sis_fb_info);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-		framebuffer_release(sis_fb_info);
-#else
-		kfree(sis_fb_info);
-#endif
-	}
+        return(sisfb_init());
+}
 
-	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
-	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
-	
-	/* TODO: Restore the initial mode 
-	 * This sounds easy but is as good as impossible
-	 * on many machines with SiS chip and video bridge
-	 * since text modes are always set up differently
-	 * from machine to machine. Depends on the type
-	 * of integration between chipset and bridge.
-	 */
-	
-	printk(KERN_INFO "sisfb: Module unloaded\n");
+static void __exit sisfb_remove_module(void)
+{
+	pci_unregister_driver(&sisfb_driver);
+	printk(KERN_DEBUG "sisfb: Module unloaded\n");
 }
 
-#endif
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+#endif 	   /*  /MODULE  */
 
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
 EXPORT_SYMBOL(sis_dispinfo);
 
 EXPORT_SYMBOL(ivideo);
-                                                                                           
+
diff -urN linux-2.4.26-pre2/drivers/video/sis/sis_main.h linux-2.4.26-pre3/drivers/video/sis/sis_main.h
--- linux-2.4.26-pre2/drivers/video/sis/sis_main.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/sis_main.h	2004-03-13 07:43:23.000000000 -0800
@@ -32,7 +32,7 @@
 
 #define VER_MAJOR                 1
 #define VER_MINOR                 6
-#define VER_LEVEL                 25
+#define VER_LEVEL                 32
 
 #include "sis.h"
 
@@ -161,12 +161,12 @@
 #define MMIO_QUEUE_WRITEPORT      0x85C4
 #define MMIO_QUEUE_READPORT       0x85C8
 
-#define IND_SIS_CRT2_WRITE_ENABLE_300 0x24
-#define IND_SIS_CRT2_WRITE_ENABLE_315 0x2F
+#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_8BPP_COLOR_MODE       0x0
 #define SIS_15BPP_COLOR_MODE      0x1 
 #define SIS_16BPP_COLOR_MODE      0x2 
 #define SIS_32BPP_COLOR_MODE      0x4 
@@ -187,10 +187,10 @@
 #define SIS315_DATA_BUS_64        0x00
 #define SIS315_DATA_BUS_128       0x01
 #define SIS315_DUAL_CHANNEL_MASK  0x0C
-#define SIS315_SINGLE_CHANNEL_1_RANK  	0x0
-#define SIS315_SINGLE_CHANNEL_2_RANK  	0x1
+#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    	0x3
+#define SIS315_DUAL_CHANNEL_1_RANK    	0x03
 
 #define SIS_SCRATCH_REG_1A_MASK   0x10
 
@@ -314,9 +314,40 @@
                                           outSISIDXREG(base,idx,__Temp); \
                                         } while (0)
 
-/* ------------------- Global Variables ----------------------------- */
+#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
 
-/* Fbcon variables */
+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;
+
+/* Fbcon stuff */
 static struct fb_info *sis_fb_info;
 
 static struct fb_var_screeninfo default_var = {
@@ -384,38 +415,28 @@
 static int currcon = 0;
 #endif
 
-/* global flags */
 static int sisfb_off = 0;
 static int sisfb_crt1off = 0;
 static int sisfb_forcecrt1 = -1;
-static int sisvga_enabled = 0;
+static int sisfb_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_registered = 0;
 static int sisfb_mem = 0;
-static int sisfb_pdc = 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_dstn = 0;
 static int sisfb_fstn = 0;
-
-VGA_ENGINE sisvga_engine = UNKNOWN_VGA;
 int 	   sisfb_accel = -1;
-
-/* These are to adapted according to VGA_ENGINE type */
-static int sisfb_hwcursor_size = 0;
-static int sisfb_CRT2_write_enable = 0;
-
-int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
-
-int sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
-
-unsigned char sisfb_detectedpdc = 0;
-
-unsigned char sisfb_detectedlcda = 0xff;
+int 	   sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
+#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;
@@ -429,10 +450,6 @@
 /* SiS private structure */
 SiS_Private  SiS_Pr;
 
-/* Card parameters */
-static unsigned long sisfb_mmio_size = 0;
-static u8            sisfb_caps = 0;
-
 typedef enum _SIS_CMDTYPE {
 	MMIO_CMD = 0,
 	AGP_CMD_QUEUE,
@@ -440,22 +457,43 @@
 } SIS_CMDTYPE;
 
 /* List of supported chips */
-static struct board {
-	u16 vendor, device;
-	const char *name;
-} sisdev_list[] = {
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     "SIS 300"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630/730 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    "SIS 315H"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     "SIS 315"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  "SIS 315PRO"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, "SIS 550 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, "SIS 65x/M65x/740 VGA"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     "SIS 330"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, "SIS 661FX/M661FX/741/760 VGA"},
-	{0, 0, NULL}
+static struct sisfb_chip_info {
+        int 		chip;
+	VGA_ENGINE 	vgaengine;
+	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" },
+};
+
+static struct pci_device_id __devinitdata sisfb_pci_table[] = {
+#ifdef CONFIG_FB_SIS_300
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
+#ifdef CONFIG_FB_SIS_315
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315H,    PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_315PRO,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+#endif
+	{ 0 }
 };
+MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
 
 #define MD_SIS300 1
 #define MD_SIS315 2
@@ -563,7 +601,11 @@
 	{"1280x768x16",  0x24, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
 	{"1280x768x24",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
 	{"1280x768x32",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x960x8",   0x7c, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315}, 
+	{"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},
@@ -587,6 +629,10 @@
 	{"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},
@@ -604,8 +650,6 @@
 #else
 int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
 #endif
-u8  sisfb_mode_no  = 0;
-u8  sisfb_rate_idx = 0;
 
 /* CR36 evaluation */
 const USHORT sis300paneltype[] =
@@ -620,15 +664,21 @@
       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
       LCD_640x480_2, LCD_640x480_3, LCD_320x480,   LCD_1024x768 };
 
+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 };
+
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
 
-static const struct _sis_crt2type {
+static struct _sis_crt2type {
 	char name[10];
 	int type_no;
 	int tvplug_no;
 	unsigned short flags;
-} sis_crt2type[] = {
+} sis_crt2type[] __initdata = {
 	{"NONE", 	0, 		-1,        0},
 	{"LCD",  	CRT2_LCD, 	-1,        0},
 	{"TV",   	CRT2_TV, 	-1,        0},
@@ -642,10 +692,10 @@
 };
 
 /* Queue mode selection for 310 series */
-static const struct _sis_queuemode {
+static struct _sis_queuemode {
 	char name[6];
 	int type_no;
-} sis_queuemode[] = {
+} sis_queuemode[] __initdata = {
 	{"AGP",  	AGP_CMD_QUEUE},
 	{"VRAM", 	VM_CMD_QUEUE},
 	{"MMIO", 	MMIO_CMD},
@@ -653,10 +703,10 @@
 };
 
 /* TV standard */
-static const struct _sis_tvtype {
+static struct _sis_tvtype {
 	char name[6];
 	int type_no;
-} sis_tvtype[] = {
+} sis_tvtype[] __initdata = {
 	{"PAL",  	TV_PAL},
 	{"NTSC", 	TV_NTSC},
 	{"\0",   	-1}
@@ -696,6 +746,7 @@
 	{1, 1152,  864,  75,  TRUE}, {2, 1152,  864,  84,  TRUE},
 	{1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
 	{1, 1280,  768,  60,  TRUE},
+	{1, 1280,  800,  60,  TRUE},
 	{1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
 	{1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
 	{4, 1280, 1024,  85,  TRUE},
@@ -705,6 +756,7 @@
 	{1, 1600, 1200,  60,  TRUE}, {2, 1600, 1200,  65,  TRUE}, {3, 1600, 1200,  70,  TRUE},
 	{4, 1600, 1200,  75,  TRUE}, {5, 1600, 1200,  85,  TRUE}, {6, 1600, 1200, 100,  TRUE},
 	{7, 1600, 1200, 120,  TRUE},
+	{1, 1680, 1050,  60,  TRUE},
 	{1, 1920, 1440,  60,  TRUE}, {2, 1920, 1440,  65,  TRUE}, {3, 1920, 1440,  70,  TRUE},
 	{4, 1920, 1440,  75,  TRUE}, {5, 1920, 1440,  85,  TRUE}, {6, 1920, 1440, 100,  TRUE},
 	{1, 2048, 1536,  60,  TRUE}, {2, 2048, 1536,  65,  TRUE}, {3, 2048, 1536,  70,  TRUE},
@@ -764,18 +816,20 @@
 static u8 sisfb_lastrates[128];
 #endif
 
-static const struct _chswtable {
+#ifdef CONFIG_FB_SIS_300
+static struct _chswtable {
     int subsysVendor;
     int subsysCard;
     char *vendorName;
     char *cardName;
-} mychswtable[] = {
+} mychswtable[] __devinitdata = {
         { 0x1631, 0x1002, "Mitachi", "0x1002" },
 	{ 0x1071, 0x7521, "Mitac"  , "7521P"  },
 	{ 0,      0,      ""       , ""       }
 };
+#endif
 
-static const struct _customttable {
+static struct _customttable {
     unsigned short chipID;
     char *biosversion;
     char *biosdate;
@@ -788,7 +842,7 @@
     char *cardName;
     unsigned long SpecialID;
     char *optionName;
-} mycustomttable[] = {
+} mycustomttable[] __devinitdata = {
 	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
 	  0x3240A8,
 	  { 0x220, 0x227, 0x228, 0x229, 0x0ee },
@@ -917,40 +971,7 @@
 	}
 };
 
-#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;
-
-static unsigned long sisfb_hwcursor_vbase;
 
 static unsigned long sisfb_heap_start;
 static unsigned long sisfb_heap_end;
@@ -1208,7 +1229,7 @@
 static void     sisfb_pre_setmode(void);
 static void     sisfb_post_setmode(void);
 
-static char *   sis_find_rom(void);
+static char *   sis_find_rom(struct pci_dev *pdev);
 static BOOLEAN  sisfb_CheckVBRetrace(void);
 static BOOLEAN  sisfbcheckvretracecrt2(void);
 static BOOLEAN  sisfbcheckvretracecrt1(void);
@@ -1224,10 +1245,6 @@
 void            sis_malloc(struct sis_memreq *req);
 void            sis_free(unsigned long base);
 
-/* Internal hardware access routines */
-void            sisfb_set_reg4(u16 port, unsigned long data);
-u32             sisfb_get_reg3(u16 port);
-
 /* Chipset-dependent internal routines */
 #ifdef CONFIG_FB_SIS_300
 static int      sisfb_get_dram_size_300(void);
@@ -1252,9 +1269,9 @@
 	         	unsigned long offset, unsigned long set, unsigned long *value);
 
 /* Sensing routines */
-void            SiS_Sense30x(void);
-int             SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
-void            SiS_SenseCh(void);
+static void     SiS_Sense30x(void);
+static int      SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
+static void     SiS_SenseCh(void);
 
 /* Routines from init.c/init301.c */
 extern USHORT   SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
@@ -1268,6 +1285,8 @@
 extern void     SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
 extern void     SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
 
+extern BOOLEAN  SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+
 extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
 
@@ -1286,6 +1305,6 @@
 extern void 	SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
 extern void 	SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
 extern void 	SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-
-			
 #endif
+
+
diff -urN linux-2.4.26-pre2/drivers/video/sis/vgatypes.h linux-2.4.26-pre3/drivers/video/sis/vgatypes.h
--- linux-2.4.26-pre2/drivers/video/sis/vgatypes.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/vgatypes.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -187,6 +184,7 @@
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
+    LCD_1280x720,
     LCD_CUSTOM,
     LCD_UNKNOWN
 } SIS_LCD_TYPE;
@@ -220,25 +218,27 @@
                                  /* of Linear VGA memory */
 
     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
+
     SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0) */
+
     UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
                                  /* defined in the data structure type  */
                                  /* "SIS_CHIP_TYPE" */
 
     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) */
 
-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
-                                 /* "SIS_LCD_TYPE" */
-                                     
     BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
                                       
     BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
@@ -254,12 +254,6 @@
                                  /* Note : restore cR registers if  */
                                  /* bSkipDramSizing = TRUE */
 #endif
-
-    PSIS_QUERYSPACE  pQueryVGAConfigSpace; /* Get/Set VGA Configuration  */
-                                           /* space */
- 
-    PSIS_QUERYSPACE  pQueryNorthBridgeSpace;/* Get/Set North Bridge  */
-                                            /* space  */
 };
 #endif
 
@@ -275,42 +269,44 @@
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	CARD32 	sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current sisfb mode */
+ 	CARD32 	chip_id;		/* PCI ID of detected chip */
+	CARD32	memory;			/* video memory in KB which sisfb manages */
+	CARD32	heapstart;             	/* heap start (= sisfb "mem" argument) in KB */
+	CARD8 	fbvidmode;		/* current sisfb mode */
+
+	CARD8 	sisfb_version;
+	CARD8	sisfb_revision;
+	CARD8 	sisfb_patchlevel;
+
+	CARD8 	sisfb_caps;		/* sisfb's capabilities */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	CARD32 	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned char sisfb_caps;	/* sisfb's capabilities */
+	CARD32 	sisfb_pcibus;      	/* The card's PCI ID */
+	CARD32 	sisfb_pcislot;
+	CARD32 	sisfb_pcifunc;
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	CARD8 	sisfb_lcdpdc;
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	CARD8	sisfb_lcda;
 
-	unsigned char sisfb_lcdpdc;
-	
-	unsigned char sisfb_lcda;
+	CARD32	sisfb_vbflags;
+	CARD32	sisfb_currentvbflags;
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	CARD32 	sisfb_scalelcd;
+	CARD32 	sisfb_specialtiming;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	CARD8 	sisfb_haveemi;
+	CARD8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	CARD8 	sisfb_haveemilcd;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	CARD8 	sisfb_lcdpdca;
 
-	char reserved[213]; 		/* for future use */
+	CARD8 reserved[212]; 		/* for future use */
 };
 #endif
 
diff -urN linux-2.4.26-pre2/drivers/video/sis/vstruct.h linux-2.4.26-pre3/drivers/video/sis/vstruct.h
--- linux-2.4.26-pre2/drivers/video/sis/vstruct.h	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/drivers/video/sis/vstruct.h	2004-03-13 07:43:23.000000000 -0800
@@ -31,13 +31,10 @@
  * * 2) Redistributions in binary form must reproduce the above copyright
  * *    notice, this list of conditions and the following disclaimer in the
  * *    documentation and/or other materials provided with the distribution.
- * * 3) All advertising materials mentioning features or use of this software
- * *    must display the following acknowledgement: "This product includes
- * *    software developed by Thomas Winischhofer, Vienna, Austria."
- * * 4) The name of the author may not be used to endorse or promote products
+ * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
  * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
@@ -164,7 +161,6 @@
 {
 	UCHAR  Ext_ModeID;
 	USHORT Ext_ModeFlag;
-	UCHAR  Ext_ModeOffset;
 	USHORT Ext_VESAID;
 	UCHAR  Ext_RESINFO;
 	UCHAR  VB_ExtTVFlickerIndex;
@@ -180,6 +176,7 @@
 	UCHAR  Ext_CRT1CRTC;
 	UCHAR  Ext_CRTVCLK;
 	UCHAR  Ext_CRT2CRTC;
+	UCHAR  Ext_CRT2CRTC_NS;
 	UCHAR  ModeID;
 	USHORT XRes;
 	USHORT YRes;
@@ -228,6 +225,8 @@
 	UCHAR  YChar;
 } SiS_ModeResInfoStruct;
 
+
+
 typedef UCHAR DRAM4Type[4];
 
 /* Defines for SiS_CustomT */
@@ -289,18 +288,21 @@
         USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
 #endif
 	BOOLEAN SiS_UseROM;
-	int    SiS_CHOverScan;
+	BOOLEAN SiS_ROMNew;
+	BOOLEAN PanelSelfDetected;
+	int     SiS_CHOverScan;
 	BOOLEAN SiS_CHSOverScan;
 	BOOLEAN SiS_ChSW;
 	BOOLEAN SiS_UseLCDA;
-	int    SiS_UseOEM;
-	ULONG  SiS_CustomT;
-	USHORT SiS_Backup70xx;
+	int     SiS_UseOEM;
+	ULONG   SiS_CustomT;
+	USHORT  SiS_Backup70xx;
 	BOOLEAN HaveEMI;
 	BOOLEAN HaveEMILCD;
 	BOOLEAN OverruleEMI;
 	UCHAR  EMI_30,EMI_31,EMI_32,EMI_33;
-	UCHAR  PDC;
+	SHORT  PDC, PDCA;
+	UCHAR  SiS_MyCR63;
 	USHORT SiS_CRT1Mode;
 	USHORT SiS_flag_clearbuffer;
 	int    SiS_RAMType;
@@ -339,32 +341,19 @@
 	USHORT SiS_DDC_Port;
 	USHORT SiS_DDC_Index;
 	USHORT SiS_DDC_Data;
+	USHORT SiS_DDC_NData;
 	USHORT SiS_DDC_Clk;
-	USHORT SiS_DDC_DataShift;
+	USHORT SiS_DDC_NClk;
 	USHORT SiS_DDC_DeviceAddr;
 	USHORT SiS_DDC_ReadAddr;
 	USHORT SiS_DDC_SecAddr;
-	USHORT SiS_Panel800x600;
-	USHORT SiS_Panel1024x768;
-	USHORT SiS_Panel1280x1024;
-	USHORT SiS_Panel1600x1200;
-	USHORT SiS_Panel1280x960;
-	USHORT SiS_Panel1400x1050;
-	USHORT SiS_Panel320x480;
-	USHORT SiS_Panel1152x768;
-	USHORT SiS_Panel1280x768;
-	USHORT SiS_Panel1024x600;
-	USHORT SiS_Panel640x480;
-	USHORT SiS_Panel640x480_2;
-	USHORT SiS_Panel640x480_3;
-	USHORT SiS_Panel1152x864;
-	USHORT SiS_PanelCustom;
-	USHORT SiS_PanelBarco1366;
-	USHORT SiS_PanelMax;
+	USHORT SiS_ChrontelInit;
+	BOOLEAN SiS_SensibleSR11;
+	USHORT SiS661LCD2TableSize;
+
 	USHORT SiS_PanelMinLVDS;
 	USHORT SiS_PanelMin301;
-	USHORT SiS_ChrontelInit;
-	
+
 	const SiS_StStruct          *SiS_SModeIDTable;
 	SiS_StandTableStruct        *SiS_StandTable;
 	const SiS_ExtStruct         *SiS_EModeIDTable;
@@ -373,11 +362,10 @@
 	const SiS_CRT1TableStruct   *SiS_CRT1Table;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_0;
 	const SiS_MCLKDataStruct    *SiS_MCLKData_1;
-	const SiS_VCLKDataStruct    *SiS_VCLKData;
-	const SiS_VBVCLKDataStruct  *SiS_VBVCLKData;
+	SiS_VCLKDataStruct    	    *SiS_VCLKData;
+	SiS_VBVCLKDataStruct        *SiS_VBVCLKData;
 	const SiS_StResInfoStruct   *SiS_StResInfo;
 	const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-	const UCHAR                 *SiS_ScreenOffset;
 
 	const UCHAR                 *pSiS_OutputSelect;
 	const UCHAR                 *pSiS_SoftSetting;
@@ -407,6 +395,12 @@
 	const USHORT *pSiS_VideoSenseData2;
 	const USHORT *pSiS_YCSenseData2;
 #endif
+
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
+	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+
+	/* SiS bridge */
+
 	const UCHAR *SiS_NTSCPhase;
 	const UCHAR *SiS_PALPhase;
 	const UCHAR *SiS_NTSCPhase2;
@@ -418,29 +412,27 @@
 	const UCHAR *SiS_SpecialPhase;
 	const UCHAR *SiS_SpecialPhaseM;
 	const UCHAR *SiS_SpecialPhaseJ;
-	const SiS_LCDDataStruct  *SiS_StLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1024x768Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1024x768Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x1024Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x720Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768_2Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x768_3Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x800Data;
+	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1280x1024Data;
 	const SiS_LCDDataStruct  *SiS_St2LCD1280x1024Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1024x768;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x1024;
-	const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1400x1050;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1600x1200;
-	const SiS_LCDDataStruct  *SiS_NoScaleData1280x768;
 	const SiS_LCDDataStruct  *SiS_StLCD1400x1050Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_StLCD1280x768Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1400x1050Data;
+	const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
 	const SiS_LCDDataStruct  *SiS_ExtLCD1600x1200Data;
-	const SiS_LCDDataStruct  *SiS_ExtLCD1280x768Data;
+	const SiS_LCDDataStruct  *SiS_LCD1680x1050Data;
 	const SiS_LCDDataStruct  *SiS_NoScaleData;
 	const SiS_TVDataStruct   *SiS_StPALData;
 	const SiS_TVDataStruct   *SiS_ExtPALData;
 	const SiS_TVDataStruct   *SiS_StNTSCData;
 	const SiS_TVDataStruct   *SiS_ExtNTSCData;
+	const SiS_TVDataStruct   *SiS_St1HiTVData;
 	const SiS_TVDataStruct   *SiS_St2HiTVData;
 	const SiS_TVDataStruct   *SiS_ExtHiTVData;
 	const SiS_TVDataStruct   *SiS_St525iData;
@@ -454,12 +446,22 @@
 	const UCHAR *SiS_HiTVExtTiming;
 	const UCHAR *SiS_HiTVSt1Timing;
 	const UCHAR *SiS_HiTVSt2Timing;
-	const UCHAR *SiS_HiTVTextTiming;
 	const UCHAR *SiS_HiTVGroup3Data;
 	const UCHAR *SiS_HiTVGroup3Simu;
+#if 0
+	const UCHAR *SiS_HiTVTextTiming;
 	const UCHAR *SiS_HiTVGroup3Text;
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
-	const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+#endif
+
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
+	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+
+	/* LVDS, Chrontel */
+
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS1024x768Data_1;
@@ -481,14 +483,6 @@
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDS320x480Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1024x768Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1280x1024Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1400x1050Data_2;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_1;
-	const SiS_LVDSDataStruct  *SiS_LCDA1600x1200Data_2;
 	const SiS_LVDSDataStruct  *SiS_LVDSXXXxXXXData_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_1;
 	const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_2;
@@ -505,6 +499,7 @@
 	const SiS_LVDSDataStruct  *SiS_CHTVUPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVOPALNData;
 	const SiS_LVDSDataStruct  *SiS_CHTVSOPALData;
+
 	const SiS_LVDSDesStruct  *SiS_PanelType00_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType01_1;
 	const SiS_LVDSDesStruct  *SiS_PanelType02_1;
@@ -539,20 +534,11 @@
 	const SiS_LVDSDesStruct  *SiS_PanelType0e_2;
 	const SiS_LVDSDesStruct  *SiS_PanelType0f_2;
 	const SiS_LVDSDesStruct  *SiS_PanelTypeNS_2;
-
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_1;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_1;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_1;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_1;
-	const SiS_LVDSDesStruct  *LVDS1024x768Des_2;
-	const SiS_LVDSDesStruct  *LVDS1280x1024Des_2;
-	const SiS_LVDSDesStruct  *LVDS1400x1050Des_2;
-	const SiS_LVDSDesStruct  *LVDS1600x1200Des_2;
-
 	const SiS_LVDSDesStruct  *SiS_CHTVUNTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVONTSCDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVUPALDesData;
 	const SiS_LVDSDesStruct  *SiS_CHTVOPALDesData;
+
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_1;
@@ -593,44 +579,13 @@
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_2_H;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3;
 	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3_H;
+	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UNTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1ONTSC;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1OPAL;
 	const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1SOPAL;
 
-	const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
-
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_1_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11024x768_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11280x1024_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11400x1050_2_H;
-	const SiS_LCDACRT1DataStruct  *SiS_LCDACRT11600x1200_2_H;
-
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_1;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_2;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1400x1050_3;
-	const SiS_Part2PortTblStruct *SiS_CRT2Part2_1600x1200_3;
-
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
@@ -640,6 +595,7 @@
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
 	const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
+
 	const UCHAR *SiS_CHTVVCLKUNTSC;
 	const UCHAR *SiS_CHTVVCLKONTSC;
 	const UCHAR *SiS_CHTVVCLKUPAL;
@@ -650,9 +606,13 @@
 	const UCHAR *SiS_CHTVVCLKOPALN;
 	const UCHAR *SiS_CHTVVCLKSOPAL;
 
-	USHORT  PanelXRes;
-	USHORT  PanelYRes;
-	
+	USHORT  PanelXRes, PanelHT;
+	USHORT  PanelYRes, PanelVT;
+	USHORT  PanelHRS,  PanelHRE;
+  	USHORT 	PanelVRS,  PanelVRE;
+	USHORT  PanelVCLKIdx300;
+	USHORT  PanelVCLKIdx315;
+
 	BOOLEAN UseCustomMode;
 	BOOLEAN CRT1UsesCustomMode;
 	USHORT  CHDisplay;
@@ -694,10 +654,11 @@
 	UCHAR Backup_1d;
 	
 	int     UsePanelScaler;
+	int	CenterScreen;
 
 	USHORT  CP_Vendor, CP_Product;
 	BOOLEAN CP_HaveCustomData;
-	int     CP_PreferredX, CP_PreferredY;
+	int     CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
 	int	CP_MaxX, CP_MaxY, CP_MaxClock;
 	BOOLEAN CP_Supports64048075;
 	int     CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
diff -urN linux-2.4.26-pre2/fs/fat/inode.c linux-2.4.26-pre3/fs/fat/inode.c
--- linux-2.4.26-pre2/fs/fat/inode.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/fs/fat/inode.c	2004-03-13 07:43:23.000000000 -0800
@@ -421,11 +421,13 @@
  *  0/  i_ino - for fast, reliable lookup if still in the cache
  *  1/  i_generation - to see if i_ino is still valid
  *          bit 0 == 0 iff directory
- *  2/  i_pos - if ino has changed, but still in cache (hi)
- *  3/  i_pos - if ino has changed, but still in cache (low)
- *  4/  i_logstart - to semi-verify inode found at i_location
- *  5/  parent->i_logstart - maybe used to hunt for the file on disc
+ *  2/  i_pos(8-39) - if ino has changed, but still in cache
+ *  3/  i_pos(4-7)|i_logstart - to semi-verify inode found at i_pos
+ *  4/  i_pos(0-3)|parent->i_logstart - maybe used to hunt for the file on disc
  *
+ * Hack for NFSv2: Maximum FAT entry number is 28bits and maximum
+ * i_pos is 40bits (blocknr(32) + dir offset(8)), so two 4bits
+ * of i_logstart is used to store the directory entry offset.
  */
 struct dentry *fat_fh_to_dentry(struct super_block *sb, __u32 *fh,
 				int len, int fhtype, int parent)
@@ -436,7 +438,7 @@
 
 	if (fhtype != 3)
 		return ERR_PTR(-ESTALE);
-	if (len < 6)
+	if (len < 5)
 		return ERR_PTR(-ESTALE);
 	/* We cannot find the parent,
 	   It better just *be* there */
@@ -444,13 +446,17 @@
 		return ERR_PTR(-ESTALE);
 
 	inode = iget(sb, fh[0]);
-	if (!inode || is_bad_inode(inode) ||
-	    inode->i_generation != fh[1]) {
-		if (inode) iput(inode);
+	if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) {
+		if (inode)
+			iput(inode);
 		inode = NULL;
 	}
 	if (!inode) {
-		loff_t i_pos = ((loff_t)fh[2] << 32) | fh[3];
+		loff_t i_pos;
+		int i_logstart = fh[3] & 0x0fffffff;
+
+		i_pos = (loff_t)fh[2] << 8;
+		i_pos |= ((fh[3] >> 24) & 0xf0) | (fh[4] >> 28);
 
 		/* try 2 - see if i_pos is in F-d-c
 		 * require i_logstart to be the same
@@ -458,7 +464,7 @@
 		 */
 
 		inode = fat_iget(sb, i_pos);
-		if (inode && MSDOS_I(inode)->i_logstart != fh[4]) {
+		if (inode && MSDOS_I(inode)->i_logstart != i_logstart) {
 			iput(inode);
 			inode = NULL;
 		}
@@ -508,24 +514,26 @@
 	result->d_op = sb->s_root->d_op;
 	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
 	return result;
-
-		
 }
 
 int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent)
 {
 	int len = *lenp;
 	struct inode *inode =  de->d_inode;
+	u32 ipos_h, ipos_m, ipos_l;
 	
-	if (len < 6)
+	if (len < 5)
 		return 255; /* no room */
-	*lenp = 6;
+
+	ipos_h = MSDOS_I(inode)->i_pos >> 8;
+	ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
+	ipos_l = (MSDOS_I(inode)->i_pos & 0x0f) << 28;
+	*lenp = 5;
 	fh[0] = inode->i_ino;
 	fh[1] = inode->i_generation;
-	fh[2] = (__u32)(MSDOS_I(inode)->i_pos >> 32);
-	fh[3] = (__u32)MSDOS_I(inode)->i_pos;
-	fh[4] = MSDOS_I(inode)->i_logstart;
-	fh[5] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
+	fh[2] = ipos_h;
+	fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
+	fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
 	return 3;
 }
 
diff -urN linux-2.4.26-pre2/fs/lockd/svc4proc.c linux-2.4.26-pre3/fs/lockd/svc4proc.c
--- linux-2.4.26-pre2/fs/lockd/svc4proc.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/fs/lockd/svc4proc.c	2004-03-13 07:43:23.000000000 -0800
@@ -471,7 +471,7 @@
 
         dprintk("lockd: GRANTED_RES   called\n");
 
-        nlmsvc_grant_reply(&argp->cookie, argp->status);
+        nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
         return rpc_success;
 }
 
diff -urN linux-2.4.26-pre2/fs/lockd/svclock.c linux-2.4.26-pre3/fs/lockd/svclock.c
--- linux-2.4.26-pre2/fs/lockd/svclock.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/fs/lockd/svclock.c	2004-03-13 07:43:23.000000000 -0800
@@ -113,11 +113,11 @@
 				(long long)lock->fl.fl_end, lock->fl.fl_type);
 	for (head = &nlm_blocked; (block = *head); head = &block->b_next) {
 		fl = &block->b_call.a_args.lock.fl;
-		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n",
+		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
 				block->b_file, fl->fl_pid,
 				(long long)fl->fl_start,
 				(long long)fl->fl_end, fl->fl_type,
-				*(unsigned int*)(block->b_call.a_args.cookie.data));
+				nlmdbg_cookie2a(&block->b_call.a_args.cookie));
 		if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
 			if (remove) {
 				*head = block->b_next;
@@ -143,14 +143,15 @@
  * Find a block with a given NLM cookie.
  */
 static inline struct nlm_block *
-nlmsvc_find_block(struct nlm_cookie *cookie)
+nlmsvc_find_block(struct nlm_cookie *cookie,  struct sockaddr_in *sin)
 {
 	struct nlm_block *block;
 
 	for (block = nlm_blocked; block; block = block->b_next) {
 		dprintk("cookie: head of blocked queue %p, block %p\n", 
 			nlm_blocked, block);
-		if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie))
+		if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie)
+				&& nlm_cmp_addr(sin, &block->b_host->h_addr))
 			break;
 	}
 
@@ -579,12 +580,16 @@
 	struct nlm_rqst		*call = (struct nlm_rqst *) task->tk_calldata;
 	struct nlm_block	*block;
 	unsigned long		timeout;
+	struct sockaddr_in	*peer_addr = RPC_PEERADDR(task->tk_client);
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
-	dprintk("callback: looking for cookie %x \n", 
-		*(unsigned int *)(call->a_args.cookie.data));
-	if (!(block = nlmsvc_find_block(&call->a_args.cookie))) {
-		dprintk("lockd: no block for cookie %x\n", *(u32 *)(call->a_args.cookie.data));
+	dprintk("callback: looking for cookie %s, host %u.%u.%u.%u\n", 
+		nlmdbg_cookie2a(&call->a_args.cookie),
+		NIPQUAD(peer_addr->sin_addr.s_addr));
+	if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
+		dprintk("lockd: no block for cookie %s, host %u.%u.%u.%u\n",
+				nlmdbg_cookie2a(&call->a_args.cookie),
+				NIPQUAD(peer_addr->sin_addr.s_addr));
 		return;
 	}
 
@@ -613,18 +618,21 @@
  * block.
  */
 void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
+nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status)
 {
 	struct nlm_block	*block;
 	struct nlm_file		*file;
 
-	if (!(block = nlmsvc_find_block(cookie)))
+	dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 
+		*(unsigned int *)(cookie->data), 
+		ntohl(rqstp->rq_addr.sin_addr.s_addr), status);
+	if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
 		return;
 	file = block->b_file;
 
 	file->f_count++;
 	down(&file->f_sema);
-	if ((block = nlmsvc_find_block(cookie)) != NULL) {
+	if ((block = nlmsvc_find_block(cookie,&rqstp->rq_addr)) != NULL) {
 		if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
 			/* Try again in a couple of seconds */
 			nlmsvc_insert_block(block, 10 * HZ);
diff -urN linux-2.4.26-pre2/fs/lockd/svcproc.c linux-2.4.26-pre3/fs/lockd/svcproc.c
--- linux-2.4.26-pre2/fs/lockd/svcproc.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/fs/lockd/svcproc.c	2004-03-13 07:43:23.000000000 -0800
@@ -499,7 +499,7 @@
 
 	dprintk("lockd: GRANTED_RES   called\n");
 
-	nlmsvc_grant_reply(&argp->cookie, argp->status);
+	nlmsvc_grant_reply(rqstp, &argp->cookie, argp->status);
 	return rpc_success;
 }
 
diff -urN linux-2.4.26-pre2/fs/lockd/xdr.c linux-2.4.26-pre3/fs/lockd/xdr.c
--- linux-2.4.26-pre2/fs/lockd/xdr.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/fs/lockd/xdr.c	2004-03-13 07:43:23.000000000 -0800
@@ -55,7 +55,7 @@
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -64,7 +64,7 @@
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -86,7 +86,7 @@
 
 	if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
 		printk(KERN_NOTICE
-			"lockd: bad fhandle size %x (should be %d)\n",
+			"lockd: bad fhandle size %d (should be %d)\n",
 			len, NFS2_FHSIZE);
 		return NULL;
 	}
@@ -534,7 +534,7 @@
  * Buffer requirements for NLM
  */
 #define NLM_void_sz		0
-#define NLM_cookie_sz		3	/* 1 len , 2 data */
+#define NLM_cookie_sz		1+QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM_caller_sz		1+QUADLEN(sizeof(system_utsname.nodename))
 #define NLM_netobj_sz		1+QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM_owner_sz		1+QUADLEN(NLM_MAXOWNER) */
@@ -643,3 +643,32 @@
 }
 #endif
 
+#ifdef RPC_DEBUG
+const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
+{
+	/*
+	 * We can get away with a static buffer because we're only
+	 * called with BKL held.
+	 */
+	static char buf[2*NLM_MAXCOOKIELEN+1];
+	int i;
+	int len = sizeof(buf);
+	char *p = buf;
+
+	len--;	/* allow for trailing \0 */
+	if (len < 3)
+		return "???";
+	for (i = 0 ; i < cookie->len ; i++) {
+		if (len < 2) {
+			strcpy(p-3, "...");
+			break;
+		}
+		sprintf(p, "%02x", cookie->data[i]);
+		p += 2;
+		len -= 2;
+	}
+	*p = '\0';
+
+	return buf;
+}
+#endif
diff -urN linux-2.4.26-pre2/fs/lockd/xdr4.c linux-2.4.26-pre3/fs/lockd/xdr4.c
--- linux-2.4.26-pre2/fs/lockd/xdr4.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/fs/lockd/xdr4.c	2004-03-13 07:43:23.000000000 -0800
@@ -56,7 +56,7 @@
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -65,7 +65,7 @@
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -540,7 +540,7 @@
  * Buffer requirements for NLM
  */
 #define NLM4_void_sz		0
-#define NLM4_cookie_sz		3	/* 1 len , 2 data */
+#define NLM4_cookie_sz		1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM4_caller_sz		1+XDR_QUADLEN(NLM_MAXSTRLEN)
 #define NLM4_netobj_sz		1+XDR_QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM4_owner_sz		1+XDR_QUADLEN(NLM4_MAXOWNER) */
diff -urN linux-2.4.26-pre2/fs/locks.c linux-2.4.26-pre3/fs/locks.c
--- linux-2.4.26-pre2/fs/locks.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-pre3/fs/locks.c	2004-03-13 07:43:23.000000000 -0800
@@ -1740,7 +1740,14 @@
 	before = &inode->i_flock;
 	while ((fl = *before) != NULL) {
 		if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) {
+			struct file *filp = fl->fl_file;
+			/* Note: locks_unlock_delete() can sleep, and
+			 * so we may race with the call to sys_close()
+			 * by the thread that actually owns this filp.
+			 */
+			get_file(filp);
 			locks_unlock_delete(before);
+			fput(filp);
 			before = &inode->i_flock;
 			continue;
 		}
diff -urN linux-2.4.26-pre2/fs/nfs/dir.c linux-2.4.26-pre3/fs/nfs/dir.c
--- linux-2.4.26-pre2/fs/nfs/dir.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/fs/nfs/dir.c	2004-03-13 07:43:23.000000000 -0800
@@ -545,6 +545,11 @@
 		/* Unhash it, so that ->d_iput() would be called */
 		return 1;
 	}
+	if (!(dentry->d_sb->s_flags & MS_ACTIVE)) {
+		/* Unhash it, so that ancestors of killed async unlink
+		 * files will be cleaned up during umount */
+		return 1;
+	}
 	return 0;
 
 }
diff -urN linux-2.4.26-pre2/fs/nfs/file.c linux-2.4.26-pre3/fs/nfs/file.c
--- linux-2.4.26-pre2/fs/nfs/file.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.26-pre3/fs/nfs/file.c	2004-03-13 07:43:23.000000000 -0800
@@ -241,6 +241,93 @@
 	goto out;
 }
 
+static int
+do_getlk(struct inode *inode, int cmd, struct file_lock *fl)
+{
+	int status;
+
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	unlock_kernel();
+	return status;
+}
+
+static int
+do_unlk(struct inode *inode, int cmd, struct file_lock *fl)
+{
+	sigset_t oldset;
+	int status;
+
+	rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	filemap_fdatasync(inode->i_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);
+	up(&inode->i_sem);
+	filemap_fdatawait(inode->i_mapping);
+
+	/* NOTE: special case
+	 *	If we're signalled while cleaning up locks on process exit, we
+	 *	still need to complete the unlock.
+	 */
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	unlock_kernel();
+	rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
+	return status;
+}
+
+static int
+do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	int status;
+
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	status = filemap_fdatasync(inode->i_mapping);
+	if (status == 0) {
+		down(&inode->i_sem);
+		status = nfs_wb_all(inode);
+		up(&inode->i_sem);
+		if (status == 0)
+			status = filemap_fdatawait(inode->i_mapping);
+	}
+	if (status < 0)
+		return status;
+
+	lock_kernel();
+	status = nlmclnt_proc(inode, cmd, fl);
+	/* If we were signalled we still need to ensure that
+	 * we clean up any state on the server. We therefore
+	 * record the lock call as having succeeded in order to
+	 * ensure that locks_remove_posix() cleans it out when
+	 * the process exits.
+	 */
+	if (status == -EINTR || status == -ERESTARTSYS)
+		posix_lock_file(filp, fl, 0);
+	unlock_kernel();
+	if (status < 0)
+		return status;
+
+	/*
+	 * Make sure we clear the cache whenever we try to get the lock.
+	 * This makes locking act as a cache coherency point.
+	 */
+	filemap_fdatasync(inode->i_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);      /* we may have slept */
+	up(&inode->i_sem);
+	filemap_fdatawait(inode->i_mapping);
+	nfs_zap_caches(inode);
+	return 0;
+}
+
 /*
  * Lock a (portion of) a file
  */
@@ -248,8 +335,6 @@
 nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode * inode = filp->f_dentry->d_inode;
-	int	status = 0;
-	int	status2;
 
 	dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_dev, inode->i_ino,
@@ -266,8 +351,8 @@
 	/* Fake OK code if mounted without NLM support */
 	if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
 		if (IS_GETLK(cmd))
-			status = LOCK_USE_CLNT;
-		goto out_ok;
+			return LOCK_USE_CLNT;
+		return 0;
 	}
 
 	/*
@@ -280,42 +365,9 @@
 	if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX)
 		return -ENOLCK;
 
-	/*
-	 * Flush all pending writes before doing anything
-	 * with locks..
-	 */
-	status = filemap_fdatasync(inode->i_mapping);
-	down(&inode->i_sem);
-	status2 = nfs_wb_all(inode);
-	if (status2 && !status)
-		status = status2;
-	up(&inode->i_sem);
-	status2 = filemap_fdatawait(inode->i_mapping);
-	if (status2 && !status)
-		status = status2;
-	if (status < 0)
-		return status;
-
-	lock_kernel();
-	status = nlmclnt_proc(inode, cmd, fl);
-	unlock_kernel();
-	if (status < 0)
-		return status;
-	
-	status = 0;
-
-	/*
-	 * Make sure we clear the cache whenever we try to get the lock.
-	 * This makes locking act as a cache coherency point.
-	 */
- out_ok:
-	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
-		filemap_fdatasync(inode->i_mapping);
-		down(&inode->i_sem);
-		nfs_wb_all(inode);      /* we may have slept */
-		up(&inode->i_sem);
-		filemap_fdatawait(inode->i_mapping);
-		nfs_zap_caches(inode);
-	}
-	return status;
+	if (IS_GETLK(cmd))
+		return do_getlk(inode, cmd, fl);
+	if (fl->fl_type == F_UNLCK)
+		return do_unlk(inode, cmd, fl);
+	return do_setlk(filp, cmd, fl);
 }
diff -urN linux-2.4.26-pre2/fs/nfs/write.c linux-2.4.26-pre3/fs/nfs/write.c
--- linux-2.4.26-pre2/fs/nfs/write.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/fs/nfs/write.c	2004-03-13 07:43:23.000000000 -0800
@@ -1268,15 +1268,14 @@
 }
 
 #ifdef CONFIG_NFS_V3
-int nfs_commit_file(struct inode *inode, struct file *file, unsigned long idx_start,
-		    unsigned int npages, int how)
+int nfs_commit_file(struct inode *inode, struct file *file, int how)
 {
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
 	spin_lock(&nfs_wreq_lock);
-	res = nfs_scan_commit(inode, &head, file, idx_start, npages);
+	res = nfs_scan_commit(inode, &head, file, 0, 0);
 	spin_unlock(&nfs_wreq_lock);
 	if (res)
 		error = nfs_commit_list(&head, how);
@@ -1306,7 +1305,7 @@
 			error = nfs_flush_file(inode, file, idx_start, npages, how);
 #ifdef CONFIG_NFS_V3
 		if (error == 0)
-			error = nfs_commit_file(inode, file, idx_start, npages, how);
+			error = nfs_commit_file(inode, file, how);
 #endif
 	} while (error > 0);
 	return error;
diff -urN linux-2.4.26-pre2/include/asm-ia64/a.out.h linux-2.4.26-pre3/include/asm-ia64/a.out.h
--- linux-2.4.26-pre2/include/asm-ia64/a.out.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/a.out.h	2004-03-13 07:43:23.000000000 -0800
@@ -7,8 +7,8 @@
  * probably would be better to clean up binfmt_elf.c so it does not
  * necessarily depend on there being a.out support.
  *
- * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000, 2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 #include <linux/types.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/bugs.h linux-2.4.26-pre3/include/asm-ia64/bugs.h
--- linux-2.4.26-pre2/include/asm-ia64/bugs.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/bugs.h	2004-03-13 07:43:23.000000000 -0800
@@ -4,8 +4,10 @@
  * Needs:
  *	void check_bugs(void);
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/bugs.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>,  Hewlett-Packard Co.
  */
 
 #include <asm/processor.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/byteorder.h linux-2.4.26-pre3/include/asm-ia64/byteorder.h
--- linux-2.4.26-pre2/include/asm-ia64/byteorder.h	2001-04-05 12:51:47.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/byteorder.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_BYTEORDER_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 #include <asm/types.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/checksum.h linux-2.4.26-pre3/include/asm-ia64/checksum.h
--- linux-2.4.26-pre2/include/asm-ia64/checksum.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/checksum.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_CHECKSUM_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /*
diff -urN linux-2.4.26-pre2/include/asm-ia64/current.h linux-2.4.26-pre3/include/asm-ia64/current.h
--- linux-2.4.26-pre2/include/asm-ia64/current.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/current.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_CURRENT_H
 
 /*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /* In kernel mode, thread pointer (r13) is used to point to the
diff -urN linux-2.4.26-pre2/include/asm-ia64/errno.h linux-2.4.26-pre3/include/asm-ia64/errno.h
--- linux-2.4.26-pre2/include/asm-ia64/errno.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/errno.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,10 +2,10 @@
 #define _ASM_IA64_ERRNO_H
 
 /*
- * This is derived from the Linux/x86 version.
+ * Based on <asm-i386/errno.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define	EPERM		 1	/* Operation not permitted */
diff -urN linux-2.4.26-pre2/include/asm-ia64/fcntl.h linux-2.4.26-pre3/include/asm-ia64/fcntl.h
--- linux-2.4.26-pre2/include/asm-ia64/fcntl.h	2000-10-09 17:54:58.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/fcntl.h	2004-03-13 07:43:23.000000000 -0800
@@ -1,10 +1,10 @@
 #ifndef _ASM_IA64_FCNTL_H
 #define _ASM_IA64_FCNTL_H
 /*
- * This is mostly compatible with Linux/x86.
+ * Based on <asm-i386/fcntl.h>.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
  */
 
 /*
diff -urN linux-2.4.26-pre2/include/asm-ia64/ioctl.h linux-2.4.26-pre3/include/asm-ia64/ioctl.h
--- linux-2.4.26-pre2/include/asm-ia64/ioctl.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/ioctl.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,10 +2,10 @@
 #define _ASM_IA64_IOCTL_H
 
 /*
- * This is mostly derived from the Linux/x86 version.
+ * Based on <asm-i386/ioctl.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 /* ioctl command encoding: 32 bits total, command in lower 16 bits,
diff -urN linux-2.4.26-pre2/include/asm-ia64/ioctls.h linux-2.4.26-pre3/include/asm-ia64/ioctls.h
--- linux-2.4.26-pre2/include/asm-ia64/ioctls.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/ioctls.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,10 @@
 #define _ASM_IA64_IOCTLS_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/ioctls.h>
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ioctl.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/mca.h linux-2.4.26-pre3/include/asm-ia64/mca.h
--- linux-2.4.26-pre2/include/asm-ia64/mca.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/mca.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,7 +2,7 @@
  * File:	mca.h
  * Purpose:	Machine check handling specific defines
  *
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander (vijay@engr.sgi.com)
  * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
  */
@@ -17,23 +17,8 @@
 #include <asm/processor.h>
 #include <asm/mca_asm.h>
 
-/* These are the return codes from all the IA64_MCA specific interfaces */
-typedef	int ia64_mca_return_code_t;
-
-enum {
-	IA64_MCA_SUCCESS	=	0,
-	IA64_MCA_FAILURE	=	1
-};
-
 #define IA64_MCA_RENDEZ_TIMEOUT		(20 * 1000)	/* value in milliseconds - 20 seconds */
 
-#define IA64_CMC_INT_DISABLE		0
-#define IA64_CMC_INT_ENABLE		1
-
-
-typedef u32 int_vector_t;
-typedef u64 millisec_t;
-
 typedef union cmcv_reg_u {
 	u64	cmcv_regval;
 	struct	{
@@ -50,10 +35,6 @@
 #define cmcv_mask		cmcv_reg_s.cmcr_mask
 #define cmcv_vector		cmcv_reg_s.cmcr_vector
 
-
-#define IA64_MCA_UCMC_HANDLER_SIZE	0x10
-#define IA64_INIT_HANDLER_SIZE		0x10
-
 enum {
 	IA64_MCA_RENDEZ_CHECKIN_NOTDONE	=	0x0,
 	IA64_MCA_RENDEZ_CHECKIN_DONE	=	0x1
@@ -82,16 +63,6 @@
 
 } ia64_mc_info_t;
 
-/* Possible rendez states passed from SAL to OS during MCA
- * handoff
- */
-enum {
-	IA64_MCA_RENDEZ_NOT_RQD		=	0x0,
-	IA64_MCA_RENDEZ_DONE_WITHOUT_INIT	=	0x1,
-	IA64_MCA_RENDEZ_DONE_WITH_INIT		=	0x2,
-	IA64_MCA_RENDEZ_FAILURE			=	-1
-};
-
 typedef struct ia64_mca_sal_to_os_state_s {
 	u64		imsto_os_gp;		/* GP of the os registered with the SAL */
 	u64		imsto_pal_proc;		/* PAL_PROC entry point - physical addr */
@@ -133,41 +104,13 @@
 						 */
 } ia64_mca_os_to_sal_state_t;
 
-typedef int (*prfunc_t)(const char * fmt, ...);
-
 extern void ia64_mca_init(void);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
 extern void ia64_mca_ucmc_handler(void);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
-extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cmc_int_caller(int,void *,struct pt_regs *);
-extern void ia64_mca_cpe_int_handler(int,void *,struct pt_regs *);
-extern void ia64_mca_cpe_int_caller(int,void *,struct pt_regs *);
-extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
-extern int  ia64_mca_check_errors(void);
-
-#define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
 
-#define platform_mem_dev_err_print ia64_log_prt_oem_data
-#define platform_pci_bus_err_print ia64_log_prt_oem_data
-#define platform_pci_comp_err_print ia64_log_prt_oem_data
-#define platform_plat_specific_err_print ia64_log_prt_oem_data
-#define platform_host_ctlr_err_print ia64_log_prt_oem_data
-#define platform_plat_bus_err_print ia64_log_prt_oem_data
-
-#undef	MCA_TEST
-
-#undef IA64_MCA_DEBUG_INFO
-
-#if defined(IA64_MCA_DEBUG_INFO)
-# define IA64_MCA_DEBUG(fmt...)	printk(fmt)
-#else
-# define IA64_MCA_DEBUG(fmt...)
-#endif
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
diff -urN linux-2.4.26-pre2/include/asm-ia64/mman.h linux-2.4.26-pre3/include/asm-ia64/mman.h
--- linux-2.4.26-pre2/include/asm-ia64/mman.h	2001-01-04 12:50:17.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/mman.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,10 @@
 #define _ASM_IA64_MMAN_H
 
 /*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/mman.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define PROT_READ	0x1		/* page can be read */
diff -urN linux-2.4.26-pre2/include/asm-ia64/namei.h linux-2.4.26-pre3/include/asm-ia64/namei.h
--- linux-2.4.26-pre2/include/asm-ia64/namei.h	2001-11-09 14:26:17.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/namei.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_NAMEI_H
 
 /*
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999, 2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ptrace.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/page.h linux-2.4.26-pre3/include/asm-ia64/page.h
--- linux-2.4.26-pre2/include/asm-ia64/page.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/page.h	2004-03-13 07:43:23.000000000 -0800
@@ -120,7 +120,13 @@
 #define is_invalid_hugepage_range(addr, len) 0
 #endif
 
-#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+# define ia64_abort()	__builtin_trap()
+#else
+# define ia64_abort()	(*(volatile int *) 0 = 0)
+#endif
+
+#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
 static __inline__ int
diff -urN linux-2.4.26-pre2/include/asm-ia64/param.h linux-2.4.26-pre3/include/asm-ia64/param.h
--- linux-2.4.26-pre2/include/asm-ia64/param.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/param.h	2004-03-13 07:43:23.000000000 -0800
@@ -4,8 +4,10 @@
 /*
  * Fundamental kernel parameters.
  *
- * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/param.h>.
+ *
+ * Modified 1998, 1999, 2002-2003
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define EXEC_PAGESIZE	65536
diff -urN linux-2.4.26-pre2/include/asm-ia64/poll.h linux-2.4.26-pre3/include/asm-ia64/poll.h
--- linux-2.4.26-pre2/include/asm-ia64/poll.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/poll.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,10 +2,10 @@
 #define _ASM_IA64_POLL_H
 
 /*
- * poll(2) bit definitions.  Chosen to be compatible with Linux/x86.
+ * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #define POLLIN		0x0001
diff -urN linux-2.4.26-pre2/include/asm-ia64/posix_types.h linux-2.4.26-pre3/include/asm-ia64/posix_types.h
--- linux-2.4.26-pre2/include/asm-ia64/posix_types.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/posix_types.h	2004-03-13 07:43:23.000000000 -0800
@@ -6,8 +6,10 @@
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/posix_types.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 typedef unsigned int	__kernel_dev_t;
diff -urN linux-2.4.26-pre2/include/asm-ia64/processor.h linux-2.4.26-pre3/include/asm-ia64/processor.h
--- linux-2.4.26-pre2/include/asm-ia64/processor.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/processor.h	2004-03-13 07:43:23.000000000 -0800
@@ -927,24 +927,13 @@
 	return retval;
 }
 
-/* XXX remove the handcoded version once we have a sufficiently clever compiler... */
-#ifdef SMART_COMPILER
-# define ia64_rotr(w,n)				\
-  ({						\
-	__u64 _w = (w), _n = (n);		\
-						\
-	(_w >> _n) | (_w << (64 - _n));		\
-  })
-#else
-# define ia64_rotr(w,n)							\
-  ({									\
-	__u64 result;							\
-	asm ("shrp %0=%1,%1,%2" : "=r"(result) : "r"(w), "i"(n));	\
-	result;								\
-  })
-#endif
+static inline __u64
+ia64_rotr (__u64 w, __u64 n)
+{
+	return (w >> n) | (w << (64 - n));
+}
 
-#define ia64_rotl(w,n)	ia64_rotr((w),(64)-(n))
+#define ia64_rotl(w,n)	ia64_rotr((w), (64) - (n))
 
 static inline __u64
 ia64_thash (__u64 addr)
diff -urN linux-2.4.26-pre2/include/asm-ia64/resource.h linux-2.4.26-pre3/include/asm-ia64/resource.h
--- linux-2.4.26-pre2/include/asm-ia64/resource.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/resource.h	2004-03-13 07:43:23.000000000 -0800
@@ -4,8 +4,10 @@
 /*
  * Resource limits
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/resource.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/ustack.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/scatterlist.h linux-2.4.26-pre3/include/asm-ia64/scatterlist.h
--- linux-2.4.26-pre2/include/asm-ia64/scatterlist.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/scatterlist.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_SCATTERLIST_H
 
 /*
- * Copyright (C) 1998-1999, 2001-2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-1999, 2001-2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 struct scatterlist {
diff -urN linux-2.4.26-pre2/include/asm-ia64/siginfo.h linux-2.4.26-pre3/include/asm-ia64/siginfo.h
--- linux-2.4.26-pre2/include/asm-ia64/siginfo.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/siginfo.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,10 @@
 #define _ASM_IA64_SIGINFO_H
 
 /*
- * Copyright (C) 1998-2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/siginfo.h>.
+ *
+ * Modified 1998-2002
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <linux/types.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/signal.h linux-2.4.26-pre3/include/asm-ia64/signal.h
--- linux-2.4.26-pre2/include/asm-ia64/signal.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/signal.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_SIGNAL_H
 
 /*
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998-2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * Unfortunately, this file is being included by bits/signal.h in
  * glibc-2.x.  Hence the #ifdef __KERNEL__ ugliness.
diff -urN linux-2.4.26-pre2/include/asm-ia64/socket.h linux-2.4.26-pre3/include/asm-ia64/socket.h
--- linux-2.4.26-pre2/include/asm-ia64/socket.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/socket.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,10 +2,12 @@
 #define _ASM_IA64_SOCKET_H
 
 /*
- * Socket related defines.  This mostly mirrors the Linux/x86 version.
+ * Socket related defines.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/socket.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <asm/sockios.h>
diff -urN linux-2.4.26-pre2/include/asm-ia64/sockios.h linux-2.4.26-pre3/include/asm-ia64/sockios.h
--- linux-2.4.26-pre2/include/asm-ia64/sockios.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/sockios.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,11 +2,12 @@
 #define _ASM_IA64_SOCKIOS_H
 
 /*
- * Socket-level I/O control calls.  This mostly mirrors the Linux/x86
- * version.
+ * Socket-level I/O control calls.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/sockios.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 #define FIOSETOWN 	0x8901
 #define SIOCSPGRP	0x8902
diff -urN linux-2.4.26-pre2/include/asm-ia64/stat.h linux-2.4.26-pre3/include/asm-ia64/stat.h
--- linux-2.4.26-pre2/include/asm-ia64/stat.h	2000-06-22 07:09:45.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/stat.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_STAT_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 struct stat {
diff -urN linux-2.4.26-pre2/include/asm-ia64/statfs.h linux-2.4.26-pre3/include/asm-ia64/statfs.h
--- linux-2.4.26-pre2/include/asm-ia64/statfs.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/statfs.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,10 @@
 #define _ASM_IA64_STATFS_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/statfs.h>.
+ *
+ * Modified 1998, 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 # ifndef __KERNEL_STRICT_NAMES
diff -urN linux-2.4.26-pre2/include/asm-ia64/termbits.h linux-2.4.26-pre3/include/asm-ia64/termbits.h
--- linux-2.4.26-pre2/include/asm-ia64/termbits.h	2000-02-06 18:42:40.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/termbits.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,10 @@
 #define _ASM_IA64_TERMBITS_H
 
 /*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-i386/termbits.h>.
+ *
+ * Modified 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * 99/01/28	Added new baudrates
  */
diff -urN linux-2.4.26-pre2/include/asm-ia64/termios.h linux-2.4.26-pre3/include/asm-ia64/termios.h
--- linux-2.4.26-pre2/include/asm-ia64/termios.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/termios.h	2004-03-13 07:43:23.000000000 -0800
@@ -2,8 +2,8 @@
 #define _ASM_IA64_TERMIOS_H
 
 /*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1999
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  *
  * 99/01/28	Added N_IRDA and N_SMSBLOCK
  */
diff -urN linux-2.4.26-pre2/include/asm-ia64/types.h linux-2.4.26-pre3/include/asm-ia64/types.h
--- linux-2.4.26-pre2/include/asm-ia64/types.h	2000-04-21 15:21:24.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/types.h	2004-03-13 07:43:23.000000000 -0800
@@ -8,8 +8,10 @@
  * not a major issue.  However, for interoperability, libraries still
  * need to be careful to avoid a name clashes.
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Based on <asm-alpha/types.h>.
+ *
+ * Modified 1998-2000
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #ifdef __ASSEMBLY__
diff -urN linux-2.4.26-pre2/include/asm-ia64/uaccess.h linux-2.4.26-pre3/include/asm-ia64/uaccess.h
--- linux-2.4.26-pre2/include/asm-ia64/uaccess.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/uaccess.h	2004-03-13 07:43:23.000000000 -0800
@@ -26,6 +26,8 @@
  * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
  * then resumes execution at the continuation point.
  *
+ * Based on <asm-alpha/uaccess.h>.
+ *
  * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
diff -urN linux-2.4.26-pre2/include/asm-ia64/unaligned.h linux-2.4.26-pre3/include/asm-ia64/unaligned.h
--- linux-2.4.26-pre2/include/asm-ia64/unaligned.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ia64/unaligned.h	2004-03-13 07:43:23.000000000 -0800
@@ -4,8 +4,9 @@
 #include <linux/types.h>
 
 /*
- * The main single-value unaligned transfer routines.  Derived from
- * the Linux/Alpha version.
+ * The main single-value unaligned transfer routines.
+ *
+ * Based on <asm-alpha/unaligned.h>.
  *
  * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
diff -urN linux-2.4.26-pre2/include/asm-ia64/unwind.h linux-2.4.26-pre3/include/asm-ia64/unwind.h
--- linux-2.4.26-pre2/include/asm-ia64/unwind.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/unwind.h	2004-03-13 07:43:23.000000000 -0800
@@ -93,6 +93,12 @@
  * The official API follows below:
  */
 
+struct unw_table_entry {
+	u64 start_offset;
+	u64 end_offset;
+	u64 info_offset;
+};
+
 /*
  * Initialize unwind support.
  */
diff -urN linux-2.4.26-pre2/include/asm-ia64/user.h linux-2.4.26-pre3/include/asm-ia64/user.h
--- linux-2.4.26-pre2/include/asm-ia64/user.h	2001-11-09 14:26:17.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ia64/user.h	2004-03-13 07:43:23.000000000 -0800
@@ -24,8 +24,8 @@
  *	current->start_stack, so we round each of these in order to be able
  *	to write an integer number of pages.
  *
- * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Modified 1998, 1999, 2001
+ *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
 #include <linux/ptrace.h>
diff -urN linux-2.4.26-pre2/include/asm-ppc/cpm2.h linux-2.4.26-pre3/include/asm-ppc/cpm2.h
--- linux-2.4.26-pre2/include/asm-ppc/cpm2.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ppc/cpm2.h	2004-03-13 07:43:23.000000000 -0800
@@ -0,0 +1,1037 @@
+/*
+ * Communication Processor Module v2.
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the CPM2 internal
+ * memory map.  See immap_cpm2.h for details.
+ */
+#ifdef __KERNEL__
+#ifndef __CPM2__
+#define __CPM2__
+
+#include <asm/immap_cpm2.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST	((uint)0x80000000)
+#define CPM_CR_PAGE	((uint)0x7c000000)
+#define CPM_CR_SBLOCK	((uint)0x03e00000)
+#define CPM_CR_FLG	((uint)0x00010000)
+#define CPM_CR_MCN	((uint)0x00003fc0)
+#define CPM_CR_OPCODE	((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK	(0x04)
+#define CPM_CR_SCC2_SBLOCK	(0x05)
+#define CPM_CR_SCC3_SBLOCK	(0x06)
+#define CPM_CR_SCC4_SBLOCK	(0x07)
+#define CPM_CR_SMC1_SBLOCK	(0x08)
+#define CPM_CR_SMC2_SBLOCK	(0x09)
+#define CPM_CR_SPI_SBLOCK	(0x0a)
+#define CPM_CR_I2C_SBLOCK	(0x0b)
+#define CPM_CR_TIMER_SBLOCK	(0x0f)
+#define CPM_CR_RAND_SBLOCK	(0x0e)
+#define CPM_CR_FCC1_SBLOCK	(0x10)
+#define CPM_CR_FCC2_SBLOCK	(0x11)
+#define CPM_CR_FCC3_SBLOCK	(0x12)
+#define CPM_CR_IDMA1_SBLOCK	(0x14)
+#define CPM_CR_IDMA2_SBLOCK	(0x15)
+#define CPM_CR_IDMA3_SBLOCK	(0x16)
+#define CPM_CR_IDMA4_SBLOCK	(0x17)
+#define CPM_CR_MCC1_SBLOCK	(0x1c)
+
+#define CPM_CR_SCC1_PAGE	(0x00)
+#define CPM_CR_SCC2_PAGE	(0x01)
+#define CPM_CR_SCC3_PAGE	(0x02)
+#define CPM_CR_SCC4_PAGE	(0x03)
+#define CPM_CR_SMC1_PAGE	(0x07)
+#define CPM_CR_SMC2_PAGE	(0x08)
+#define CPM_CR_SPI_PAGE		(0x09)
+#define CPM_CR_I2C_PAGE		(0x0a)
+#define CPM_CR_TIMER_PAGE	(0x0a)
+#define CPM_CR_RAND_PAGE	(0x0a)
+#define CPM_CR_FCC1_PAGE	(0x04)
+#define CPM_CR_FCC2_PAGE	(0x05)
+#define CPM_CR_FCC3_PAGE	(0x06)
+#define CPM_CR_IDMA1_PAGE	(0x07)
+#define CPM_CR_IDMA2_PAGE	(0x08)
+#define CPM_CR_IDMA3_PAGE	(0x09)
+#define CPM_CR_IDMA4_PAGE	(0x0a)
+#define CPM_CR_MCC1_PAGE	(0x07)
+#define CPM_CR_MCC2_PAGE	(0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX		((ushort)0x0000)
+#define CPM_CR_INIT_RX		((ushort)0x0001)
+#define CPM_CR_INIT_TX		((ushort)0x0002)
+#define CPM_CR_HUNT_MODE	((ushort)0x0003)
+#define CPM_CR_STOP_TX		((ushort)0x0004)
+#define CPM_CR_RESTART_TX	((ushort)0x0006)
+#define CPM_CR_SET_GADDR	((ushort)0x0008)
+#define CPM_CR_START_IDMA	((ushort)0x0009)
+#define CPM_CR_STOP_IDMA	((ushort)0x000b)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses.  The first 16K is available for almost
+ * any CPM use, so we put the BDs there.  The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that.  All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE	((uint)128)
+#define CPM_DP_NOSPACE		((uint)0x7fffffff)
+#ifdef CONFIG_8272
+#define CPM_DATAONLY_SIZE	((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x00009000)
+#else
+#define CPM_DATAONLY_SIZE	((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE	((uint)0x0000b000)
+#endif
+
+/* The number of pages of host memory we allocate for CPM.  This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES	2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern		cpm_cpm2_t	*cpmp;	 /* Pointer to comm processor */
+uint		cpm2_dpalloc(uint size, uint align);
+uint		cpm2_hostalloc(uint size, uint align);
+void		cpm2_setbrg(uint brg, uint rate);
+void		cpm2_fastbrg(uint brg, uint rate, int div16);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+	ushort	cbd_sc;		/* Status and Control */
+	ushort	cbd_datlen;	/* Data length in buffer */
+	uint	cbd_bufaddr;	/* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
+#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
+#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
+#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
+#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
+#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
+#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
+#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
+#define BD_SC_BR	((ushort)0x0020)	/* Break received */
+#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
+#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
+#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
+#define BD_SC_CD	((ushort)0x0001)	/* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
+#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
+#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
+#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
+#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#define PROFF_SCC1		((uint)0x8000)
+#define PROFF_SCC2		((uint)0x8100)
+#define PROFF_SCC3		((uint)0x8200)
+#define PROFF_SCC4		((uint)0x8300)
+#define PROFF_FCC1		((uint)0x8400)
+#define PROFF_FCC2		((uint)0x8500)
+#define PROFF_FCC3		((uint)0x8600)
+#define PROFF_MCC1		((uint)0x8700)
+#define PROFF_SMC1_BASE		((uint)0x87fc)
+#define PROFF_IDMA1_BASE	((uint)0x87fe)
+#define PROFF_MCC2		((uint)0x8800)
+#define PROFF_SMC2_BASE		((uint)0x88fc)
+#define PROFF_IDMA2_BASE	((uint)0x88fe)
+#define PROFF_SPI_BASE		((uint)0x89fc)
+#define PROFF_IDMA3_BASE	((uint)0x89fe)
+#define PROFF_TIMERS		((uint)0x8ae0)
+#define PROFF_REVNUM		((uint)0x8af0)
+#define PROFF_RAND		((uint)0x8af8)
+#define PROFF_I2C_BASE		((uint)0x8afc)
+#define PROFF_IDMA4_BASE	((uint)0x8afe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1	(0)
+#define PROFF_SMC2	(64)
+
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	smc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	smc_rfcr;	/* Rx function code */
+	u_char	smc_tfcr;	/* Tx function code */
+	ushort	smc_mrblr;	/* Max receive buffer length */
+	uint	smc_rstate;	/* Internal */
+	uint	smc_idp;	/* Internal */
+	ushort	smc_rbptr;	/* Internal */
+	ushort	smc_ibc;	/* Internal */
+	uint	smc_rxtmp;	/* Internal */
+	uint	smc_tstate;	/* Internal */
+	uint	smc_tdp;	/* Internal */
+	ushort	smc_tbptr;	/* Internal */
+	ushort	smc_tbc;	/* Internal */
+	uint	smc_txtmp;	/* Internal */
+	ushort	smc_maxidl;	/* Maximum idle characters */
+	ushort	smc_tmpidl;	/* Temporary idle counter */
+	ushort	smc_brklen;	/* Last received break length */
+	ushort	smc_brkec;	/* rcv'd break condition counter */
+	ushort	smc_brkcr;	/* xmt break count register */
+	ushort	smc_rmask;	/* Temporary bit mask */
+	uint	smc_stmp;	/* SDMA Temp */
+} smc_uart_t;
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define SMCMR_REN	((ushort)0x0001)
+#define SMCMR_TEN	((ushort)0x0002)
+#define SMCMR_DM	((ushort)0x000c)
+#define SMCMR_SM_GCI	((ushort)0x0000)
+#define SMCMR_SM_UART	((ushort)0x0020)
+#define SMCMR_SM_TRANS	((ushort)0x0030)
+#define SMCMR_SM_MASK	((ushort)0x0030)
+#define SMCMR_PM_EVEN	((ushort)0x0100)	/* Even parity, else odd */
+#define SMCMR_REVD	SMCMR_PM_EVEN
+#define SMCMR_PEN	((ushort)0x0200)	/* Parity enable */
+#define SMCMR_BS	SMCMR_PEN
+#define SMCMR_SL	((ushort)0x0400)	/* Two stops, else one */
+#define SMCR_CLEN_MASK	((ushort)0x7800)	/* Character length */
+#define smcr_mk_clen(C)	(((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
+#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
+#define SMCM_TXE	((unsigned char)0x10)
+#define SMCM_BSY	((unsigned char)0x04)
+#define SMCM_TX		((unsigned char)0x02)
+#define SMCM_RX		((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST		((uint)0x00020000)
+#define CPM_BRG_EN		((uint)0x00010000)
+#define CPM_BRG_EXTC_INT	((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
+#define CPM_BRG_ATB		((uint)0x00002000)
+#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
+#define CPM_BRG_DIV16		((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP		((uint)0x00040000)
+#define SCC_GSMRH_GDE		((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
+#define SCC_GSMRH_REVD		((uint)0x00002000)
+#define SCC_GSMRH_TRX		((uint)0x00001000)
+#define SCC_GSMRH_TTX		((uint)0x00000800)
+#define SCC_GSMRH_CDP		((uint)0x00000400)
+#define SCC_GSMRH_CTSP		((uint)0x00000200)
+#define SCC_GSMRH_CDS		((uint)0x00000100)
+#define SCC_GSMRH_CTSS		((uint)0x00000080)
+#define SCC_GSMRH_TFL		((uint)0x00000040)
+#define SCC_GSMRH_RFW		((uint)0x00000020)
+#define SCC_GSMRH_TXSY		((uint)0x00000010)
+#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8		((uint)0x00000008)
+#define SCC_GSMRH_SYNL4		((uint)0x00000004)
+#define SCC_GSMRH_RTSM		((uint)0x00000002)
+#define SCC_GSMRH_RSYN		((uint)0x00000001)
+
+#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
+#define SCC_GSMRL_TCI		((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
+#define SCC_GSMRL_RINV		((uint)0x02000000)
+#define SCC_GSMRL_TINV		((uint)0x01000000)
+#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48	((uint)0x00800000)
+#define SCC_GSMRL_TPL_32	((uint)0x00600000)
+#define SCC_GSMRL_TPL_16	((uint)0x00400000)
+#define SCC_GSMRL_TPL_8		((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
+#define SCC_GSMRL_TPP_01	((uint)0x00100000)
+#define SCC_GSMRL_TPP_10	((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
+#define SCC_GSMRL_TEND		((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
+#define SCC_GSMRL_ENR		((uint)0x00000020)
+#define SCC_GSMRL_ENT		((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
+
+#define SCC_TODR_TOD		((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE	((unsigned char)0x10)
+#define SCCM_BSY	((unsigned char)0x04)
+#define SCCM_TX		((unsigned char)0x02)
+#define SCCM_RX		((unsigned char)0x01)
+
+typedef struct scc_param {
+	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
+	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
+	u_char	scc_rfcr;	/* Rx function code */
+	u_char	scc_tfcr;	/* Tx function code */
+	ushort	scc_mrblr;	/* Max receive buffer length */
+	uint	scc_rstate;	/* Internal */
+	uint	scc_idp;	/* Internal */
+	ushort	scc_rbptr;	/* Internal */
+	ushort	scc_ibc;	/* Internal */
+	uint	scc_rxtmp;	/* Internal */
+	uint	scc_tstate;	/* Internal */
+	uint	scc_tdp;	/* Internal */
+	ushort	scc_tbptr;	/* Internal */
+	ushort	scc_tbc;	/* Internal */
+	uint	scc_txtmp;	/* Internal */
+	uint	scc_rcrc;	/* Internal */
+	uint	scc_tcrc;	/* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+	sccp_t	sen_genscc;
+	uint	sen_cpres;	/* Preset CRC */
+	uint	sen_cmask;	/* Constant mask for CRC */
+	uint	sen_crcec;	/* CRC Error counter */
+	uint	sen_alec;	/* alignment error counter */
+	uint	sen_disfc;	/* discard frame counter */
+	ushort	sen_pads;	/* Tx short frame pad character */
+	ushort	sen_retlim;	/* Retry limit threshold */
+	ushort	sen_retcnt;	/* Retry limit counter */
+	ushort	sen_maxflr;	/* maximum frame length register */
+	ushort	sen_minflr;	/* minimum frame length register */
+	ushort	sen_maxd1;	/* maximum DMA1 length */
+	ushort	sen_maxd2;	/* maximum DMA2 length */
+	ushort	sen_maxd;	/* Rx max DMA */
+	ushort	sen_dmacnt;	/* Rx DMA counter */
+	ushort	sen_maxb;	/* Max BD byte count */
+	ushort	sen_gaddr1;	/* Group address filter */
+	ushort	sen_gaddr2;
+	ushort	sen_gaddr3;
+	ushort	sen_gaddr4;
+	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf0rba;	/* Internal */
+	uint	sen_tbuf0crc;	/* Internal */
+	ushort	sen_tbuf0bcnt;	/* Internal */
+	ushort	sen_paddrh;	/* physical address (MSB) */
+	ushort	sen_paddrm;
+	ushort	sen_paddrl;	/* physical address (LSB) */
+	ushort	sen_pper;	/* persistence */
+	ushort	sen_rfbdptr;	/* Rx first BD pointer */
+	ushort	sen_tfbdptr;	/* Tx first BD pointer */
+	ushort	sen_tlbdptr;	/* Tx last BD pointer */
+	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
+	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
+	uint	sen_tbuf1rba;	/* Internal */
+	uint	sen_tbuf1crc;	/* Internal */
+	ushort	sen_tbuf1bcnt;	/* Internal */
+	ushort	sen_txlen;	/* Tx Frame length counter */
+	ushort	sen_iaddr1;	/* Individual address filter */
+	ushort	sen_iaddr2;
+	ushort	sen_iaddr3;
+	ushort	sen_iaddr4;
+	ushort	sen_boffcnt;	/* Backoff counter */
+
+	/* NOTE: Some versions of the manual have the following items
+	 * incorrectly documented.  Below is the proper order.
+	 */
+	ushort	sen_taddrh;	/* temp address (MSB) */
+	ushort	sen_taddrm;
+	ushort	sen_taddrl;	/* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
+#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
+#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
+#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
+#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
+#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
+#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
+#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
+#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
+#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
+#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
+#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
+#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
+#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY	((ushort)0x8000)
+#define BD_ENET_RX_WRAP		((ushort)0x2000)
+#define BD_ENET_RX_INTR		((ushort)0x1000)
+#define BD_ENET_RX_LAST		((ushort)0x0800)
+#define BD_ENET_RX_FIRST	((ushort)0x0400)
+#define BD_ENET_RX_MISS		((ushort)0x0100)
+#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
+#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
+#define BD_ENET_RX_LG		((ushort)0x0020)
+#define BD_ENET_RX_NO		((ushort)0x0010)
+#define BD_ENET_RX_SH		((ushort)0x0008)
+#define BD_ENET_RX_CR		((ushort)0x0004)
+#define BD_ENET_RX_OV		((ushort)0x0002)
+#define BD_ENET_RX_CL		((ushort)0x0001)
+#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY	((ushort)0x8000)
+#define BD_ENET_TX_PAD		((ushort)0x4000)
+#define BD_ENET_TX_WRAP		((ushort)0x2000)
+#define BD_ENET_TX_INTR		((ushort)0x1000)
+#define BD_ENET_TX_LAST		((ushort)0x0800)
+#define BD_ENET_TX_TC		((ushort)0x0400)
+#define BD_ENET_TX_DEF		((ushort)0x0200)
+#define BD_ENET_TX_HB		((ushort)0x0100)
+#define BD_ENET_TX_LC		((ushort)0x0080)
+#define BD_ENET_TX_RL		((ushort)0x0040)
+#define BD_ENET_TX_RCMASK	((ushort)0x003c)
+#define BD_ENET_TX_UN		((ushort)0x0002)
+#define BD_ENET_TX_CSL		((ushort)0x0001)
+#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+	sccp_t	scc_genscc;
+	uint	scc_res1;	/* Reserved */
+	uint	scc_res2;	/* Reserved */
+	ushort	scc_maxidl;	/* Maximum idle chars */
+	ushort	scc_idlc;	/* temp idle counter */
+	ushort	scc_brkcr;	/* Break count register */
+	ushort	scc_parec;	/* receive parity error counter */
+	ushort	scc_frmec;	/* receive framing error counter */
+	ushort	scc_nosec;	/* receive noise counter */
+	ushort	scc_brkec;	/* receive break condition counter */
+	ushort	scc_brkln;	/* last received break length */
+	ushort	scc_uaddr1;	/* UART address character 1 */
+	ushort	scc_uaddr2;	/* UART address character 2 */
+	ushort	scc_rtemp;	/* Temp storage */
+	ushort	scc_toseq;	/* Transmit out of sequence char */
+	ushort	scc_char1;	/* control character 1 */
+	ushort	scc_char2;	/* control character 2 */
+	ushort	scc_char3;	/* control character 3 */
+	ushort	scc_char4;	/* control character 4 */
+	ushort	scc_char5;	/* control character 5 */
+	ushort	scc_char6;	/* control character 6 */
+	ushort	scc_char7;	/* control character 7 */
+	ushort	scc_char8;	/* control character 8 */
+	ushort	scc_rccm;	/* receive control character mask */
+	ushort	scc_rccr;	/* receive control character register */
+	ushort	scc_rlbc;	/* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR		((ushort)0x1000)
+#define UART_SCCM_GLT		((ushort)0x0800)
+#define UART_SCCM_AB		((ushort)0x0200)
+#define UART_SCCM_IDL		((ushort)0x0100)
+#define UART_SCCM_GRA		((ushort)0x0080)
+#define UART_SCCM_BRKE		((ushort)0x0040)
+#define UART_SCCM_BRKS		((ushort)0x0020)
+#define UART_SCCM_CCR		((ushort)0x0008)
+#define UART_SCCM_BSY		((ushort)0x0004)
+#define UART_SCCM_TX		((ushort)0x0002)
+#define UART_SCCM_RX		((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC		((ushort)0x8000)
+#define SCU_PSMR_SL		((ushort)0x4000)
+#define SCU_PSMR_CL		((ushort)0x3000)
+#define SCU_PSMR_UM		((ushort)0x0c00)
+#define SCU_PSMR_FRZ		((ushort)0x0200)
+#define SCU_PSMR_RZS		((ushort)0x0100)
+#define SCU_PSMR_SYN		((ushort)0x0080)
+#define SCU_PSMR_DRT		((ushort)0x0040)
+#define SCU_PSMR_PEN		((ushort)0x0010)
+#define SCU_PSMR_RPM		((ushort)0x000c)
+#define SCU_PSMR_REVP		((ushort)0x0008)
+#define SCU_PSMR_TPM		((ushort)0x0003)
+#define SCU_PSMR_TEVP		((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+	sccp_t	st_genscc;
+	uint	st_cpres;	/* Preset CRC */
+	uint	st_cmask;	/* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST		((ushort)0x0800)
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
+#define FCC_GFMR_TCI		((uint)0x20000000)
+#define FCC_GFMR_TRX		((uint)0x10000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_TTX		((uint)0x08000000)
+#define FCC_GFMR_CDP		((uint)0x04000000)
+#define FCC_GFMR_CTSP		((uint)0x02000000)
+#define FCC_GFMR_CDS		((uint)0x01000000)
+#define FCC_GFMR_CTSS		((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
+#define FCC_GFMR_SYNL_8		((uint)0x00008000)
+#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
+#define FCC_GFMR_RTSM		((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
+#define FCC_GFMR_REVD		((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
+#define FCC_GFMR_TCRC_16	((uint)0x00000000)
+#define FCC_GFMR_TCRC_32	((uint)0x00000080)
+#define FCC_GFMR_ENR		((uint)0x00000020)
+#define FCC_GFMR_ENT		((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+	ushort	fcc_riptr;	/* Rx Internal temp pointer */
+	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
+	ushort	fcc_res1;
+	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
+	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_rbase;	/* Receive BD base */
+	ushort	fcc_rbdstat;	/* RxBD status */
+	ushort	fcc_rbdlen;	/* RxBD down counter */
+	uint	fcc_rdptr;	/* RxBD internal data pointer */
+	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
+	uint	fcc_tbase;	/* Transmit BD base */
+	ushort	fcc_tbdstat;	/* TxBD status */
+	ushort	fcc_tbdlen;	/* TxBD down counter */
+	uint	fcc_tdptr;	/* TxBD internal data pointer */
+	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
+	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
+	uint	fcc_rcrc;	/* Rx temp CRC */
+	uint	fcc_res2;
+	uint	fcc_tcrc;	/* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+	fccp_t	fen_genfcc;
+	uint	fen_statbuf;	/* Internal status buffer */
+	uint	fen_camptr;	/* CAM address */
+	uint	fen_cmask;	/* Constant mask for CRC */
+	uint	fen_cpres;	/* Preset CRC */
+	uint	fen_crcec;	/* CRC Error counter */
+	uint	fen_alec;	/* alignment error counter */
+	uint	fen_disfc;	/* discard frame counter */
+	ushort	fen_retlim;	/* Retry limit */
+	ushort	fen_retcnt;	/* Retry counter */
+	ushort	fen_pper;	/* Persistence */
+	ushort	fen_boffcnt;	/* backoff counter */
+	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
+	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
+	ushort	fen_tfcstat;	/* out of sequence TxBD */
+	ushort	fen_tfclen;
+	uint	fen_tfcptr;
+	ushort	fen_mflr;	/* Maximum frame length (1518) */
+	ushort	fen_paddrh;	/* MAC address */
+	ushort	fen_paddrm;
+	ushort	fen_paddrl;
+	ushort	fen_ibdcount;	/* Internal BD counter */
+	ushort	fen_ibdstart;	/* Internal BD start pointer */
+	ushort	fen_ibdend;	/* Internal BD end pointer */
+	ushort	fen_txlen;	/* Internal Tx frame length counter */
+	uint	fen_ibdbase[8]; /* Internal use */
+	uint	fen_iaddrh;	/* Individual address filter */
+	uint	fen_iaddrl;
+	ushort	fen_minflr;	/* Minimum frame length (64) */
+	ushort	fen_taddrh;	/* Filter transfer MAC address */
+	ushort	fen_taddrm;
+	ushort	fen_taddrl;
+	ushort	fen_padptr;	/* Pointer to pad byte buffer */
+	ushort	fen_cftype;	/* control frame type */
+	ushort	fen_cfrange;	/* control frame range */
+	ushort	fen_maxb;	/* maximum BD count */
+	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
+	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
+	ushort	fen_maxd;	/* internal max DMA count */
+	ushort	fen_dmacnt;	/* internal DMA counter */
+	uint	fen_octc;	/* Total octect counter */
+	uint	fen_colc;	/* Total collision counter */
+	uint	fen_broc;	/* Total broadcast packet counter */
+	uint	fen_mulc;	/* Total multicast packet count */
+	uint	fen_uspc;	/* Total packets < 64 bytes */
+	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
+	uint	fen_ospc;	/* Total packets > 1518 */
+	uint	fen_jbrc;	/* Total packets > 1518 with errors */
+	uint	fen_p64c;	/* Total packets == 64 bytes */
+	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
+	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
+	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
+	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
+	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
+	uint	fen_cambuf;	/* Internal CAM buffer poiner */
+	ushort	fen_rfthr;	/* Received frames threshold */
+	ushort	fen_rfcnt;	/* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
+#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
+#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
+#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
+#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
+#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
+#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
+#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
+#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
+#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
+#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
+#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
+#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
+#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
+#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
+#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
+#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
+	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
+	u_char	iic_rfcr;	/* Rx function code */
+	u_char	iic_tfcr;	/* Tx function code */
+	ushort	iic_mrblr;	/* Max receive buffer length */
+	uint	iic_rstate;	/* Internal */
+	uint	iic_rdp;	/* Internal */
+	ushort	iic_rbptr;	/* Internal */
+	ushort	iic_rbc;	/* Internal */
+	uint	iic_rxtmp;	/* Internal */
+	uint	iic_tstate;	/* Internal */
+	uint	iic_tdp;	/* Internal */
+	ushort	iic_tbptr;	/* Internal */
+	ushort	iic_tbc;	/* Internal */
+	uint	iic_txtmp;	/* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+	ushort	spi_rbase;	/* Rx Buffer descriptor base address */
+	ushort	spi_tbase;	/* Tx Buffer descriptor base address */
+	u_char	spi_rfcr;	/* Rx function code */
+	u_char	spi_tfcr;	/* Tx function code */
+	ushort	spi_mrblr;	/* Max receive buffer length */
+	uint	spi_rstate;	/* Internal */
+	uint	spi_rdp;	/* Internal */
+	ushort	spi_rbptr;	/* Internal */
+	ushort	spi_rbc;	/* Internal */
+	uint	spi_rxtmp;	/* Internal */
+	uint	spi_tstate;	/* Internal */
+	uint	spi_tdp;	/* Internal */
+	ushort	spi_tbptr;	/* Internal */
+	ushort	spi_tbc;	/* Internal */
+	uint	spi_txtmp;	/* Internal */
+	uint	spi_res;	/* Tx temp. */
+	uint	spi_res1[4];	/* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP	((ushort)0x4000)	/* Loopback */
+#define SPMODE_CI	((ushort)0x2000)	/* Clock Invert */
+#define SPMODE_CP	((ushort)0x1000)	/* Clock Phase */
+#define SPMODE_DIV16	((ushort)0x0800)	/* BRG/16 mode */
+#define SPMODE_REV	((ushort)0x0400)	/* Reversed Data */
+#define SPMODE_MSTR	((ushort)0x0200)	/* SPI Master */
+#define SPMODE_EN	((ushort)0x0100)	/* Enable */
+#define SPMODE_LENMSK	((ushort)0x00f0)	/* character length */
+#define SPMODE_PMMSK	((ushort)0x000f)	/* prescale modulus */
+
+#define SPMODE_LEN(x)	((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x)	((x) &0xF)
+
+#define SPI_EB		((u_char)0x10)		/* big endian byte order */
+
+#define BD_IIC_START		((ushort)0x0400)
+
+/* IDMA parameter RAM
+*/
+typedef struct idma {
+	ushort ibase;		/* IDMA buffer descriptor table base address */
+	ushort dcm;		/* DMA channel mode */
+	ushort ibdptr;		/* IDMA current buffer descriptor pointer */
+	ushort dpr_buf;		/* IDMA transfer buffer base address */
+	ushort buf_inv;		/* internal buffer inventory */
+	ushort ss_max;		/* steady-state maximum transfer size */
+	ushort dpr_in_ptr;	/* write pointer inside the internal buffer */
+	ushort sts;		/* source transfer size */
+	ushort dpr_out_ptr;	/* read pointer inside the internal buffer */
+	ushort seob;		/* source end of burst */
+	ushort deob;		/* destination end of burst */
+	ushort dts;		/* destination transfer size */
+	ushort ret_add;		/* return address when working in ERM=1 mode */
+	ushort res0;		/* reserved */
+	uint   bd_cnt;		/* internal byte count */
+	uint   s_ptr;		/* source internal data pointer */
+	uint   d_ptr;		/* destination internal data pointer */
+	uint   istate;		/* internal state */
+	u_char res1[20];	/* pad to 64-byte length */
+} idma_t;
+
+/* DMA channel mode bit fields
+*/
+#define IDMA_DCM_FB		((ushort)0x8000) /* fly-by mode */
+#define IDMA_DCM_LP		((ushort)0x4000) /* low priority */
+#define IDMA_DCM_TC2		((ushort)0x0400) /* value driven on TC[2] */
+#define IDMA_DCM_DMA_WRAP_MASK	((ushort)0x01c0) /* mask for DMA wrap */
+#define IDMA_DCM_DMA_WRAP_64	((ushort)0x0000) /* 64-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_128	((ushort)0x0040) /* 128-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_256	((ushort)0x0080) /* 256-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_512	((ushort)0x00c0) /* 512-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_1024	((ushort)0x0100) /* 1024-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_2048	((ushort)0x0140) /* 2048-byte DMA xfer buffer */
+#define IDMA_DCM_SINC		((ushort)0x0020) /* source inc addr */
+#define IDMA_DCM_DINC		((ushort)0x0010) /* destination inc addr */
+#define IDMA_DCM_ERM		((ushort)0x0008) /* external request mode */
+#define IDMA_DCM_DT		((ushort)0x0004) /* DONE treatment */
+#define IDMA_DCM_SD_MASK	((ushort)0x0003) /* mask for SD bit field */
+#define IDMA_DCM_SD_MEM2MEM	((ushort)0x0000) /* memory-to-memory xfer */
+#define IDMA_DCM_SD_PER2MEM	((ushort)0x0002) /* peripheral-to-memory xfer */
+#define IDMA_DCM_SD_MEM2PER	((ushort)0x0001) /* memory-to-peripheral xfer */
+
+/* IDMA Buffer Descriptors
+*/
+typedef struct idma_bd {
+	uint flags;
+	uint len;	/* data length */
+	uint src;	/* source data buffer pointer */
+	uint dst;	/* destination data buffer pointer */
+} idma_bd_t;
+
+/* IDMA buffer descriptor flag bit fields
+*/
+#define IDMA_BD_V	((uint)0x80000000)	/* valid */
+#define IDMA_BD_W	((uint)0x20000000)	/* wrap */
+#define IDMA_BD_I	((uint)0x10000000)	/* interrupt */
+#define IDMA_BD_L	((uint)0x08000000)	/* last */
+#define IDMA_BD_CM	((uint)0x02000000)	/* continuous mode */
+#define IDMA_BD_SDN	((uint)0x00400000)	/* source done */
+#define IDMA_BD_DDN	((uint)0x00200000)	/* destination done */
+#define IDMA_BD_DGBL	((uint)0x00100000)	/* destination global */
+#define IDMA_BD_DBO_LE	((uint)0x00040000)	/* little-end dest byte order */
+#define IDMA_BD_DBO_BE	((uint)0x00080000)	/* big-end dest byte order */
+#define IDMA_BD_DDTB	((uint)0x00010000)	/* destination data bus */
+#define IDMA_BD_SGBL	((uint)0x00002000)	/* source global */
+#define IDMA_BD_SBO_LE	((uint)0x00000800)	/* little-end src byte order */
+#define IDMA_BD_SBO_BE	((uint)0x00001000)	/* big-end src byte order */
+#define IDMA_BD_SDTB	((uint)0x00000200)	/* source data bus */
+
+/* per-channel IDMA registers
+*/
+typedef struct im_idma {
+	u_char idsr;			/* IDMAn event status register */
+	u_char res0[3];
+	u_char idmr;			/* IDMAn event mask register */
+	u_char res1[3];
+} im_idma_t;
+
+/* IDMA event register bit fields
+*/
+#define IDMA_EVENT_SC	((unsigned char)0x08)	/* stop completed */
+#define IDMA_EVENT_OB	((unsigned char)0x04)	/* out of buffers */
+#define IDMA_EVENT_EDN	((unsigned char)0x02)	/* external DONE asserted */
+#define IDMA_EVENT_BC	((unsigned char)0x01)	/* buffer descriptor complete */
+
+/* RISC Controller Configuration Register (RCCR) bit fields
+*/
+#define RCCR_TIME	((uint)0x80000000) /* timer enable */
+#define RCCR_TIMEP_MASK	((uint)0x3f000000) /* mask for timer period bit field */
+#define RCCR_DR0M	((uint)0x00800000) /* IDMA0 request mode */
+#define RCCR_DR1M	((uint)0x00400000) /* IDMA1 request mode */
+#define RCCR_DR2M	((uint)0x00000080) /* IDMA2 request mode */
+#define RCCR_DR3M	((uint)0x00000040) /* IDMA3 request mode */
+#define RCCR_DR0QP_MASK	((uint)0x00300000) /* mask for IDMA0 req priority */
+#define RCCR_DR0QP_HIGH ((uint)0x00000000) /* IDMA0 has high req priority */
+#define RCCR_DR0QP_MED	((uint)0x00100000) /* IDMA0 has medium req priority */
+#define RCCR_DR0QP_LOW	((uint)0x00200000) /* IDMA0 has low req priority */
+#define RCCR_DR1QP_MASK	((uint)0x00030000) /* mask for IDMA1 req priority */
+#define RCCR_DR1QP_HIGH ((uint)0x00000000) /* IDMA1 has high req priority */
+#define RCCR_DR1QP_MED	((uint)0x00010000) /* IDMA1 has medium req priority */
+#define RCCR_DR1QP_LOW	((uint)0x00020000) /* IDMA1 has low req priority */
+#define RCCR_DR2QP_MASK	((uint)0x00000030) /* mask for IDMA2 req priority */
+#define RCCR_DR2QP_HIGH ((uint)0x00000000) /* IDMA2 has high req priority */
+#define RCCR_DR2QP_MED	((uint)0x00000010) /* IDMA2 has medium req priority */
+#define RCCR_DR2QP_LOW	((uint)0x00000020) /* IDMA2 has low req priority */
+#define RCCR_DR3QP_MASK	((uint)0x00000003) /* mask for IDMA3 req priority */
+#define RCCR_DR3QP_HIGH ((uint)0x00000000) /* IDMA3 has high req priority */
+#define RCCR_DR3QP_MED	((uint)0x00000001) /* IDMA3 has medium req priority */
+#define RCCR_DR3QP_LOW	((uint)0x00000002) /* IDMA3 has low req priority */
+#define RCCR_EIE	((uint)0x00080000) /* external interrupt enable */
+#define RCCR_SCD	((uint)0x00040000) /* scheduler configuration */
+#define RCCR_ERAM_MASK	((uint)0x0000e000) /* mask for enable RAM microcode */
+#define RCCR_ERAM_0KB	((uint)0x00000000) /* use 0KB of dpram for microcode */
+#define RCCR_ERAM_2KB	((uint)0x00002000) /* use 2KB of dpram for microcode */
+#define RCCR_ERAM_4KB	((uint)0x00004000) /* use 4KB of dpram for microcode */
+#define RCCR_ERAM_6KB	((uint)0x00006000) /* use 6KB of dpram for microcode */
+#define RCCR_ERAM_8KB	((uint)0x00008000) /* use 8KB of dpram for microcode */
+#define RCCR_ERAM_10KB	((uint)0x0000a000) /* use 10KB of dpram for microcode */
+#define RCCR_ERAM_12KB	((uint)0x0000c000) /* use 12KB of dpram for microcode */
+#define RCCR_EDM0	((uint)0x00000800) /* DREQ0 edge detect mode */
+#define RCCR_EDM1	((uint)0x00000400) /* DREQ1 edge detect mode */
+#define RCCR_EDM2	((uint)0x00000200) /* DREQ2 edge detect mode */
+#define RCCR_EDM3	((uint)0x00000100) /* DREQ3 edge detect mode */
+#define RCCR_DEM01	((uint)0x00000008) /* DONE0/DONE1 edge detect mode */
+#define RCCR_DEM23	((uint)0x00000004) /* DONE2/DONE3 edge detect mode */
+
+/*-----------------------------------------------------------------------
+ * CMXFCR - CMX FCC Clock Route Register
+ */
+#define CMXFCR_FC1         0x40000000   /* FCC1 connection              */
+#define CMXFCR_RF1CS_MSK   0x38000000   /* Receive FCC1 Clock Source Mask */
+#define CMXFCR_TF1CS_MSK   0x07000000   /* Transmit FCC1 Clock Source Mask */
+#define CMXFCR_FC2         0x00400000   /* FCC2 connection              */
+#define CMXFCR_RF2CS_MSK   0x00380000   /* Receive FCC2 Clock Source Mask */
+#define CMXFCR_TF2CS_MSK   0x00070000   /* Transmit FCC2 Clock Source Mask */
+#define CMXFCR_FC3         0x00004000   /* FCC3 connection              */
+#define CMXFCR_RF3CS_MSK   0x00003800   /* Receive FCC3 Clock Source Mask */
+#define CMXFCR_TF3CS_MSK   0x00000700   /* Transmit FCC3 Clock Source Mask */
+
+#define CMXFCR_RF1CS_BRG5  0x00000000   /* Receive FCC1 Clock Source is BRG5 */
+#define CMXFCR_RF1CS_BRG6  0x08000000   /* Receive FCC1 Clock Source is BRG6 */
+#define CMXFCR_RF1CS_BRG7  0x10000000   /* Receive FCC1 Clock Source is BRG7 */
+#define CMXFCR_RF1CS_BRG8  0x18000000   /* Receive FCC1 Clock Source is BRG8 */
+#define CMXFCR_RF1CS_CLK9  0x20000000   /* Receive FCC1 Clock Source is CLK9 */
+#define CMXFCR_RF1CS_CLK10 0x28000000   /* Receive FCC1 Clock Source is CLK10 */
+#define CMXFCR_RF1CS_CLK11 0x30000000   /* Receive FCC1 Clock Source is CLK11 */
+#define CMXFCR_RF1CS_CLK12 0x38000000   /* Receive FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_TF1CS_BRG5  0x00000000   /* Transmit FCC1 Clock Source is BRG5 */
+#define CMXFCR_TF1CS_BRG6  0x01000000   /* Transmit FCC1 Clock Source is BRG6 */
+#define CMXFCR_TF1CS_BRG7  0x02000000   /* Transmit FCC1 Clock Source is BRG7 */
+#define CMXFCR_TF1CS_BRG8  0x03000000   /* Transmit FCC1 Clock Source is BRG8 */
+#define CMXFCR_TF1CS_CLK9  0x04000000   /* Transmit FCC1 Clock Source is CLK9 */
+#define CMXFCR_TF1CS_CLK10 0x05000000   /* Transmit FCC1 Clock Source is CLK10 */
+#define CMXFCR_TF1CS_CLK11 0x06000000   /* Transmit FCC1 Clock Source is CLK11 */
+#define CMXFCR_TF1CS_CLK12 0x07000000   /* Transmit FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_RF2CS_BRG5  0x00000000   /* Receive FCC2 Clock Source is BRG5 */
+#define CMXFCR_RF2CS_BRG6  0x00080000   /* Receive FCC2 Clock Source is BRG6 */
+#define CMXFCR_RF2CS_BRG7  0x00100000   /* Receive FCC2 Clock Source is BRG7 */
+#define CMXFCR_RF2CS_BRG8  0x00180000   /* Receive FCC2 Clock Source is BRG8 */
+#define CMXFCR_RF2CS_CLK13 0x00200000   /* Receive FCC2 Clock Source is CLK13 */
+#define CMXFCR_RF2CS_CLK14 0x00280000   /* Receive FCC2 Clock Source is CLK14 */
+#define CMXFCR_RF2CS_CLK15 0x00300000   /* Receive FCC2 Clock Source is CLK15 */
+#define CMXFCR_RF2CS_CLK16 0x00380000   /* Receive FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_TF2CS_BRG5  0x00000000   /* Transmit FCC2 Clock Source is BRG5 */
+#define CMXFCR_TF2CS_BRG6  0x00010000   /* Transmit FCC2 Clock Source is BRG6 */
+#define CMXFCR_TF2CS_BRG7  0x00020000   /* Transmit FCC2 Clock Source is BRG7 */
+#define CMXFCR_TF2CS_BRG8  0x00030000   /* Transmit FCC2 Clock Source is BRG8 */
+#define CMXFCR_TF2CS_CLK13 0x00040000   /* Transmit FCC2 Clock Source is CLK13 */
+#define CMXFCR_TF2CS_CLK14 0x00050000   /* Transmit FCC2 Clock Source is CLK14 */
+#define CMXFCR_TF2CS_CLK15 0x00060000   /* Transmit FCC2 Clock Source is CLK15 */
+#define CMXFCR_TF2CS_CLK16 0x00070000   /* Transmit FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_RF3CS_BRG5  0x00000000   /* Receive FCC3 Clock Source is BRG5 */
+#define CMXFCR_RF3CS_BRG6  0x00000800   /* Receive FCC3 Clock Source is BRG6 */
+#define CMXFCR_RF3CS_BRG7  0x00001000   /* Receive FCC3 Clock Source is BRG7 */
+#define CMXFCR_RF3CS_BRG8  0x00001800   /* Receive FCC3 Clock Source is BRG8 */
+#define CMXFCR_RF3CS_CLK13 0x00002000   /* Receive FCC3 Clock Source is CLK13 */
+#define CMXFCR_RF3CS_CLK14 0x00002800   /* Receive FCC3 Clock Source is CLK14 */
+#define CMXFCR_RF3CS_CLK15 0x00003000   /* Receive FCC3 Clock Source is CLK15 */
+#define CMXFCR_RF3CS_CLK16 0x00003800   /* Receive FCC3 Clock Source is CLK16 */
+
+#define CMXFCR_TF3CS_BRG5  0x00000000   /* Transmit FCC3 Clock Source is BRG5 */
+#define CMXFCR_TF3CS_BRG6  0x00000100   /* Transmit FCC3 Clock Source is BRG6 */
+#define CMXFCR_TF3CS_BRG7  0x00000200   /* Transmit FCC3 Clock Source is BRG7 */
+#define CMXFCR_TF3CS_BRG8  0x00000300   /* Transmit FCC3 Clock Source is BRG8 */
+#define CMXFCR_TF3CS_CLK13 0x00000400   /* Transmit FCC3 Clock Source is CLK13 */
+#define CMXFCR_TF3CS_CLK14 0x00000500   /* Transmit FCC3 Clock Source is CLK14 */
+#define CMXFCR_TF3CS_CLK15 0x00000600   /* Transmit FCC3 Clock Source is CLK15 */
+#define CMXFCR_TF3CS_CLK16 0x00000700   /* Transmit FCC3 Clock Source is CLK16 */
+
+/*-----------------------------------------------------------------------
+ * CMXSCR - CMX SCC Clock Route Register
+ */
+#define CMXSCR_GR1         0x80000000   /* Grant Support of SCC1        */
+#define CMXSCR_SC1         0x40000000   /* SCC1 connection              */
+#define CMXSCR_RS1CS_MSK   0x38000000   /* Receive SCC1 Clock Source Mask */
+#define CMXSCR_TS1CS_MSK   0x07000000   /* Transmit SCC1 Clock Source Mask */
+#define CMXSCR_GR2         0x00800000   /* Grant Support of SCC2        */
+#define CMXSCR_SC2         0x00400000   /* SCC2 connection              */
+#define CMXSCR_RS2CS_MSK   0x00380000   /* Receive SCC2 Clock Source Mask */
+#define CMXSCR_TS2CS_MSK   0x00070000   /* Transmit SCC2 Clock Source Mask */
+#define CMXSCR_GR3         0x00008000   /* Grant Support of SCC3        */
+#define CMXSCR_SC3         0x00004000   /* SCC3 connection              */
+#define CMXSCR_RS3CS_MSK   0x00003800   /* Receive SCC3 Clock Source Mask */
+#define CMXSCR_TS3CS_MSK   0x00000700   /* Transmit SCC3 Clock Source Mask */
+#define CMXSCR_GR4         0x00000080   /* Grant Support of SCC4        */
+#define CMXSCR_SC4         0x00000040   /* SCC4 connection              */
+#define CMXSCR_RS4CS_MSK   0x00000038   /* Receive SCC4 Clock Source Mask */
+#define CMXSCR_TS4CS_MSK   0x00000007   /* Transmit SCC4 Clock Source Mask */
+
+#define CMXSCR_RS1CS_BRG1  0x00000000   /* SCC1 Rx Clock Source is BRG1 */
+#define CMXSCR_RS1CS_BRG2  0x08000000   /* SCC1 Rx Clock Source is BRG2 */
+#define CMXSCR_RS1CS_BRG3  0x10000000   /* SCC1 Rx Clock Source is BRG3 */
+#define CMXSCR_RS1CS_BRG4  0x18000000   /* SCC1 Rx Clock Source is BRG4 */
+#define CMXSCR_RS1CS_CLK11 0x20000000   /* SCC1 Rx Clock Source is CLK11 */
+#define CMXSCR_RS1CS_CLK12 0x28000000   /* SCC1 Rx Clock Source is CLK12 */
+#define CMXSCR_RS1CS_CLK3  0x30000000   /* SCC1 Rx Clock Source is CLK3 */
+#define CMXSCR_RS1CS_CLK4  0x38000000   /* SCC1 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS1CS_BRG1  0x00000000   /* SCC1 Tx Clock Source is BRG1 */
+#define CMXSCR_TS1CS_BRG2  0x01000000   /* SCC1 Tx Clock Source is BRG2 */
+#define CMXSCR_TS1CS_BRG3  0x02000000   /* SCC1 Tx Clock Source is BRG3 */
+#define CMXSCR_TS1CS_BRG4  0x03000000   /* SCC1 Tx Clock Source is BRG4 */
+#define CMXSCR_TS1CS_CLK11 0x04000000   /* SCC1 Tx Clock Source is CLK11 */
+#define CMXSCR_TS1CS_CLK12 0x05000000   /* SCC1 Tx Clock Source is CLK12 */
+#define CMXSCR_TS1CS_CLK3  0x06000000   /* SCC1 Tx Clock Source is CLK3 */
+#define CMXSCR_TS1CS_CLK4  0x07000000   /* SCC1 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS2CS_BRG1  0x00000000   /* SCC2 Rx Clock Source is BRG1 */
+#define CMXSCR_RS2CS_BRG2  0x00080000   /* SCC2 Rx Clock Source is BRG2 */
+#define CMXSCR_RS2CS_BRG3  0x00100000   /* SCC2 Rx Clock Source is BRG3 */
+#define CMXSCR_RS2CS_BRG4  0x00180000   /* SCC2 Rx Clock Source is BRG4 */
+#define CMXSCR_RS2CS_CLK11 0x00200000   /* SCC2 Rx Clock Source is CLK11 */
+#define CMXSCR_RS2CS_CLK12 0x00280000   /* SCC2 Rx Clock Source is CLK12 */
+#define CMXSCR_RS2CS_CLK3  0x00300000   /* SCC2 Rx Clock Source is CLK3 */
+#define CMXSCR_RS2CS_CLK4  0x00380000   /* SCC2 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS2CS_BRG1  0x00000000   /* SCC2 Tx Clock Source is BRG1 */
+#define CMXSCR_TS2CS_BRG2  0x00010000   /* SCC2 Tx Clock Source is BRG2 */
+#define CMXSCR_TS2CS_BRG3  0x00020000   /* SCC2 Tx Clock Source is BRG3 */
+#define CMXSCR_TS2CS_BRG4  0x00030000   /* SCC2 Tx Clock Source is BRG4 */
+#define CMXSCR_TS2CS_CLK11 0x00040000   /* SCC2 Tx Clock Source is CLK11 */
+#define CMXSCR_TS2CS_CLK12 0x00050000   /* SCC2 Tx Clock Source is CLK12 */
+#define CMXSCR_TS2CS_CLK3  0x00060000   /* SCC2 Tx Clock Source is CLK3 */
+#define CMXSCR_TS2CS_CLK4  0x00070000   /* SCC2 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS3CS_BRG1  0x00000000   /* SCC3 Rx Clock Source is BRG1 */
+#define CMXSCR_RS3CS_BRG2  0x00000800   /* SCC3 Rx Clock Source is BRG2 */
+#define CMXSCR_RS3CS_BRG3  0x00001000   /* SCC3 Rx Clock Source is BRG3 */
+#define CMXSCR_RS3CS_BRG4  0x00001800   /* SCC3 Rx Clock Source is BRG4 */
+#define CMXSCR_RS3CS_CLK5  0x00002000   /* SCC3 Rx Clock Source is CLK5 */
+#define CMXSCR_RS3CS_CLK6  0x00002800   /* SCC3 Rx Clock Source is CLK6 */
+#define CMXSCR_RS3CS_CLK7  0x00003000   /* SCC3 Rx Clock Source is CLK7 */
+#define CMXSCR_RS3CS_CLK8  0x00003800   /* SCC3 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS3CS_BRG1  0x00000000   /* SCC3 Tx Clock Source is BRG1 */
+#define CMXSCR_TS3CS_BRG2  0x00000100   /* SCC3 Tx Clock Source is BRG2 */
+#define CMXSCR_TS3CS_BRG3  0x00000200   /* SCC3 Tx Clock Source is BRG3 */
+#define CMXSCR_TS3CS_BRG4  0x00000300   /* SCC3 Tx Clock Source is BRG4 */
+#define CMXSCR_TS3CS_CLK5  0x00000400   /* SCC3 Tx Clock Source is CLK5 */
+#define CMXSCR_TS3CS_CLK6  0x00000500   /* SCC3 Tx Clock Source is CLK6 */
+#define CMXSCR_TS3CS_CLK7  0x00000600   /* SCC3 Tx Clock Source is CLK7 */
+#define CMXSCR_TS3CS_CLK8  0x00000700   /* SCC3 Tx Clock Source is CLK8 */
+
+#define CMXSCR_RS4CS_BRG1  0x00000000   /* SCC4 Rx Clock Source is BRG1 */
+#define CMXSCR_RS4CS_BRG2  0x00000008   /* SCC4 Rx Clock Source is BRG2 */
+#define CMXSCR_RS4CS_BRG3  0x00000010   /* SCC4 Rx Clock Source is BRG3 */
+#define CMXSCR_RS4CS_BRG4  0x00000018   /* SCC4 Rx Clock Source is BRG4 */
+#define CMXSCR_RS4CS_CLK5  0x00000020   /* SCC4 Rx Clock Source is CLK5 */
+#define CMXSCR_RS4CS_CLK6  0x00000028   /* SCC4 Rx Clock Source is CLK6 */
+#define CMXSCR_RS4CS_CLK7  0x00000030   /* SCC4 Rx Clock Source is CLK7 */
+#define CMXSCR_RS4CS_CLK8  0x00000038   /* SCC4 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS4CS_BRG1  0x00000000   /* SCC4 Tx Clock Source is BRG1 */
+#define CMXSCR_TS4CS_BRG2  0x00000001   /* SCC4 Tx Clock Source is BRG2 */
+#define CMXSCR_TS4CS_BRG3  0x00000002   /* SCC4 Tx Clock Source is BRG3 */
+#define CMXSCR_TS4CS_BRG4  0x00000003   /* SCC4 Tx Clock Source is BRG4 */
+#define CMXSCR_TS4CS_CLK5  0x00000004   /* SCC4 Tx Clock Source is CLK5 */
+#define CMXSCR_TS4CS_CLK6  0x00000005   /* SCC4 Tx Clock Source is CLK6 */
+#define CMXSCR_TS4CS_CLK7  0x00000006   /* SCC4 Tx Clock Source is CLK7 */
+#define CMXSCR_TS4CS_CLK8  0x00000007   /* SCC4 Tx Clock Source is CLK8 */
+
+#endif /* __CPM2__ */
+#endif /* __KERNEL__ */
+
+
diff -urN linux-2.4.26-pre2/include/asm-ppc/cpm_8260.h linux-2.4.26-pre3/include/asm-ppc/cpm_8260.h
--- linux-2.4.26-pre2/include/asm-ppc/cpm_8260.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ppc/cpm_8260.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,702 +0,0 @@
-/*
- * MPC8260 Communication Processor Module.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *
- * This file contains structures and information for the communication
- * processor channels found in the dual port RAM or parameter RAM.
- * All CPM control and status is available through the MPC8260 internal
- * memory map.  See immap.h for details.
- */
-#ifdef __KERNEL__
-#ifndef __CPM_82XX__
-#define __CPM_82XX__
-
-#include <asm/immap_8260.h>
-
-/* CPM Command register.
-*/
-#define CPM_CR_RST	((uint)0x80000000)
-#define CPM_CR_PAGE	((uint)0x7c000000)
-#define CPM_CR_SBLOCK	((uint)0x03e00000)
-#define CPM_CR_FLG	((uint)0x00010000)
-#define CPM_CR_MCN	((uint)0x00003fc0)
-#define CPM_CR_OPCODE	((uint)0x0000000f)
-
-/* Device sub-block and page codes.
-*/
-#define CPM_CR_SCC1_SBLOCK	(0x04)
-#define CPM_CR_SCC2_SBLOCK	(0x05)
-#define CPM_CR_SCC3_SBLOCK	(0x06)
-#define CPM_CR_SCC4_SBLOCK	(0x07)
-#define CPM_CR_SMC1_SBLOCK	(0x08)
-#define CPM_CR_SMC2_SBLOCK	(0x09)
-#define CPM_CR_SPI_SBLOCK	(0x0a)
-#define CPM_CR_I2C_SBLOCK	(0x0b)
-#define CPM_CR_TIMER_SBLOCK	(0x0f)
-#define CPM_CR_RAND_SBLOCK	(0x0e)
-#define CPM_CR_FCC1_SBLOCK	(0x10)
-#define CPM_CR_FCC2_SBLOCK	(0x11)
-#define CPM_CR_FCC3_SBLOCK	(0x12)
-#define CPM_CR_IDMA1_SBLOCK	(0x14)
-#define CPM_CR_IDMA2_SBLOCK	(0x15)
-#define CPM_CR_IDMA3_SBLOCK	(0x16)
-#define CPM_CR_IDMA4_SBLOCK	(0x17)
-#define CPM_CR_MCC1_SBLOCK	(0x1c)
-
-#define CPM_CR_SCC1_PAGE	(0x00)
-#define CPM_CR_SCC2_PAGE	(0x01)
-#define CPM_CR_SCC3_PAGE	(0x02)
-#define CPM_CR_SCC4_PAGE	(0x03)
-#define CPM_CR_SMC1_PAGE	(0x07)
-#define CPM_CR_SMC2_PAGE	(0x08)
-#define CPM_CR_SPI_PAGE		(0x09)
-#define CPM_CR_I2C_PAGE		(0x0a)
-#define CPM_CR_TIMER_PAGE	(0x0a)
-#define CPM_CR_RAND_PAGE	(0x0a)
-#define CPM_CR_FCC1_PAGE	(0x04)
-#define CPM_CR_FCC2_PAGE	(0x05)
-#define CPM_CR_FCC3_PAGE	(0x06)
-#define CPM_CR_IDMA1_PAGE	(0x07)
-#define CPM_CR_IDMA2_PAGE	(0x08)
-#define CPM_CR_IDMA3_PAGE	(0x09)
-#define CPM_CR_IDMA4_PAGE	(0x0a)
-#define CPM_CR_MCC1_PAGE	(0x07)
-#define CPM_CR_MCC2_PAGE	(0x08)
-
-/* Some opcodes (there are more...later)
-*/
-#define CPM_CR_INIT_TRX		((ushort)0x0000)
-#define CPM_CR_INIT_RX		((ushort)0x0001)
-#define CPM_CR_INIT_TX		((ushort)0x0002)
-#define CPM_CR_HUNT_MODE	((ushort)0x0003)
-#define CPM_CR_STOP_TX		((ushort)0x0004)
-#define CPM_CR_RESTART_TX	((ushort)0x0006)
-#define CPM_CR_SET_GADDR	((ushort)0x0008)
-
-#define mk_cr_cmd(PG, SBC, MCN, OP) \
-	((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
-
-/* Dual Port RAM addresses.  The first 16K is available for almost
- * any CPM use, so we put the BDs there.  The first 128 bytes are
- * used for SMC1 and SMC2 parameter RAM, so we start allocating
- * BDs above that.  All of this must change when we start
- * downloading RAM microcode.
- */
-#define CPM_DATAONLY_BASE	((uint)128)
-#define CPM_DATAONLY_SIZE	((uint)(16 * 1024) - CPM_DATAONLY_BASE)
-#define CPM_DP_NOSPACE		((uint)0x7fffffff)
-#define CPM_FCC_SPECIAL_BASE	((uint)0x0000b000)
-
-/* The number of pages of host memory we allocate for CPM.  This is
- * done early in kernel initialization to get physically contiguous
- * pages.
- */
-#define NUM_CPM_HOST_PAGES	2
-
-
-/* Export the base address of the communication processor registers
- * and dual port ram.
- */
-extern	cpm8260_t	*cpmp;		/* Pointer to comm processor */
-uint		m8260_cpm_dpalloc(uint size, uint align);
-uint		m8260_cpm_hostalloc(uint size, uint align);
-void		m8260_cpm_setbrg(uint brg, uint rate);
-void		m8260_cpm_fastbrg(uint brg, uint rate, int div16);
-
-/* Buffer descriptors used by many of the CPM protocols.
-*/
-typedef struct cpm_buf_desc {
-	ushort	cbd_sc;		/* Status and Control */
-	ushort	cbd_datlen;	/* Data length in buffer */
-	uint	cbd_bufaddr;	/* Buffer address in host memory */
-} cbd_t;
-
-#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
-#define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
-#define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
-#define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
-#define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame */
-#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
-#define BD_SC_ID	((ushort)0x0100)	/* Rec'd too many idles */
-#define BD_SC_P		((ushort)0x0100)	/* xmt preamble */
-#define BD_SC_BR	((ushort)0x0020)	/* Break received */
-#define BD_SC_FR	((ushort)0x0010)	/* Framing error */
-#define BD_SC_PR	((ushort)0x0008)	/* Parity error */
-#define BD_SC_OV	((ushort)0x0002)	/* Overrun */
-#define BD_SC_CD	((ushort)0x0001)	/* ?? */
-
-/* Function code bits, usually generic to devices.
-*/
-#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
-#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
-#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
-#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
-#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
-
-/* Parameter RAM offsets from the base.
-*/
-#define PROFF_SCC1		((uint)0x8000)
-#define PROFF_SCC2		((uint)0x8100)
-#define PROFF_SCC3		((uint)0x8200)
-#define PROFF_SCC4		((uint)0x8300)
-#define PROFF_FCC1		((uint)0x8400)
-#define PROFF_FCC2		((uint)0x8500)
-#define PROFF_FCC3		((uint)0x8600)
-#define PROFF_MCC1		((uint)0x8700)
-#define PROFF_SMC1_BASE		((uint)0x87fc)
-#define PROFF_IDMA1_BASE	((uint)0x87fe)
-#define PROFF_MCC2		((uint)0x8800)
-#define PROFF_SMC2_BASE		((uint)0x88fc)
-#define PROFF_IDMA2_BASE	((uint)0x88fe)
-#define PROFF_SPI_BASE		((uint)0x89fc)
-#define PROFF_IDMA3_BASE	((uint)0x89fe)
-#define PROFF_TIMERS		((uint)0x8ae0)
-#define PROFF_REVNUM		((uint)0x8af0)
-#define PROFF_RAND		((uint)0x8af8)
-#define PROFF_I2C_BASE		((uint)0x8afc)
-#define PROFF_IDMA4_BASE	((uint)0x8afe)
-
-/* The SMCs are relocated to any of the first eight DPRAM pages.
- * We will fix these at the first locations of DPRAM, until we
- * get some microcode patches :-).
- * The parameter ram space for the SMCs is fifty-some bytes, and
- * they are required to start on a 64 byte boundary.
- */
-#define PROFF_SMC1	(0)
-#define PROFF_SMC2	(64)
-
-
-/* Define enough so I can at least use the serial port as a UART.
- */
-typedef struct smc_uart {
-	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
-	ushort	smc_tbase;	/* Tx Buffer descriptor base address */
-	u_char	smc_rfcr;	/* Rx function code */
-	u_char	smc_tfcr;	/* Tx function code */
-	ushort	smc_mrblr;	/* Max receive buffer length */
-	uint	smc_rstate;	/* Internal */
-	uint	smc_idp;	/* Internal */
-	ushort	smc_rbptr;	/* Internal */
-	ushort	smc_ibc;	/* Internal */
-	uint	smc_rxtmp;	/* Internal */
-	uint	smc_tstate;	/* Internal */
-	uint	smc_tdp;	/* Internal */
-	ushort	smc_tbptr;	/* Internal */
-	ushort	smc_tbc;	/* Internal */
-	uint	smc_txtmp;	/* Internal */
-	ushort	smc_maxidl;	/* Maximum idle characters */
-	ushort	smc_tmpidl;	/* Temporary idle counter */
-	ushort	smc_brklen;	/* Last received break length */
-	ushort	smc_brkec;	/* rcv'd break condition counter */
-	ushort	smc_brkcr;	/* xmt break count register */
-	ushort	smc_rmask;	/* Temporary bit mask */
-	uint	smc_stmp;	/* SDMA Temp */
-} smc_uart_t;
-
-/* SMC uart mode register (Internal memory map).
-*/
-#define SMCMR_REN	((ushort)0x0001)
-#define SMCMR_TEN	((ushort)0x0002)
-#define SMCMR_DM	((ushort)0x000c)
-#define SMCMR_SM_GCI	((ushort)0x0000)
-#define SMCMR_SM_UART	((ushort)0x0020)
-#define SMCMR_SM_TRANS	((ushort)0x0030)
-#define SMCMR_SM_MASK	((ushort)0x0030)
-#define SMCMR_PM_EVEN	((ushort)0x0100)	/* Even parity, else odd */
-#define SMCMR_REVD	SMCMR_PM_EVEN
-#define SMCMR_PEN	((ushort)0x0200)	/* Parity enable */
-#define SMCMR_BS	SMCMR_PEN
-#define SMCMR_SL	((ushort)0x0400)	/* Two stops, else one */
-#define SMCR_CLEN_MASK	((ushort)0x7800)	/* Character length */
-#define smcr_mk_clen(C)	(((C) << 11) & SMCR_CLEN_MASK)
-
-/* SMC Event and Mask register.
-*/
-#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
-#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
-#define SMCM_TXE	((unsigned char)0x10)
-#define SMCM_BSY	((unsigned char)0x04)
-#define SMCM_TX		((unsigned char)0x02)
-#define SMCM_RX		((unsigned char)0x01)
-
-/* Baud rate generators.
-*/
-#define CPM_BRG_RST		((uint)0x00020000)
-#define CPM_BRG_EN		((uint)0x00010000)
-#define CPM_BRG_EXTC_INT	((uint)0x00000000)
-#define CPM_BRG_EXTC_CLK3_9	((uint)0x00004000)
-#define CPM_BRG_EXTC_CLK5_15	((uint)0x00008000)
-#define CPM_BRG_ATB		((uint)0x00002000)
-#define CPM_BRG_CD_MASK		((uint)0x00001ffe)
-#define CPM_BRG_DIV16		((uint)0x00000001)
-
-/* SCCs.
-*/
-#define SCC_GSMRH_IRP		((uint)0x00040000)
-#define SCC_GSMRH_GDE		((uint)0x00010000)
-#define SCC_GSMRH_TCRC_CCITT	((uint)0x00008000)
-#define SCC_GSMRH_TCRC_BISYNC	((uint)0x00004000)
-#define SCC_GSMRH_TCRC_HDLC	((uint)0x00000000)
-#define SCC_GSMRH_REVD		((uint)0x00002000)
-#define SCC_GSMRH_TRX		((uint)0x00001000)
-#define SCC_GSMRH_TTX		((uint)0x00000800)
-#define SCC_GSMRH_CDP		((uint)0x00000400)
-#define SCC_GSMRH_CTSP		((uint)0x00000200)
-#define SCC_GSMRH_CDS		((uint)0x00000100)
-#define SCC_GSMRH_CTSS		((uint)0x00000080)
-#define SCC_GSMRH_TFL		((uint)0x00000040)
-#define SCC_GSMRH_RFW		((uint)0x00000020)
-#define SCC_GSMRH_TXSY		((uint)0x00000010)
-#define SCC_GSMRH_SYNL16	((uint)0x0000000c)
-#define SCC_GSMRH_SYNL8		((uint)0x00000008)
-#define SCC_GSMRH_SYNL4		((uint)0x00000004)
-#define SCC_GSMRH_RTSM		((uint)0x00000002)
-#define SCC_GSMRH_RSYN		((uint)0x00000001)
-
-#define SCC_GSMRL_SIR		((uint)0x80000000)	/* SCC2 only */
-#define SCC_GSMRL_EDGE_NONE	((uint)0x60000000)
-#define SCC_GSMRL_EDGE_NEG	((uint)0x40000000)
-#define SCC_GSMRL_EDGE_POS	((uint)0x20000000)
-#define SCC_GSMRL_EDGE_BOTH	((uint)0x00000000)
-#define SCC_GSMRL_TCI		((uint)0x10000000)
-#define SCC_GSMRL_TSNC_3	((uint)0x0c000000)
-#define SCC_GSMRL_TSNC_4	((uint)0x08000000)
-#define SCC_GSMRL_TSNC_14	((uint)0x04000000)
-#define SCC_GSMRL_TSNC_INF	((uint)0x00000000)
-#define SCC_GSMRL_RINV		((uint)0x02000000)
-#define SCC_GSMRL_TINV		((uint)0x01000000)
-#define SCC_GSMRL_TPL_128	((uint)0x00c00000)
-#define SCC_GSMRL_TPL_64	((uint)0x00a00000)
-#define SCC_GSMRL_TPL_48	((uint)0x00800000)
-#define SCC_GSMRL_TPL_32	((uint)0x00600000)
-#define SCC_GSMRL_TPL_16	((uint)0x00400000)
-#define SCC_GSMRL_TPL_8		((uint)0x00200000)
-#define SCC_GSMRL_TPL_NONE	((uint)0x00000000)
-#define SCC_GSMRL_TPP_ALL1	((uint)0x00180000)
-#define SCC_GSMRL_TPP_01	((uint)0x00100000)
-#define SCC_GSMRL_TPP_10	((uint)0x00080000)
-#define SCC_GSMRL_TPP_ZEROS	((uint)0x00000000)
-#define SCC_GSMRL_TEND		((uint)0x00040000)
-#define SCC_GSMRL_TDCR_32	((uint)0x00030000)
-#define SCC_GSMRL_TDCR_16	((uint)0x00020000)
-#define SCC_GSMRL_TDCR_8	((uint)0x00010000)
-#define SCC_GSMRL_TDCR_1	((uint)0x00000000)
-#define SCC_GSMRL_RDCR_32	((uint)0x0000c000)
-#define SCC_GSMRL_RDCR_16	((uint)0x00008000)
-#define SCC_GSMRL_RDCR_8	((uint)0x00004000)
-#define SCC_GSMRL_RDCR_1	((uint)0x00000000)
-#define SCC_GSMRL_RENC_DFMAN	((uint)0x00003000)
-#define SCC_GSMRL_RENC_MANCH	((uint)0x00002000)
-#define SCC_GSMRL_RENC_FM0	((uint)0x00001000)
-#define SCC_GSMRL_RENC_NRZI	((uint)0x00000800)
-#define SCC_GSMRL_RENC_NRZ	((uint)0x00000000)
-#define SCC_GSMRL_TENC_DFMAN	((uint)0x00000600)
-#define SCC_GSMRL_TENC_MANCH	((uint)0x00000400)
-#define SCC_GSMRL_TENC_FM0	((uint)0x00000200)
-#define SCC_GSMRL_TENC_NRZI	((uint)0x00000100)
-#define SCC_GSMRL_TENC_NRZ	((uint)0x00000000)
-#define SCC_GSMRL_DIAG_LE	((uint)0x000000c0)	/* Loop and echo */
-#define SCC_GSMRL_DIAG_ECHO	((uint)0x00000080)
-#define SCC_GSMRL_DIAG_LOOP	((uint)0x00000040)
-#define SCC_GSMRL_DIAG_NORM	((uint)0x00000000)
-#define SCC_GSMRL_ENR		((uint)0x00000020)
-#define SCC_GSMRL_ENT		((uint)0x00000010)
-#define SCC_GSMRL_MODE_ENET	((uint)0x0000000c)
-#define SCC_GSMRL_MODE_DDCMP	((uint)0x00000009)
-#define SCC_GSMRL_MODE_BISYNC	((uint)0x00000008)
-#define SCC_GSMRL_MODE_V14	((uint)0x00000007)
-#define SCC_GSMRL_MODE_AHDLC	((uint)0x00000006)
-#define SCC_GSMRL_MODE_PROFIBUS	((uint)0x00000005)
-#define SCC_GSMRL_MODE_UART	((uint)0x00000004)
-#define SCC_GSMRL_MODE_SS7	((uint)0x00000003)
-#define SCC_GSMRL_MODE_ATALK	((uint)0x00000002)
-#define SCC_GSMRL_MODE_HDLC	((uint)0x00000000)
-
-#define SCC_TODR_TOD		((ushort)0x8000)
-
-/* SCC Event and Mask register.
-*/
-#define SCCM_TXE	((unsigned char)0x10)
-#define SCCM_BSY	((unsigned char)0x04)
-#define SCCM_TX		((unsigned char)0x02)
-#define SCCM_RX		((unsigned char)0x01)
-
-typedef struct scc_param {
-	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
-	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
-	u_char	scc_rfcr;	/* Rx function code */
-	u_char	scc_tfcr;	/* Tx function code */
-	ushort	scc_mrblr;	/* Max receive buffer length */
-	uint	scc_rstate;	/* Internal */
-	uint	scc_idp;	/* Internal */
-	ushort	scc_rbptr;	/* Internal */
-	ushort	scc_ibc;	/* Internal */
-	uint	scc_rxtmp;	/* Internal */
-	uint	scc_tstate;	/* Internal */
-	uint	scc_tdp;	/* Internal */
-	ushort	scc_tbptr;	/* Internal */
-	ushort	scc_tbc;	/* Internal */
-	uint	scc_txtmp;	/* Internal */
-	uint	scc_rcrc;	/* Internal */
-	uint	scc_tcrc;	/* Internal */
-} sccp_t;
-
-/* CPM Ethernet through SCC1.
- */
-typedef struct scc_enet {
-	sccp_t	sen_genscc;
-	uint	sen_cpres;	/* Preset CRC */
-	uint	sen_cmask;	/* Constant mask for CRC */
-	uint	sen_crcec;	/* CRC Error counter */
-	uint	sen_alec;	/* alignment error counter */
-	uint	sen_disfc;	/* discard frame counter */
-	ushort	sen_pads;	/* Tx short frame pad character */
-	ushort	sen_retlim;	/* Retry limit threshold */
-	ushort	sen_retcnt;	/* Retry limit counter */
-	ushort	sen_maxflr;	/* maximum frame length register */
-	ushort	sen_minflr;	/* minimum frame length register */
-	ushort	sen_maxd1;	/* maximum DMA1 length */
-	ushort	sen_maxd2;	/* maximum DMA2 length */
-	ushort	sen_maxd;	/* Rx max DMA */
-	ushort	sen_dmacnt;	/* Rx DMA counter */
-	ushort	sen_maxb;	/* Max BD byte count */
-	ushort	sen_gaddr1;	/* Group address filter */
-	ushort	sen_gaddr2;
-	ushort	sen_gaddr3;
-	ushort	sen_gaddr4;
-	uint	sen_tbuf0data0;	/* Save area 0 - current frame */
-	uint	sen_tbuf0data1;	/* Save area 1 - current frame */
-	uint	sen_tbuf0rba;	/* Internal */
-	uint	sen_tbuf0crc;	/* Internal */
-	ushort	sen_tbuf0bcnt;	/* Internal */
-	ushort	sen_paddrh;	/* physical address (MSB) */
-	ushort	sen_paddrm;
-	ushort	sen_paddrl;	/* physical address (LSB) */
-	ushort	sen_pper;	/* persistence */
-	ushort	sen_rfbdptr;	/* Rx first BD pointer */
-	ushort	sen_tfbdptr;	/* Tx first BD pointer */
-	ushort	sen_tlbdptr;	/* Tx last BD pointer */
-	uint	sen_tbuf1data0;	/* Save area 0 - current frame */
-	uint	sen_tbuf1data1;	/* Save area 1 - current frame */
-	uint	sen_tbuf1rba;	/* Internal */
-	uint	sen_tbuf1crc;	/* Internal */
-	ushort	sen_tbuf1bcnt;	/* Internal */
-	ushort	sen_txlen;	/* Tx Frame length counter */
-	ushort	sen_iaddr1;	/* Individual address filter */
-	ushort	sen_iaddr2;
-	ushort	sen_iaddr3;
-	ushort	sen_iaddr4;
-	ushort	sen_boffcnt;	/* Backoff counter */
-
-	/* NOTE: Some versions of the manual have the following items
-	 * incorrectly documented.  Below is the proper order.
-	 */
-	ushort	sen_taddrh;	/* temp address (MSB) */
-	ushort	sen_taddrm;
-	ushort	sen_taddrl;	/* temp address (LSB) */
-} scc_enet_t;
-
-
-/* SCC Event register as used by Ethernet.
-*/
-#define SCCE_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
-#define SCCE_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
-#define SCCE_ENET_RXF	((ushort)0x0008)	/* Full frame received */
-#define SCCE_ENET_BSY	((ushort)0x0004)	/* All incoming buffers full */
-#define SCCE_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
-#define SCCE_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
-
-/* SCC Mode Register (PSMR) as used by Ethernet.
-*/
-#define SCC_PSMR_HBC	((ushort)0x8000)	/* Enable heartbeat */
-#define SCC_PSMR_FC	((ushort)0x4000)	/* Force collision */
-#define SCC_PSMR_RSH	((ushort)0x2000)	/* Receive short frames */
-#define SCC_PSMR_IAM	((ushort)0x1000)	/* Check individual hash */
-#define SCC_PSMR_ENCRC	((ushort)0x0800)	/* Ethernet CRC mode */
-#define SCC_PSMR_PRO	((ushort)0x0200)	/* Promiscuous mode */
-#define SCC_PSMR_BRO	((ushort)0x0100)	/* Catch broadcast pkts */
-#define SCC_PSMR_SBT	((ushort)0x0080)	/* Special backoff timer */
-#define SCC_PSMR_LPB	((ushort)0x0040)	/* Set Loopback mode */
-#define SCC_PSMR_SIP	((ushort)0x0020)	/* Sample Input Pins */
-#define SCC_PSMR_LCW	((ushort)0x0010)	/* Late collision window */
-#define SCC_PSMR_NIB22	((ushort)0x000a)	/* Start frame search */
-#define SCC_PSMR_FDE	((ushort)0x0001)	/* Full duplex enable */
-
-/* Buffer descriptor control/status used by Ethernet receive.
- * Common to SCC and FCC.
- */
-#define BD_ENET_RX_EMPTY	((ushort)0x8000)
-#define BD_ENET_RX_WRAP		((ushort)0x2000)
-#define BD_ENET_RX_INTR		((ushort)0x1000)
-#define BD_ENET_RX_LAST		((ushort)0x0800)
-#define BD_ENET_RX_FIRST	((ushort)0x0400)
-#define BD_ENET_RX_MISS		((ushort)0x0100)
-#define BD_ENET_RX_BC		((ushort)0x0080)	/* FCC Only */
-#define BD_ENET_RX_MC		((ushort)0x0040)	/* FCC Only */
-#define BD_ENET_RX_LG		((ushort)0x0020)
-#define BD_ENET_RX_NO		((ushort)0x0010)
-#define BD_ENET_RX_SH		((ushort)0x0008)
-#define BD_ENET_RX_CR		((ushort)0x0004)
-#define BD_ENET_RX_OV		((ushort)0x0002)
-#define BD_ENET_RX_CL		((ushort)0x0001)
-#define BD_ENET_RX_STATS	((ushort)0x01ff)	/* All status bits */
-
-/* Buffer descriptor control/status used by Ethernet transmit.
- * Common to SCC and FCC.
- */
-#define BD_ENET_TX_READY	((ushort)0x8000)
-#define BD_ENET_TX_PAD		((ushort)0x4000)
-#define BD_ENET_TX_WRAP		((ushort)0x2000)
-#define BD_ENET_TX_INTR		((ushort)0x1000)
-#define BD_ENET_TX_LAST		((ushort)0x0800)
-#define BD_ENET_TX_TC		((ushort)0x0400)
-#define BD_ENET_TX_DEF		((ushort)0x0200)
-#define BD_ENET_TX_HB		((ushort)0x0100)
-#define BD_ENET_TX_LC		((ushort)0x0080)
-#define BD_ENET_TX_RL		((ushort)0x0040)
-#define BD_ENET_TX_RCMASK	((ushort)0x003c)
-#define BD_ENET_TX_UN		((ushort)0x0002)
-#define BD_ENET_TX_CSL		((ushort)0x0001)
-#define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
-
-/* SCC as UART
-*/
-typedef struct scc_uart {
-	sccp_t	scc_genscc;
-	uint	scc_res1;	/* Reserved */
-	uint	scc_res2;	/* Reserved */
-	ushort	scc_maxidl;	/* Maximum idle chars */
-	ushort	scc_idlc;	/* temp idle counter */
-	ushort	scc_brkcr;	/* Break count register */
-	ushort	scc_parec;	/* receive parity error counter */
-	ushort	scc_frmec;	/* receive framing error counter */
-	ushort	scc_nosec;	/* receive noise counter */
-	ushort	scc_brkec;	/* receive break condition counter */
-	ushort	scc_brkln;	/* last received break length */
-	ushort	scc_uaddr1;	/* UART address character 1 */
-	ushort	scc_uaddr2;	/* UART address character 2 */
-	ushort	scc_rtemp;	/* Temp storage */
-	ushort	scc_toseq;	/* Transmit out of sequence char */
-	ushort	scc_char1;	/* control character 1 */
-	ushort	scc_char2;	/* control character 2 */
-	ushort	scc_char3;	/* control character 3 */
-	ushort	scc_char4;	/* control character 4 */
-	ushort	scc_char5;	/* control character 5 */
-	ushort	scc_char6;	/* control character 6 */
-	ushort	scc_char7;	/* control character 7 */
-	ushort	scc_char8;	/* control character 8 */
-	ushort	scc_rccm;	/* receive control character mask */
-	ushort	scc_rccr;	/* receive control character register */
-	ushort	scc_rlbc;	/* receive last break character */
-} scc_uart_t;
-
-/* SCC Event and Mask registers when it is used as a UART.
-*/
-#define UART_SCCM_GLR		((ushort)0x1000)
-#define UART_SCCM_GLT		((ushort)0x0800)
-#define UART_SCCM_AB		((ushort)0x0200)
-#define UART_SCCM_IDL		((ushort)0x0100)
-#define UART_SCCM_GRA		((ushort)0x0080)
-#define UART_SCCM_BRKE		((ushort)0x0040)
-#define UART_SCCM_BRKS		((ushort)0x0020)
-#define UART_SCCM_CCR		((ushort)0x0008)
-#define UART_SCCM_BSY		((ushort)0x0004)
-#define UART_SCCM_TX		((ushort)0x0002)
-#define UART_SCCM_RX		((ushort)0x0001)
-
-/* The SCC PMSR when used as a UART.
-*/
-#define SCU_PMSR_FLC		((ushort)0x8000)
-#define SCU_PMSR_SL		((ushort)0x4000)
-#define SCU_PMSR_CL		((ushort)0x3000)
-#define SCU_PMSR_UM		((ushort)0x0c00)
-#define SCU_PMSR_FRZ		((ushort)0x0200)
-#define SCU_PMSR_RZS		((ushort)0x0100)
-#define SCU_PMSR_SYN		((ushort)0x0080)
-#define SCU_PMSR_DRT		((ushort)0x0040)
-#define SCU_PMSR_PEN		((ushort)0x0010)
-#define SCU_PMSR_RPM		((ushort)0x000c)
-#define SCU_PMSR_REVP		((ushort)0x0008)
-#define SCU_PMSR_TPM		((ushort)0x0003)
-#define SCU_PMSR_TEVP		((ushort)0x0003)
-
-/* CPM Transparent mode SCC.
- */
-typedef struct scc_trans {
-	sccp_t	st_genscc;
-	uint	st_cpres;	/* Preset CRC */
-	uint	st_cmask;	/* Constant mask for CRC */
-} scc_trans_t;
-
-#define BD_SCC_TX_LAST		((ushort)0x0800)
-
-/* How about some FCCs.....
-*/
-#define FCC_GFMR_DIAG_NORM	((uint)0x00000000)
-#define FCC_GFMR_DIAG_LE	((uint)0x40000000)
-#define FCC_GFMR_DIAG_AE	((uint)0x80000000)
-#define FCC_GFMR_DIAG_ALE	((uint)0xc0000000)
-#define FCC_GFMR_TCI		((uint)0x20000000)
-#define FCC_GFMR_TRX		((uint)0x10000000)
-#define FCC_GFMR_TTX		((uint)0x08000000)
-#define FCC_GFMR_TTX		((uint)0x08000000)
-#define FCC_GFMR_CDP		((uint)0x04000000)
-#define FCC_GFMR_CTSP		((uint)0x02000000)
-#define FCC_GFMR_CDS		((uint)0x01000000)
-#define FCC_GFMR_CTSS		((uint)0x00800000)
-#define FCC_GFMR_SYNL_NONE	((uint)0x00000000)
-#define FCC_GFMR_SYNL_AUTO	((uint)0x00004000)
-#define FCC_GFMR_SYNL_8		((uint)0x00008000)
-#define FCC_GFMR_SYNL_16	((uint)0x0000c000)
-#define FCC_GFMR_RTSM		((uint)0x00002000)
-#define FCC_GFMR_RENC_NRZ	((uint)0x00000000)
-#define FCC_GFMR_RENC_NRZI	((uint)0x00000800)
-#define FCC_GFMR_REVD		((uint)0x00000400)
-#define FCC_GFMR_TENC_NRZ	((uint)0x00000000)
-#define FCC_GFMR_TENC_NRZI	((uint)0x00000100)
-#define FCC_GFMR_TCRC_16	((uint)0x00000000)
-#define FCC_GFMR_TCRC_32	((uint)0x00000080)
-#define FCC_GFMR_ENR		((uint)0x00000020)
-#define FCC_GFMR_ENT		((uint)0x00000010)
-#define FCC_GFMR_MODE_ENET	((uint)0x0000000c)
-#define FCC_GFMR_MODE_ATM	((uint)0x0000000a)
-#define FCC_GFMR_MODE_HDLC	((uint)0x00000000)
-
-/* Generic FCC parameter ram.
-*/
-typedef struct fcc_param {
-	ushort	fcc_riptr;	/* Rx Internal temp pointer */
-	ushort	fcc_tiptr;	/* Tx Internal temp pointer */
-	ushort	fcc_res1;
-	ushort	fcc_mrblr;	/* Max receive buffer length, mod 32 bytes */
-	uint	fcc_rstate;	/* Upper byte is Func code, must be set */
-	uint	fcc_rbase;	/* Receive BD base */
-	ushort	fcc_rbdstat;	/* RxBD status */
-	ushort	fcc_rbdlen;	/* RxBD down counter */
-	uint	fcc_rdptr;	/* RxBD internal data pointer */
-	uint	fcc_tstate;	/* Upper byte is Func code, must be set */
-	uint	fcc_tbase;	/* Transmit BD base */
-	ushort	fcc_tbdstat;	/* TxBD status */
-	ushort	fcc_tbdlen;	/* TxBD down counter */
-	uint	fcc_tdptr;	/* TxBD internal data pointer */
-	uint	fcc_rbptr;	/* Rx BD Internal buf pointer */
-	uint	fcc_tbptr;	/* Tx BD Internal buf pointer */
-	uint	fcc_rcrc;	/* Rx temp CRC */
-	uint	fcc_res2;
-	uint	fcc_tcrc;	/* Tx temp CRC */
-} fccp_t;
-
-
-/* Ethernet controller through FCC.
-*/
-typedef struct fcc_enet {
-	fccp_t	fen_genfcc;
-	uint	fen_statbuf;	/* Internal status buffer */
-	uint	fen_camptr;	/* CAM address */
-	uint	fen_cmask;	/* Constant mask for CRC */
-	uint	fen_cpres;	/* Preset CRC */
-	uint	fen_crcec;	/* CRC Error counter */
-	uint	fen_alec;	/* alignment error counter */
-	uint	fen_disfc;	/* discard frame counter */
-	ushort	fen_retlim;	/* Retry limit */
-	ushort	fen_retcnt;	/* Retry counter */
-	ushort	fen_pper;	/* Persistence */
-	ushort	fen_boffcnt;	/* backoff counter */
-	uint	fen_gaddrh;	/* Group address filter, high 32-bits */
-	uint	fen_gaddrl;	/* Group address filter, low 32-bits */
-	ushort	fen_tfcstat;	/* out of sequence TxBD */
-	ushort	fen_tfclen;
-	uint	fen_tfcptr;
-	ushort	fen_mflr;	/* Maximum frame length (1518) */
-	ushort	fen_paddrh;	/* MAC address */
-	ushort	fen_paddrm;
-	ushort	fen_paddrl;
-	ushort	fen_ibdcount;	/* Internal BD counter */
-	ushort	fen_idbstart;	/* Internal BD start pointer */
-	ushort	fen_ibdend;	/* Internal BD end pointer */
-	ushort	fen_txlen;	/* Internal Tx frame length counter */
-	uint	fen_ibdbase[8]; /* Internal use */
-	uint	fen_iaddrh;	/* Individual address filter */
-	uint	fen_iaddrl;
-	ushort	fen_minflr;	/* Minimum frame length (64) */
-	ushort	fen_taddrh;	/* Filter transfer MAC address */
-	ushort	fen_taddrm;
-	ushort	fen_taddrl;
-	ushort	fen_padptr;	/* Pointer to pad byte buffer */
-	ushort	fen_cftype;	/* control frame type */
-	ushort	fen_cfrange;	/* control frame range */
-	ushort	fen_maxb;	/* maximum BD count */
-	ushort	fen_maxd1;	/* Max DMA1 length (1520) */
-	ushort	fen_maxd2;	/* Max DMA2 length (1520) */
-	ushort	fen_maxd;	/* internal max DMA count */
-	ushort	fen_dmacnt;	/* internal DMA counter */
-	uint	fen_octc;	/* Total octect counter */
-	uint	fen_colc;	/* Total collision counter */
-	uint	fen_broc;	/* Total broadcast packet counter */
-	uint	fen_mulc;	/* Total multicast packet count */
-	uint	fen_uspc;	/* Total packets < 64 bytes */
-	uint	fen_frgc;	/* Total packets < 64 bytes with errors */
-	uint	fen_ospc;	/* Total packets > 1518 */
-	uint	fen_jbrc;	/* Total packets > 1518 with errors */
-	uint	fen_p64c;	/* Total packets == 64 bytes */
-	uint	fen_p65c;	/* Total packets 64 < bytes <= 127 */
-	uint	fen_p128c;	/* Total packets 127 < bytes <= 255 */
-	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
-	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
-	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
-	uint	fen_cambuf;	/* Internal CAM buffer poiner */
-	ushort	fen_rfthr;	/* Received frames threshold */
-	ushort	fen_rfcnt;	/* Received frames count */
-} fcc_enet_t;
-
-/* FCC Event/Mask register as used by Ethernet.
-*/
-#define FCC_ENET_GRA	((ushort)0x0080)	/* Graceful stop complete */
-#define FCC_ENET_RXC	((ushort)0x0040)	/* Control Frame Received */
-#define FCC_ENET_TXC	((ushort)0x0020)	/* Out of seq. Tx sent */
-#define FCC_ENET_TXE	((ushort)0x0010)	/* Transmit Error */
-#define FCC_ENET_RXF	((ushort)0x0008)	/* Full frame received */
-#define FCC_ENET_BSY	((ushort)0x0004)	/* Busy.  Rx Frame dropped */
-#define FCC_ENET_TXB	((ushort)0x0002)	/* A buffer was transmitted */
-#define FCC_ENET_RXB	((ushort)0x0001)	/* A buffer was received */
-
-/* FCC Mode Register (FPSMR) as used by Ethernet.
-*/
-#define FCC_PSMR_HBC	((uint)0x80000000)	/* Enable heartbeat */
-#define FCC_PSMR_FC	((uint)0x40000000)	/* Force Collision */
-#define FCC_PSMR_SBT	((uint)0x20000000)	/* Stop backoff timer */
-#define FCC_PSMR_LPB	((uint)0x10000000)	/* Local protect. 1 = FDX */
-#define FCC_PSMR_LCW	((uint)0x08000000)	/* Late collision select */
-#define FCC_PSMR_FDE	((uint)0x04000000)	/* Full Duplex Enable */
-#define FCC_PSMR_MON	((uint)0x02000000)	/* RMON Enable */
-#define FCC_PSMR_PRO	((uint)0x00400000)	/* Promiscuous Enable */
-#define FCC_PSMR_FCE	((uint)0x00200000)	/* Flow Control Enable */
-#define FCC_PSMR_RSH	((uint)0x00100000)	/* Receive Short Frames */
-#define FCC_PSMR_CAM	((uint)0x00000400)	/* CAM enable */
-#define FCC_PSMR_BRO	((uint)0x00000200)	/* Broadcast pkt discard */
-#define FCC_PSMR_ENCRC	((uint)0x00000080)	/* Use 32-bit CRC */
-
-/* IIC parameter RAM.
-*/
-typedef struct iic {
-	ushort	iic_rbase;	/* Rx Buffer descriptor base address */
-	ushort	iic_tbase;	/* Tx Buffer descriptor base address */
-	u_char	iic_rfcr;	/* Rx function code */
-	u_char	iic_tfcr;	/* Tx function code */
-	ushort	iic_mrblr;	/* Max receive buffer length */
-	uint	iic_rstate;	/* Internal */
-	uint	iic_rdp;	/* Internal */
-	ushort	iic_rbptr;	/* Internal */
-	ushort	iic_rbc;	/* Internal */
-	uint	iic_rxtmp;	/* Internal */
-	uint	iic_tstate;	/* Internal */
-	uint	iic_tdp;	/* Internal */
-	ushort	iic_tbptr;	/* Internal */
-	ushort	iic_tbc;	/* Internal */
-	uint	iic_txtmp;	/* Internal */
-} iic_t;
-
-#define BD_IIC_START		((ushort)0x0400)
-
-#endif /* __CPM_82XX__ */
-#endif /* __KERNEL__ */
diff -urN linux-2.4.26-pre2/include/asm-ppc/immap_8260.h linux-2.4.26-pre3/include/asm-ppc/immap_8260.h
--- linux-2.4.26-pre2/include/asm-ppc/immap_8260.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ppc/immap_8260.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,433 +0,0 @@
-/*
- * MPC8260 Internal Memory Map
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
- *
- * The Internal Memory Map of the 8260.  I don't know how generic
- * this will be, as I don't have any knowledge of the subsequent
- * parts at this time.  I copied this from the 8xx_immap.h.
- */
-#ifdef __KERNEL__
-#ifndef __IMMAP_82XX__
-#define __IMMAP_82XX__
-
-/* System configuration registers.
-*/
-typedef	struct sys_conf {
-	uint	sc_siumcr;
-	uint	sc_sypcr;
-	char	res1[6];
-	ushort	sc_swsr;
-	char	res2[20];
-	uint	sc_bcr;
-	u_char	sc_ppc_acr;
-	char	res3[3];
-	uint	sc_ppc_alrh;
-	uint	sc_ppc_alrl;
-	u_char	sc_lcl_acr;
-	char	res4[3];
-	uint	sc_lcl_alrh;
-	uint	sc_lcl_alrl;
-	uint	sc_tescr1;
-	uint	sc_tescr2;
-	uint	sc_ltescr1;
-	uint	sc_ltescr2;
-	uint	sc_pdtea;
-	u_char	sc_pdtem;
-	char	res5[3];
-	uint	sc_ldtea;
-	u_char	sc_ldtem;
-	char	res6[163];
-} sysconf8260_t;
-
-
-/* Memory controller registers.
-*/
-typedef struct	mem_ctlr {
-	uint	memc_br0;
-	uint	memc_or0;
-	uint	memc_br1;
-	uint	memc_or1;
-	uint	memc_br2;
-	uint	memc_or2;
-	uint	memc_br3;
-	uint	memc_or3;
-	uint	memc_br4;
-	uint	memc_or4;
-	uint	memc_br5;
-	uint	memc_or5;
-	uint	memc_br6;
-	uint	memc_or6;
-	uint	memc_br7;
-	uint	memc_or7;
-	uint	memc_br8;
-	uint	memc_or8;
-	uint	memc_br9;
-	uint	memc_or9;
-	uint	memc_br10;
-	uint	memc_or10;
-	uint	memc_br11;
-	uint	memc_or11;
-	char	res1[8];
-	uint	memc_mar;
-	char	res2[4];
-	uint	memc_mamr;
-	uint	memc_mbmr;
-	uint	memc_mcmr;
-	char	res3[8];
-	ushort	memc_mptpr;
-	char	res4[2];
-	uint	memc_mdr;
-	char	res5[4];
-	uint	memc_psdmr;
-	uint	memc_lsdmr;
-	u_char	memc_purt;
-	char	res6[3];
-	u_char	memc_psrt;
-	char	res7[3];
-	u_char	memc_lurt;
-	char	res8[3];
-	u_char	memc_lsrt;
-	char	res9[3];
-	uint	memc_immr;
-	char	res10[84];
-} memctl8260_t;
-
-/* System Integration Timers.
-*/
-typedef struct	sys_int_timers {
-	char	res1[32];
-	ushort	sit_tmcntsc;
-	char	res2[2];
-	uint	sit_tmcnt;
-	char	res3[4];
-	uint	sit_tmcntal;
-	char	res4[16];
-	ushort	sit_piscr;
-	char	res5[2];
-	uint	sit_pitc;
-	uint	sit_pitr;
-	char	res6[94];
-	char	res7[2390];
-} sit8260_t;
-
-#define PISCR_PIRQ_MASK		((ushort)0xff00)
-#define PISCR_PS		((ushort)0x0080)
-#define PISCR_PIE		((ushort)0x0004)
-#define PISCR_PTF		((ushort)0x0002)
-#define PISCR_PTE		((ushort)0x0001)
-
-/* Interrupt Controller.
-*/
-typedef struct interrupt_controller {
-	ushort	ic_sicr;
-	char	res1[2];
-	uint	ic_sivec;
-	uint	ic_sipnrh;
-	uint	ic_sipnrl;
-	uint	ic_siprr;
-	uint	ic_scprrh;
-	uint	ic_scprrl;
-	uint	ic_simrh;
-	uint	ic_simrl;
-	uint	ic_siexr;
-	char	res2[88];
-} intctl8260_t;
-
-/* Clocks and Reset.
-*/
-typedef struct clk_and_reset {
-	uint	car_sccr;
-	char	res1[4];
-	uint	car_scmr;
-	char	res2[4];
-	uint	car_rsr;
-	uint	car_rmr;
-	char	res[104];
-} car8260_t;
-
-/* Input/Output Port control/status registers.
- * Names consistent with processor manual, although they are different
- * from the original 8xx names.......
- */
-typedef struct io_port {
-	uint	iop_pdira;
-	uint	iop_ppara;
-	uint	iop_psora;
-	uint	iop_podra;
-	uint	iop_pdata;
-	char	res1[12];
-	uint	iop_pdirb;
-	uint	iop_pparb;
-	uint	iop_psorb;
-	uint	iop_podrb;
-	uint	iop_pdatb;
-	char	res2[12];
-	uint	iop_pdirc;
-	uint	iop_pparc;
-	uint	iop_psorc;
-	uint	iop_podrc;
-	uint	iop_pdatc;
-	char	res3[12];
-	uint	iop_pdird;
-	uint	iop_ppard;
-	uint	iop_psord;
-	uint	iop_podrd;
-	uint	iop_pdatd;
-	char	res4[12];
-} iop8260_t;
-
-/* Communication Processor Module Timers
-*/
-typedef struct cpm_timers {
-	u_char	cpmt_tgcr1;
-	char	res1[3];
-	u_char	cpmt_tgcr2;
-	char	res2[11];
-	ushort	cpmt_tmr1;
-	ushort	cpmt_tmr2;
-	ushort	cpmt_trr1;
-	ushort	cpmt_trr2;
-	ushort	cpmt_tcr1;
-	ushort	cpmt_tcr2;
-	ushort	cpmt_tcn1;
-	ushort	cpmt_tcn2;
-	ushort	cpmt_tmr3;
-	ushort	cpmt_tmr4;
-	ushort	cpmt_trr3;
-	ushort	cpmt_trr4;
-	ushort	cpmt_tcr3;
-	ushort	cpmt_tcr4;
-	ushort	cpmt_tcn3;
-	ushort	cpmt_tcn4;
-	ushort	cpmt_ter1;
-	ushort	cpmt_ter2;
-	ushort	cpmt_ter3;
-	ushort	cpmt_ter4;
-	char	res3[584];
-} cpmtimer8260_t;
-
-/* DMA control/status registers.
-*/
-typedef struct sdma_csr {
-	char	res0[24];
-	u_char	sdma_sdsr;
-	char	res1[3];
-	u_char	sdma_sdmr;
-	char	res2[3];
-	u_char	sdma_idsr1;
-	char	res3[3];
-	u_char	sdma_idmr1;
-	char	res4[3];
-	u_char	sdma_idsr2;
-	char	res5[3];
-	u_char	sdma_idmr2;
-	char	res6[3];
-	u_char	sdma_idsr3;
-	char	res7[3];
-	u_char	sdma_idmr3;
-	char	res8[3];
-	u_char	sdma_idsr4;
-	char	res9[3];
-	u_char	sdma_idmr4;
-	char	res10[707];
-} sdma8260_t;
-
-/* Fast controllers
-*/
-typedef struct fcc {
-	uint	fcc_gfmr;
-	uint	fcc_fpsmr;
-	ushort	fcc_ftodr;
-	char	res1[2];
-	ushort	fcc_fdsr;
-	char	res2[2];
-	ushort	fcc_fcce;
-	char	res3[2];
-	ushort	fcc_fccm;
-	char	res4[2];
-	u_char	fcc_fccs;
-	char	res5[3];
-	u_char	fcc_ftirr_phy[4];
-} fcc_t;
-
-/* I2C
-*/
-typedef struct i2c {
-	u_char	i2c_i2mod;
-	char	res1[3];
-	u_char	i2c_i2add;
-	char	res2[3];
-	u_char	i2c_i2brg;
-	char	res3[3];
-	u_char	i2c_i2com;
-	char	res4[3];
-	u_char	i2c_i2cer;
-	char	res5[3];
-	u_char	i2c_i2cmr;
-	char	res6[331];
-} i2c8260_t;
-
-typedef struct scc {		/* Serial communication channels */
-	uint	scc_gsmrl;
-	uint	scc_gsmrh;
-	ushort	scc_pmsr;
-	char	res1[2];
-	ushort	scc_todr;
-	ushort	scc_dsr;
-	ushort	scc_scce;
-	char	res2[2];
-	ushort	scc_sccm;
-	char	res3;
-	u_char	scc_sccs;
-	char	res4[8];
-} scc_t;
-
-typedef struct smc {		/* Serial management channels */
-	char	res1[2];
-	ushort	smc_smcmr;
-	char	res2[2];
-	u_char	smc_smce;
-	char	res3[3];
-	u_char	smc_smcm;
-	char	res4[5];
-} smc_t;
-
-/* Serial Peripheral Interface.
-*/
-typedef struct spi {
-	ushort	spi_spmode;
-	char	res1[4];
-	u_char	spi_spie;
-	char	res2[3];
-	u_char	spi_spim;
-	char	res3[2];
-	u_char	spi_spcom;
-	char	res4[82];
-} spi_t;
-
-/* CPM Mux.
-*/
-typedef struct cpmux {
-	u_char	cmx_si1cr;
-	char	res1;
-	u_char	cmx_si2cr;
-	char	res2;
-	uint	cmx_fcr;
-	uint	cmx_scr;
-	u_char	cmx_smr;
-	char	res3;
-	ushort	cmx_uar;
-	char	res4[16];
-} cpmux_t;
-
-/* SIRAM control
-*/
-typedef struct siram {
-	ushort	si_amr;
-	ushort	si_bmr;
-	ushort	si_cmr;
-	ushort	si_dmr;
-	u_char	si_gmr;
-	char	res1;
-	u_char	si_cmdr;
-	char	res2;
-	u_char	si_str;
-	char	res3;
-	ushort	si_rsr;
-} siramctl_t;
-
-typedef struct mcc {
-	ushort	mcc_mcce;
-	char	res1[2];
-	ushort	mcc_mccm;
-	char	res2[2];
-	u_char	mcc_mccf;
-	char	res3[7];
-} mcc_t;
-
-typedef struct comm_proc {
-	uint	cp_cpcr;
-	uint	cp_rccr;
-	char	res1[14];
-	ushort	cp_rter;
-	char	res2[2];
-	ushort	cp_rtmr;
-	ushort	cp_rtscr;
-	char	res3[2];
-	uint	cp_rtsr;
-	char	res4[12];
-} cpm8260_t;
-
-/* ...and the whole thing wrapped up....
-*/
-typedef struct immap {
-	/* Some references are into the unique and known dpram spaces,
-	 * others are from the generic base.
-	 */
-#define im_dprambase	im_dpram1
-	u_char		im_dpram1[16*1024];
-	char		res1[16*1024];
-	u_char		im_dpram2[4*1024];
-	char		res2[8*1024];
-	u_char		im_dpram3[4*1024];
-	char		res3[16*1024];
-
-	sysconf8260_t	im_siu_conf;	/* SIU Configuration */
-	memctl8260_t	im_memctl;	/* Memory Controller */
-	sit8260_t	im_sit;		/* System Integration Timers */
-	intctl8260_t	im_intctl;	/* Interrupt Controller */
-	car8260_t	im_clkrst;	/* Clocks and reset */
-	iop8260_t	im_ioport;	/* IO Port control/status */
-	cpmtimer8260_t	im_cpmtimer;	/* CPM timers */
-	sdma8260_t	im_sdma;	/* SDMA control/status */
-
-	fcc_t		im_fcc[3];	/* Three FCCs */
-
-	char		res4[159];
-
-	/* First set of baud rate generators.
-	*/
-	char		res4a[496];
-	uint		im_brgc5;
-	uint		im_brgc6;
-	uint		im_brgc7;
-	uint		im_brgc8;
-
-	char		res5[608];
-
-	i2c8260_t	im_i2c;		/* I2C control/status */
-	cpm8260_t	im_cpm;		/* Communication processor */
-
-	/* Second set of baud rate generators.
-	*/
-	uint		im_brgc1;
-	uint		im_brgc2;
-	uint		im_brgc3;
-	uint		im_brgc4;
-
-	scc_t		im_scc[4];	/* Four SCCs */
-	smc_t		im_smc[2];	/* Couple of SMCs */
-	spi_t		im_spi;		/* A SPI */
-	cpmux_t		im_cpmux;	/* CPM clock route mux */
-	siramctl_t	im_siramctl1;	/* First SI RAM Control */
-	mcc_t		im_mcc1;	/* First MCC */
-	siramctl_t	im_siramctl2;	/* Second SI RAM Control */
-	mcc_t		im_mcc2;	/* Second MCC */
-
-	char		res6[1184];
-
-	ushort		im_si1txram[256];
-	char		res7[512];
-	ushort		im_si1rxram[256];
-	char		res8[512];
-	ushort		im_si2txram[256];
-	char		res9[512];
-	ushort		im_si2rxram[256];
-	char		res10[512];
-	char		res11[4096];
-} immap_t;
-
-extern immap_t	*immr;
-
-#endif /* __IMMAP_82XX__ */
-#endif /* __KERNEL__ */
diff -urN linux-2.4.26-pre2/include/asm-ppc/immap_cpm2.h linux-2.4.26-pre3/include/asm-ppc/immap_cpm2.h
--- linux-2.4.26-pre2/include/asm-ppc/immap_cpm2.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ppc/immap_cpm2.h	2004-03-13 07:43:23.000000000 -0800
@@ -0,0 +1,648 @@
+/*
+ * CPM2 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map for devices with CPM2 on them.  This
+ * is the superset of all CPM2 devices (8260, 8266, 8280, 8272,
+ * 8560). 
+ */
+#ifdef __KERNEL__
+#ifndef __IMMAP_CPM2__
+#define __IMMAP_CPM2__
+
+/* System configuration registers.
+*/
+typedef	struct sys_82xx_conf {
+	u32	sc_siumcr;
+	u32	sc_sypcr;
+	u8	res1[6];
+	u16	sc_swsr;
+	u8	res2[20];
+	u32	sc_bcr;
+	u8	sc_ppc_acr;
+	u8	res3[3];
+	u32	sc_ppc_alrh;
+	u32	sc_ppc_alrl;
+	u8	sc_lcl_acr;
+	u8	res4[3];
+	u32	sc_lcl_alrh;
+	u32	sc_lcl_alrl;
+	u32	sc_tescr1;
+	u32	sc_tescr2;
+	u32	sc_ltescr1;
+	u32	sc_ltescr2;
+	u32	sc_pdtea;
+	u8	sc_pdtem;
+	u8	res5[3];
+	u32	sc_ldtea;
+	u8	sc_ldtem;
+	u8	res6[163];
+} sysconf_82xx_cpm2_t;
+
+typedef	struct sys_85xx_conf {
+	u32	sc_cear;
+	u16	sc_ceer;
+	u16	sc_cemr;
+	u8	res1[70];
+	u32	sc_smaer;
+	u8	res2[4];
+	u32	sc_smevr;
+	u32	sc_smctr;
+	u32	sc_lmaer;
+	u8	res3[4];
+	u32	sc_lmevr;
+	u32	sc_lmctr;
+	u8	res4[144];
+} sysconf_85xx_cpm2_t;
+
+typedef union sys_conf {
+	sysconf_82xx_cpm2_t	siu_82xx;
+	sysconf_85xx_cpm2_t	siu_85xx;
+} sysconf_cpm2_t;
+
+
+
+/* Memory controller registers.
+*/
+typedef struct	mem_ctlr {
+	u32	memc_br0;
+	u32	memc_or0;
+	u32	memc_br1;
+	u32	memc_or1;
+	u32	memc_br2;
+	u32	memc_or2;
+	u32	memc_br3;
+	u32	memc_or3;
+	u32	memc_br4;
+	u32	memc_or4;
+	u32	memc_br5;
+	u32	memc_or5;
+	u32	memc_br6;
+	u32	memc_or6;
+	u32	memc_br7;
+	u32	memc_or7;
+	u32	memc_br8;
+	u32	memc_or8;
+	u32	memc_br9;
+	u32	memc_or9;
+	u32	memc_br10;
+	u32	memc_or10;
+	u32	memc_br11;
+	u32	memc_or11;
+	u8	res1[8];
+	u32	memc_mar;
+	u8	res2[4];
+	u32	memc_mamr;
+	u32	memc_mbmr;
+	u32	memc_mcmr;
+	u8	res3[8];
+	u16	memc_mptpr;
+	u8	res4[2];
+	u32	memc_mdr;
+	u8	res5[4];
+	u32	memc_psdmr;
+	u32	memc_lsdmr;
+	u8	memc_purt;
+	u8	res6[3];
+	u8	memc_psrt;
+	u8	res7[3];
+	u8	memc_lurt;
+	u8	res8[3];
+	u8	memc_lsrt;
+	u8	res9[3];
+	u32	memc_immr;
+	u32	memc_pcibr0;
+	u32	memc_pcibr1;
+	u8	res10[16];
+	u32	memc_pcimsk0;
+	u32	memc_pcimsk1;
+	u8	res11[52];
+} memctl_cpm2_t;
+
+/* System Integration Timers.
+*/
+typedef struct	sys_int_timers {
+	u8	res1[32];
+	u16	sit_tmcntsc;
+	u8	res2[2];
+	u32	sit_tmcnt;
+	u8	res3[4];
+	u32	sit_tmcntal;
+	u8	res4[16];
+	u16	sit_piscr;
+	u8	res5[2];
+	u32	sit_pitc;
+	u32	sit_pitr;
+	u8	res6[92];
+	u8	res7[390];
+} sit_cpm2_t;
+
+#define PISCR_PIRQ_MASK		((u16)0xff00)
+#define PISCR_PS		((u16)0x0080)
+#define PISCR_PIE		((u16)0x0004)
+#define PISCR_PTF		((u16)0x0002)
+#define PISCR_PTE		((u16)0x0001)
+
+/* PCI Controller.
+*/
+typedef struct pci_ctlr {
+	u32	pci_omisr;
+	u32	pci_omimr;
+	u8	res1[8];
+	u32	pci_ifqpr;
+	u32	pci_ofqpr;
+	u8	res2[8];
+	u32	pci_imr0;
+	u32	pci_imr1;
+	u32	pci_omr0;
+	u32	pci_omr1;
+	u32	pci_odr;
+	u8	res3[4];
+	u32	pci_idr;
+	u8	res4[20];
+	u32	pci_imisr;
+	u32	pci_imimr;
+	u8	res5[24];
+	u32	pci_ifhpr;
+	u8	res6[4];
+	u32	pci_iftpr;
+	u8	res7[4];
+	u32	pci_iphpr;
+	u8	res8[4];
+	u32	pci_iptpr;
+	u8	res9[4];
+	u32	pci_ofhpr;
+	u8	res10[4];
+	u32	pci_oftpr;
+	u8	res11[4];
+	u32	pci_ophpr;
+	u8	res12[4];
+	u32	pci_optpr;
+	u8	res13[8];
+	u32	pci_mucr;
+	u8	res14[8];
+	u32	pci_qbar;
+	u8	res15[12];
+	u32	pci_dmamr0;
+	u32	pci_dmasr0;
+	u32	pci_dmacdar0;
+	u8	res16[4];
+	u32	pci_dmasar0;
+	u8	res17[4];
+	u32	pci_dmadar0;
+	u8	res18[4];
+	u32	pci_dmabcr0;
+	u32	pci_dmandar0;
+	u8	res19[86];
+	u32	pci_dmamr1;
+	u32	pci_dmasr1;
+	u32	pci_dmacdar1;
+	u8	res20[4];
+	u32	pci_dmasar1;
+	u8	res21[4];
+	u32	pci_dmadar1;
+	u8	res22[4];
+	u32	pci_dmabcr1;
+	u32	pci_dmandar1;
+	u8	res23[88];
+	u32	pci_dmamr2;
+	u32	pci_dmasr2;
+	u32	pci_dmacdar2;
+	u8	res24[4];
+	u32	pci_dmasar2;
+	u8	res25[4];
+	u32	pci_dmadar2;
+	u8	res26[4];
+	u32	pci_dmabcr2;
+	u32	pci_dmandar2;
+	u8	res27[88];
+	u32	pci_dmamr3;
+	u32	pci_dmasr3;
+	u32	pci_dmacdar3;
+	u8	res28[4];
+	u32	pci_dmasar3;
+	u8	res29[4];
+	u32	pci_dmadar3;
+	u8	res30[4];
+	u32	pci_dmabcr3;
+	u32	pci_dmandar3;
+	u8	res31[344];
+	u32	pci_potar0;
+	u8	res32[4];
+	u32	pci_pobar0;
+	u8	res33[4];
+	u32	pci_pocmr0;
+	u8	res34[4];
+	u32	pci_potar1;
+	u8	res35[4];
+	u32	pci_pobar1;
+	u8	res36[4];
+	u32	pci_pocmr1;
+	u8	res37[4];
+	u32	pci_potar2;
+	u8	res38[4];
+	u32	pci_pobar2;
+	u8	res39[4];
+	u32	pci_pocmr2;
+	u8	res40[50];
+	u32	pci_ptcr;
+	u32	pci_gpcr;
+	u32	pci_gcr;
+	u32	pci_esr;
+	u32	pci_emr;
+	u32	pci_ecr;
+	u32	pci_eacr;
+	u8	res41[4];
+	u32	pci_edcr;
+	u8	res42[4];
+	u32	pci_eccr;
+	u8	res43[44];
+	u32	pci_pitar1;
+	u8	res44[4];
+	u32	pci_pibar1;
+	u8	res45[4];
+	u32	pci_picmr1;
+	u8	res46[4];
+	u32	pci_pitar0;
+	u8	res47[4];
+	u32	pci_pibar0;
+	u8	res48[4];
+	u32	pci_picmr0;
+	u8	res49[4];
+	u32	pci_cfg_addr;
+	u32	pci_cfg_data;
+	u32	pci_int_ack;
+	u8	res50[756];
+} pci_cpm2_t;
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+	u16	ic_sicr;
+	u8	res1[2];
+	u32	ic_sivec;
+	u32	ic_sipnrh;
+	u32	ic_sipnrl;
+	u32	ic_siprr;
+	u32	ic_scprrh;
+	u32	ic_scprrl;
+	u32	ic_simrh;
+	u32	ic_simrl;
+	u32	ic_siexr;
+	u8	res2[88];
+} intctl_cpm2_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+	u32	car_sccr;
+	u8	res1[4];
+	u32	car_scmr;
+	u8	res2[4];
+	u32	car_rsr;
+	u32	car_rmr;
+	u8	res[104];
+} car_cpm2_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+	u32	iop_pdira;
+	u32	iop_ppara;
+	u32	iop_psora;
+	u32	iop_podra;
+	u32	iop_pdata;
+	u8	res1[12];
+	u32	iop_pdirb;
+	u32	iop_pparb;
+	u32	iop_psorb;
+	u32	iop_podrb;
+	u32	iop_pdatb;
+	u8	res2[12];
+	u32	iop_pdirc;
+	u32	iop_pparc;
+	u32	iop_psorc;
+	u32	iop_podrc;
+	u32	iop_pdatc;
+	u8	res3[12];
+	u32	iop_pdird;
+	u32	iop_ppard;
+	u32	iop_psord;
+	u32	iop_podrd;
+	u32	iop_pdatd;
+	u8	res4[12];
+} iop_cpm2_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+	u8	cpmt_tgcr1;
+	u8	res1[3];
+	u8	cpmt_tgcr2;
+	u8	res2[11];
+	u16	cpmt_tmr1;
+	u16	cpmt_tmr2;
+	u16	cpmt_trr1;
+	u16	cpmt_trr2;
+	u16	cpmt_tcr1;
+	u16	cpmt_tcr2;
+	u16	cpmt_tcn1;
+	u16	cpmt_tcn2;
+	u16	cpmt_tmr3;
+	u16	cpmt_tmr4;
+	u16	cpmt_trr3;
+	u16	cpmt_trr4;
+	u16	cpmt_tcr3;
+	u16	cpmt_tcr4;
+	u16	cpmt_tcn3;
+	u16	cpmt_tcn4;
+	u16	cpmt_ter1;
+	u16	cpmt_ter2;
+	u16	cpmt_ter3;
+	u16	cpmt_ter4;
+	u8	res3[584];
+} cpmtimer_cpm2_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+	u8	res0[24];
+	u8	sdma_sdsr;
+	u8	res1[3];
+	u8	sdma_sdmr;
+	u8	res2[3];
+	u8	sdma_idsr1;
+	u8	res3[3];
+	u8	sdma_idmr1;
+	u8	res4[3];
+	u8	sdma_idsr2;
+	u8	res5[3];
+	u8	sdma_idmr2;
+	u8	res6[3];
+	u8	sdma_idsr3;
+	u8	res7[3];
+	u8	sdma_idmr3;
+	u8	res8[3];
+	u8	sdma_idsr4;
+	u8	res9[3];
+	u8	sdma_idmr4;
+	u8	res10[707];
+} sdma_cpm2_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+	u32	fcc_gfmr;
+	u32	fcc_fpsmr;
+	u16	fcc_ftodr;
+	u8	res1[2];
+	u16	fcc_fdsr;
+	u8	res2[2];
+	u16	fcc_fcce;
+	u8	res3[2];
+	u16	fcc_fccm;
+	u8	res4[2];
+	u8	fcc_fccs;
+	u8	res5[3];
+	u8	fcc_ftirr_phy[4];
+} fcc_t;
+
+/* Fast controllers continued
+ */
+typedef struct fcc_c {
+	u32	fcc_firper;
+	u32	fcc_firer;
+	u32	fcc_firsr_hi;
+	u32	fcc_firsr_lo;
+	u8	fcc_gfemr;
+	u8	res1[15];
+} fcc_c_t;
+
+/* TC Layer
+ */
+typedef struct tclayer {
+	u16	tc_tcmode;
+	u16	tc_cdsmr;
+	u16	tc_tcer;
+	u16	tc_rcc;
+	u16	tc_tcmr;
+	u16	tc_fcc;
+	u16	tc_ccc;
+	u16	tc_icc;
+	u16	tc_tcc;
+	u16	tc_ecc;
+	u8	res1[12];
+} tclayer_t;
+
+
+/* I2C
+*/
+typedef struct i2c {
+	u8	i2c_i2mod;
+	u8	res1[3];
+	u8	i2c_i2add;
+	u8	res2[3];
+	u8	i2c_i2brg;
+	u8	res3[3];
+	u8	i2c_i2com;
+	u8	res4[3];
+	u8	i2c_i2cer;
+	u8	res5[3];
+	u8	i2c_i2cmr;
+	u8	res6[331];
+} i2c_cpm2_t;
+
+typedef struct scc {		/* Serial communication channels */
+	u32	scc_gsmrl;
+	u32	scc_gsmrh;
+	u16	scc_psmr;
+	u8	res1[2];
+	u16	scc_todr;
+	u16	scc_dsr;
+	u16	scc_scce;
+	u8	res2[2];
+	u16	scc_sccm;
+	u8	res3;
+	u8	scc_sccs;
+	u8	res4[8];
+} scc_t;
+
+typedef struct smc {		/* Serial management channels */
+	u8	res1[2];
+	u16	smc_smcmr;
+	u8	res2[2];
+	u8	smc_smce;
+	u8	res3[3];
+	u8	smc_smcm;
+	u8	res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct spi_ctrl {
+	u16	spi_spmode;
+	u8	res1[4];
+	u8	spi_spie;
+	u8	res2[3];
+	u8	spi_spim;
+	u8	res3[2];
+	u8	spi_spcom;
+	u8	res4[82];
+} spictl_cpm2_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+	u8	cmx_si1cr;
+	u8	res1;
+	u8	cmx_si2cr;
+	u8	res2;
+	u32	cmx_fcr;
+	u32	cmx_scr;
+	u8	cmx_smr;
+	u8	res3;
+	u16	cmx_uar;
+	u8	res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+	u16	si_amr;
+	u16	si_bmr;
+	u16	si_cmr;
+	u16	si_dmr;
+	u8	si_gmr;
+	u8	res1;
+	u8	si_cmdr;
+	u8	res2;
+	u8	si_str;
+	u8	res3;
+	u16	si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+	u16	mcc_mcce;
+	u8	res1[2];
+	u16	mcc_mccm;
+	u8	res2[2];
+	u8	mcc_mccf;
+	u8	res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+	u32	cp_cpcr;
+	u32	cp_rccr;
+	u8	res1[14];
+	u16	cp_rter;
+	u8	res2[2];
+	u16	cp_rtmr;
+	u16	cp_rtscr;
+	u8	res3[2];
+	u32	cp_rtsr;
+	u8	res4[12];
+} cpm_cpm2_t;
+
+/* USB Controller.
+*/
+typedef struct usb_ctlr {
+	u8	usb_usmod;
+	u8	usb_usadr;
+	u8	usb_uscom;
+	u8	res1[1];
+	u16	usb_usep1;
+	u16	usb_usep2;
+	u16	usb_usep3;
+	u16	usb_usep4;
+	u8	res2[4];
+	u16	usb_usber;
+	u8	res3[2];
+	u16	usb_usbmr;
+	u8	usb_usbs;
+	u8	res4[7];
+} usb_cpm2_t;
+
+/* ...and the whole thing wrapped up....
+*/
+
+typedef struct immap {
+	/* Some references are into the unique and known dpram spaces,
+	 * others are from the generic base.
+	 */
+#define im_dprambase	im_dpram1
+	u8		im_dpram1[16*1024];
+	u8		res1[16*1024];
+	u8		im_dpram2[4*1024];
+	u8		res2[8*1024];
+	u8		im_dpram3[4*1024];
+	u8		res3[16*1024];
+
+	sysconf_cpm2_t	im_siu_conf;	/* SIU Configuration */
+	memctl_cpm2_t	im_memctl;	/* Memory Controller */
+	sit_cpm2_t	im_sit;		/* System Integration Timers */
+	pci_cpm2_t	im_pci;		/* PCI Controller */
+	intctl_cpm2_t	im_intctl;	/* Interrupt Controller */
+	car_cpm2_t	im_clkrst;	/* Clocks and reset */
+	iop_cpm2_t	im_ioport;	/* IO Port control/status */
+	cpmtimer_cpm2_t	im_cpmtimer;	/* CPM timers */
+	sdma_cpm2_t	im_sdma;	/* SDMA control/status */
+
+	fcc_t		im_fcc[3];	/* Three FCCs */
+	u8		res4z[32];
+	fcc_c_t		im_fcc_c[3];	/* Continued FCCs */
+
+	u8		res4[32];
+
+	tclayer_t	im_tclayer[8];	/* Eight TCLayers */
+	u16		tc_tcgsr;
+	u16		tc_tcger;
+	
+	/* First set of baud rate generators.
+	*/
+	u8		res[236];
+	u32		im_brgc5;
+	u32		im_brgc6;
+	u32		im_brgc7;
+	u32		im_brgc8;
+
+	u8		res5[608];
+
+	i2c_cpm2_t	im_i2c;		/* I2C control/status */
+	cpm_cpm2_t	im_cpm;		/* Communication processor */
+
+	/* Second set of baud rate generators.
+	*/
+	u32		im_brgc1;
+	u32		im_brgc2;
+	u32		im_brgc3;
+	u32		im_brgc4;
+
+	scc_t		im_scc[4];	/* Four SCCs */
+	smc_t		im_smc[2];	/* Couple of SMCs */
+	spictl_cpm2_t	im_spi;		/* A SPI */
+	cpmux_t		im_cpmux;	/* CPM clock route mux */
+	siramctl_t	im_siramctl1;	/* First SI RAM Control */
+	mcc_t		im_mcc1;	/* First MCC */
+	siramctl_t	im_siramctl2;	/* Second SI RAM Control */
+	mcc_t		im_mcc2;	/* Second MCC */
+	usb_cpm2_t	im_usb;		/* USB Controller */
+
+	u8		res6[1153];
+
+	u16		im_si1txram[256];
+	u8		res7[512];
+	u16		im_si1rxram[256];
+	u8		res8[512];
+	u16		im_si2txram[256];
+	u8		res9[512];
+	u16		im_si2rxram[256];
+	u8		res10[512];
+	u8		res11[4096];
+} cpm2_map_t;
+
+extern cpm2_map_t	*cpm2_immr;
+
+#endif /* __IMMAP_CPM2__ */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.26-pre2/include/asm-ppc/mpc8260.h linux-2.4.26-pre3/include/asm-ppc/mpc8260.h
--- linux-2.4.26-pre2/include/asm-ppc/mpc8260.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.26-pre3/include/asm-ppc/mpc8260.h	2004-03-13 07:43:23.000000000 -0800
@@ -12,10 +12,18 @@
 
 #ifdef CONFIG_8260
 
+#ifdef CONFIG_RPX6
+#include <platforms/rpx8260.h>
+#endif
+
 #ifdef CONFIG_EST8260
 #include <platforms/est8260.h>
 #endif
 
+#ifdef CONFIG_PQ2ADS
+#include <platforms/pq2ads.h>
+#endif
+
 /* I don't yet have the ISA or PCI stuff done....no 8260 with
  * such thing.....
  */
diff -urN linux-2.4.26-pre2/include/asm-ppc/ppcboot.h linux-2.4.26-pre3/include/asm-ppc/ppcboot.h
--- linux-2.4.26-pre2/include/asm-ppc/ppcboot.h	2001-11-02 17:43:54.000000000 -0800
+++ linux-2.4.26-pre3/include/asm-ppc/ppcboot.h	2004-03-13 07:43:23.000000000 -0800
@@ -52,7 +52,7 @@
 	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
 	unsigned long	bi_sramstart;	/* start of SRAM memory */
 	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
-#if defined(CONFIG_8xx) || defined(CONFIG_8260)
+#if defined(CONFIG_8xx) || defined(CONFIG_CPM2)
 	unsigned long	bi_immr_base;	/* base of IMMR register */
 #endif
 	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
@@ -61,7 +61,7 @@
 	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
 	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
 	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
-#if defined(CONFIG_8260)
+#if defined(CONFIG_CPM2)
 	unsigned long	bi_cpmfreq;	/* CPM_CLK Freq, in MHz */
 	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
 	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
diff -urN linux-2.4.26-pre2/include/linux/lockd/debug.h linux-2.4.26-pre3/include/linux/lockd/debug.h
--- linux-2.4.26-pre2/include/linux/lockd/debug.h	2001-11-22 11:47:20.000000000 -0800
+++ linux-2.4.26-pre3/include/linux/lockd/debug.h	2004-03-13 07:43:23.000000000 -0800
@@ -49,4 +49,13 @@
 #define NLMDBG_ALL		0x7fff
 
 
+/*
+ * Support for printing NLM cookies in dprintk()
+ */
+#ifdef RPC_DEBUG
+struct nlm_cookie;
+/* Call this function with the BKL held (it uses a static buffer) */
+extern const char *nlmdbg_cookie2a(const struct nlm_cookie *);
+#endif
+
 #endif /* LINUX_LOCKD_DEBUG_H */
diff -urN linux-2.4.26-pre2/include/linux/lockd/lockd.h linux-2.4.26-pre3/include/linux/lockd/lockd.h
--- linux-2.4.26-pre2/include/linux/lockd/lockd.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre3/include/linux/lockd/lockd.h	2004-03-13 07:43:23.000000000 -0800
@@ -164,7 +164,7 @@
 unsigned long	  nlmsvc_retry_blocked(void);
 int		  nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
 					int action);
-void	  nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status);
+void	  nlmsvc_grant_reply(struct svc_rqst *, struct nlm_cookie *, u32);
 
 /*
  * File handling for the server personality
diff -urN linux-2.4.26-pre2/include/linux/lockd/xdr.h linux-2.4.26-pre3/include/linux/lockd/xdr.h
--- linux-2.4.26-pre2/include/linux/lockd/xdr.h	2001-11-22 11:47:20.000000000 -0800
+++ linux-2.4.26-pre3/include/linux/lockd/xdr.h	2004-03-13 07:43:23.000000000 -0800
@@ -33,14 +33,15 @@
 };
 
 /*
- *	NLM cookies. Technically they can be 1K, Nobody uses over 8 bytes
- *	however.
+ *	NLM cookies. Technically they can be 1K, Few people use over 8 bytes,
+ *	FreeBSD uses 16, Apple Mac OS-X 10.3 uses 20.
  */
  
 struct nlm_cookie
 {
-	unsigned char data[8];
 	unsigned int len;
+#define NLM_MAXCOOKIELEN    	32
+	unsigned char data[NLM_MAXCOOKIELEN];
 };
 
 /*
diff -urN linux-2.4.26-pre2/include/linux/nfs_fs.h linux-2.4.26-pre3/include/linux/nfs_fs.h
--- linux-2.4.26-pre2/include/linux/nfs_fs.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-pre3/include/linux/nfs_fs.h	2004-03-13 07:43:23.000000000 -0800
@@ -215,7 +215,7 @@
 extern int  nfs_scan_lru_dirty(struct nfs_server *, struct list_head *);
 extern int  nfs_scan_lru_dirty_timeout(struct nfs_server *, struct list_head *);
 #ifdef CONFIG_NFS_V3
-extern int  nfs_commit_file(struct inode *, struct file *, unsigned long, unsigned int, int);
+extern int  nfs_commit_file(struct inode *, struct file *, int);
 extern int  nfs_commit_list(struct list_head *, int);
 extern int  nfs_scan_lru_commit(struct nfs_server *, struct list_head *);
 extern int  nfs_scan_lru_commit_timeout(struct nfs_server *, struct list_head *);
diff -urN linux-2.4.26-pre2/include/linux/sisfb.h linux-2.4.26-pre3/include/linux/sisfb.h
--- linux-2.4.26-pre2/include/linux/sisfb.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/include/linux/sisfb.h	2004-03-13 07:43:23.000000000 -0800
@@ -38,7 +38,8 @@
 #define TV_AVIDEO               0x00000100
 #define TV_SVIDEO               0x00000200
 #define TV_SCART                0x00000400
-#define VB_CONEXANT		0x00000800
+#define VB_CONEXANT		0x00000800	/* 661 series only */
+#define VB_TRUMPION		VB_CONEXANT	/* 300 series only */
 #define TV_PALM                 0x00001000
 #define TV_PALN                 0x00002000
 #define TV_NTSCJ		0x00001000
@@ -71,7 +72,8 @@
 #define TV_YPBPR525I		TV_NTSC
 #define TV_YPBPR525P		TV_PAL
 #define TV_YPBPR750P		TV_PALM
-#define TV_YPBPRALL 		(TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P)
+#define TV_YPBPR1080I		TV_PALN
+#define TV_YPBPRALL 		(TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P | TV_YPBPR1080I)
 
 #define VB_SISBRIDGE            (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
 #define VB_SISTVBRIDGE          (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)
@@ -121,42 +123,44 @@
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
 
 struct _SISFB_INFO {
-	unsigned long sisfb_id;         /* for identifying sisfb */
+	u32    	sisfb_id;         	/* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #endif
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which sisfb manages */
-	int    heapstart;               /* heap start (= sisfb "mem" argument) in KB */
-	unsigned char 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 */
 
-	unsigned char sisfb_version;
-	unsigned char sisfb_revision;
-	unsigned char sisfb_patchlevel;
+	u8     	sisfb_version;
+	u8     	sisfb_revision;
+	u8 	sisfb_patchlevel;
 
-	unsigned char sisfb_caps;	/* Sisfb capabilities */
+	u8 	sisfb_caps;		/* Sisfb capabilities */
 
-	int    sisfb_tqlen;		/* turbo queue length (in KB) */
+	u32    	sisfb_tqlen;		/* turbo queue length (in KB) */
 
-	unsigned int sisfb_pcibus;      /* The card's PCI ID */
-	unsigned int sisfb_pcislot;
-	unsigned int sisfb_pcifunc;
+	u32 	sisfb_pcibus;      	/* The card's PCI ID */
+	u32 	sisfb_pcislot;
+	u32 	sisfb_pcifunc;
 
-	unsigned char sisfb_lcdpdc;	/* PanelDelayCompensation */
+	u8 	sisfb_lcdpdc;		/* PanelDelayCompensation */
 
-	unsigned char sisfb_lcda;	/* Detected status of LCDA for low res/text modes */
+	u8 	sisfb_lcda;		/* Detected status of LCDA for low res/text modes */
 
-	unsigned long sisfb_vbflags;
-	unsigned long sisfb_currentvbflags;
+	u32 	sisfb_vbflags;
+	u32 	sisfb_currentvbflags;
 
-	int sisfb_scalelcd;
-	unsigned long sisfb_specialtiming;
+	u32 	sisfb_scalelcd;
+	u32 	sisfb_specialtiming;
 
-	unsigned char sisfb_haveemi;
-	unsigned char sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	unsigned char sisfb_haveemilcd;
+	u8 	sisfb_haveemi;
+	u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	u8 	sisfb_haveemilcd;
 
-	char reserved[213]; 		/* for future use */
+	u8 	sisfb_lcdpdca;		/* PanelDelayCompensation for LCD-via-CRT1 */
+
+	u8 	reserved[212]; 		/* for future use */
 };
 
 /* For fb memory manager */
@@ -221,62 +225,84 @@
 } VGA_ENGINE;
 
 struct video_info {
-	int           chip_id;
-	unsigned int  video_size;
-	unsigned long video_base;
-	char  *       video_vbase;
-	unsigned long mmio_base;
-	char  *       mmio_vbase;
-	unsigned long vga_base;
-	unsigned long mtrr;
-	unsigned long heapstart;
-
-	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 */
+	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;
+        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[200];
+	char reserved[166];
 };
 
 extern struct video_info ivideo;
diff -urN linux-2.4.26-pre2/include/linux/sysctl.h linux-2.4.26-pre3/include/linux/sysctl.h
--- linux-2.4.26-pre2/include/linux/sysctl.h	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/include/linux/sysctl.h	2004-03-13 07:43:23.000000000 -0800
@@ -313,6 +313,7 @@
 	NET_TCP_LOW_LATENCY=93,
 	NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
 	NET_TCP_WESTWOOD=95,
+	NET_IPV4_IGMP_MAX_MSF=96,
 };
 
 enum {
@@ -390,7 +391,8 @@
 	NET_IPV6_NEIGH=17,
 	NET_IPV6_ROUTE=18,
 	NET_IPV6_ICMP=19,
-	NET_IPV6_BINDV6ONLY=20
+	NET_IPV6_BINDV6ONLY=20,
+	NET_IPV6_MLD_MAX_MSF=25,
 };
 
 enum {
diff -urN linux-2.4.26-pre2/include/net/ipv6.h linux-2.4.26-pre3/include/net/ipv6.h
--- linux-2.4.26-pre2/include/net/ipv6.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-pre3/include/net/ipv6.h	2004-03-13 07:43:23.000000000 -0800
@@ -104,6 +104,7 @@
 
 /* sysctls */
 extern int sysctl_ipv6_bindv6only;
+extern int sysctl_mld_max_msf;
 
 extern struct ipv6_mib		ipv6_statistics[NR_CPUS*2];
 #define IP6_INC_STATS(field)		SNMP_INC_STATS(ipv6_statistics, field)
diff -urN linux-2.4.26-pre2/mm/mremap.c linux-2.4.26-pre3/mm/mremap.c
--- linux-2.4.26-pre2/mm/mremap.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/mm/mremap.c	2004-03-13 07:43:23.000000000 -0800
@@ -77,12 +77,16 @@
 static int move_one_page(struct mm_struct *mm, unsigned long old_addr, unsigned long new_addr)
 {
 	int error = 0;
-	pte_t * src;
+	pte_t * src, * dst;
 
 	spin_lock(&mm->page_table_lock);
 	src = get_one_pte(mm, old_addr);
-	if (src)
-		error = copy_one_pte(mm, src, alloc_one_pte(mm, new_addr));
+	if (src) {
+		dst = alloc_one_pte(mm, new_addr);
+		src = get_one_pte(mm, old_addr);
+		if (src) 
+			error = copy_one_pte(mm, src, dst);
+	}
 	spin_unlock(&mm->page_table_lock);
 	return error;
 }
diff -urN linux-2.4.26-pre2/mm/vmalloc.c linux-2.4.26-pre3/mm/vmalloc.c
--- linux-2.4.26-pre2/mm/vmalloc.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/mm/vmalloc.c	2004-03-13 07:43:23.000000000 -0800
@@ -181,6 +181,8 @@
 	flush_cache_all();
 	return 0;
 err:
+	spin_unlock(&init_mm.page_table_lock);
+	flush_cache_all();
 	if (address > start)
 		vmfree_area_pages((address - start), address - start);
 	return -ENOMEM;
diff -urN linux-2.4.26-pre2/net/ipv4/igmp.c linux-2.4.26-pre3/net/ipv4/igmp.c
--- linux-2.4.26-pre2/net/ipv4/igmp.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv4/igmp.c	2004-03-13 07:43:23.000000000 -0800
@@ -101,7 +101,8 @@
 #endif
 
 
-#define IP_MAX_MEMBERSHIPS 20
+#define IP_MAX_MEMBERSHIPS	20
+#define IP_MAX_MSF		10
 
 #ifdef CONFIG_IP_MULTICAST
 /* Parameter names and values are taken from igmp-v2-06 draft */
@@ -1311,6 +1312,7 @@
  *	Join a socket to a group
  */
 int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
+int sysctl_igmp_max_msf = IP_MAX_MSF;
 
 
 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
@@ -1772,6 +1774,10 @@
 	}
 	/* else, add a new source to the filter */
 
+	if (psl && psl->sl_count >= sysctl_igmp_max_msf) {
+		err = -ENOBUFS;
+		goto done;
+	}
 	if (!psl || psl->sl_count == psl->sl_max) {
 		struct ip_sf_socklist *newpsl;
 		int count = IP_SFBLOCK;
diff -urN linux-2.4.26-pre2/net/ipv4/ip_sockglue.c linux-2.4.26-pre3/net/ipv4/ip_sockglue.c
--- linux-2.4.26-pre2/net/ipv4/ip_sockglue.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv4/ip_sockglue.c	2004-03-13 07:43:23.000000000 -0800
@@ -609,6 +609,7 @@
 		case IP_MSFILTER:
 		{
 			extern int sysctl_optmem_max;
+			extern int sysctl_igmp_max_msf;
 			struct ip_msfilter *msf;
 
 			if (optlen < IP_MSFILTER_SIZE(0))
@@ -627,9 +628,14 @@
 				kfree(msf);
 				break;
 			}
-			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) < 
-			    IP_MSFILTER_SIZE(0) ||
-			    IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
+			/* numsrc >= (1G-4) overflow in 32 bits */
+			if (msf->imsf_numsrc >= 0x3ffffffcU ||
+			    msf->imsf_numsrc > sysctl_igmp_max_msf) {
+				kfree(msf);
+				err = -ENOBUFS;
+				break;
+			}
+			if (IP_MSFILTER_SIZE(msf->imsf_numsrc) > optlen) {
 				kfree(msf);
 				err = -EINVAL;
 				break;
@@ -756,6 +762,8 @@
 		}
 		case MCAST_MSFILTER:
 		{
+			extern int sysctl_optmem_max;
+			extern int sysctl_igmp_max_msf;
 			struct sockaddr_in *psin;
 			struct ip_msfilter *msf = 0;
 			struct group_filter *gsf = 0;
@@ -763,6 +771,10 @@
 
 			if (optlen < GROUP_FILTER_SIZE(0))
 				goto e_inval;
+			if (optlen > sysctl_optmem_max) {
+				err = -ENOBUFS;
+				break;
+			}
 			gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
 			if (gsf == 0) {
 				err = -ENOBUFS;
@@ -772,7 +784,13 @@
 			if (copy_from_user(gsf, optval, optlen)) {
 				goto mc_msf_out;
 			}
-			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) {
+			/* numsrc >= (4G-140)/128 overflow in 32 bits */
+			if (gsf->gf_numsrc >= 0x1ffffff ||
+			    gsf->gf_numsrc > sysctl_igmp_max_msf) {
+				err = -ENOBUFS;
+				goto mc_msf_out;
+			}
+			if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 				err = EINVAL;
 				goto mc_msf_out;
 			}
diff -urN linux-2.4.26-pre2/net/ipv4/ipvs/ip_vs_ctl.c linux-2.4.26-pre3/net/ipv4/ipvs/ip_vs_ctl.c
--- linux-2.4.26-pre2/net/ipv4/ipvs/ip_vs_ctl.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv4/ipvs/ip_vs_ctl.c	2004-03-13 07:43:23.000000000 -0800
@@ -1737,9 +1737,9 @@
 	 * Check for valid protocol: TCP or UDP. Even for fwmark!=0
 	 */
 	if (urule->protocol!=IPPROTO_TCP && urule->protocol!=IPPROTO_UDP) {
-		IP_VS_INFO("vs_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s",
-			   ntohs(urule->protocol), NIPQUAD(urule->vaddr),
-			   ntohs(urule->vport), urule->sched_name);
+		IP_VS_ERR("set_ctl: invalid protocol %d %d.%d.%d.%d:%d %s\n",
+			  urule->protocol, NIPQUAD(urule->vaddr),
+			  ntohs(urule->vport), urule->sched_name);
 		ret = -EFAULT;
 		goto out_unlock;
 	}
diff -urN linux-2.4.26-pre2/net/ipv4/sysctl_net_ipv4.c linux-2.4.26-pre3/net/ipv4/sysctl_net_ipv4.c
--- linux-2.4.26-pre2/net/ipv4/sysctl_net_ipv4.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv4/sysctl_net_ipv4.c	2004-03-13 07:43:23.000000000 -0800
@@ -38,6 +38,7 @@
 
 /* From igmp.c */
 extern int sysctl_igmp_max_memberships;
+extern int sysctl_igmp_max_msf;
 
 /* From inetpeer.c */
 extern int inet_peer_threshold;
@@ -185,6 +186,8 @@
 	{NET_IPV4_IGMP_MAX_MEMBERSHIPS, "igmp_max_memberships",
 	 &sysctl_igmp_max_memberships, sizeof(int), 0644, NULL, &proc_dointvec},
 #endif
+	{NET_IPV4_IGMP_MAX_MSF, "igmp_max_msf",
+	 &sysctl_igmp_max_msf, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_INET_PEER_THRESHOLD, "inet_peer_threshold",
 	 &inet_peer_threshold, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_INET_PEER_MINTTL, "inet_peer_minttl",
diff -urN linux-2.4.26-pre2/net/ipv6/ipv6_sockglue.c linux-2.4.26-pre3/net/ipv6/ipv6_sockglue.c
--- linux-2.4.26-pre2/net/ipv6/ipv6_sockglue.c	2004-03-13 07:43:21.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv6/ipv6_sockglue.c	2004-03-13 07:43:23.000000000 -0800
@@ -453,6 +453,7 @@
 	case MCAST_MSFILTER:
 	{
 		extern int sysctl_optmem_max;
+		extern int sysctl_mld_max_msf;
 		struct group_filter *gsf;
 
 		if (optlen < GROUP_FILTER_SIZE(0))
@@ -471,8 +472,14 @@
 			kfree(gsf);
 			break;
 		}
-		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < GROUP_FILTER_SIZE(0) ||
-		    GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
+		/* numsrc >= (4G-140)/128 overflow in 32 bits */
+		if (gsf->gf_numsrc >= 0x1ffffffU ||
+		    gsf->gf_numsrc > sysctl_mld_max_msf) {
+			kfree(gsf);
+			retv = -ENOBUFS;
+			break;
+		}
+		if (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
 			kfree(gsf);
 			retv = -EINVAL;
 			break;
diff -urN linux-2.4.26-pre2/net/ipv6/mcast.c linux-2.4.26-pre3/net/ipv6/mcast.c
--- linux-2.4.26-pre2/net/ipv6/mcast.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/net/ipv6/mcast.c	2004-03-13 07:43:23.000000000 -0800
@@ -163,6 +163,10 @@
 #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value)
 #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value)
 
+#define IPV6_MLD_MAX_MSF	10
+
+int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF;
+
 /*
  *	socket join on multicast group
  */
@@ -401,6 +405,10 @@
 	}
 	/* else, add a new source to the filter */
 
+	if (psl && psl->sl_count >= sysctl_mld_max_msf) {
+		err = -ENOBUFS;
+		goto done;
+	}
 	if (!psl || psl->sl_count == psl->sl_max) {
 		struct ip6_sf_socklist *newpsl;
 		int count = IP6_SFBLOCK;
diff -urN linux-2.4.26-pre2/net/ipv6/sysctl_net_ipv6.c linux-2.4.26-pre3/net/ipv6/sysctl_net_ipv6.c
--- linux-2.4.26-pre2/net/ipv6/sysctl_net_ipv6.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.26-pre3/net/ipv6/sysctl_net_ipv6.c	2004-03-13 07:43:23.000000000 -0800
@@ -24,6 +24,8 @@
 	{NET_IPV6_ICMP, "icmp", NULL, 0, 0500, ipv6_icmp_table},
 	{NET_IPV6_BINDV6ONLY, "bindv6only",
 	 &sysctl_ipv6_bindv6only, sizeof(int), 0644, NULL, &proc_dointvec},
+	{NET_IPV6_MLD_MAX_MSF, "mld_max_msf",
+	 &sysctl_mld_max_msf, sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
 };
 
diff -urN linux-2.4.26-pre2/net/sched/sch_red.c linux-2.4.26-pre3/net/sched/sch_red.c
--- linux-2.4.26-pre2/net/sched/sch_red.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-pre3/net/sched/sch_red.c	2004-03-13 07:43:23.000000000 -0800
@@ -41,9 +41,6 @@
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
 
-#define RED_ECN_ECT  0x02
-#define RED_ECN_CE   0x01
-
 
 /*	Random Early Detection (RED) algorithm.
 	=======================================
@@ -165,28 +162,16 @@
 
 	switch (skb->protocol) {
 	case __constant_htons(ETH_P_IP):
-	{
-		u8 tos = skb->nh.iph->tos;
-
-		if (!(tos & RED_ECN_ECT))
+		if (!INET_ECN_is_capable(skb->nh.iph->tos))
 			return 0;
-
-		if (!(tos & RED_ECN_CE))
+		if (INET_ECN_is_not_ce(skb->nh.iph->tos))
 			IP_ECN_set_ce(skb->nh.iph);
-
 		return 1;
-	}
-
 	case __constant_htons(ETH_P_IPV6):
-	{
-		u32 label = *(u32*)skb->nh.raw;
-
-		if (!(label & __constant_htonl(RED_ECN_ECT<<20)))
+		if (!INET_ECN_is_capable(ip6_get_dsfield(skb->nh.ipv6h)))
 			return 0;
-		label |= __constant_htonl(RED_ECN_CE<<20);
+		IP6_ECN_set_ce(skb->nh.ipv6h);
 		return 1;
-	}
-
 	default:
 		return 0;
 	}
