patch-2.4.15 linux/drivers/video/sis/sis_main.c

Next file: linux/drivers/video/sis/sis_main.h
Previous file: linux/drivers/video/sis/sis_301.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.14/linux/drivers/video/sis/sis_main.c linux/drivers/video/sis/sis_main.c
@@ -1,5 +1,5 @@
 /*
- * SiS 300/630/540 frame buffer device For Kernal 2.4.x
+ * SiS 300/630/540/315H/315 frame buffer device For Kernal 2.4.x
  *
  * This driver is partly based on the VBE 2.0 compliant graphic 
  * boards framebuffer driver, which is 
@@ -8,7 +8,7 @@
  *
  */
 
-#undef  SISFBDEBUG
+//#undef SISFBDEBUG
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -27,10 +27,13 @@
 #include <linux/pci.h>
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
-#include <linux/sisfb.h>
 #include <linux/fs.h>
+#include <linux/agp_backend.h>
+#include <linux/types.h>
+#include <linux/sisfb.h>
 
 #include <asm/io.h>
+#include <asm/mtrr.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -38,568 +41,543 @@
 #include <video/fbcon-cfb24.h>
 #include <video/fbcon-cfb32.h>
 
-#include "sis.h"
-#ifdef NOBIOS
-#include "bios.h"
-#endif
-
-/* ------------------- Constant Definitions ------------------------- */
-
-/* capabilities */
-#define TURBO_QUEUE_CAP      0x80
-#define HW_CURSOR_CAP        0x40
+#include "osdef.h"
+#include "vgatypes.h"
+#include "sis_main.h"
 
-/* VGA register Offsets */
-#define SEQ_ADR                   (0x14)
-#define SEQ_DATA                  (0x15)
-#define DAC_ADR                   (0x18)
-#define DAC_DATA                  (0x19)
-#define CRTC_ADR                  (0x24)
-#define CRTC_DATA                 (0x25)
+/* -------------------- Macro definitions ---------------------------- */
 
-#define DAC2_ADR                   0x16 - 0x30
-#define DAC2_DATA                  0x17 - 0x30
-
-
-/* SiS indexed register indexes */
-#define IND_SIS_PASSWORD          (0x05)
-#define IND_SIS_DRAM_SIZE         (0x14)
-#define IND_SIS_MODULE_ENABLE     (0x1E)
-#define IND_SIS_PCI_ADDRESS_SET   (0x20)
-#define IND_SIS_TURBOQUEUE_ADR    (0x26)
-#define IND_SIS_TURBOQUEUE_SET    (0x27)
-
-/* Sis register value */
-#define SIS_PASSWORD              (0x86)
-
-#define SIS_2D_ENABLE             (0x40)
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
 
-#define SIS_MEM_MAP_IO_ENABLE     (0x01)
-#define SIS_PCI_ADDR_ENABLE       (0x80)
+#define vgawb(reg,data) \
+           (outb(data, ivideo.vga_base+reg))
+#define vgaww(reg,data) \
+           (outw(data, ivideo.vga_base+reg))
+#define vgawl(reg,data) \
+           (outl(data, ivideo.vga_base+reg))
+#define vgarb(reg)      \
+           (inb(ivideo.vga_base+reg))
 
-//#define MMIO_SIZE                 0x10000	/* 64K MMIO capability */
-#define MAX_ROM_SCAN              0x10000
+/* --------------- Hardware Access Routines -------------------------- */
 
-#define RESERVED_MEM_SIZE_4M      0x400000	/* 4M */
-#define RESERVED_MEM_SIZE_8M      0x800000	/* 8M */
+void sisfb_set_reg1 (u16 port, u16 index, u16 data)
+{
+	outb ((u8) (index & 0xff), port);
+	port++;
+	outb ((u8) (data & 0xff), port);
+}
 
-/* Mode set stuff */
-#define DEFAULT_MODE         0	/* 640x480x8 */
-#define DEFAULT_LCDMODE      9	/* 800x600x8 */
-#define DEFAULT_TVMODE       9	/* 800x600x8 */
+void sisfb_set_reg3 (u16 port, u16 data)
+{
+	outb ((u8) (data & 0xff), port);
+}
 
-/* heap stuff */
-#define OH_ALLOC_SIZE         4000
-#define SENTINEL              0x7fffffff
+void sisfb_set_reg4 (u16 port, unsigned long data)
+{
+	outl ((u32) (data & 0xffffffff), port);
+}
 
-#define TURBO_QUEUE_AREA_SIZE 0x80000	/* 512K */
-#define HW_CURSOR_AREA_SIZE   0x1000	/* 4K */
+u8 sisfb_get_reg1 (u16 port, u16 index)
+{
+	u8 data;
 
-/* ------------------- Global Variables ----------------------------- */
+	outb ((u8) (index & 0xff), port);
+	port += 1;
+	data = inb (port);
+	return (data);
+}
 
-struct video_info ivideo;
-HW_DEVICE_EXTENSION HwExt={0,0,0,0,0,0};
+u8 sisfb_get_reg2 (u16 port)
+{
+	u8 data;
 
-struct GlyInfo {
-	unsigned char ch;
-	int fontwidth;
-	int fontheight;
-	u8 gmask[72];
-	int ngmask;
-};
+	data = inb (port);
 
-/* Supported SiS Chips list */
-static struct board {
-	u16 vendor, device;
-	const char *name;
-} dev_list[] = {
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,     "SIS 300"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, "SIS 540"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, "SIS 630"},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730_VGA, "SIS 730"},
-	{0, 0, NULL}
-};
+	return (data);
+}
 
-/* card parameters */
-unsigned long rom_base;
-unsigned long rom_vbase;
-
-/* mode */
-static int video_type = FB_TYPE_PACKED_PIXELS;
-static int video_linelength;
-static int video_cmap_len;
-static int sisfb_off = 0;
-static int crt1off = 0;
-
-static struct fb_var_screeninfo default_var = {
-	0, 0, 0, 0,
-	0, 0,
-	0,
-	0,
-	{0, 8, 0},
-	{0, 8, 0},
-	{0, 8, 0},
-	{0, 0, 0},
-	0,
-	FB_ACTIVATE_NOW, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
-	0,
-	FB_VMODE_NONINTERLACED,
-	{0, 0, 0, 0, 0, 0}
-};
+u32 sisfb_get_reg3 (u16 port)
+{
+	u32 data;
 
-static struct display disp;
-static struct fb_info fb_info;
-static struct {
-	u16 blue, green, red, pad;
-} palette[256];
-static union {
-#ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB24
-	u32 cfb24[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
-#endif
-} fbcon_cmap;
+	data = inl (port);
+	return (data);
+}
 
-static int inverse = 0;
-static int currcon = 0;
+/* --------------- Interface to BIOS code ---------------------------- */
 
-static struct display_switch sisfb_sw;
+BOOLEAN sisfb_query_VGA_config_space (PSIS_HW_DEVICE_INFO psishw_ext,
+			      unsigned long offset, unsigned long set,
+			      unsigned long *value)
+{
+	static struct pci_dev *pdev = NULL;
+	static unsigned char init = 0, valid_pdev = 0;
 
-static u8 caps = 0;
-static unsigned long MMIO_SIZE = 0;
-
-/* ModeSet stuff */
-unsigned char  uDispType = 0;
-int mode_idx = -1;
-u8 mode_no = 0;
-u8 rate_idx = 0;
-
-static const struct _sisbios_mode {
-	char name[15];
-	u8 mode_no;
-	u16 xres;
-	u16 yres;
-	u16 bpp;
-	u16 rate_idx;
-	u16 cols;
-	u16 rows;
-} sisbios_mode[] = {
-	{"640x480x8",    0x2E,  640,  480,  8, 1,  80, 30},
-	{"640x480x16",   0x44,  640,  480, 16, 1,  80, 30},
-	{"640x480x32",   0x62,  640,  480, 32, 1,  80, 30},
-	{"720x480x8",    0x31,  720,  480,  8, 1,  90, 30}, 	/* NTSC TV */
-	{"720x480x16",   0x33,  720,  480, 16, 1,  90, 30}, 
-	{"720x480x32",   0x35,  720,  480, 32, 1,  90, 30}, 
-	{"720x576x8",    0x32,  720,  576,  8, 1,  90, 36}, 	/* PAL TV */
-	{"720x576x16",   0x34,  720,  576, 16, 1,  90, 36}, 
-	{"720x576x32",   0x36,  720,  576, 32, 1,  90, 36}, 
-	{"800x600x8",    0x30,  800,  600,  8, 2, 100, 37},
-	{"800x600x16",   0x47,  800,  600, 16, 2, 100, 37},
-	{"800x600x32",   0x63,  800,  600, 32, 2, 100, 37}, 
-	{"1024x768x8",   0x38, 1024,  768,  8, 2, 128, 48},
-	{"1024x768x16",  0x4A, 1024,  768, 16, 2, 128, 48},
-	{"1024x768x32",  0x64, 1024,  768, 32, 2, 128, 48},
-	{"1280x1024x8",  0x3A, 1280, 1024,  8, 2, 160, 64},
-	{"1280x1024x16", 0x4D, 1280, 1024, 16, 2, 160, 64},
-	{"1280x1024x32", 0x65, 1280, 1024, 32, 2, 160, 64},
-	{"1600x1200x8",  0x3C, 1600, 1200,  8, 1, 200, 75},
-	{"1600x1200x16", 0x3D, 1600, 1200, 16, 1, 200, 75},
-	{"1600x1200x32", 0x66, 1600, 1200, 32, 1, 200, 75},
-	{"1920x1440x8",  0x68, 1920, 1440,  8, 1, 240, 75},
-	{"1920x1440x16", 0x69, 1920, 1440, 16, 1, 240, 75},
-	{"1920x1440x32", 0x6B, 1920, 1440, 32, 1, 240, 75},
-	{"\0", 0x00, 0, 0, 0, 0, 0, 0}
-};
+	if (!set)
+		DPRINTK ("Get VGA offset 0x%lx\n", offset);
+	else
+		DPRINTK ("Set offset 0x%lx to 0x%lx\n", offset, *value);
 
-static struct _vrate {
-	u16 idx;
-	u16 xres;
-	u16 yres;
-	u16 refresh;
-} vrate[] = {
-	{1,  640,  480,  60}, {2,  640, 480,  72}, {3,  640, 480,  75}, {4,  640, 480,  85},
-	{5,  640,  480, 100}, {6,  640, 480, 120}, {7,  640, 480, 160}, {8,  640, 480, 200},
-	{1,  720,  480,  60},
-	{1,  720,  576,  50},
-	{1,  800,  600,  56}, {2,  800, 600,  60}, {3,  800, 600,  72}, {4,  800, 600,  75},
-	{5,  800,  600,  85}, {6,  800, 600, 100}, {7,  800, 600, 120}, {8,  800, 600, 160},
-	{1, 1024,  768,  43}, {2, 1024, 768,  60}, {3, 1024, 768,  70}, {4, 1024, 768,  75},
-	{5, 1024,  768,  85}, {6, 1024, 768, 100}, {7, 1024, 768, 120},
-	{1, 1280, 1024,  43}, {2, 1280, 1024, 60}, {3, 1280, 1024, 75}, {4, 1280, 1024, 85},
-	{1, 1600, 1200,  60}, {2, 1600, 1200, 65}, {3, 1600, 1200, 70}, {4, 1600, 1200, 75},
-	{5, 1600, 1200,  85},
-	{1, 1920, 1440,  60},
-	{0, 0, 0, 0}
-};
+	if (!init) {
+		init = TRUE;
+		pci_for_each_dev (pdev) {
+			DPRINTK ("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 "Can't find SiS %d VGA device.\n",
+			ivideo.chip_id);
+		return FALSE;
+	}
 
-/* HEAP stuff */
+	if (set == 0)
+		pci_read_config_dword (pdev, offset, (u32 *) value);
+	else
+		pci_write_config_dword (pdev, offset, (u32) (*value));
 
-struct OH {
-	struct OH *pohNext;
-	struct OH *pohPrev;
-	unsigned long ulOffset;
-	unsigned long ulSize;
-};
+	return TRUE;
+}
 
-struct OHALLOC {
-	struct OHALLOC *pohaNext;
-	struct OH aoh[1];
-};
+BOOLEAN sisfb_query_north_bridge_space (PSIS_HW_DEVICE_INFO psishw_ext,
+				unsigned long offset, unsigned long set,
+				unsigned long *value)
+{
+	static struct pci_dev *pdev = NULL;
+	static unsigned char init = 0, valid_pdev = 0;
+	u16 nbridge_id = 0;
 
-struct HEAP {
-	struct OH ohFree;
-	struct OH ohUsed;
-	struct OH *pohFreeList;
-	struct OHALLOC *pohaChain;
+	if (!init) {
+		init = TRUE;
+		switch (ivideo.chip) {
+		case SIS_540:
+			nbridge_id = PCI_DEVICE_ID_SI_540;
+			break;
+		case SIS_630:
+			nbridge_id = PCI_DEVICE_ID_SI_630;
+			break;
+		case SIS_730:
+			nbridge_id = PCI_DEVICE_ID_SI_730;
+			break;
+		case SIS_550:
+			nbridge_id = PCI_DEVICE_ID_SI_550;
+			break;
+		default:
+			nbridge_id = 0;
+			break;
+		}
 
-	unsigned long ulMaxFreeSize;
-};
+		pci_for_each_dev (pdev) {
+			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;
+			}
+		}
+	}
 
-struct HEAP heap;
-unsigned long heap_start;
-unsigned long heap_end;
-unsigned long heap_size;
+	if (!valid_pdev) {
+		printk (KERN_DEBUG "Can't find SiS %d North Bridge device.\n",
+			nbridge_id);
+		return FALSE;
+	}
 
-unsigned int tqueue_pos;
-unsigned long hwcursor_vbase;
+	if (set == 0)
+		pci_read_config_dword (pdev, offset, (u32 *) value);
+	else
+		pci_write_config_dword (pdev, offset, (u32) (*value));
 
+	return TRUE;
+}
 
-/* -------------------- Macro definitions --------------------------- */
+/* -------------------- Export functions ----------------------------- */
 
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
+static void sis_get_glyph (SIS_GLYINFO * gly)
+{
+	struct display *p = &fb_display[currcon];
+	u16 c;
+	u8 *cdat;
+	int widthb;
+	u8 *gbuf = gly->gmask;
+	int size;
 
-#define vgawb(reg,data) \
-           (outb(data, ivideo.vga_base+reg))
-#define vgaww(reg,data) \
-           (outw(data, ivideo.vga_base+reg))
-#define vgawl(reg,data) \
-           (outl(data, ivideo.vga_base+reg))
-#define vgarb(reg)      \
-           (inb(ivideo.vga_base+reg))
+	gly->fontheight = fontheight (p);
+	gly->fontwidth = fontwidth (p);
+	widthb = (fontwidth (p) + 7) / 8;
 
-/* ---------------------- Routine Prototype ------------------------- */
+	c = gly->ch & p->charmask;
+	if (fontwidth (p) <= 8)
+		cdat = p->fontdata + c * fontheight (p);
+	else
+		cdat = p->fontdata + (c * fontheight (p) << 1);
 
-/* Interface used by the world */
-int sisfb_setup(char *options);
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info);
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg, int con,
-		       struct fb_info *info);
+	size = fontheight (p) * widthb;
+	memcpy (gbuf, cdat, size);
+	gly->ngmask = size;
+}
 
-/* Interface to the low level console driver */
-int sisfb_init(void);
-static int sisfb_update_var(int con, struct fb_info *info);
-static int sisfb_switch(int con, struct fb_info *info);
-static void sisfb_blank(int blank, struct fb_info *info);
+void sis_dispinfo (struct ap_data *rec)
+{
+	rec->minfo.bpp = ivideo.video_bpp;
+	rec->minfo.xres = ivideo.video_width;
+	rec->minfo.yres = ivideo.video_height;
+	rec->minfo.v_xres = ivideo.video_vwidth;
+	rec->minfo.v_yres = ivideo.video_vheight;
+	rec->minfo.org_x = ivideo.org_x;
+	rec->minfo.org_y = ivideo.org_y;
+	rec->minfo.vrate = ivideo.refresh_rate;
+	rec->iobase = ivideo.vga_base - 0x30;
+	rec->mem_size = ivideo.video_size;
+	rec->disp_state = ivideo.disp_state;
+	rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
+	rec->hasVB = ivideo.hasVB;
+	rec->TV_type = ivideo.TV_type;
+	rec->TV_plug = ivideo.TV_plug;
+	rec->chip = ivideo.chip;
+}
 
-/* Internal routines */
-static void crtc_to_var(struct fb_var_screeninfo *var);
-static void sisfb_set_disp(int con, struct fb_var_screeninfo *var);
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			 unsigned *blue, unsigned *transp,
-			 struct fb_info *fb_info);
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green,
-			 unsigned blue, unsigned transp,
-			 struct fb_info *fb_info);
-static void do_install_cmap(int con, struct fb_info *info);
-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
-		      struct fb_info *info);
+/* ------------------ Internal Routines ------------------------------ */
 
-/* set-mode routines */
-void SetReg1(u16 port, u16 index, u16 data);
-void SetReg3(u16 port, u16 data);
-void SetReg4(u16 port, unsigned long data);
-u8 GetReg1(u16 port, u16 index);
-u8 GetReg2(u16 port);
-u32 GetReg3(u16 port);
-extern BOOLEAN SiSSetMode(PHW_DEVICE_EXTENSION HwDeviceExtension,
-				USHORT ModeNo);
-extern BOOLEAN SiSInit300(PHW_DEVICE_EXTENSION HwDeviceExtension);
-static void pre_setmode(void);
-static void post_setmode(void);
-static void search_mode(const char *name);
-static u8 search_refresh_rate(unsigned int rate);
+static void sisfb_search_mode (const char *name)
+{
+	int i = 0;
 
-/* heap routines */
-static int sisfb_heap_init(void);
-static struct OH *poh_new_node(void);
-static struct OH *poh_allocate(unsigned long size);
-static struct OH *poh_free(unsigned long base);
-static void delete_node(struct OH *poh);
-static void insert_node(struct OH *pohList, struct OH *poh);
-static void free_node(struct OH *poh);
+	if (name == NULL)
+		return;
 
-/* ---------------------- Internal Routines ------------------------- */
+	while (sisbios_mode[i].mode_no != 0) {
+		if (!strcmp (name, sisbios_mode[i].name)) {
+			sisfb_mode_idx = i;
+			break;
+		}
+		i++;
+	}
 
-inline static u32 RD32(unsigned char *base, s32 off)
-{
-	return readl(base + off);
+	if (sisfb_mode_idx < 0)
+		DPRINTK ("Invalid user mode : %s\n", name);
 }
 
-inline static void WR32(unsigned char *base, s32 off, u32 v)
+static void sisfb_validate_mode (void)
 {
-	writel(v, base + off);
-}
+	switch (ivideo.disp_state & DISPTYPE_DISP2) {
+	case DISPTYPE_LCD:
+// Eden Chen
+		switch (sishw_ext.ulCRT2LCDType) {
+		case LCD_1024x768:
+			if (sisbios_mode[sisfb_mode_idx].xres > 1024)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_1280x1024:
+		case LCD_1280x960:
+			if (sisbios_mode[sisfb_mode_idx].xres > 1280)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_2048x1536:
+			if (sisbios_mode[sisfb_mode_idx].xres > 2048)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_1920x1440:
+			if (sisbios_mode[sisfb_mode_idx].xres > 1920)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_1600x1200:
+			if (sisbios_mode[sisfb_mode_idx].xres > 1600)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_800x600:
+			if (sisbios_mode[sisfb_mode_idx].xres > 800)
+				sisfb_mode_idx = -1;
+			break;
+		case LCD_640x480:
+			if (sisbios_mode[sisfb_mode_idx].xres > 640)
+				sisfb_mode_idx = -1;
+			break;
+		default:
+			sisfb_mode_idx = -1;
+		}
+// ~Eden Chen
 
-inline static void WR16(unsigned char *base, s32 off, u16 v)
-{
-	writew(v, base + off);
+		if (sisbios_mode[sisfb_mode_idx].xres == 720)
+			sisfb_mode_idx = -1;
+		break;
+	case DISPTYPE_TV:
+		switch (sisbios_mode[sisfb_mode_idx].xres) {
+		case 800:
+		case 640:
+			break;
+		case 720:
+			if (ivideo.TV_type == TVMODE_NTSC) {
+				if (sisbios_mode[sisfb_mode_idx].yres != 480)
+					sisfb_mode_idx = -1;
+			} else if (ivideo.TV_type == TVMODE_PAL) {
+				if (sisbios_mode[sisfb_mode_idx].yres != 576)
+					sisfb_mode_idx = -1;
+			}
+			break;
+			/*karl */
+		case 1024:
+			if (ivideo.TV_type == TVMODE_NTSC) {
+				if (sisbios_mode[sisfb_mode_idx].bpp == 32)
+					sisfb_mode_idx -= 1;
+			}
+			break;
+		default:
+			sisfb_mode_idx = -1;
+		}
+		break;
+	}
 }
 
-inline static void WR8(unsigned char *base, s32 off, u8 v)
+static u8 sisfb_search_refresh_rate (unsigned int rate)
 {
-	writeb(v, base + off);
-}
+	u16 xres, yres;
+	int i = 0;
 
-inline static u32 regrl(s32 off)
-{
-	return RD32(ivideo.mmio_vbase, off);
-}
+	xres = sisbios_mode[sisfb_mode_idx].xres;
+	yres = sisbios_mode[sisfb_mode_idx].yres;
 
-inline static void regwl(s32 off, u32 v)
-{
-	WR32(ivideo.mmio_vbase, off, v);
-}
+	sisfb_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;
+				break;
+			} else if (sisfb_vrate[i].refresh > rate) {
+				if ((sisfb_vrate[i].refresh - rate) <= 2) {
+					DPRINTK
+					    ("Adjust rate from %d up to %d\n",
+					     rate, sisfb_vrate[i].refresh);
+					sisfb_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("Adjust rate from %d down to %d\n",
+					     rate, sisfb_vrate[i - 1].refresh);
+					sisfb_rate_idx = sisfb_vrate[i - 1].idx;
+					ivideo.refresh_rate = sisfb_vrate[i - 1].refresh;
+				}
+				break;
+			}
+		}
+		i++;
+	}
+
+	if (sisfb_rate_idx > 0) {
+		return sisfb_rate_idx;
+	} else {
+		DPRINTK ("Unsupported rate %d for %dx%d mode\n", rate, xres,
+			 yres);
+		return 0;
+	}
 
-inline static void regww(s32 off, u16 v)
-{
-	WR16(ivideo.mmio_vbase, off, v);
 }
 
-inline static void regwb(s32 off, u8 v)
+static int sis_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
+	       unsigned *transp, struct fb_info *fb_info)
 {
-	WR8(ivideo.mmio_vbase, off, v);
+	if (regno >= video_cmap_len)
+		return 1;
+
+	*red = palette[regno].red;
+	*green = palette[regno].green;
+	*blue = palette[regno].blue;
+	*transp = 0;
+	return 0;
 }
 
-/* 
- *    Get CRTC registers to set var 
- */
-static void crtc_to_var(struct fb_var_screeninfo *var)
+static int sis_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+	       unsigned transp, struct fb_info *fb_info)
 {
-	u16 VRE, VBE, VRS, VBS, VDE, VT;
-	u16 HRE, HBE, HRS, HBS, HDE, HT;
-	u8 uSRdata, uCRdata, uCRdata2, uCRdata3, uMRdata;
-	int A, B, C, D, E, F, temp;
-	double hrate, drate;
-
-	vgawb(SEQ_ADR, 0x6);
-	uSRdata = vgarb(SEQ_DATA);
 
-	if (uSRdata & 0x20)
-		var->vmode = FB_VMODE_INTERLACED;
-	else
-		var->vmode = FB_VMODE_NONINTERLACED;
+	if (regno >= video_cmap_len)
+		return 1;
 
-	switch ((uSRdata & 0x1c) >> 2) {
-	case 0:
-		var->bits_per_pixel = 8;
-		break;
-	case 2:
-		var->bits_per_pixel = 16;
-		break;
-	case 4:
-		var->bits_per_pixel = 32;
-		break;
-	}
+	palette[regno].red = red;
+	palette[regno].green = green;
+	palette[regno].blue = blue;
 
-	switch (var->bits_per_pixel) {
+	switch (ivideo.video_bpp) {
+#ifdef FBCON_HAS_CFB8
 	case 8:
-		var->red.length = 6;
-		var->green.length = 6;
-		var->blue.length = 6;
-		video_cmap_len = 256;
-		break;
-	case 16:		/* RGB 565 */
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		video_cmap_len = 16;
+		vgawb (DAC_ADR, regno);
+		vgawb (DAC_DATA, red >> 10);
+		vgawb (DAC_DATA, green >> 10);
+		vgawb (DAC_DATA, blue >> 10);
+		if (ivideo.disp_state & DISPTYPE_DISP2) {
+			vgawb (DAC2_ADR, regno);
+			vgawb (DAC2_DATA, red >> 8);
+			vgawb (DAC2_DATA, green >> 8);
+			vgawb (DAC2_DATA, blue >> 8);
+		}
 
 		break;
-	case 24:		/* RGB 888 */
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		video_cmap_len = 16;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 15:
+	case 16:
+		fbcon_cmap.cfb16[regno] =
+		    ((red & 0xf800)) |
+		    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+		fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue);
 		break;
+#endif
+#ifdef FBCON_HAS_CFB32
 	case 32:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		video_cmap_len = 16;
+		red >>= 8;
+		green >>= 8;
+		blue >>= 8;
+		fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
 		break;
+#endif
 	}
+	return 0;
+}
 
-	vgawb(SEQ_ADR, 0xa);
-	uSRdata = vgarb(SEQ_DATA);
-
-	vgawb(CRTC_ADR, 0x6);
-	uCRdata = vgarb(CRTC_DATA);
-	vgawb(CRTC_ADR, 0x7);
-	uCRdata2 = vgarb(CRTC_DATA);
-	VT =
-	    (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x01) << 8) |
-	    ((u16) (uCRdata2 & 0x20) << 4) | ((u16) (uSRdata & 0x01) <<
-					      10);
-	A = VT + 2;
-
-	vgawb(CRTC_ADR, 0x12);
-	uCRdata = vgarb(CRTC_DATA);
-	VDE =
-	    (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x02) << 7) |
-	    ((u16) (uCRdata2 & 0x40) << 3) | ((u16) (uSRdata & 0x02) << 9);
-	E = VDE + 1;
-
-	vgawb(CRTC_ADR, 0x10);
-	uCRdata = vgarb(CRTC_DATA);
-	VRS =
-	    (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x04) << 6) |
-	    ((u16) (uCRdata2 & 0x80) << 2) | ((u16) (uSRdata & 0x08) << 7);
-	F = VRS + 1 - E;
-
-	vgawb(CRTC_ADR, 0x15);
-	uCRdata = vgarb(CRTC_DATA);
-	vgawb(CRTC_ADR, 0x9);
-	uCRdata3 = vgarb(CRTC_DATA);
-	VBS =
-	    (uCRdata & 0xff) | ((u16) (uCRdata2 & 0x08) << 5) |
-	    ((u16) (uCRdata3 & 0x20) << 4) | ((u16) (uSRdata & 0x04) << 8);
-
-	vgawb(CRTC_ADR, 0x16);
-	uCRdata = vgarb(CRTC_DATA);
-	VBE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x10) << 4);
-	temp = VBE - ((E - 1) & 511);
-	B = (temp > 0) ? temp : (temp + 512);
-
-	vgawb(CRTC_ADR, 0x11);
-	uCRdata = vgarb(CRTC_DATA);
-	VRE = (uCRdata & 0x0f) | ((uSRdata & 0x20) >> 1);
-	temp = VRE - ((E + F - 1) & 31);
-	C = (temp > 0) ? temp : (temp + 32);
-
-	D = B - F - C;
-
-	var->yres = var->yres_virtual = E;
-	var->upper_margin = D;
-	var->lower_margin = F;
-	var->vsync_len = C;
-
-	vgawb(SEQ_ADR, 0xb);
-	uSRdata = vgarb(SEQ_DATA);
-
-	vgawb(CRTC_ADR, 0x0);
-	uCRdata = vgarb(CRTC_DATA);
-	HT = (uCRdata & 0xff) | ((u16) (uSRdata & 0x03) << 8);
-	A = HT + 5;
-
-	vgawb(CRTC_ADR, 0x1);
-	uCRdata = vgarb(CRTC_DATA);
-	HDE = (uCRdata & 0xff) | ((u16) (uSRdata & 0x0C) << 6);
-	E = HDE + 1;
+static int sisfb_do_set_var (struct fb_var_screeninfo *var, int isactive,
+		  struct fb_info *info)
+{
+	unsigned int htotal =
+	    var->left_margin + var->xres + var->right_margin + var->hsync_len;
+	unsigned int vtotal =
+	    var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
+	double drate = 0, hrate = 0;
+	int found_mode = 0;
+	int old_mode;
 
-	vgawb(CRTC_ADR, 0x4);
-	uCRdata = vgarb(CRTC_DATA);
-	HRS = (uCRdata & 0xff) | ((u16) (uSRdata & 0xC0) << 2);
-	F = HRS - E - 3;
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+		vtotal <<= 1;
+	else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+		vtotal <<= 2;
+	else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		var->yres <<= 1;
 
-	vgawb(CRTC_ADR, 0x2);
-	uCRdata = vgarb(CRTC_DATA);
-	HBS = (uCRdata & 0xff) | ((u16) (uSRdata & 0x30) << 4);
-
-	vgawb(SEQ_ADR, 0xc);
-	uSRdata = vgarb(SEQ_DATA);
-	vgawb(CRTC_ADR, 0x3);
-	uCRdata = vgarb(CRTC_DATA);
-	vgawb(CRTC_ADR, 0x5);
-	uCRdata2 = vgarb(CRTC_DATA);
-	HBE =
-	    (uCRdata & 0x1f) | ((u16) (uCRdata2 & 0x80) >> 2) |
-	    ((u16) (uSRdata & 0x03) << 6);
-	HRE = (uCRdata2 & 0x1f) | ((uSRdata & 0x04) << 3);
+	if (!htotal || !vtotal) {
+		DPRINTK ("Invalid 'var' Information!\n");
+		return -EINVAL;
+	}
 
-	temp = HBE - ((E - 1) & 255);
-	B = (temp > 0) ? temp : (temp + 256);
+	drate = 1E12 / var->pixclock;
+	hrate = drate / htotal;
+	ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
 
-	temp = HRE - ((E + F + 3) & 63);
-	C = (temp > 0) ? temp : (temp + 64);
+	DPRINTK ("Chagne mode to %dx%dx%d-%dMHz\n",
+		 var->xres, var->yres, var->bits_per_pixel,
+		 ivideo.refresh_rate);
+
+	old_mode = sisfb_mode_idx;
+	sisfb_mode_idx = 0;
+
+	while ((sisbios_mode[sisfb_mode_idx].mode_no != 0)
+	       && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) {
+		if ((sisbios_mode[sisfb_mode_idx].xres == var->xres)
+		    && (sisbios_mode[sisfb_mode_idx].yres == var->yres)
+		    && (sisbios_mode[sisfb_mode_idx].bpp ==
+			var->bits_per_pixel)) {
+			sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+			found_mode = 1;
+			break;
+		}
+		sisfb_mode_idx++;
+	}
 
-	D = B - F - C;
+	if (found_mode)
+		sisfb_validate_mode ();
+	else
+		sisfb_mode_idx = -1;
 
-	var->xres = var->xres_virtual = E * 8;
-	var->left_margin = D * 8;
-	var->right_margin = F * 8;
-	var->hsync_len = C * 8;
+	if (sisfb_mode_idx < 0) {
+		DPRINTK ("sisfb does not support mode %dx%d-%d\n", var->xres,
+			 var->yres, var->bits_per_pixel);
+		sisfb_mode_idx = old_mode;
+		return -EINVAL;
+	}
 
-	var->activate = FB_ACTIVATE_NOW;
+	if (sisfb_search_refresh_rate (ivideo.refresh_rate) == 0) {
+		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
+		ivideo.refresh_rate = 60;
+	}
 
-	var->sync = 0;
+	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
+		sisfb_pre_setmode ();
 
-	uMRdata = vgarb(0x1C);
-	if (uMRdata & 0x80)
-		var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-	else
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+// Eden Chen
+/*
+#ifdef CONFIG_FB_SIS_300
+		if (SiSSetMode(&sishw_ext, sisfb_mode_no)) {
+			DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);
+			return -1;
+		}
+#endif
 
-	if (uMRdata & 0x40)
-		var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-	else
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+#ifdef CONFIG_FB_SIS_315
+		if (SiSSetMode310(&sishw_ext, sisfb_mode_no)) {
+			DPRINTK("set mode[0x%x]: failed\n", sisfb_mode_no);
+			return -1;
+		}
 
-	VT += 2;
-	VT <<= 1;
-	HT = (HT + 5) * 8;
+#endif
+*/
+		if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+			DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);
+			return -1;
+		}
+
+		vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+		vgawb (SEQ_DATA, SIS_PASSWORD);
+// ~Eden Chen
+		sisfb_post_setmode ();
+
+		DPRINTK ("Set New Mode : %dx%dx%d-%d \n",
+			 sisbios_mode[sisfb_mode_idx].xres,
+			 sisbios_mode[sisfb_mode_idx].yres,
+			 sisbios_mode[sisfb_mode_idx].bpp, ivideo.refresh_rate);
+
+		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+		ivideo.video_vwidth = ivideo.video_width =
+		    sisbios_mode[sisfb_mode_idx].xres;
+		ivideo.video_vheight = ivideo.video_height =
+		    sisbios_mode[sisfb_mode_idx].yres;
+		ivideo.org_x = ivideo.org_y = 0;
+		video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
 
-	hrate = (double) ivideo.refresh_rate * (double) VT / 2;
-	drate = hrate * HT;
-	var->pixclock = (u32) (1E12 / drate);
+	}
+	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_fix_screeninfo fix;
 	struct display *display;
 	struct display_switch *sw;
-	long flags;
+	u32 flags;
 
 	if (con >= 0)
 		display = &fb_display[con];
 	else
-		display = &disp;	/* used during initialization */
+		display = &disp;
 
-	sisfb_get_fix(&fix, con, 0);
+	sisfb_get_fix (&fix, con, 0);
 
 	display->screen_base = ivideo.video_vbase;
 	display->visual = fix.visual;
@@ -609,12 +587,11 @@
 	display->ywrapstep = fix.ywrapstep;
 	display->line_length = fix.line_length;
 	display->next_line = fix.line_length;
-	/*display->can_soft_blank = 1; */
 	display->can_soft_blank = 0;
-	display->inverse = inverse;
+	display->inverse = sisfb_inverse;
 	display->var = *var;
 
-	save_flags(flags);
+	save_flags (flags);
 	switch (ivideo.video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
@@ -644,852 +621,1380 @@
 		sw = &fbcon_dummy;
 		return;
 	}
-	memcpy(&sisfb_sw, sw, sizeof(*sw));
+	memcpy (&sisfb_sw, sw, sizeof (*sw));
 	display->dispsw = &sisfb_sw;
-	restore_flags(flags);
+	restore_flags (flags);
 
 	display->scrollmode = SCROLL_YREDRAW;
 	sisfb_sw.bmove = fbcon_redraw_bmove;
-
 }
 
-/*
- *    Read a single color register and split it into colors/transparent. 
- *    Return != 0 for invalid regno.
- */
-static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
-			 unsigned *transp, struct fb_info *fb_info)
+static void sisfb_do_install_cmap (int con, struct fb_info *info)
 {
-	if (regno >= video_cmap_len)
-		return 1;
+	if (con != currcon)
+		return;
 
-	*red = palette[regno].red;
-	*green = palette[regno].green;
-	*blue = palette[regno].blue;
-	*transp = 0;
-	return 0;
+	if (fb_display[con].cmap.len)
+		fb_set_cmap (&fb_display[con].cmap, 1, sis_setcolreg, info);
+	else
+		fb_set_cmap (fb_default_cmap (video_cmap_len), 1,
+			     sis_setcolreg, info);
 }
 
-/*
- *    Set a single color register. The values supplied are already
- *    rounded down to the hardware's capabilities (according to the
- *    entries in the var structure). Return != 0 for invalid regno.
- */
-static int sis_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-			 unsigned transp, struct fb_info *fb_info)
-{
-
-	if (regno >= video_cmap_len)
-		return 1;
-
-	palette[regno].red = red;
-	palette[regno].green = green;
-	palette[regno].blue = blue;
+/* --------------- Chip-dependent Routines --------------------------- */
 
-	switch (ivideo.video_bpp) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		vgawb(DAC_ADR, regno);
-		vgawb(DAC_DATA, red >> 10);
-		vgawb(DAC_DATA, green >> 10);
-		vgawb(DAC_DATA, blue >> 10);
-		if(uDispType & MASK_DISPTYPE_DISP2)
-		{
-			/* VB connected */
-			vgawb(DAC2_ADR,  regno);
-			vgawb(DAC2_DATA, red   >> 8);
-			vgawb(DAC2_DATA, green >> 8);
-			vgawb(DAC2_DATA, blue  >> 8);
-		}
+#ifdef CONFIG_FB_SIS_300	/* for SiS 300/630/540/730 */
+static int 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) {
+	case SIS_540:
+		nbridge_id = PCI_DEVICE_ID_SI_540;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 15:
-	case 16:
-		fbcon_cmap.cfb16[regno] =
-		    ((red & 0xf800)) |
-		    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+	case SIS_630:
+		nbridge_id = PCI_DEVICE_ID_SI_630;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB24
-	case 24:
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-		fbcon_cmap.cfb24[regno] =
-		    (red << 16) | (green << 8) | (blue);
+	case SIS_730:
+		nbridge_id = PCI_DEVICE_ID_SI_730;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		red >>= 8;
-		green >>= 8;
-		blue >>= 8;
-		fbcon_cmap.cfb32[regno] =
-		    (red << 16) | (green << 8) | (blue);
+	default:
+		nbridge_id = 0;
 		break;
-#endif
 	}
-	return 0;
-}
 
-static void do_install_cmap(int con, struct fb_info *info)
-{
-	if (con != currcon)
-		return;
+	if (nbridge_id == 0) {
+		vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+		ivideo.video_size =
+		    ((unsigned
+		      int) ((vgarb (SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20);
+	} else {
+		pci_for_each_dev (pdev) {
+			if ((pdev->vendor == PCI_VENDOR_ID_SI)
+			    && (pdev->device == nbridge_id)) {
+				//&& (pdev->device == PCI_DEVICE_ID_SI_630)) {
+				pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+						      &pci_data);
+				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+				ivideo.video_size =
+				    (unsigned int) (1 << (pci_data + 21));
+				pdev_valid = 1;
 
-	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, 1, sis_setcolreg, info);
-	else
-		fb_set_cmap(fb_default_cmap(video_cmap_len), 1,
-			    sis_setcolreg, info);
+				reg = SIS_DATA_BUS_64 << 6;
+				vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+				switch (pci_data) {
+				case BRI_DRAM_SIZE_2MB:
+					reg |= SIS_DRAM_SIZE_2MB;
+					break;
+				case BRI_DRAM_SIZE_4MB:
+					reg |= SIS_DRAM_SIZE_4MB;
+					break;
+				case BRI_DRAM_SIZE_8MB:
+					reg |= SIS_DRAM_SIZE_8MB;
+					break;
+				case BRI_DRAM_SIZE_16MB:
+					reg |= SIS_DRAM_SIZE_16MB;
+					break;
+				case BRI_DRAM_SIZE_32MB:
+					reg |= SIS_DRAM_SIZE_32MB;
+					break;
+				case BRI_DRAM_SIZE_64MB:
+					reg |= SIS_DRAM_SIZE_64MB;
+					break;
+				}
+				vgawb (SEQ_DATA, reg);
+				break;
+			}
+		}
+
+		if (!pdev_valid)
+			return -1;
+	}
+
+	return 0;
 }
 
-static int do_set_var(struct fb_var_screeninfo *var, int isactive,
-		      struct fb_info *info)
+static void sisfb_detect_VB_connect_300(void)
 {
-	unsigned int htotal =
-	    var->left_margin + var->xres + var->right_margin +
-	    var->hsync_len;
-	unsigned int vtotal =
-	    var->upper_margin + var->yres + var->lower_margin +
-	    var->vsync_len;
-	double drate = 0, hrate = 0;
-	int found_mode = 0;
-	int old_mode;
+	u8 sr16, sr17, cr32, temp;
 
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
-		vtotal <<= 1;
-	else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
-		vtotal <<= 2;
-	else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
-		var->yres <<= 1;
+	vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_17);
+	sr17 = vgarb (SEQ_DATA);
+	vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+	cr32 = vgarb (CRTC_DATA);
 
+	ivideo.TV_plug = ivideo.TV_type = 0;
+	if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+		if ((sr17 & 0x01) && !sisfb_crt1off)
+			sisfb_crt1off = 0;
+		else {
+			if (sr17 & 0x0E)
+				sisfb_crt1off = 1;
+			else
+				sisfb_crt1off = 0;
+		}
 
-	if (!htotal || !vtotal) {
-		DPRINTK("Invalid 'var' Information!\n");
-		return 1;
-	}
+		if (sr17 & 0x08)
+			ivideo.disp_state = DISPTYPE_CRT2;
+		else if (sr17 & 0x02)
+			ivideo.disp_state = DISPTYPE_LCD;
+		else if (sr17 & 0x04) {
+			ivideo.disp_state = DISPTYPE_TV;
+			if (sr17 & 0x20)
+				ivideo.TV_plug = TVPLUG_SVIDEO;
+			else if (sr17 & 0x10)
+				ivideo.TV_plug = TVPLUG_COMPOSITE;
 
-	drate = 1E12 / var->pixclock;
-	hrate = drate / htotal;
-	ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
+			vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_16);
+			sr16 = vgarb (SEQ_DATA);
+			if (sr16 & 0x20)
+				ivideo.TV_type = TVMODE_PAL;
+			else
+				ivideo.TV_type = TVMODE_NTSC;
+		} else
+			ivideo.disp_state = 0;
+	} else {
+		if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+			sisfb_crt1off = 0;
+		else {
+			if (cr32 & 0x5F)
+				sisfb_crt1off = 1;
+			else
+				sisfb_crt1off = 0;
+		}
 
-	old_mode = mode_idx;
-	mode_idx = 0;
+		if (cr32 & SIS_VB_CRT2)
+			ivideo.disp_state = DISPTYPE_CRT2;
+		else if (cr32 & SIS_VB_LCD)
+			ivideo.disp_state = DISPTYPE_LCD;
+		else if (cr32 & SIS_VB_TV) {
+			ivideo.disp_state = DISPTYPE_TV;
+			if (cr32 & SIS_VB_HIVISION) {
+				ivideo.TV_type = TVMODE_HIVISION;
+				ivideo.TV_plug = TVPLUG_SVIDEO;
+			} else if (cr32 & SIS_VB_SVIDEO)
+				ivideo.TV_plug = TVPLUG_SVIDEO;
+			else if (cr32 & SIS_VB_COMPOSITE)
+				ivideo.TV_plug = TVPLUG_COMPOSITE;
+			else if (cr32 & SIS_VB_SCART)
+				ivideo.TV_plug = TVPLUG_SCART;
 
-	while ((sisbios_mode[mode_idx].mode_no != 0)
-	       && (sisbios_mode[mode_idx].xres <= var->xres)) {
-		if ((sisbios_mode[mode_idx].xres == var->xres)
-		    && (sisbios_mode[mode_idx].yres == var->yres)
-		    && (sisbios_mode[mode_idx].bpp == var->bits_per_pixel)) {
-			mode_no = sisbios_mode[mode_idx].mode_no;
-			found_mode = 1;
-			break;
-		}
-		mode_idx++;
+			if (ivideo.TV_type == 0) {
+				// Eden Chen
+				//temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52));
+				//if (temp&0x40) {
+				//      temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53));
+				//} else {
+				vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+				temp = vgarb (SEQ_DATA);
+				//}
+				// ~Eden Chen
+				if (temp & 0x01)
+					ivideo.TV_type = TVMODE_PAL;
+				else
+					ivideo.TV_type = TVMODE_NTSC;
+			}
+		} else
+			ivideo.disp_state = 0;
 	}
+}
 
-	if(found_mode)
-	{
-		switch(uDispType & MASK_DISPTYPE_DISP2)
-		{
-		case MASK_DISPTYPE_LCD:
-			switch(HwExt.usLCDType)
-			{
-			case LCD1024:
-				if(var->xres > 1024)
-					found_mode = 0;
-				break;
-			case LCD1280:
-				if(var->xres > 1280)
-					found_mode = 0;
-				break;
-			case LCD2048:
-				if(var->xres > 2048)
-					found_mode = 0;
+static void sisfb_get_VB_type_300 (void)
+{
+	u8 reg;
+
+	if (ivideo.chip != SIS_300) {
+		if (!sisfb_has_VB_300 ()) {
+			vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR37);
+			reg = vgarb (CRTC_DATA);
+
+			switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
+			case SIS_EXTERNAL_CHIP_SIS301:
+				ivideo.hasVB = HASVB_301;
 				break;
-			case LCD1920:
-				if(var->xres > 1920)
-					found_mode = 0;
+			case SIS_EXTERNAL_CHIP_LVDS:
+				ivideo.hasVB = HASVB_LVDS;
 				break;
-			case LCD1600:
-				if(var->xres > 1600)
-					found_mode = 0;
+			case SIS_EXTERNAL_CHIP_TRUMPION:
+				ivideo.hasVB = HASVB_TRUMPION;
 				break;
-			case LCD800:
-				if(var->xres > 800)
-					found_mode = 0;
+			case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
 				break;
-			case LCD640:
-				if(var->xres > 640)
-					found_mode = 0;
+			case SIS_EXTERNAL_CHIP_CHRONTEL:
+				ivideo.hasVB = HASVB_CHRONTEL;
 				break;
 			default:
-				found_mode = 0;
-			}
-			if(var->xres == 720)	/* mode only for TV */
-				found_mode = 0;	
-			break;
-		case MASK_DISPTYPE_TV:
-			switch(var->xres)
-			{
-			case 800:
-			case 640:
 				break;
-			case 720:
-				if(ivideo.TV_type == TVMODE_NTSC)
-				{
-					if(sisbios_mode[mode_idx].yres != 480)
-						found_mode = 0;
-				}
-				else if(ivideo.TV_type == TVMODE_PAL)
-				{
-					if(sisbios_mode[mode_idx].yres != 576)
-						found_mode = 0;
+			}
+		}
+	} else {
+		sisfb_has_VB_300 ();
+	}
+
+	//sishw_ext.hasVB = ivideo.hasVB;
+}
+
+static int sisfb_has_VB_300 (void)
+{
+	// Eden Chen
+	//u8 sr38, sr39, vb_chipid;
+	u8 vb_chipid;
+
+	//vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+	//sr38 = vgarb(SEQ_DATA);
+	//vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2);
+	//sr39 = vgarb(SEQ_DATA);
+	vgawb (VB_PART4_ADR, 0x0);
+	vb_chipid = vgarb (VB_PART4_DATA);
+
+	switch (vb_chipid) {
+	case 0x01:
+		ivideo.hasVB = HASVB_301;
+		break;
+	case 0x02:
+		ivideo.hasVB = HASVB_302;
+		break;
+	case 0x03:
+		ivideo.hasVB = HASVB_303;
+		break;
+	default:
+		ivideo.hasVB = HASVB_NONE;
+		return FALSE;
+	}
+	return TRUE;
+}
+
+#endif				/* CONFIG_FB_SIS_300 */
+
+#ifdef CONFIG_FB_SIS_315	/* for SiS 315H/315 */
+static int sisfb_get_dram_size_315 (void)
+{
+#ifdef LINUXBIOS
+	struct pci_dev *pdev = NULL;
+	int pdev_valid = 0;
+	u8 pci_data;
+#endif
+	u8 reg = 0;
+
+	if (ivideo.chip == SIS_550) {
+#ifdef LINUXBIOS
+		pci_for_each_dev (pdev) {
+			if ((pdev->vendor == PCI_VENDOR_ID_SI)
+			    && (pdev->device == PCI_DEVICE_ID_SI_550)) {
+				pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
+						      &pci_data);
+				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
+				ivideo.video_size =
+				    (unsigned int) (1 << (pci_data + 21));
+				pdev_valid = 1;
+
+				vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+				reg = vgarb (SEQ_DATA) & 0xC0;
+
+				switch (pci_data) {
+					//case BRI_DRAM_SIZE_2MB:
+					//      reg |= (SIS315_DRAM_SIZE_2MB << 4); break;
+				case BRI_DRAM_SIZE_4MB:
+					reg |= SIS550_DRAM_SIZE_4MB;
+					break;
+				case BRI_DRAM_SIZE_8MB:
+					reg |= SIS550_DRAM_SIZE_8MB;
+					break;
+				case BRI_DRAM_SIZE_16MB:
+					reg |= SIS550_DRAM_SIZE_16MB;
+					break;
+				case BRI_DRAM_SIZE_32MB:
+					reg |= SIS550_DRAM_SIZE_32MB;
+					break;
+				case BRI_DRAM_SIZE_64MB:
+					reg |= SIS550_DRAM_SIZE_64MB;
+					break;
+					/* case BRI_DRAM_SIZE_128MB:
+					   reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */
 				}
+
+				/* TODO : set Dual channel and bus width bits here */
+
+				vgawb (SEQ_DATA, reg);
 				break;
-			default:
-				/* illegal mode */
-				found_mode = 0;
 			}
+		}
+
+		if (!pdev_valid)
+			return -1;
+#else
+		vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+		reg = vgarb (SEQ_DATA);
+		switch (reg & SIS550_DRAM_SIZE_MASK) {
+		case SIS550_DRAM_SIZE_4MB:
+			ivideo.video_size = 0x400000;
+			break;
+		case SIS550_DRAM_SIZE_8MB:
+			ivideo.video_size = 0x800000;
+			break;
+		case SIS550_DRAM_SIZE_16MB:
+			ivideo.video_size = 0x1000000;
+			break;
+		case SIS550_DRAM_SIZE_24MB:
+			ivideo.video_size = 0x1800000;
+			break;
+		case SIS550_DRAM_SIZE_32MB:
+			ivideo.video_size = 0x2000000;
+			break;
+		case SIS550_DRAM_SIZE_64MB:
+			ivideo.video_size = 0x4000000;
+			break;
+		case SIS550_DRAM_SIZE_96MB:
+			ivideo.video_size = 0x6000000;
+			break;
+		case SIS550_DRAM_SIZE_128MB:
+			ivideo.video_size = 0x8000000;
+			break;
+		case SIS550_DRAM_SIZE_256MB:
+			ivideo.video_size = 0x10000000;
+			break;
+		default:
+			return -1;
+		}
+#endif
+		return 0;
+	} else {
+		vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
+		reg = vgarb (SEQ_DATA);
+		switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
+		case SIS315_DRAM_SIZE_2MB:
+			ivideo.video_size = 0x200000;
+			break;
+		case SIS315_DRAM_SIZE_4MB:
+			ivideo.video_size = 0x400000;
+			break;
+		case SIS315_DRAM_SIZE_8MB:
+			ivideo.video_size = 0x800000;
+			break;
+		case SIS315_DRAM_SIZE_16MB:
+			ivideo.video_size = 0x1000000;
 			break;
+		case SIS315_DRAM_SIZE_32MB:
+			ivideo.video_size = 0x2000000;
+			break;
+		case SIS315_DRAM_SIZE_64MB:
+			ivideo.video_size = 0x4000000;
+			break;
+		case SIS315_DRAM_SIZE_128MB:
+			ivideo.video_size = 0x8000000;
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	reg &= SIS315_DUAL_CHANNEL_MASK;
+	reg >>= 2;
+	switch (reg) {
+	case SIS315_SINGLE_CHANNEL_2_RANK:
+		ivideo.video_size <<= 1;
+		break;
+	case SIS315_DUAL_CHANNEL_1_RANK:
+		ivideo.video_size <<= 1;
+		break;
+	}
+
+	return 0;
+}
+
+static void sisfb_detect_VB_connect_315 (void)
+{
+	u8 cr32, temp;
+
+	vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
+	cr32 = vgarb (CRTC_DATA);
+
+	ivideo.TV_plug = ivideo.TV_type = 0;
+	if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
+		sisfb_crt1off = 0;
+	else {
+		if (cr32 & 0x5F)
+			sisfb_crt1off = 1;
+		else
+			sisfb_crt1off = 0;
+	}
+
+	if (cr32 & SIS_VB_CRT2)
+		ivideo.disp_state = DISPTYPE_CRT2;
+	else if (cr32 & SIS_VB_LCD)
+		ivideo.disp_state = DISPTYPE_LCD;
+	else if (cr32 & SIS_VB_TV) {
+		ivideo.disp_state = DISPTYPE_TV;
+
+		if (cr32 & SIS_VB_HIVISION) {
+			ivideo.TV_type = TVMODE_HIVISION;
+			ivideo.TV_plug = TVPLUG_SVIDEO;
+		} else if (cr32 & SIS_VB_SVIDEO)
+			ivideo.TV_plug = TVPLUG_SVIDEO;
+		else if (cr32 & SIS_VB_COMPOSITE)
+			ivideo.TV_plug = TVPLUG_COMPOSITE;
+		else if (cr32 & SIS_VB_SCART)
+			ivideo.TV_plug = TVPLUG_SCART;
+
+		if (ivideo.TV_type == 0) {
+			vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
+			temp = vgarb (SEQ_DATA);
+
+			if (temp & 0x01)
+				ivideo.TV_type = TVMODE_PAL;
+			else
+				ivideo.TV_type = TVMODE_NTSC;
 		}
+	} else
+		ivideo.disp_state = 0;
+}
+
+static void sisfb_get_VB_type_315 (void)
+{
+	u8 vb_chipid;
+
+	vgawb (VB_PART4_ADR, 0x0);
+	vb_chipid = vgarb (VB_PART4_DATA);
+
+	switch (vb_chipid) {
+	case 0x01:
+		ivideo.hasVB = HASVB_301;
+		break;
+	case 0x02:
+		ivideo.hasVB = HASVB_302;
+		break;
+	case 0x03:
+		ivideo.hasVB = HASVB_303;
+		break;
+	default:
+		ivideo.hasVB = HASVB_NONE;
 	}
+	// Eden Chen
+	//sishw_ext.hasVB = ivideo.hasVB;
+	// ~Eden Chen
+}
+#endif				/* CONFIG_FB_SIS_315 */
+
+/* --------------------- Heap Routines ------------------------------- */
+
+static int sisfb_heap_init (void)
+{
+	SIS_OH *poh;
+	u8 temp = 0;
+#ifdef CONFIG_FB_SIS_315
+	int agp_enabled = 1;
+	u32 agp_size;
+	unsigned long *cmdq_baseport = 0;
+	unsigned long *read_port = 0;
+	unsigned long *write_port = 0;
+	SIS_CMDTYPE cmd_type;
+#ifndef AGPOFF
+	agp_kern_info *agp_info;
+	agp_memory *agp;
+	u32 agp_phys;
+#endif
+#endif
+	/*karl:10/01/2001 */
+	if (!sisfb_mem) {
 
-	if (!found_mode) {
-		printk("sisfb does not support mode %dx%d-%d\n", var->xres,
-		       var->yres, var->bits_per_pixel);
-		mode_idx = old_mode;
-		return 1;
+		if (ivideo.video_size > 0x800000)
+			sisfb_heap_start =
+			    (unsigned long) ivideo.video_vbase + 0x800000;
+		else
+			sisfb_heap_start =
+			    (unsigned long) ivideo.video_vbase + 0x400000;
+	} else
+		sisfb_heap_start =
+		    (unsigned long) (ivideo.video_vbase + sisfb_mem * 0x100000);
+
+	sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
+	sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
+
+#ifdef CONFIG_FB_SIS_315
+
+	cmdq_baseport =
+	    (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
+	write_port =
+	    (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
+	read_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
+
+	DPRINTK ("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport,
+		 read_port, write_port);
+
+	agp_size = COMMAND_QUEUE_AREA_SIZE;
+
+#ifndef AGPOFF
+
+	agp_info = vmalloc (sizeof (agp_kern_info));
+	memset ((void *) agp_info, 0x00, sizeof (agp_kern_info));
+	agp_copy_info (agp_info);
+
+	agp_backend_acquire ();
+
+	agp =
+	    agp_allocate_memory (COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
+				 AGP_NORMAL_MEMORY);
+	if (agp == NULL) {
+		DPRINTK ("Allocate AGP buffer failed.\n");
+		agp_enabled = 0;
+	} else {
+		if (agp_bind_memory (agp, agp->pg_start) != 0) {
+			DPRINTK ("AGP : can not bind memory\n");
+			agp_enabled = 0;
+		} else {
+			agp_enable (0);
+		}
 	}
 
-	if (search_refresh_rate(ivideo.refresh_rate) == 0) {
-		/* not supported rate */
-		rate_idx = sisbios_mode[mode_idx].rate_idx;
-		ivideo.refresh_rate = 60;
-	}
+#else
+	agp_enabled = 0;
+#endif
+	if (agp_enabled)
+		cmd_type = AGP_CMD_QUEUE;
+	else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)
+		cmd_type = VM_CMD_QUEUE;
+	else
+		cmd_type = MMIO_CMD;
 
-	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
-		pre_setmode();
+	switch (agp_size) {
+	case 0x80000:
+		temp = SIS_CMD_QUEUE_SIZE_512k;
+		break;
+	case 0x100000:
+		temp = SIS_CMD_QUEUE_SIZE_1M;
+		break;
+	case 0x200000:
+		temp = SIS_CMD_QUEUE_SIZE_2M;
+		break;
+	case 0x400000:
+		temp = SIS_CMD_QUEUE_SIZE_4M;
+		break;
+	}
 
-		if (SiSSetMode(&HwExt, mode_no)) {
-			DPRINTK("sisfb: set mode[0x%x]: failed\n",
-				mode_no);
-			return 1;
-		}
+	switch (cmd_type) {
+	case AGP_CMD_QUEUE:
+#ifndef AGPOFF
+		DPRINTK ("AGP buffer base:0x%lx, offset:0x%x, size is %dK\n",
+			 agp_info->aper_base, agp->physical, agp_size / 1024);
 
-		post_setmode();
+		agp_phys = agp_info->aper_base + agp->physical;
 
-		printk(KERN_DEBUG "Current Mode: %dx%dx%d-%d \n", sisbios_mode[mode_idx].xres, 
-			sisbios_mode[mode_idx].yres, sisbios_mode[mode_idx].bpp, ivideo.refresh_rate);
+		vgawb (CRTC_ADR, IND_SIS_AGP_IO_PAD);
+		vgawb (CRTC_DATA, 0);
+		vgawb (CRTC_DATA, SIS_AGP_2X);
 
-		ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
-		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
-		ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;
-		ivideo.org_x = ivideo.org_y = 0;
-		video_linelength =
-		    ivideo.video_width * (ivideo.video_bpp >> 3);
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+		vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
 
-		DPRINTK("Current Mode: %dx%d-%d line_length=%d\n",
-			ivideo.video_width, ivideo.video_height,
-			ivideo.video_bpp, video_linelength);
-	}
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+		vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
 
-	return 0;
-}
+		*write_port = *read_port;
 
-/* ---------------------- Draw Funtions ----------------------------- */
+		temp |= SIS_AGP_CMDQUEUE_ENABLE;
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+		vgawb (SEQ_DATA, temp);
 
-static void sis_get_glyph(struct GlyInfo *gly)
-{
-	struct display *p = &fb_display[currcon];
-	u16 c;
-	u8 *cdat;
-	int widthb;
-	u8 *gbuf = gly->gmask;
-	int size;
+		*cmdq_baseport = agp_phys;
 
+		sisfb_caps |= AGP_CMD_QUEUE_CAP;
+#endif
+		break;
 
-	gly->fontheight = fontheight(p);
-	gly->fontwidth = fontwidth(p);
-	widthb = (fontwidth(p) + 7) / 8;
+	case VM_CMD_QUEUE:
+		sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
 
-	c = gly->ch & p->charmask;
-	if (fontwidth(p) <= 8)
-		cdat = p->fontdata + c * fontheight(p);
-	else
-		cdat = p->fontdata + (c * fontheight(p) << 1);
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
+		vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
 
-	size = fontheight(p) * widthb;
-	memcpy(gbuf, cdat, size);
-	gly->ngmask = size;
-}
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+		vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
 
+		*write_port = *read_port;
 
-/* ---------------------- HEAP Routines ----------------------------- */
+		temp |= SIS_VRAM_CMDQUEUE_ENABLE;
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+		vgawb (SEQ_DATA, temp);
 
-/* 
- *  Heap Initialization
- */
+		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
 
-static int sisfb_heap_init(void)
-{
-	struct OH *poh;
-	u8 jTemp, tq_state;
+		sisfb_caps |= VM_CMD_QUEUE_CAP;
 
-	if(ivideo.video_size > 0x800000)
-		/* video ram is large than 8M */
-		heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_8M;
-	else
-		heap_start = (unsigned long) ivideo.video_vbase + RESERVED_MEM_SIZE_4M;
+		DPRINTK ("VM Cmd Queue offset = 0x%lx, size is %dK\n",
+			 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE / 1024);
+		break;
+	default:
+		vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
+		vgawb (SEQ_DATA, SIS_MMIO_CMD_ENABLE);
+		break;
+	}
 
-	heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
-	heap_size = heap_end - heap_start;
+#endif
 
+#ifdef CONFIG_FB_SIS_300
+	if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
+		unsigned int tqueue_pos;
+		u8 tq_state;
 
-	/* Setting for Turbo Queue */
-	if (heap_size >= TURBO_QUEUE_AREA_SIZE) {
 		tqueue_pos =
-		    (ivideo.video_size -
-		     TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
-		jTemp = (u8) (tqueue_pos & 0xff);
-		vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
-		tq_state = vgarb(SEQ_DATA);
+		    (ivideo.video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+		temp = (u8) (tqueue_pos & 0xff);
+		vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
+		tq_state = vgarb (SEQ_DATA);
 		tq_state |= 0xf0;
 		tq_state &= 0xfc;
 		tq_state |= (u8) (tqueue_pos >> 8);
-		vgawb(SEQ_DATA, tq_state);
-		vgawb(SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
-		vgawb(SEQ_DATA, jTemp);
-
-		caps |= TURBO_QUEUE_CAP;
-
-		heap_end -= TURBO_QUEUE_AREA_SIZE;
-		heap_size -= TURBO_QUEUE_AREA_SIZE;
+		vgawb (SEQ_DATA, tq_state);
+		vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
+		vgawb (SEQ_DATA, temp);
+
+		sisfb_caps |= TURBO_QUEUE_CAP;
+
+		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
+		DPRINTK ("Turbo Queue: start at 0x%lx, size is %dK\n",
+			 sisfb_heap_end, TURBO_QUEUE_AREA_SIZE / 1024);
 	}
+#endif
 
-	/* Setting for HW cursor(4K) */
-	if (heap_size >= HW_CURSOR_AREA_SIZE) {
-		heap_end -= HW_CURSOR_AREA_SIZE;
-		heap_size -= HW_CURSOR_AREA_SIZE;
-		hwcursor_vbase = heap_end;
+	if (sisfb_heap_size >= HW_CURSOR_AREA_SIZE) {
+		sisfb_heap_end -= HW_CURSOR_AREA_SIZE;
+		sisfb_heap_size -= HW_CURSOR_AREA_SIZE;
+		sisfb_hwcursor_vbase = sisfb_heap_end;
 
-		caps |= HW_CURSOR_CAP;
+		sisfb_caps |= HW_CURSOR_CAP;
+
+		DPRINTK ("Hardware Cursor: start at 0x%lx, size is %dK\n",
+			 sisfb_heap_end, HW_CURSOR_AREA_SIZE / 1024);
 	}
 
-	heap.pohaChain = NULL;
-	heap.pohFreeList = NULL;
+	sisfb_heap.poha_chain = NULL;
+	sisfb_heap.poh_freelist = NULL;
 
-	poh = poh_new_node();
+	poh = sisfb_poh_new_node ();
 
 	if (poh == NULL)
 		return 1;
 
-	/* The first node describles the entire heap size */
-	poh->pohNext = &heap.ohFree;
-	poh->pohPrev = &heap.ohFree;
-	poh->ulSize = heap_end - heap_start + 1;
-	poh->ulOffset = heap_start - (unsigned long) ivideo.video_vbase;
-
-	DPRINTK("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
-		(char *) heap_start, (char *) heap_end,
-		(unsigned int) poh->ulSize / 1024);
-
-	DPRINTK("sisfb:First Node offset:0x%x, size:%dk\n",
-		(unsigned int) poh->ulOffset, (unsigned int) poh->ulSize / 1024);
-
-	/* The second node in our free list sentinel */
-	heap.ohFree.pohNext = poh;
-	heap.ohFree.pohPrev = poh;
-	heap.ohFree.ulSize = 0;
-	heap.ulMaxFreeSize = poh->ulSize;
-
-	/* Initialize the discardable list */
-	heap.ohUsed.pohNext = &heap.ohUsed;
-	heap.ohUsed.pohPrev = &heap.ohUsed;
-	heap.ohUsed.ulSize = SENTINEL;
+	poh->poh_next = &sisfb_heap.oh_free;
+	poh->poh_prev = &sisfb_heap.oh_free;
+	poh->size = sisfb_heap_end - sisfb_heap_start + 1;
+	poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
+
+	DPRINTK ("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n",
+		 (char *) sisfb_heap_start, (char *) sisfb_heap_end,
+		 (unsigned int) poh->size / 1024);
+
+	DPRINTK ("sisfb:First Node offset:0x%x, size:%dk\n",
+		 (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
+
+	sisfb_heap.oh_free.poh_next = poh;
+	sisfb_heap.oh_free.poh_prev = poh;
+	sisfb_heap.oh_free.size = 0;
+	sisfb_heap.max_freesize = poh->size;
+
+	sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+	sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+	sisfb_heap.oh_used.size = SENTINEL;
 
 	return 0;
 }
 
-/*
- *  Allocates a basic memory unit in which we'll pack our data structures.
- */
-
-static struct OH *poh_new_node(void)
+static SIS_OH *sisfb_poh_new_node (void)
 {
 	int i;
 	unsigned long cOhs;
-	struct OHALLOC *poha;
-	struct OH *poh;
+	SIS_OHALLOC *poha;
+	SIS_OH *poh;
 
-	if (heap.pohFreeList == NULL) {
-		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
-		if (!poha)
-			return NULL;
+	if (sisfb_heap.poh_freelist == NULL) {
+		poha = kmalloc (OH_ALLOC_SIZE, GFP_KERNEL);
 
-		poha->pohaNext = heap.pohaChain;
-		heap.pohaChain = poha;
+		poha->poha_next = sisfb_heap.poha_chain;
+		sisfb_heap.poha_chain = poha;
 
 		cOhs =
 		    (OH_ALLOC_SIZE -
-		     sizeof(struct OHALLOC)) / sizeof(struct OH) + 1;
+		     sizeof (SIS_OHALLOC)) / sizeof (SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
 		for (i = cOhs - 1; i != 0; i--) {
-			poh->pohNext = poh + 1;
+			poh->poh_next = poh + 1;
 			poh = poh + 1;
 		}
 
-		poh->pohNext = NULL;
-		heap.pohFreeList = &poha->aoh[0];
+		poh->poh_next = NULL;
+		sisfb_heap.poh_freelist = &poha->aoh[0];
 	}
 
-	poh = heap.pohFreeList;
-	heap.pohFreeList = poh->pohNext;
+	poh = sisfb_heap.poh_freelist;
+	sisfb_heap.poh_freelist = poh->poh_next;
 
 	return (poh);
 }
 
-/* 
- *  Allocates space, return NULL when failed
- */
-
-static struct OH *poh_allocate(unsigned long size)
+static SIS_OH *sisfb_poh_allocate (unsigned long size)
 {
-	struct OH *pohThis;
-	struct OH *pohRoot;
+	SIS_OH *pohThis;
+	SIS_OH *pohRoot;
 	int bAllocated = 0;
 
-	if (size > heap.ulMaxFreeSize) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
-			(unsigned int) size / 1024);
+	if (size > sisfb_heap.max_freesize) {
+		DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+			 (unsigned int) size / 1024);
 		return (NULL);
 	}
 
-	pohThis = heap.ohFree.pohNext;
+	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &heap.ohFree) {
-		if (size <= pohThis->ulSize) {
+	while (pohThis != &sisfb_heap.oh_free) {
+		if (size <= pohThis->size) {
 			bAllocated = 1;
 			break;
 		}
-		pohThis = pohThis->pohNext;
+		pohThis = pohThis->poh_next;
 	}
 
 	if (!bAllocated) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
-			(unsigned int) size / 1024);
+		DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n",
+			 (unsigned int) size / 1024);
 		return (NULL);
 	}
 
-	if (size == pohThis->ulSize) {
+	if (size == pohThis->size) {
 		pohRoot = pohThis;
-		delete_node(pohThis);
+		sisfb_delete_node (pohThis);
 	} else {
-		pohRoot = poh_new_node();
+		pohRoot = sisfb_poh_new_node ();
 
 		if (pohRoot == NULL) {
 			return (NULL);
 		}
 
-		pohRoot->ulOffset = pohThis->ulOffset;
-		pohRoot->ulSize = size;
+		pohRoot->offset = pohThis->offset;
+		pohRoot->size = size;
 
-		pohThis->ulOffset += size;
-		pohThis->ulSize -= size;
+		pohThis->offset += size;
+		pohThis->size -= size;
 	}
 
-	heap.ulMaxFreeSize -= size;
+	sisfb_heap.max_freesize -= size;
 
-	pohThis = &heap.ohUsed;
-	insert_node(pohThis, pohRoot);
+	pohThis = &sisfb_heap.oh_used;
+	sisfb_insert_node (pohThis, pohRoot);
 
 	return (pohRoot);
 }
 
-/* 
- *  To remove a node from a list.
- */
-
-static void delete_node(struct OH *poh)
+static void sisfb_delete_node (SIS_OH * poh)
 {
-	struct OH *pohPrev;
-	struct OH *pohNext;
+	SIS_OH *poh_prev;
+	SIS_OH *poh_next;
 
+	poh_prev = poh->poh_prev;
+	poh_next = poh->poh_next;
 
-	pohPrev = poh->pohPrev;
-	pohNext = poh->pohNext;
-
-	pohPrev->pohNext = pohNext;
-	pohNext->pohPrev = pohPrev;
+	poh_prev->poh_next = poh_next;
+	poh_next->poh_prev = poh_prev;
 
 	return;
 }
 
-/* 
- *  To insert a node into a list.
- */
-
-static void insert_node(struct OH *pohList, struct OH *poh)
+static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh)
 {
-	struct OH *pohTemp;
+	SIS_OH *pohTemp;
 
-	pohTemp = pohList->pohNext;
+	pohTemp = pohList->poh_next;
 
-	pohList->pohNext = poh;
-	pohTemp->pohPrev = poh;
+	pohList->poh_next = poh;
+	pohTemp->poh_prev = poh;
 
-	poh->pohPrev = pohList;
-	poh->pohNext = pohTemp;
+	poh->poh_prev = pohList;
+	poh->poh_next = pohTemp;
 }
 
-/*
- *  Frees an off-screen heap allocation.
- */
-
-static struct OH *poh_free(unsigned long base)
+static SIS_OH *sisfb_poh_free (unsigned long base)
 {
 
-	struct OH *pohThis;
-	struct OH *pohFreed;
-	struct OH *pohPrev;
-	struct OH *pohNext;
+	SIS_OH *pohThis;
+	SIS_OH *poh_freed;
+	SIS_OH *poh_prev;
+	SIS_OH *poh_next;
 	unsigned long ulUpper;
 	unsigned long ulLower;
 	int foundNode = 0;
 
-	pohFreed = heap.ohUsed.pohNext;
+	poh_freed = sisfb_heap.oh_used.poh_next;
 
-	while (pohFreed != &heap.ohUsed) {
-		if (pohFreed->ulOffset == base) {
+	while (poh_freed != &sisfb_heap.oh_used) {
+		if (poh_freed->offset == base) {
 			foundNode = 1;
 			break;
 		}
 
-		pohFreed = pohFreed->pohNext;
+		poh_freed = poh_freed->poh_next;
 	}
 
 	if (!foundNode)
 		return (NULL);
 
-	heap.ulMaxFreeSize += pohFreed->ulSize;
+	sisfb_heap.max_freesize += poh_freed->size;
 
-	pohPrev = pohNext = NULL;
-	ulUpper = pohFreed->ulOffset + pohFreed->ulSize;
-	ulLower = pohFreed->ulOffset;
+	poh_prev = poh_next = NULL;
+	ulUpper = poh_freed->offset + poh_freed->size;
+	ulLower = poh_freed->offset;
 
-	pohThis = heap.ohFree.pohNext;
+	pohThis = sisfb_heap.oh_free.poh_next;
 
-	while (pohThis != &heap.ohFree) {
-		if (pohThis->ulOffset == ulUpper) {
-			pohNext = pohThis;
+	while (pohThis != &sisfb_heap.oh_free) {
+		if (pohThis->offset == ulUpper) {
+			poh_next = pohThis;
+		} else if ((pohThis->offset + pohThis->size) == ulLower) {
+			poh_prev = pohThis;
 		}
-			else if ((pohThis->ulOffset + pohThis->ulSize) ==
-				 ulLower) {
-			pohPrev = pohThis;
-		}
-		pohThis = pohThis->pohNext;
+		pohThis = pohThis->poh_next;
 	}
 
-	delete_node(pohFreed);
+	sisfb_delete_node (poh_freed);
 
-	if (pohPrev && pohNext) {
-		pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize);
-		delete_node(pohNext);
-		free_node(pohFreed);
-		free_node(pohNext);
-		return (pohPrev);
+	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);
 	}
 
-	if (pohPrev) {
-		pohPrev->ulSize += pohFreed->ulSize;
-		free_node(pohFreed);
-		return (pohPrev);
+	if (poh_prev) {
+		poh_prev->size += poh_freed->size;
+		sisfb_free_node (poh_freed);
+		return (poh_prev);
 	}
 
-	if (pohNext) {
-		pohNext->ulSize += pohFreed->ulSize;
-		pohNext->ulOffset = pohFreed->ulOffset;
-		free_node(pohFreed);
-		return (pohNext);
+	if (poh_next) {
+		poh_next->size += poh_freed->size;
+		poh_next->offset = poh_freed->offset;
+		sisfb_free_node (poh_freed);
+		return (poh_next);
 	}
 
-	insert_node(&heap.ohFree, pohFreed);
+	sisfb_insert_node (&sisfb_heap.oh_free, poh_freed);
 
-	return (pohFreed);
+	return (poh_freed);
 }
 
-/*
- *  Frees our basic data structure allocation unit by adding it to a free
- *  list.
- */
-
-static void free_node(struct OH *poh)
+static void sisfb_free_node (SIS_OH * poh)
 {
 	if (poh == NULL) {
 		return;
 	}
 
-	poh->pohNext = heap.pohFreeList;
-	heap.pohFreeList = poh;
+	poh->poh_next = sisfb_heap.poh_freelist;
+	sisfb_heap.poh_freelist = poh;
 
 	return;
 }
 
-void sis_malloc(struct sis_memreq *req)
+void sis_malloc (struct sis_memreq *req)
 {
-	struct OH *poh;
+	SIS_OH *poh;
 
-	poh = poh_allocate(req->size);
+	poh = sisfb_poh_allocate (req->size);
 
 	if (poh == NULL) {
 		req->offset = 0;
 		req->size = 0;
-		DPRINTK("sisfb: VMEM Allocation Failed\n");
+		DPRINTK ("sisfb: VMEM Allocation Failed\n");
 	} else {
-		DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n",
-			(char *) (poh->ulOffset +
-				  (unsigned long) ivideo.video_vbase));
+		DPRINTK ("sisfb: VMEM Allocation Successed : 0x%p\n",
+			 (char *) (poh->offset +
+				   (unsigned long) ivideo.video_vbase));
 
-		req->offset = poh->ulOffset;
-		req->size = poh->ulSize;
+		req->offset = poh->offset;
+		req->size = poh->size;
 	}
 
 }
 
-void sis_free(unsigned long base)
+void sis_free (unsigned long base)
 {
-	struct OH *poh;
+	SIS_OH *poh;
 
-	poh = poh_free(base);
+	poh = sisfb_poh_free (base);
 
 	if (poh == NULL) {
-		DPRINTK("sisfb: poh_free() failed at base 0x%x\n",
-			(unsigned int) base);
+		DPRINTK ("sisfb: sisfb_poh_free() failed at base 0x%x\n",
+			 (unsigned int) base);
 	}
 }
 
-void sis_dispinfo(struct ap_data *rec)
+/* ------------------ SetMode Routines ------------------------------- */
+
+static void sisfb_pre_setmode (void)
 {
-	rec->minfo.bpp    = ivideo.video_bpp;
-	rec->minfo.xres   = ivideo.video_width;
-	rec->minfo.yres   = ivideo.video_height;
-	rec->minfo.v_xres = ivideo.video_vwidth;
-	rec->minfo.v_yres = ivideo.video_vheight;
-	rec->minfo.org_x  = ivideo.org_x;
-	rec->minfo.org_y  = ivideo.org_y;
-	rec->minfo.vrate  = ivideo.refresh_rate;
-	rec->iobase       = ivideo.vga_base - 0x30;
-	rec->mem_size     = ivideo.video_size;
-	rec->disp_state   = ivideo.disp_state; 
-	switch(HwExt.jChipID)
-	{
-	case SIS_Glamour:
-		rec->chip = SiS_300;
-		break;
-	case SIS_Trojan:
-		if((HwExt.revision_id & 0xf0) == 0x30)
-			rec->chip = SiS_630S;
-		else
-			rec->chip = SiS_630;
-		break;
-	case SIS_Spartan:
-		rec->chip = SiS_540;
-		break;
-	case SIS_730:
-		rec->chip = SiS_730;
+	u8 cr30 = 0, cr31 = 0;
+
+	vgawb (CRTC_ADR, 0x31);
+	cr31 = vgarb (CRTC_DATA) & ~0x60;
+
+	switch (ivideo.disp_state & DISPTYPE_DISP2) {
+	case DISPTYPE_CRT2:
+		cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		cr31 |= SIS_DRIVER_MODE;
+		break;
+	case DISPTYPE_LCD:
+		cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		cr31 |= SIS_DRIVER_MODE;
+		break;
+	case DISPTYPE_TV:
+		if (ivideo.TV_type == TVMODE_HIVISION)
+			cr30 =
+			    (SIS_VB_OUTPUT_HIVISION |
+			     SIS_SIMULTANEOUS_VIEW_ENABLE);
+		else if (ivideo.TV_plug == TVPLUG_SVIDEO)
+			cr30 =
+			    (SIS_VB_OUTPUT_SVIDEO |
+			     SIS_SIMULTANEOUS_VIEW_ENABLE);
+		else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
+			cr30 =
+			    (SIS_VB_OUTPUT_COMPOSITE |
+			     SIS_SIMULTANEOUS_VIEW_ENABLE);
+		else if (ivideo.TV_plug == TVPLUG_SCART)
+			cr30 =
+			    (SIS_VB_OUTPUT_SCART |
+			     SIS_SIMULTANEOUS_VIEW_ENABLE);
+		cr31 |= SIS_DRIVER_MODE;
+
+		/*karl */
+		if (sisfb_tvmode == 1)
+			cr31 |= 0x1;
+		if (sisfb_tvmode == 2)
+			cr31 &= ~0x1;
+
 		break;
 	default:
-		rec->chip = SiS_UNKNOWN;
-		break;
+		cr30 = 0x00;
+		cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 	}
-}
-
-
-/* ---------------------- SetMode Routines -------------------------- */
 
-void SetReg1(u16 port, u16 index, u16 data)
-{
-	outb((u8) (index & 0xff), port);
-	port++;
-	outb((u8) (data & 0xff), port);
+	vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR30);
+	vgawb (CRTC_DATA, cr30);
+	vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR31);
+	vgawb (CRTC_DATA, cr31);
+	vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR33);
+	vgawb (CRTC_DATA, sisfb_rate_idx & 0x0F);
 }
 
-void SetReg3(u16 port, u16 data)
+static void sisfb_post_setmode (void)
 {
-	outb((u8) (data & 0xff), port);
-}
+	u8 reg;
 
-void SetReg4(u16 port, unsigned long data)
-{
-	outl((u32) (data & 0xffffffff), port);
-}
+	vgawb (CRTC_ADR, 0x17);
+	reg = vgarb (CRTC_DATA);
 
-u8 GetReg1(u16 port, u16 index)
-{
-	u8 data;
+	if ((ivideo.hasVB == HASVB_LVDS)
+	    || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) if (ivideo.video_bpp == 8)
+			sisfb_crt1off = 0;
 
-	outb((u8) (index & 0xff), port);
-	port += 1;
-	data = inb(port);
-	return (data);
-}
+	if (sisfb_crt1off)
+		reg &= ~0x80;
+	else
+		reg |= 0x80;
+	vgawb (CRTC_DATA, reg);
 
-u8 GetReg2(u16 port)
-{
-	u8 data;
+	vgawb (SEQ_ADR, IND_SIS_RAMDAC_CONTROL);
+	reg = vgarb (SEQ_DATA);
+	reg &= ~0x04;
+	vgawb (SEQ_DATA, reg);
+
+	if ((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {
+		/*karl */
+		vgawb (VB_PART4_ADR, 0x01);
+		reg = vgarb (VB_PART4_DATA);
+
+		if ((reg != 0xB1) && (reg != 0xB0)) {	/*301B Revision ID */
+			// Eden Chen
+			switch (ivideo.video_width) {
+			case 320:
+				filter_tb =
+				    (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
+				break;
+			case 640:
+				filter_tb =
+				    (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
+				break;
+			case 720:
+				filter_tb =
+				    (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
+				break;
+			case 800:
+				filter_tb =
+				    (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
+				break;
+			default:
+				filter = -1;
+				break;
+			}
+			// ~Eden Chen
 
-	data = inb(port);
+			// Eden Chen
+			//vgawb(VB_PART1_ADR,  0x24);
+			vgawb (VB_PART1_ADR, IND_SIS_CRT2_WRITE_ENABLE);
+			// ~Eden Chen
+			vgawb (VB_PART1_DATA, 0x1);
+
+			// Eden Chen for Debug
+			// ~Eden Chen
+
+			if (ivideo.TV_type == TVMODE_NTSC) {
+				vgawb (VB_PART2_ADR, 0x3A);
+				reg = vgarb (VB_PART2_DATA);
+				reg &= 0x1F;
+				vgawb (VB_PART2_DATA, reg);
+
+				if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+					vgawb (VB_PART2_ADR, 0x30);
+					reg = vgarb (VB_PART2_DATA);
+					reg &= 0xDF;
+					vgawb (VB_PART2_DATA, reg);
+				} else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+					vgawb (VB_PART2_ADR, 0x30);
+					reg = vgarb (VB_PART2_DATA);
+					reg |= 0x20;
+					vgawb (VB_PART2_DATA, reg);
+
+					switch (ivideo.video_width) {
+					case 640:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xEB);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0x04);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x25);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0x18);
+						break;
+					case 720:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xEE);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0x0C);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x22);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0x08);
+						break;
+					case 800:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xEB);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0x15);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x25);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0xF6);
+						break;
+					}
+				}
+			} else if (ivideo.TV_type == TVMODE_PAL) {
+				vgawb (VB_PART2_ADR, 0x3A);
+				reg = vgarb (VB_PART2_DATA);
+				reg &= 0x1F;
+				vgawb (VB_PART2_DATA, reg);
+
+				if (ivideo.TV_plug == TVPLUG_SVIDEO) {
+					vgawb (VB_PART2_ADR, 0x30);
+					reg = vgarb (VB_PART2_DATA);
+					reg &= 0xDF;
+					vgawb (VB_PART2_DATA, reg);
+				} else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
+					vgawb (VB_PART2_ADR, 0x30);
+					reg = vgarb (VB_PART2_DATA);
+					reg |= 0x20;
+					vgawb (VB_PART2_DATA, reg);
+
+					switch (ivideo.video_width) {
+					case 640:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xF1);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0xF7);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x1F);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0x32);
+						break;
+					case 720:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xF3);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0x00);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x1D);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0x20);
+						break;
+					case 800:
+						vgawb (VB_PART2_ADR, 0x35);
+						vgawb (VB_PART2_DATA, 0xFC);
+						vgawb (VB_PART2_ADR, 0x36);
+						vgawb (VB_PART2_DATA, 0xFB);
+						vgawb (VB_PART2_ADR, 0x37);
+						vgawb (VB_PART2_DATA, 0x14);
+						vgawb (VB_PART2_ADR, 0x38);
+						vgawb (VB_PART2_DATA, 0x2A);
+						break;
+					}
+				}
+			}
+			// Eden 
+			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]
+				    );
+				vgawb (VB_PART2_ADR, 0x35);
+				vgawb (VB_PART2_DATA,
+				       sis_TV_filter[filter_tb].
+				       filter[filter][0]);
+				vgawb (VB_PART2_ADR, 0x36);
+				vgawb (VB_PART2_DATA,
+				       sis_TV_filter[filter_tb].
+				       filter[filter][1]);
+				vgawb (VB_PART2_ADR, 0x37);
+				vgawb (VB_PART2_DATA,
+				       sis_TV_filter[filter_tb].
+				       filter[filter][2]);
+				vgawb (VB_PART2_ADR, 0x38);
+				vgawb (VB_PART2_DATA,
+				       sis_TV_filter[filter_tb].
+				       filter[filter][3]);
+			}
+			// ~Eden 
+		}
+	}
 
-	return (data);
 }
 
-u32 GetReg3(u16 port)
+static void sisfb_crtc_to_var (struct fb_var_screeninfo *var)
 {
-	u32 data;
-
-	data = inl(port);
-	return (data);
-}
+	u16 VRE, VBE, VRS, VBS, VDE, VT;
+	u16 HRE, HBE, HRS, HBS, HDE, HT;
+	u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
+	int A, B, C, D, E, F, temp;
+	double hrate, drate;
 
-void ClearDAC(u16 port)
-{
-	int i,j;
+	vgawb (SEQ_ADR, IND_SIS_COLOR_MODE);
+	sr_data = vgarb (SEQ_DATA);
 
-	vgawb(DAC_ADR, 0x00);
-	for(i=0; i<256; i++)
-		for(j=0; j<3; j++)
-			vgawb(DAC_DATA, 0);
-}
+	if (sr_data & SIS_INTERLACED_MODE)
+		var->vmode = FB_VMODE_INTERLACED;
+	else
+		var->vmode = FB_VMODE_NONINTERLACED;
 
-void ClearBuffer(PHW_DEVICE_EXTENSION pHwExt)
-{
-	memset((char *) ivideo.video_vbase, 0,
-		video_linelength * ivideo.video_height);
-}
+	switch ((sr_data & 0x1C) >> 2) {
+	case SIS_8BPP_COLOR_MODE:
+		var->bits_per_pixel = 8;
+		break;
+	case SIS_16BPP_COLOR_MODE:
+		var->bits_per_pixel = 16;
+		break;
+	case SIS_32BPP_COLOR_MODE:
+		var->bits_per_pixel = 32;
+		break;
+	}
 
-static void pre_setmode(void)
-{
-	unsigned char  uCR30=0, uCR31=0;
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.length = 6;
+		var->green.length = 6;
+		var->blue.length = 6;
+		video_cmap_len = 256;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		video_cmap_len = 16;
 
-	switch(uDispType & MASK_DISPTYPE_DISP2)
-	{
-	case MASK_DISPTYPE_CRT2:
-		uCR30 = 0x41;
-		uCR31 = 0x40; 
-		break;
-	case MASK_DISPTYPE_LCD:
-		uCR30 = 0x21;
-		uCR31 = 0x40;
-		break;
-	case MASK_DISPTYPE_TV:
-		if(ivideo.TV_type == TVMODE_HIVISION)
-			uCR30 = 0x81;
-		else if(ivideo.TV_plug == TVPLUG_SVIDEO)
-			uCR30 = 0x09;
-		else if(ivideo.TV_plug == TVPLUG_COMPOSITE)
-			uCR30 = 0x05;
-		else if(ivideo.TV_plug == TVPLUG_SCART)
-			uCR30 = 0x11;
-		uCR31 = 0x40;  /* CR31[0] will be set in setmode() */
 		break;
-	default:
-		uCR30 = 0x00;
-		uCR31 = 0x60;
+	case 24:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		video_cmap_len = 16;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		video_cmap_len = 16;
+		break;
 	}
 
-	vgawb(CRTC_ADR, 0x30);
-	vgawb(CRTC_DATA, uCR30);
-	vgawb(CRTC_ADR, 0x31);
-	vgawb(CRTC_DATA, uCR31);
-    vgawb(CRTC_ADR, 0x33);
-    vgawb(CRTC_DATA, rate_idx & 0x0f);
-}
+	vgawb (SEQ_ADR, 0xA);
+	sr_data = vgarb (SEQ_DATA);
 
-static void post_setmode(void)
-{
-	u8 uTemp;
+	vgawb (CRTC_ADR, 0x6);
+	cr_data = vgarb (CRTC_DATA);
+	vgawb (CRTC_ADR, 0x7);
+	cr_data2 = vgarb (CRTC_DATA);
+	VT =
+	    (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
+	    ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+	A = VT + 2;
 
-	vgawb(CRTC_ADR, 0x17);
-	uTemp = vgarb(CRTC_DATA);
+	vgawb (CRTC_ADR, 0x12);
+	cr_data = vgarb (CRTC_DATA);
+	VDE =
+	    (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
+	    ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+	E = VDE + 1;
 
-	if(crt1off)	  /* turn off CRT1 */
-		uTemp &= ~0x80;
-	else 	      /* turn on CRT1 */
-		uTemp |= 0x80;
-	vgawb(CRTC_DATA, uTemp);
+	vgawb (CRTC_ADR, 0x10);
+	cr_data = vgarb (CRTC_DATA);
+	VRS =
+	    (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
+	    ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+	F = VRS + 1 - E;
 
-	/* disable 24-bit palette RAM and Gamma correction */
-	vgawb(SEQ_ADR, 0x07);
-	uTemp = vgarb(SEQ_DATA);
-	uTemp &= ~0x04;
-	vgawb(SEQ_DATA, uTemp);
-}
+	vgawb (CRTC_ADR, 0x15);
+	cr_data = vgarb (CRTC_DATA);
+	vgawb (CRTC_ADR, 0x9);
+	cr_data3 = vgarb (CRTC_DATA);
+	VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
+	    ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+
+	vgawb (CRTC_ADR, 0x16);
+	cr_data = vgarb (CRTC_DATA);
+	VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
+	temp = VBE - ((E - 1) & 511);
+	B = (temp > 0) ? temp : (temp + 512);
 
-static void search_mode(const char *name)
-{
-	int i = 0;
+	vgawb (CRTC_ADR, 0x11);
+	cr_data = vgarb (CRTC_DATA);
+	VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
+	temp = VRE - ((E + F - 1) & 31);
+	C = (temp > 0) ? temp : (temp + 32);
 
-	if (name == NULL)
-		return;
+	D = B - F - C;
 
-	while (sisbios_mode[i].mode_no != 0) {
-		if (!strcmp(name, sisbios_mode[i].name)) {
-			mode_idx = i;
-			break;
-		}
-		i++;
-	}
+	var->yres = var->yres_virtual = E;
+	var->upper_margin = D;
+	var->lower_margin = F;
+	var->vsync_len = C;
 
-	if (mode_idx < 0)
-		DPRINTK("Invalid user mode : %s\n", name);
-}
+	vgawb (SEQ_ADR, 0xb);
+	sr_data = vgarb (SEQ_DATA);
 
-static u8 search_refresh_rate(unsigned int rate)
-{
-	u16 xres, yres;
-	int i = 0;
+	vgawb (CRTC_ADR, 0x0);
+	cr_data = vgarb (CRTC_DATA);
+	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
+	A = HT + 5;
 
-	xres = sisbios_mode[mode_idx].xres;
-	yres = sisbios_mode[mode_idx].yres;
+	vgawb (CRTC_ADR, 0x1);
+	cr_data = vgarb (CRTC_DATA);
+	HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
+	E = HDE + 1;
 
-	while ((vrate[i].idx != 0) && (vrate[i].xres <= xres)) {
-		if ((vrate[i].xres == xres) && (vrate[i].yres == yres)
-		    && (vrate[i].refresh == rate)) {
-			rate_idx = vrate[i].idx;
-			return rate_idx;
-		}
-		i++;
-	}
+	vgawb (CRTC_ADR, 0x4);
+	cr_data = vgarb (CRTC_DATA);
+	HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
+	F = HRS - E - 3;
 
-	DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres,
-		yres);
+	vgawb (CRTC_ADR, 0x2);
+	cr_data = vgarb (CRTC_DATA);
+	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
+
+	vgawb (SEQ_ADR, 0xc);
+	sr_data = vgarb (SEQ_DATA);
+	vgawb (CRTC_ADR, 0x3);
+	cr_data = vgarb (CRTC_DATA);
+	vgawb (CRTC_ADR, 0x5);
+	cr_data2 = vgarb (CRTC_DATA);
+	HBE =
+	    (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
+	    ((u16) (sr_data & 0x03) << 6);
+	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 
-	return 0;
-}
+	temp = HBE - ((E - 1) & 255);
+	B = (temp > 0) ? temp : (temp + 256);
 
-/* ------------------ Public Routines ------------------------------- */
+	temp = HRE - ((E + F + 3) & 63);
+	C = (temp > 0) ? temp : (temp + 64);
 
-/*
- *    Get the Fixed Part of the Display
- */
+	D = B - F - C;
 
-static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
-{
-	DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con);
+	var->xres = var->xres_virtual = E * 8;
+	var->left_margin = D * 8;
+	var->right_margin = F * 8;
+	var->hsync_len = C * 8;
 
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, fb_info.modename);
+	var->activate = FB_ACTIVATE_NOW;
 
-	fix->smem_start = ivideo.video_base;
-	if(ivideo.video_size > 0x800000)
-		fix->smem_len = RESERVED_MEM_SIZE_8M;	/* reserved for Xserver */
+	var->sync = 0;
+
+	mr_data = vgarb (0x1C);
+	if (mr_data & 0x80)
+		var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+	else
+		var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	if (mr_data & 0x40)
+		var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
 	else
-		fix->smem_len = RESERVED_MEM_SIZE_4M;	/* reserved for Xserver */
+		var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+	VT += 2;
+	VT <<= 1;
+	HT = (HT + 5) * 8;
+
+	hrate = (double) ivideo.refresh_rate * (double) VT / 2;
+	drate = hrate * HT;
+	var->pixclock = (u32) (1E12 / drate);
+}
+
+/* ------------------ Public Routines -------------------------------- */
+
+static int sisfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
+	strcpy (fix->id, fb_info.modename);
+
+	fix->smem_start = ivideo.video_base;
+
+	/*karl:10/01/2001 */
+	if (!sisfb_mem) {
+		if (ivideo.video_size > 0x800000)
+			fix->smem_len = 0x800000;
+		else
+			fix->smem_len = 0x400000;
+	} else
+		fix->smem_len = sisfb_mem * 0x100000;
 
 	fix->type = video_type;
 	fix->type_aux = 0;
@@ -1502,135 +2007,110 @@
 	fix->ywrapstep = 0;
 	fix->line_length = video_linelength;
 	fix->mmio_start = ivideo.mmio_base;
-	fix->mmio_len = MMIO_SIZE;
+	fix->mmio_len = sisfb_mmio_size;
 	fix->accel = FB_ACCEL_SIS_GLAMOUR;
 	fix->reserved[0] = ivideo.video_size & 0xFFFF;
 	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = caps;	/* capabilities */
+	fix->reserved[2] = sisfb_caps;
 
 	return 0;
-}
-
-/*
- *    Get the User Defined Part of the Display
- */
 
-static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-	DPRINTK("sisfb: sisfb_get_var:[%d]\n", con);
+}
 
+static int sisfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
 	if (con == -1)
-		memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+		memcpy (var, &default_var, sizeof (struct fb_var_screeninfo));
 	else
 		*var = fb_display[con].var;
+
 	return 0;
 }
 
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+static int sisfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
 	int err;
 	unsigned int cols, rows;
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 
-	/* Set mode */
-	if (do_set_var(var, con == currcon, info)) {
-		crtc_to_var(var);	/* return current mode to user */
+	if (sisfb_do_set_var (var, con == currcon, info)) {
+		sisfb_crtc_to_var (var);
 		return -EINVAL;
 	}
 
-	/* get actual setting value */
-	crtc_to_var(var);
+	sisfb_crtc_to_var (var);
 
-	/* update display of current console */
-	sisfb_set_disp(con, var);
+	sisfb_set_disp (con, var);
 
 	if (info->changevar)
 		(*info->changevar) (con);
 
-	if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+	if ((err = fb_alloc_cmap (&fb_display[con].cmap, 0, 0)))
 		return err;
 
-	do_install_cmap(con, info);
+	sisfb_do_install_cmap (con, info);
 
-	/* inform console to update struct display */
-	cols = sisbios_mode[mode_idx].cols;
-	rows = sisbios_mode[mode_idx].rows;
-	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+	cols = sisbios_mode[sisfb_mode_idx].cols;
+	rows = sisbios_mode[sisfb_mode_idx].rows;
+	vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
 
 	return 0;
-}
 
+}
 
-/*
- *    Get the Colormap
- */
-
-static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+static int sisfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-	DPRINTK("sisfb: sisfb_get_cmap:[%d]\n", con);
-
 	if (con == currcon)
-		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
-	else if (fb_display[con].cmap.len)	/* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+		return fb_get_cmap (cmap, kspc, sis_getcolreg, info);
+	else if (fb_display[con].cmap.len)
+		fb_copy_cmap (&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
-		fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2);
+		fb_copy_cmap (fb_default_cmap (video_cmap_len), cmap,
+			      kspc ? 0 : 2);
+
 	return 0;
 }
 
-/*
- *    Set the Colormap
- */
-
-static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+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) {	/* no colormap allocated */
-		err = fb_alloc_cmap(&fb_display[con].cmap, video_cmap_len, 0);
+	if (!fb_display[con].cmap.len) {
+		err = fb_alloc_cmap (&fb_display[con].cmap, video_cmap_len, 0);
 		if (err)
 			return err;
 	}
-	if (con == currcon)	/* current console */
-		return fb_set_cmap(cmap, kspc, sis_setcolreg, info);
+	if (con == currcon)
+		return fb_set_cmap (cmap, kspc, sis_setcolreg, info);
 	else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+		fb_copy_cmap (cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
 }
 
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg, int con,
-		       struct fb_info *info)
+static int sisfb_ioctl (struct inode *inode, struct file *file,
+	     unsigned int cmd, unsigned long arg, int con, struct fb_info *info)
 {
 	switch (cmd) {
 	case FBIO_ALLOC:
-		if(!capable(CAP_SYS_RAWIO))
+		if (!capable (CAP_SYS_RAWIO))
 			return -EPERM;
-		sis_malloc((struct sis_memreq *) arg);
+		sis_malloc ((struct sis_memreq *) arg);
 		break;
 	case FBIO_FREE:
-		if(!capable(CAP_SYS_RAWIO))
+		if (!capable (CAP_SYS_RAWIO))
 			return -EPERM;
-		sis_free(*(unsigned long *) arg);
+		sis_free (*(unsigned long *) arg);
 		break;
 	case FBIOGET_GLYPH:
-		sis_get_glyph((struct GlyInfo *) arg);
+		sis_get_glyph ((SIS_GLYINFO *) arg);
 		break;
 	case FBIOGET_HWCINFO:
 		{
 			unsigned long *hwc_offset = (unsigned long *) arg;
 
-			if (caps & HW_CURSOR_CAP)
-				*hwc_offset = hwcursor_vbase -
+			if (sisfb_caps & HW_CURSOR_CAP)
+				*hwc_offset = sisfb_hwcursor_vbase -
 				    (unsigned long) ivideo.video_vbase;
 			else
 				*hwc_offset = 0;
@@ -1638,32 +2118,31 @@
 			break;
 		}
 	case FBIOPUT_MODEINFO:
-		{    
-			struct mode_info *x = (struct mode_info *)arg;
+		{
+			struct mode_info *x = (struct mode_info *) arg;
+
+			ivideo.video_bpp = x->bpp;
+			ivideo.video_width = x->xres;
+			ivideo.video_height = x->yres;
+			ivideo.video_vwidth = x->v_xres;
+			ivideo.video_vheight = x->v_yres;
+			ivideo.org_x = x->org_x;
+			ivideo.org_y = x->org_y;
+			ivideo.refresh_rate = x->vrate;
 
-			/* Set Mode Parameters by XServer */        
-			ivideo.video_bpp      = x->bpp;
-			ivideo.video_width    = x->xres;
-			ivideo.video_height   = x->yres;
-			ivideo.video_vwidth   = x->v_xres;
-			ivideo.video_vheight  = x->v_yres;
-			ivideo.org_x          = x->org_x;
-			ivideo.org_y          = x->org_y;
-			ivideo.refresh_rate   = x->vrate;
-			
 			break;
 		}
 	case FBIOGET_DISPINFO:
-		sis_dispinfo((struct ap_data *)arg);
+		sis_dispinfo ((struct ap_data *) arg);
 		break;
 	default:
 		return -EINVAL;
 	}
 	return 0;
+
 }
 
-static int sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
+static int sisfb_mmap (struct fb_info *info, struct file *file, struct vm_area_struct *vma)
 {
 	struct fb_var_screeninfo var;
 	unsigned long start;
@@ -1674,18 +2153,16 @@
 		return -EINVAL;
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
-	/* frame buffer memory */
 	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
+	len = PAGE_ALIGN ((start & ~PAGE_MASK) + ivideo.video_size);
 
 	if (off >= len) {
-		/* memory mapped io */
 		off -= len;
-		sisfb_get_var(&var, currcon, info);
+		sisfb_get_var (&var, currcon, info);
 		if (var.accel_flags)
 			return -EINVAL;
 		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + MMIO_SIZE);
+		len = PAGE_ALIGN ((start & ~PAGE_MASK) + sisfb_mmio_size);
 	}
 
 	start &= PAGE_MASK;
@@ -1694,617 +2171,599 @@
 	off += start;
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
 	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+		pgprot_val (vma->vm_page_prot) |= _PAGE_PCD;
 #endif
-	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 struct fb_ops sisfb_ops = {
-	owner:		THIS_MODULE,
-	fb_get_fix:	sisfb_get_fix,
-	fb_get_var:	sisfb_get_var,
-	fb_set_var:	sisfb_set_var,
-	fb_get_cmap:	sisfb_get_cmap,
-	fb_set_cmap:	sisfb_set_cmap,
-	fb_ioctl:	sisfb_ioctl,
-	fb_mmap:	sisfb_mmap,
+	owner:THIS_MODULE,
+	fb_get_fix:sisfb_get_fix,
+	fb_get_var:sisfb_get_var,
+	fb_set_var:sisfb_set_var,
+	fb_get_cmap:sisfb_get_cmap,
+	fb_set_cmap:sisfb_set_cmap,
+	fb_ioctl:sisfb_ioctl,
+	fb_mmap:sisfb_mmap,
 };
 
-int sisfb_setup(char *options)
-{
-	char *this_opt;
-
-	fb_info.fontname[0] = '\0';
-	ivideo.refresh_rate = 0;
-
-	if (!options || !*options)
-		return 0;
-
-	while (this_opt = strsep(&options, ",")) {
-		if (!*this_opt)
-			continue;
-
-		if (!strcmp(this_opt, "inverse")) {
-			inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5)) {
-			strcpy(fb_info.fontname, this_opt + 5);
-		} else if (!strncmp(this_opt, "mode:", 5)) {
-			search_mode(this_opt + 5);
-		} else if (!strncmp(this_opt, "vrate:", 6)) {
-			ivideo.refresh_rate =
-			    simple_strtoul(this_opt + 6, NULL, 0);
-		} else if (!strncmp(this_opt, "off", 3)) {
-			sisfb_off = 1;
-		} else if (!strncmp(this_opt, "crt1off", 7)) {
-			crt1off = 1;
-		} else
-			DPRINTK("invalid parameter %s\n", this_opt);
-	}
-	return 0;
-}
+/* ------------ Interface to the low level console driver -------------*/
 
-static int sisfb_update_var(int con, struct fb_info *info)
+static int sisfb_update_var (int con, struct fb_info *info)
 {
 	return 0;
 }
 
-/*
- *    Switch Console (called by fbcon.c)
- */
-
-static int sisfb_switch(int con, struct fb_info *info)
+static int sisfb_switch (int con, struct fb_info *info)
 {
 	int cols, rows;
 
-	DPRINTK("sisfb: switch console from [%d] to [%d]\n", currcon, con);
-
-	/* update colormap of current console */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+		fb_get_cmap (&fb_display[currcon].cmap, 1, sis_getcolreg, info);
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 
-	/* same mode, needn't change mode actually */
-
-	if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo))) 
-	{
+	if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof (struct fb_var_screeninfo))) {
 		currcon = con;
 		return 1;
 	}
 
 	currcon = con;
 
-	do_set_var(&fb_display[con].var, 1, info);
+	sisfb_do_set_var (&fb_display[con].var, 1, info);
 
-	sisfb_set_disp(con, &fb_display[con].var);
+	sisfb_set_disp (con, &fb_display[con].var);
 
-	/* Install new colormap */
-	do_install_cmap(con, info);
+	sisfb_do_install_cmap (con, info);
 
-	cols = sisbios_mode[mode_idx].cols;
-	rows = sisbios_mode[mode_idx].rows;
-	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
+	cols = sisbios_mode[sisfb_mode_idx].cols;
+	rows = sisbios_mode[sisfb_mode_idx].rows;
+	vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
 
-	sisfb_update_var(con, info);
+	sisfb_update_var (con, info);
 
 	return 1;
 
 }
 
-/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
-
-static void sisfb_blank(int blank, struct fb_info *info)
+static void sisfb_blank (int blank, struct fb_info *info)
 {
-	u8 CRData;
+	u8 reg;
 
-	vgawb(CRTC_ADR, 0x17);
-	CRData = vgarb(CRTC_DATA);
+	vgawb (CRTC_ADR, 0x17);
+	reg = vgarb (CRTC_DATA);
 
-	if (blank > 0)		/* turn off CRT1 */
-		CRData &= 0x7f;
-	else			/* turn on CRT1 */
-		CRData |= 0x80;
+	if (blank > 0)
+		reg &= 0x7f;
+	else
+		reg |= 0x80;
 
-	vgawb(CRTC_ADR, 0x17);
-	vgawb(CRTC_DATA, CRData);
+	vgawb (CRTC_ADR, 0x17);
+	vgawb (CRTC_DATA, reg);
 }
 
-int has_VB(void)
+int sisfb_setup (char *options)
 {
-	u8 uSR38, uSR39, uVBChipID;
-
-	vgawb(SEQ_ADR, 0x38);
-	uSR38 = vgarb(SEQ_DATA);
-	vgawb(SEQ_ADR, 0x39);
-	uSR39 = vgarb(SEQ_DATA);
-	vgawb(IND_SIS_CRT2_PORT_14, 0x0);
-	uVBChipID = vgarb(IND_SIS_CRT2_PORT_14+1);
+	char *this_opt;
 
-	if (
-		( (HwExt.jChipID == SIS_Glamour) && (uSR38 & 0x20) ) /* 300 */
-		||
-		( (HwExt.jChipID >= SIS_Trojan ) && (uSR38 & 0x20) && (!(uSR39 & 0x80)) ) /* 630/540 */
-		||
-		( (HwExt.jChipID == SIS_Trojan ) && ((HwExt.revision_id & 0xf0) == 0x30) && (uVBChipID == 1) ) /* 630s */
-		||
-		( (HwExt.jChipID == SIS_730) && (uVBChipID == 1) ) /* 730 */
-	   )
-	{
-		ivideo.hasVB = HASVB_301;
-		return TRUE;
-	}
-	else
-	{
-		ivideo.hasVB = HASVB_NONE;
-		return FALSE;
-	}
-}
+	fb_info.fontname[0] = '\0';
+	ivideo.refresh_rate = 0;
 
-void sis_get301info(void)
-{
-	u8 uCRData;
-	unsigned long disp_state=0;
+	if (!options || !*options)
+		return 0;
 
-	if (HwExt.jChipID >= SIS_Trojan)
-	{
-		if (!has_VB())
-		{
-			vgawb(CRTC_ADR, 0x37);
-			uCRData = vgarb(CRTC_DATA);
+	for (this_opt = strtok (options, ","); this_opt;
+	     this_opt = strtok (NULL, ",")) {
+		if (!*this_opt)
+			continue;
 
-			switch((uCRData >> 1) & 0x07)
-			{
-			case 2:
-				ivideo.hasVB = HASVB_LVDS;
-				break;
-			case 4:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				break;
-			case 3:
-				ivideo.hasVB = HASVB_TRUMPION;
-				break;
-			default:
-				break;
-			}
+		if (!strcmp (this_opt, "inverse")) {
+			sisfb_inverse = 1;
+			fb_invert_cmaps ();
+		} else if (!strncmp (this_opt, "font:", 5)) {
+			strcpy (fb_info.fontname, this_opt + 5);
+		} else if (!strncmp (this_opt, "mode:", 5)) {
+			sisfb_search_mode (this_opt + 5);
+		} else if (!strncmp (this_opt, "vrate:", 6)) {
+			ivideo.refresh_rate =
+			    simple_strtoul (this_opt + 6, NULL, 0);
+		} else if (!strncmp (this_opt, "off", 3)) {
+			sisfb_off = 1;
+		} else if (!strncmp (this_opt, "crt1off", 7)) {
+			sisfb_crt1off = 1;
+		} else if (!strncmp (this_opt, "filter:", 7)) {
+			filter = (int) simple_strtoul (this_opt + 7, NULL, 0);
+		}
+		/*karl */
+		else if (!strncmp (this_opt, "tvmode:", 7)) {
+			if (!strncmp (this_opt + 7, "pal", 3))
+				sisfb_tvmode = 1;
+			if (!strncmp (this_opt + 7, "ntsc", 4))
+				sisfb_tvmode = 2;
 		}
-	}
-	else
-	{
-		has_VB();
-	}
+		/*karl:10/01/2001 */
+		else if (!strncmp (this_opt, "mem:", 4)) {
 
-	vgawb(CRTC_ADR, 0x32);
-	uCRData = vgarb(CRTC_DATA);
- 
-	switch(uDispType)
-	{
-	case MASK_DISPTYPE_CRT2: 
-		disp_state = DISPTYPE_CRT2;
-		break;
-	case MASK_DISPTYPE_LCD:
-		disp_state = DISPTYPE_LCD;
-		break;
-	case MASK_DISPTYPE_TV:
-		disp_state = DISPTYPE_TV;
-		break;
-	}
+			sisfb_mem = simple_strtoul (this_opt + 4, NULL, 0);
 
-	if(disp_state & 0x7)
-	{
-		if(crt1off)
-			disp_state |= DISPMODE_SINGLE;
-		else
-			disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+		} else
+			DPRINTK ("invalid parameter %s\n", this_opt);
 	}
-	else
-		disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
-
-	ivideo.disp_state = disp_state;
+	return 0;
 }
 
-
-int __init sisfb_init(void)
+int __init sisfb_init (void)
 {
 	struct pci_dev *pdev = NULL;
 	struct board *b;
 	int pdev_valid = 0;
-	unsigned char jTemp;
-	u8 uSRData, uCRData;
+	//unsigned long rom_vbase;
+	u32 reg32;
+	u16 reg16;
+	u8 reg;
+	int nRes;
 
-	outb(0x77, 0x80);
+	outb (0x77, 0x80);
 
 	if (sisfb_off)
 		return -ENXIO;
 
-	pci_for_each_dev(pdev) {
-		for (b = dev_list; b->vendor; b++) 
-		{
+	pci_for_each_dev (pdev)
+	{
+		for (b = sisdev_list; b->vendor; b++) {
 			if ((b->vendor == pdev->vendor)
-			    && (b->device == pdev->device)) 
-			{
+			    && (b->device == pdev->device)) {
 				pdev_valid = 1;
-				strcpy(fb_info.modename, b->name);
+				strcpy (fb_info.modename, b->name);
 				ivideo.chip_id = pdev->device;
-				pci_read_config_byte(pdev, PCI_REVISION_ID, &HwExt.revision_id);
+				pci_read_config_byte (pdev, PCI_REVISION_ID,
+						      &ivideo.revision_id);
+				pci_read_config_word (pdev, PCI_COMMAND, &reg16);
+				// Eden Chen
+				//sishw_ext.uRevisionID = ivideo.revision_id;
+				sishw_ext.jChipRevision = ivideo.revision_id;
+				// ~Eden Chen
+				sisvga_enabled = reg16 & 0x1;
 				break;
 			}
 		}
-
+	
 		if (pdev_valid)
 			break;
 	}
-
+	
 	if (!pdev_valid)
 		return -1;
-
-	switch(ivideo.chip_id)
-	{
+	
+	// Eden Chen
+	switch (ivideo.chip_id) {
 	case PCI_DEVICE_ID_SI_300:
-		HwExt.jChipID = SIS_Glamour;
+		ivideo.chip = SIS_300;
+		sisvga_engine = SIS_300_VGA;
 		break;
 	case PCI_DEVICE_ID_SI_630_VGA:
-		HwExt.jChipID = SIS_Trojan;
+	{
+		sisfb_set_reg4 (0xCF8, 0x80000000);
+		reg32 = sisfb_get_reg3 (0xCFC);
+		if (reg32 == 0x07301039) {
+			ivideo.chip = SIS_730;
+			strcpy (fb_info.modename, "SIS 730");
+		} else
+			ivideo.chip = SIS_630;
+
+		sisvga_engine = SIS_300_VGA;
 		break;
+	}
 	case PCI_DEVICE_ID_SI_540_VGA:
-		HwExt.jChipID = SIS_Spartan;
+		ivideo.chip = SIS_540;
+		sisvga_engine = SIS_300_VGA;
 		break;
-	case PCI_DEVICE_ID_SI_730_VGA:
-		HwExt.jChipID = SIS_730;
+	case PCI_DEVICE_ID_SI_315H:
+		ivideo.chip = SIS_315H;
+		sisvga_engine = SIS_315_VGA;
+		break;
+	case PCI_DEVICE_ID_SI_315:
+		ivideo.chip = SIS_315;
+		sisvga_engine = SIS_315_VGA;
+		break;
+	case PCI_DEVICE_ID_SI_315PRO:
+		ivideo.chip = SIS_315PRO;
+		sisvga_engine = SIS_315_VGA;
+		break;
+	case PCI_DEVICE_ID_SI_550_VGA:
+		ivideo.chip = SIS_550;
+		sisvga_engine = SIS_315_VGA;
 		break;
 	}
 
-	ivideo.video_base = pci_resource_start(pdev, 0);
-	ivideo.mmio_base = pci_resource_start(pdev, 1);
-	ivideo.vga_base = pci_resource_start(pdev, 2) + 0x30;
-
-	HwExt.IOAddress = (unsigned short)ivideo.vga_base; 
-	rom_base = 0x000C0000;
+	// Eden Chen
+	//sishw_ext.jChipID = ivideo.chip;
+	sishw_ext.jChipType = ivideo.chip;
+	// for Debug
+	if ((sishw_ext.jChipType == SIS_315PRO)
+	    || (sishw_ext.jChipType == SIS_315))
+		sishw_ext.jChipType = SIS_315H;
+		// ~Eden Chen
+
+	DPRINTK ("%s is used as %s device(VGA Engine %d).\n",
+		 fb_info.modename, sisvga_enabled ? "primary" : "secondary",
+		 sisvga_engine);
+	
+	ivideo.video_base = pci_resource_start (pdev, 0);
+	ivideo.mmio_base = pci_resource_start (pdev, 1);
+	// Eden Chen
+	//sishw_ext.IOAddress = (unsigned short) ivideo.vga_base 
+	//      = pci_resource_start(pdev, 2) + 0x30;
+	sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base = pci_resource_start (pdev, 2) + 0x30;
+	// ~Eden Chen
+
+	sisfb_mmio_size = pci_resource_len (pdev, 1);
+
+	if (!sisvga_enabled)
+		if (pci_enable_device (pdev))
+			return -EIO;
+	
+	vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+	vgawb (SEQ_DATA, SIS_PASSWORD);
 
-	MMIO_SIZE =  pci_resource_len(pdev, 1);
+#ifdef LINUXBIOS
+#ifdef CONFIG_FB_SIS_300
+	if (sisvga_engine == SIS_300_VGA)
+	{
+		vgawb (SEQ_ADR, 0x28);
+		vgawb (SEQ_DATA, 0x37);
 
-#ifdef NOBIOS
-	if (pci_enable_device(pdev))
-		return -EIO;
-	/* Image file instead of VGA-bios */
-	HwExt.VirtualRomBase = rom_vbase = (unsigned long) RomData;
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-	if (pci_enable_device(pdev))
-		return -EIO;
-	HwExt.VirtualRomBase = rom_vbase = 0;
-#else
-	request_region(rom_base, 32, "sisfb");
-	HwExt.VirtualRomBase = rom_vbase 
-		= (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
-#endif
-#endif
-	/* set passwd */
-	vgawb(SEQ_ADR, IND_SIS_PASSWORD);
-	vgawb(SEQ_DATA, SIS_PASSWORD);
-
-	/* Enable MMIO & PCI linear address */
-	vgawb(SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
-	jTemp = vgarb(SEQ_DATA);
-	jTemp |= SIS_PCI_ADDR_ENABLE;
-	jTemp |= SIS_MEM_MAP_IO_ENABLE;
-	vgawb(SEQ_DATA, jTemp);
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-	pdev_valid = 0;
-	pci_for_each_dev(pdev) {
-		u8 uPCIData=0;
+		vgawb (SEQ_ADR, 0x29);
+		vgawb (SEQ_DATA, 0x61);
 
-		if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device==0x630)) 
-		{
-			pci_read_config_byte(pdev, 0x63, &uPCIData);
-			uPCIData = (uPCIData & 0x70) >> 4;
-			ivideo.video_size = (unsigned int)(1 << (uPCIData+21));
-			pdev_valid = 1;
-			break;
-		}
+		vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+		reg = vgarb (SEQ_DATA);
+		reg |= SIS_SCRATCH_REG_1A_MASK;
+		vgawb (SEQ_DATA, reg);
 	}
-
-	if (!pdev_valid)
-		return -1;
-#else
-	vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);
-	ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);
 #endif
+#ifdef CONFIG_FB_SIS_315
+	if (ivideo.chip == SIS_550) {
+		vgawb (SEQ_ADR, 0x28);
+		vgawb (SEQ_DATA, 0x5A);
+	
+		vgawb (SEQ_ADR, 0x29);
+		vgawb (SEQ_DATA, 0x64);
 
+		vgawb (CRTC_ADR, 0x3A);
+		vgawb (CRTC_DATA, 0x00);
+	}
+#endif
+#endif
 
-	/* get CRT2 connection state */
-	vgawb(SEQ_ADR, 0x17);
-	uSRData = vgarb(SEQ_DATA);
-	vgawb(CRTC_ADR, 0x32);
-	uCRData = vgarb(CRTC_DATA);
-
-	ivideo.TV_plug = ivideo.TV_type = 0;
-	if((uSRData&0x0F) && (HwExt.jChipID>=SIS_Trojan))
-	{
-		/* CRT1 connect detection */
-		if((uSRData & 0x01) && !crt1off)
-			crt1off = 0;
-		else
-		{
-			if(uSRData&0x0E)     /* DISP2 connected */
-				crt1off = 1;
-			else
-				crt1off = 0;
-		}
-
-		/* detection priority : CRT2 > LCD > TV */
-		if(uSRData & 0x08 )
-			uDispType = MASK_DISPTYPE_CRT2;
-		else if(uSRData & 0x02)
-			uDispType = MASK_DISPTYPE_LCD;
-		else if(uSRData & 0x04)
-		{
-			if(uSRData & 0x80)
-			{
-				ivideo.TV_type = TVMODE_HIVISION;
-				ivideo.TV_plug = TVPLUG_SVIDEO;
-			}
-			else if(uSRData & 0x20)
-				ivideo.TV_plug = TVPLUG_SVIDEO;
-			else if(uSRData & 0x10)
-				ivideo.TV_plug = TVPLUG_COMPOSITE;
-			else if(uSRData & 0x40)
-				ivideo.TV_plug = TVPLUG_SCART;
-
-			if(ivideo.TV_type == 0)
-			{
-				u8 uSR16;
-				vgawb(SEQ_ADR, 0x16);
-				uSR16 = vgarb(SEQ_DATA);
-				if(uSR16 & 0x20)
-					ivideo.TV_type = TVMODE_PAL;
-				else
-					ivideo.TV_type = TVMODE_NTSC;
-			}
-
-			uDispType = MASK_DISPTYPE_TV;
+	if (sisvga_engine == SIS_315_VGA) {
+		switch (ivideo.chip) {
+		case SIS_315H:
+		case SIS_315:
+			sishw_ext.bIntegratedMMEnabled = TRUE;
+			break;
+		case SIS_550:
+			// Eden Chen
+			//vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+			//reg = vgarb(SEQ_DATA);
+			//if (reg & SIS_SCRATCH_REG_1A_MASK)
+			//      sishw_ext.bIntegratedMMEnabled = TRUE;
+			//else
+			//      sishw_ext.bIntegratedMMEnabled = FALSE;
+			//for Debug
+			sishw_ext.bIntegratedMMEnabled = TRUE;
+			// ~Eden Chen
+			break;
+		default:
+			break;
 		}
-	} 
-	else
-	{
-		if((uCRData & 0x20) && !crt1off)
-			crt1off = 0;
-		else
-		{
-			if(uCRData&0x5F)   /* DISP2 connected */
-				crt1off = 1;
+	} else if (sisvga_engine == SIS_300_VGA) {
+		if (ivideo.chip == SIS_300) {
+			sishw_ext.bIntegratedMMEnabled = TRUE;
+		} else {
+			vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
+			reg = vgarb (SEQ_DATA);
+			if (reg & SIS_SCRATCH_REG_1A_MASK)
+				sishw_ext.bIntegratedMMEnabled = TRUE;
 			else
-				crt1off = 0;
+				sishw_ext.bIntegratedMMEnabled = FALSE;
 		}
+	}
+	// Eden Chen
+	sishw_ext.pDevice = NULL;
+	sishw_ext.pjVirtualRomBase = NULL;
+	sishw_ext.pjCustomizedROMImage = NULL;
+	sishw_ext.bSkipDramSizing = 0;
+	sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
+	sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
+	strcpy (sishw_ext.szVBIOSVer, "0.84");
+
+	sishw_ext.pSR = vmalloc (sizeof (SIS_DSReg) * SR_BUFFER_SIZE);
+	if (sishw_ext.pSR == NULL)
+		printk (KERN_DEBUG "Allocated SRReg space fail.\n");
+	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
+
+	sishw_ext.pCR = vmalloc (sizeof (SIS_DSReg) * CR_BUFFER_SIZE);
+	if (sishw_ext.pCR == NULL)
+		printk (KERN_DEBUG "Allocated CRReg space fail.\n");
+	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
+	// ~Eden Chen
+
+	#ifdef CONFIG_FB_SIS_300
+	if (sisvga_engine == SIS_300_VGA) {
+		if (!sisvga_enabled) {
+			// Eden Chen
+			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x2000000);
+			//SiSInit300(&sishw_ext);
+			SiSInit (&sishw_ext);
+			vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+			vgawb (SEQ_DATA, SIS_PASSWORD);
+			// ~Eden Chen
+		}
+#ifdef LINUXBIOS
+		else {
+			// Eden Chen
+			sishw_ext.pjVideoMemoryAddress
+			    = ioremap (ivideo.video_base, 0x2000000);
+			//SiSInit300(&sishw_ext);
+			SiSInit (&sishw_ext);
+			vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+			vgawb (SEQ_DATA, SIS_PASSWORD);
+			// ~Eden Chen
+		}
+		vgawb (SEQ_ADR, 0x7);
+		reg = vgarb (SEQ_DATA);
+		reg |= 0x10;
+		vgawb (SEQ_DATA, reg);
+#endif
+		sisfb_get_dram_size_300 ();
+	}
+#endif
 
-		if(uCRData & 0x10)
-			uDispType = MASK_DISPTYPE_CRT2;
-		else if(uCRData & 0x08)
-			uDispType = MASK_DISPTYPE_LCD;
-		else if(uCRData & 0x47)
-		{
-			uDispType = MASK_DISPTYPE_TV;
-
-			if(uCRData & 0x40)
-			{
-				ivideo.TV_type = TVMODE_HIVISION;
-				ivideo.TV_plug = TVPLUG_SVIDEO;
-			}
-			else if(uCRData & 0x02)
-				ivideo.TV_plug = TVPLUG_SVIDEO;
-			else if(uCRData & 0x01)
-				ivideo.TV_plug = TVPLUG_COMPOSITE;
-			else if(uCRData & 0x04)
-				ivideo.TV_plug = TVPLUG_SCART;
+	#ifdef CONFIG_FB_SIS_315
+	if (sisvga_engine == SIS_315_VGA) {
+		if (!sisvga_enabled) {
+			/* Mapping Max FB Size for 315 Init */
+			// Eden Chen
+			//sishw_ext.VirtualVideoMemoryAddress 
+			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+			//SiSInit310(&sishw_ext);
+			SiSInit (&sishw_ext);
+	
+			vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+			vgawb (SEQ_DATA, SIS_PASSWORD);
+	
+			sishw_ext.bSkipDramSizing = TRUE;
+			vgawb (SEQ_ADR, 0x13);
+			sishw_ext.pSR[0].jIdx = 0x13;
+			sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+			vgawb (SEQ_ADR, 0x14);
+			sishw_ext.pSR[1].jIdx = 0x14;
+			sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+			sishw_ext.pSR[2].jIdx = 0xFF;
+			sishw_ext.pSR[2].jVal = 0xFF;
+			// Eden Chen
+		}
+#ifdef LINUXBIOS
+		else {
+			sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
+			SiSInit (&sishw_ext);
+			vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+			vgawb (SEQ_DATA, SIS_PASSWORD);
+	
+			sishw_ext.bSkipDramSizing = TRUE;
+			vgawb (SEQ_ADR, 0x13);
+			sishw_ext.pSR[0].jIdx = 0x13;
+			sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
+			vgawb (SEQ_ADR, 0x14);
+			sishw_ext.pSR[1].jIdx = 0x14;
+			sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
+			sishw_ext.pSR[2].jIdx = 0xFF;
+			sishw_ext.pSR[2].jVal = 0xFF;
+		}
+#endif
+		sisfb_get_dram_size_315 ();
+	}
+#endif
+	//Eden Chen 
+	vgawb (SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
+	reg = vgarb (SEQ_DATA);
+	reg |= SIS_PCI_ADDR_ENABLE;
+	reg |= SIS_MEM_MAP_IO_ENABLE;
+	vgawb (SEQ_DATA, reg);
+
+	vgawb (SEQ_ADR, IND_SIS_MODULE_ENABLE);
+	reg = vgarb (SEQ_DATA);
+	reg |= SIS_ENABLE_2D;
+	vgawb (SEQ_DATA, reg);
+	//~Eden Chen
+
+	// Eden Chen
+	sishw_ext.ulVideoMemorySize = ivideo.video_size;
+	// ~Eden Chen
+	if (!request_mem_region (ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+		printk (KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
+		return -ENODEV;
+	}
 
-			if(ivideo.TV_type == 0)
-			{
-				u8 uTemp;
-				uTemp = *((u8 *)(HwExt.VirtualRomBase+0x52));
-				if(uTemp&0x40)
-				{
-					uTemp=*((u8 *)(HwExt.VirtualRomBase+0x53));
-				}
-				else
-				{
-					vgawb(SEQ_ADR, 0x38);
-					uTemp = vgarb(SEQ_DATA);
-				}
-				if(uTemp & 0x01)
-					ivideo.TV_type = TVMODE_PAL;
-				else
-					ivideo.TV_type = TVMODE_NTSC;
-			}
+	if (!request_mem_region (ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
+		printk (KERN_ERR "sisfb: cannot reserve MMIO region\n");
+		release_mem_region (ivideo.video_base, ivideo.video_size);
+		return -ENODEV;
+	}
+	// Eden Chen
+	//sishw_ext.VirtualVideoMemoryAddress = ivideo.video_vbase 
+	sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase = ioremap (ivideo.video_base, ivideo.video_size);
+	// Eden Chen
+	ivideo.mmio_vbase = ioremap (ivideo.mmio_base, sisfb_mmio_size);
+
+	printk (KERN_INFO
+		"sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+		ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
+
+	printk (KERN_INFO
+		"sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
+		ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);
+
+	#ifdef CONFIG_FB_SIS_300
+	if (sisvga_engine == SIS_300_VGA) {
+		sisfb_get_VB_type_300 ();
+		if (ivideo.hasVB != HASVB_NONE) {
+			sisfb_detect_VB_connect_300 ();
 		}
 	}
+#endif
 
-	if(uDispType == MASK_DISPTYPE_LCD)   // LCD conntected
-	{
-		// TODO: set LCDType by EDID
-		HwExt.usLCDType = LCD1024;
+#ifdef CONFIG_FB_SIS_315
+	if (sisvga_engine == SIS_315_VGA) {
+		sisfb_get_VB_type_315 ();
+		if (ivideo.hasVB != HASVB_NONE) {
+			sisfb_detect_VB_connect_315 ();
+		}
 	}
+#endif
 
-	if (HwExt.jChipID >= SIS_Trojan)
-	{
-		vgawb(SEQ_ADR, 0x1A);
-		uSRData = vgarb(SEQ_DATA);
-		if (uSRData & 0x10)
-			HwExt.bIntegratedMMEnabled = TRUE;
+	// Eden Chen
+sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
+sishw_ext.usExternalChip = 0;
+
+	switch (ivideo.hasVB) {
+	case HASVB_301:
+		/*karl */
+		vgawb (VB_PART4_ADR, 0x01);
+		reg = vgarb (VB_PART4_DATA);
+		if ((reg != 0xB1) && (reg != 0xB0))
+			sishw_ext.ujVBChipID = VB_CHIP_301;
 		else
-			HwExt.bIntegratedMMEnabled = FALSE;
+			sishw_ext.ujVBChipID = VB_CHIP_301B;
+		break;
+	case HASVB_302:
+		sishw_ext.ujVBChipID = VB_CHIP_302;
+		break;
+	case HASVB_303:
+		sishw_ext.ujVBChipID = VB_CHIP_303;
+		break;
+	case HASVB_LVDS:
+		sishw_ext.usExternalChip = 0x1;
+		break;
+	case HASVB_TRUMPION:
+		sishw_ext.usExternalChip = 0x2;
+		break;
+	case HASVB_CHRONTEL:
+		sishw_ext.usExternalChip = 0x4;
+		break;
+	case HASVB_LVDS_CHRONTEL:
+		sishw_ext.usExternalChip = 0x5;
+		break;
+	default:
+		break;
 	}
 
-	if(mode_idx >= 0)	/* mode found */
-	{
-		/* Filtering mode for VB */
-		switch(uDispType & MASK_DISPTYPE_DISP2)
-		{
-		case MASK_DISPTYPE_LCD:
-			switch(HwExt.usLCDType)
-			{
-	    	case LCD1024:
-				if(sisbios_mode[mode_idx].xres > 1024)
-					mode_idx = -1;
-				break;
-	    	case LCD1280:
-				if(sisbios_mode[mode_idx].xres > 1280)
-					mode_idx = -1;
-				break;
-	    	case LCD2048:
-				if(sisbios_mode[mode_idx].xres > 2048)
-					mode_idx = -1;
-				break;
-	    	case LCD1920:
-				if(sisbios_mode[mode_idx].xres > 1920)
-					mode_idx = -1;
-				break;
-	    	case LCD1600:
-				if(sisbios_mode[mode_idx].xres > 1600)
-					mode_idx = -1;
-				break;
-	    	case LCD800:
-				if(sisbios_mode[mode_idx].xres > 800)
-					mode_idx = -1;
-				break;
-	    	case LCD640:
-				if(sisbios_mode[mode_idx].xres > 640)
-					mode_idx = -1;
-				break;
-			default:
-				mode_idx = -1;
-			}
+	// ~Eden Chen
 
-			if(sisbios_mode[mode_idx].xres == 720)  /* only for TV */
-				mode_idx = -1;
+	if (ivideo.disp_state & DISPTYPE_DISP2) {
+		if (sisfb_crt1off)
+			ivideo.disp_state |= DISPMODE_SINGLE;
+		else
+			ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
+	} else
+		ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
+
+	if (ivideo.disp_state & DISPTYPE_LCD) {
+		vgawb (CRTC_ADR, IND_SIS_LCD_PANEL);
+		reg = vgarb (CRTC_DATA);
+		// Eden Chen
+		switch (reg) {
+		case SIS_LCD_PANEL_800X600:
+			sishw_ext.ulCRT2LCDType = LCD_800x600;
 			break;
-		case MASK_DISPTYPE_TV:
-			switch(sisbios_mode[mode_idx].xres)
-			{
-			case 800:
-			case 640:
-				break;
-			case 720:
-				if(ivideo.TV_type == TVMODE_NTSC)
-				{
-					if(sisbios_mode[mode_idx].yres != 480)
-						mode_idx = -1;
-				}
-				else if(ivideo.TV_type == TVMODE_PAL)
-				{
-					if(sisbios_mode[mode_idx].yres != 576)
-						mode_idx = -1;
-				}
-				break;
-			default:
-				/* illegal mode */
-				mode_idx = -1;
-			}
+		case SIS_LCD_PANEL_1024X768:
+			sishw_ext.ulCRT2LCDType = LCD_1024x768;
+			break;
+		case SIS_LCD_PANEL_1280X1024:
+			sishw_ext.ulCRT2LCDType = LCD_1280x1024;
+			break;
+		case SIS_LCD_PANEL_640X480:
+			sishw_ext.ulCRT2LCDType = LCD_640x480;
+			break;
+		case SIS_LCD_PANEL_1280X960:
+			sishw_ext.ulCRT2LCDType = LCD_1280x960;
+			break;
+		default:
+			sishw_ext.ulCRT2LCDType = LCD_1024x768;
 			break;
 		}
-	}	
+	// ~Eden Chen
+	}
+
+	if (sisfb_mode_idx >= 0)
+		sisfb_validate_mode ();
 	
-	if (mode_idx < 0)
-	{
-		switch(uDispType & MASK_DISPTYPE_DISP2)
-		{
-		case MASK_DISPTYPE_LCD:
-			mode_idx = DEFAULT_LCDMODE;
+	if (sisfb_mode_idx < 0) {
+		switch (ivideo.disp_state & DISPTYPE_DISP2) {
+		case DISPTYPE_LCD:
+			sisfb_mode_idx = DEFAULT_LCDMODE;
 			break;
-		case MASK_DISPTYPE_TV:
-			mode_idx = DEFAULT_TVMODE;
+		case DISPTYPE_TV:
+			sisfb_mode_idx = DEFAULT_TVMODE;
 			break;
 		default:
-			mode_idx = DEFAULT_MODE;
+			sisfb_mode_idx = DEFAULT_MODE;
+			break;
 		}
 	}
-
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-	mode_idx = DEFAULT_MODE;
-	rate_idx = sisbios_mode[mode_idx].rate_idx;
-	/* set to default refresh rate 60MHz */
-	ivideo.refresh_rate = 60;
-#endif
-
-	mode_no = sisbios_mode[mode_idx].mode_no;
-
+	
+	sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+	
 	if (ivideo.refresh_rate != 0)
-		search_refresh_rate(ivideo.refresh_rate);
+		sisfb_search_refresh_rate (ivideo.refresh_rate);
 
-	if (rate_idx == 0) {
-		rate_idx = sisbios_mode[mode_idx].rate_idx;	
-		/* set to default refresh rate 60MHz */
+	if (sisfb_rate_idx == 0) {
+		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
 		ivideo.refresh_rate = 60;
 	}
 
-	ivideo.video_bpp = sisbios_mode[mode_idx].bpp;
-	ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres;
-	ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres;
+	ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
+	ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
+	ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
 	ivideo.org_x = ivideo.org_y = 0;
 	video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
 
-	printk(KERN_DEBUG "FB base: 0x%lx, size: 0x%dK\n", 
-		ivideo.video_base, (unsigned int)ivideo.video_size/1024);
-	printk(KERN_DEBUG "MMIO base: 0x%lx, size: 0x%dK\n", 
-		ivideo.mmio_base, (unsigned int)MMIO_SIZE/1024);
-
-
-	if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) 
-	{
-		printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n");
-		return -ENODEV;
-	}
-
-	if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO")) 
-	{
-		printk(KERN_ERR "sisfb: cannot reserve MMIO region\n");
-		release_mem_region(ivideo.video_base, ivideo.video_size);
-		return -ENODEV;
-	}
-
-	HwExt.VirtualVideoMemoryAddress = ivideo.video_vbase 
-		= ioremap(ivideo.video_base, ivideo.video_size);
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);
-
-#ifdef NOBIOS
-	SiSInit300(&HwExt);
-#else
-#ifdef CONFIG_FB_SIS_LINUXBIOS
-	SiSInit300(&HwExt);
-#endif
-#endif
-	printk(KERN_INFO
-	       "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       ivideo.video_base, ivideo.video_vbase,
-	       ivideo.video_size / 1024);
-	printk(KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
-	       ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-	       video_linelength);
-
-	/* enable 2D engine */
-	vgawb(SEQ_ADR, IND_SIS_MODULE_ENABLE);
-	jTemp = vgarb(SEQ_DATA);
-	jTemp |= SIS_2D_ENABLE;
-	vgawb(SEQ_DATA, jTemp);
+	printk (KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n",
+		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
+		video_linelength);
+
+	// Eden Chen
+	// Check interface correction  For Debug
+	DPRINTK ("VM Adr=0x%p\n", sishw_ext.pjVideoMemoryAddress);
+	DPRINTK ("VM Size=%ldK\n", sishw_ext.ulVideoMemorySize / 1024);
+	DPRINTK ("IO Adr=0x%lx\n", sishw_ext.ulIOAddress);
+	DPRINTK ("Chip=%d\n", sishw_ext.jChipType);
+	DPRINTK ("ChipRevision=%d\n", sishw_ext.jChipRevision);
+	DPRINTK ("VBChip=%d\n", sishw_ext.ujVBChipID);
+	DPRINTK ("ExtVB=%d\n", sishw_ext.usExternalChip);
+	DPRINTK ("LCD=%ld\n", sishw_ext.ulCRT2LCDType);
+	DPRINTK ("bIntegratedMMEnabled=%d\n", sishw_ext.bIntegratedMMEnabled);
+	// ~Eden Chen
 
-	pre_setmode();
+	sisfb_pre_setmode ();
 
-	if (SiSSetMode(&HwExt, mode_no)) {
-		DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no);
+	if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
+		DPRINTK ("set mode[0x%x]: failed\n", sisfb_mode_no);
 		return -1;
 	}
+	vgawb (SEQ_ADR, IND_SIS_PASSWORD);
+	vgawb (SEQ_DATA, SIS_PASSWORD);
+	// Eden Chen
 
-	post_setmode();
-
-	/* Get VB functions */
-	sis_get301info();
+	sisfb_post_setmode ();
 
-	crtc_to_var(&default_var);
+	sisfb_crtc_to_var (&default_var);
 
 	fb_info.changevar = NULL;
 	fb_info.node = -1;
@@ -2315,20 +2774,22 @@
 	fb_info.blank = &sisfb_blank;
 	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
-	sisfb_set_disp(-1, &default_var);
+	sisfb_set_disp (-1, &default_var);
 
-	if (sisfb_heap_init()) {
-		DPRINTK("sisfb: Failed to enable offscreen heap\n");
+	if (sisfb_heap_init ()) {
+		DPRINTK ("sisfb: Failed to enable offscreen heap\n");
 	}
+	
+	/*H.C. */
+	nRes = 	mtrr_add ((unsigned int) ivideo.video_base, (unsigned int) ivideo.video_size,  MTRR_TYPE_WRCOMB, 1);
+	vc_resize_con (1, 1, 0);
 
-	/* to avoid the inversed bgcolor bug of the initial state */
-	vc_resize_con(1, 1, 0);
-
-	if (register_framebuffer(&fb_info) < 0)
+	if (register_framebuffer (&fb_info) < 0)
 		return -EINVAL;
 
-	printk(KERN_INFO "fb%d: %s frame buffer device\n",
-	       GET_FB_IDX(fb_info.node), fb_info.modename);
+	printk (KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
+		GET_FB_IDX (fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR,
+		VER_LEVEL);
 
 	return 0;
 }
@@ -2339,35 +2800,36 @@
 static unsigned int rate = 0;
 static unsigned int crt1 = 1;
 
-MODULE_PARM(mode, "s");
-MODULE_PARM(rate, "i");
-MODULE_PARM(crt1, "i");	/* default: CRT1 enable */
+MODULE_PARM (mode, "s");
+MODULE_PARM (rate, "i");
+MODULE_PARM (crt1, "i");
+MODULE_PARM (filter, "i");
 
-int init_module(void)
+int init_module (void)
 {
 	if (mode)
-		search_mode(mode);
+		sisfb_search_mode (mode);
 
 	ivideo.refresh_rate = rate;
 
-	if(crt1 == 0)
-		crt1off = 1;
+	if (crt1 == 0)
+		sisfb_crt1off = 1;
 	else
-		crt1off = 0;
-	
-	sisfb_init();
+		sisfb_crt1off = 0;
+
+	sisfb_init ();
 
 	return 0;
 }
 
-void cleanup_module(void)
+void cleanup_module (void)
 {
-	unregister_framebuffer(&fb_info);
+	unregister_framebuffer (&fb_info);
 }
-#endif				/* MODULE */
-
+#endif
 
-EXPORT_SYMBOL(sis_malloc);
-EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL (sis_malloc);
+EXPORT_SYMBOL (sis_free);
+EXPORT_SYMBOL (sis_dispinfo);
 
-EXPORT_SYMBOL(ivideo);
+EXPORT_SYMBOL (ivideo);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)